Tail now works (costs 6k). Several other updates.
-Erik
This commit is contained in:
parent
c24db7b591
commit
1792f8c489
@ -2,19 +2,19 @@
|
|||||||
* New Apps: ping and hostname contributed by Randolph Chung
|
* New Apps: ping and hostname contributed by Randolph Chung
|
||||||
<tausq@debian.org>. 2 items off the TODO list!
|
<tausq@debian.org>. 2 items off the TODO list!
|
||||||
* I wrote free (just calls "cat /proc/meminfo").
|
* I wrote free (just calls "cat /proc/meminfo").
|
||||||
|
* Added tail, based on tail from GNU textutils-1.19, but adjusted
|
||||||
|
to suit my evil purposes. Costs 6k.
|
||||||
* on reboot, init called 'umount -a -n', which caused errors
|
* on reboot, init called 'umount -a -n', which caused errors
|
||||||
when BB_MTAB was not enabled. Changed to 'umount -a',
|
when BB_MTAB was not enabled. Changed to 'umount -a',
|
||||||
which does the right thing.
|
which does the right thing.
|
||||||
* init will now try to run /sbin/getty if it is present (for easy
|
* init will now try to run /sbin/getty if it is present (for easy
|
||||||
integration with the about-to-be-released tinylogin.)
|
integration with the about-to-be-released tinylogin.)
|
||||||
* kill now behaves itself properly, added 'kill -l' to list signals
|
* kill now behaves itself properly, added 'kill -l' to list signals
|
||||||
* Began to add tail, but it doesn't work yet.
|
* 'ls -l' was failing on long directories, since my_getid was leaking
|
||||||
* my_getid was leaking file descriptors, causing 'ls -l' on long
|
one file descriptor per file. Oops.
|
||||||
directories to fail
|
|
||||||
|
|
||||||
-Erik Andrsen
|
-Erik Andrsen
|
||||||
|
|
||||||
|
|
||||||
0.38
|
0.38
|
||||||
* Fixed a segfault in 'umount -a' when a badly formed /etc/fstab
|
* Fixed a segfault in 'umount -a' when a badly formed /etc/fstab
|
||||||
file existed.
|
file existed.
|
||||||
|
7
TODO
7
TODO
@ -18,13 +18,14 @@ around to it some time. If you have any good ideas, please let me know.
|
|||||||
* traceroute/nslookup/netstat
|
* traceroute/nslookup/netstat
|
||||||
* rdate
|
* rdate
|
||||||
* hwclock
|
* hwclock
|
||||||
* login/getty
|
|
||||||
* killall
|
* killall
|
||||||
* tee
|
* tee
|
||||||
* stty
|
* stty
|
||||||
* head/tail
|
* head
|
||||||
* sort/uniq
|
* sort/uniq
|
||||||
* wc
|
* wc
|
||||||
* tr
|
* tr
|
||||||
* expr (maybe)?
|
* expr (maybe)? (ash builtin?)
|
||||||
|
* login/sulogin/passwd/getty (These are actully now part of tinylogin, which
|
||||||
|
I've just started to maintain).
|
||||||
|
|
||||||
|
@ -48,54 +48,10 @@ static const char dd_usage[] =
|
|||||||
"\tcount=n\tcopy only n input blocks\n"
|
"\tcount=n\tcopy only n input blocks\n"
|
||||||
//"\tskip=n\tskip n input blocks\n"
|
//"\tskip=n\tskip n input blocks\n"
|
||||||
"\n"
|
"\n"
|
||||||
"BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
|
"BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a number with a possible multiplier.
|
|
||||||
* Returns -1 if the number format is illegal.
|
|
||||||
*/
|
|
||||||
static long getNum (const char *cp)
|
|
||||||
{
|
|
||||||
long value;
|
|
||||||
|
|
||||||
if (!isDecimal (*cp))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
value = 0;
|
|
||||||
|
|
||||||
while (isDecimal (*cp))
|
|
||||||
value = value * 10 + *cp++ - '0';
|
|
||||||
|
|
||||||
switch (*cp++) {
|
|
||||||
case 'k':
|
|
||||||
value *= 1024;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
value *= 512;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
value *= 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\0':
|
|
||||||
return value;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*cp)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern int dd_main (int argc, char **argv)
|
extern int dd_main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *inFile = NULL;
|
const char *inFile = NULL;
|
||||||
|
176
coreutils/tail.c
176
coreutils/tail.c
@ -13,35 +13,16 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
/* Can display any amount of data, unlike the Unix version, which uses
|
|
||||||
a fixed size buffer and therefore can only deliver a limited number
|
|
||||||
of lines.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-b Tail by N 512-byte blocks.
|
|
||||||
-c, --bytes=N[bkm] Tail by N bytes
|
|
||||||
[or 512-byte blocks, kilobytes, or megabytes].
|
|
||||||
-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.
|
|
||||||
-n, --lines=N Tail by N lines.
|
|
||||||
-q, --quiet, --silent Never print filename headers.
|
|
||||||
-v, --verbose Always print filename headers.
|
|
||||||
|
|
||||||
If a number (N) starts with a `+', begin printing with the Nth item
|
|
||||||
from the start of each file, instead of from the end.
|
|
||||||
|
|
||||||
Reads from standard input if no files are given or when a filename of
|
|
||||||
``-'' is encountered.
|
|
||||||
By default, filename headers are printed only more than one file
|
|
||||||
is given.
|
|
||||||
By default, prints the last 10 lines (tail -n 10).
|
|
||||||
|
|
||||||
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
|
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
|
||||||
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
|
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
|
||||||
tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */
|
tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.
|
||||||
|
|
||||||
|
Rewrote the option parser, removed locales support,
|
||||||
|
and generally busyboxed, Erik Andersen <andersen@lineo.com>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@ -49,16 +30,25 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Disable assertions. Some systems have broken assert macros. */
|
/* Disable assertions. Some systems have broken assert macros. */
|
||||||
#define NDEBUG 1
|
#define NDEBUG 1
|
||||||
|
|
||||||
|
|
||||||
static void error(int i, int errnum, char* fmt, const char *msg)
|
static void error(int i, int errnum, char* fmt, ...)
|
||||||
{
|
{
|
||||||
fprintf(stderr, fmt, msg);
|
va_list arguments;
|
||||||
perror( errnum);
|
|
||||||
|
va_start(arguments, fmt);
|
||||||
|
vfprintf(stderr, fmt, arguments);
|
||||||
|
fprintf(stderr, "\n%s\n", strerror( errnum));
|
||||||
|
va_end(arguments);
|
||||||
exit(i);
|
exit(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +59,7 @@ static void error(int i, int errnum, char* fmt, const char *msg)
|
|||||||
assert ((fd) == 1); \
|
assert ((fd) == 1); \
|
||||||
assert ((n_bytes) >= 0); \
|
assert ((n_bytes) >= 0); \
|
||||||
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
||||||
error (EXIT_FAILURE, errno, "write error", NULL); \
|
error (EXIT_FAILURE, errno, "write error"); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
@ -110,7 +100,6 @@ enum header_mode
|
|||||||
};
|
};
|
||||||
|
|
||||||
char *xmalloc ();
|
char *xmalloc ();
|
||||||
int safe_read ();
|
|
||||||
|
|
||||||
/* The name this program was run with. */
|
/* The name this program was run with. */
|
||||||
char *program_name;
|
char *program_name;
|
||||||
@ -118,33 +107,24 @@ char *program_name;
|
|||||||
/* Nonzero if we have ever read standard input. */
|
/* Nonzero if we have ever read standard input. */
|
||||||
static int have_read_stdin;
|
static int have_read_stdin;
|
||||||
|
|
||||||
/* If nonzero, display usage information and exit. */
|
|
||||||
static int show_help;
|
|
||||||
|
|
||||||
/* If nonzero, print the version on standard output then exit. */
|
|
||||||
static int show_version;
|
|
||||||
|
|
||||||
static const char tail_usage[] =
|
static const char tail_usage[] =
|
||||||
"tail [OPTION]... [FILE]...\n\
|
"tail [OPTION]... [FILE]...\n\
|
||||||
|
\n\
|
||||||
Print last 10 lines of each FILE to standard output.\n\
|
Print last 10 lines of each FILE to standard output.\n\
|
||||||
With more than one FILE, precede each with a header giving the file name.\n\
|
With more than one FILE, precede each with a header giving the file name.\n\
|
||||||
With no FILE, or when FILE is -, read standard input.\n\
|
With no FILE, or when FILE is -, read standard input.\n\
|
||||||
\n\
|
\n\
|
||||||
-c, --bytes=N output the last N bytes\n\
|
-c=N[kbm] output the last N bytes\n\
|
||||||
-f, --follow output appended data as the file grows\n\
|
-f output appended data as the file grows\n\
|
||||||
-n, --lines=N output the last N lines, instead of last 10\n\
|
-n=N output the last N lines, instead of last 10\n\
|
||||||
-q, --quiet, --silent never output headers giving file names\n\
|
-q never output headers giving file names\n\
|
||||||
-v, --verbose always output headers giving file names\n\
|
-v always output headers giving file names\n\
|
||||||
--help display this help and exit\n\
|
--help display this help and exit\n\
|
||||||
--version output version information and exit\n\
|
|
||||||
\n\
|
\n\
|
||||||
If the first character of N (the number of bytes or lines) is a `+',\n\
|
If the first character of N (bytes or lines) is a `+', output begins with \n\
|
||||||
print beginning with the Nth item from the start of each file, otherwise,\n\
|
the Nth item from the start of each file, otherwise, print the last N items\n\
|
||||||
print the last N items in the file. N may have a multiplier suffix:\n\
|
in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
|
||||||
b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\
|
|
||||||
or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\
|
|
||||||
the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\
|
|
||||||
or -c +VALUE.\n";
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_header (const char *filename, const char *comment)
|
write_header (const char *filename, const char *comment)
|
||||||
@ -184,7 +164,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
|||||||
reads will be on block boundaries, which might increase efficiency. */
|
reads will be on block boundaries, which might increase efficiency. */
|
||||||
pos -= bytes_read;
|
pos -= bytes_read;
|
||||||
lseek (fd, pos, SEEK_SET);
|
lseek (fd, pos, SEEK_SET);
|
||||||
bytes_read = safe_read (fd, buffer, bytes_read);
|
bytes_read = fullRead (fd, buffer, bytes_read);
|
||||||
if (bytes_read == -1)
|
if (bytes_read == -1)
|
||||||
{
|
{
|
||||||
error (0, errno, "%s", filename);
|
error (0, errno, "%s", filename);
|
||||||
@ -220,7 +200,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
|||||||
pos -= BUFSIZ;
|
pos -= BUFSIZ;
|
||||||
lseek (fd, pos, SEEK_SET);
|
lseek (fd, pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0);
|
while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
|
||||||
if (bytes_read == -1)
|
if (bytes_read == -1)
|
||||||
{
|
{
|
||||||
error (0, errno, "%s", filename);
|
error (0, errno, "%s", filename);
|
||||||
@ -255,7 +235,7 @@ pipe_lines (const char *filename, int fd, long int n_lines)
|
|||||||
tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER));
|
tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER));
|
||||||
|
|
||||||
/* Input is always read into a fresh buffer. */
|
/* Input is always read into a fresh buffer. */
|
||||||
while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0)
|
while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
tmp->nlines = 0;
|
tmp->nlines = 0;
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
@ -374,7 +354,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes)
|
|||||||
tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER));
|
tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER));
|
||||||
|
|
||||||
/* Input is always read into a fresh buffer. */
|
/* Input is always read into a fresh buffer. */
|
||||||
while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0)
|
while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
|
|
||||||
@ -453,7 +433,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes)
|
|||||||
char buffer[BUFSIZ];
|
char buffer[BUFSIZ];
|
||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
|
|
||||||
while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
|
while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0)
|
||||||
n_bytes -= bytes_read;
|
n_bytes -= bytes_read;
|
||||||
if (bytes_read == -1)
|
if (bytes_read == -1)
|
||||||
{
|
{
|
||||||
@ -476,7 +456,7 @@ start_lines (const char *filename, int fd, long int n_lines)
|
|||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
int bytes_to_skip = 0;
|
int bytes_to_skip = 0;
|
||||||
|
|
||||||
while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
|
while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
bytes_to_skip = 0;
|
bytes_to_skip = 0;
|
||||||
while (bytes_to_skip < bytes_read)
|
while (bytes_to_skip < bytes_read)
|
||||||
@ -509,7 +489,7 @@ dump_remainder (const char *filename, int fd)
|
|||||||
|
|
||||||
total = 0;
|
total = 0;
|
||||||
output:
|
output:
|
||||||
while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
|
while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
XWRITE (STDOUT_FILENO, buffer, bytes_read);
|
XWRITE (STDOUT_FILENO, buffer, bytes_read);
|
||||||
total += bytes_read;
|
total += bytes_read;
|
||||||
@ -731,7 +711,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
|||||||
int fd, errors;
|
int fd, errors;
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
|
|
||||||
if (!strcmp (filename, "-")
|
if (!strcmp (filename, "-"))
|
||||||
{
|
{
|
||||||
have_read_stdin = 1;
|
have_read_stdin = 1;
|
||||||
filename = "standard input";
|
filename = "standard input";
|
||||||
@ -815,16 +795,15 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
tai_main (int argc, char **argv)
|
tail_main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int stopit = 0;
|
||||||
enum header_mode header_mode = multiple_files;
|
enum header_mode header_mode = multiple_files;
|
||||||
int exit_status = 0;
|
int exit_status = 0;
|
||||||
/* If from_start, the number of items to skip before printing; otherwise,
|
/* If from_start, the number of items to skip before printing; otherwise,
|
||||||
the number of items at the end of the file to print. Initially, -1
|
the number of items at the end of the file to print. Initially, -1
|
||||||
means the value has not been set. */
|
means the value has not been set. */
|
||||||
off_t n_units = -1;
|
off_t n_units = -1;
|
||||||
long int tmp_long;
|
|
||||||
int c; /* Option character. */
|
|
||||||
int n_files;
|
int n_files;
|
||||||
char **file;
|
char **file;
|
||||||
|
|
||||||
@ -832,48 +811,38 @@ tai_main (int argc, char **argv)
|
|||||||
have_read_stdin = 0;
|
have_read_stdin = 0;
|
||||||
count_lines = 1;
|
count_lines = 1;
|
||||||
forever = forever_multiple = from_start = print_headers = 0;
|
forever = forever_multiple = from_start = print_headers = 0;
|
||||||
|
|
||||||
if (argc > 1
|
/* Parse any options */
|
||||||
&& ((argv[1][0] == '-' && ISDIGIT (argv[1][1]))
|
//fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
|
||||||
|| (argv[1][0] == '+' && (ISDIGIT (argv[1][1])
|
while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) {
|
||||||
|| argv[1][1] == 0))))
|
if (**argv == '+') {
|
||||||
{
|
from_start = 1;
|
||||||
/* Old option syntax: a dash or plus, one or more digits (zero digits
|
}
|
||||||
are acceptable with a plus), and one or more option letters. */
|
stopit = 0;
|
||||||
if (argv[1][0] == '+')
|
while (stopit == 0 && *(++(*argv))) {
|
||||||
from_start = 1;
|
switch (**argv) {
|
||||||
if (argv[1][1] != '\0')
|
|
||||||
{
|
|
||||||
strtol_error s_err;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm");
|
|
||||||
n_units = tmp_long;
|
|
||||||
if (s_err == LONGINT_OVERFLOW)
|
|
||||||
{
|
|
||||||
STRTOL_FATAL_ERROR (argv[1], "argument", s_err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a [bkm] suffix was given then count bytes, not lines. */
|
|
||||||
if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm')
|
|
||||||
count_lines = 0;
|
|
||||||
|
|
||||||
/* Parse any appended option letters. */
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
switch (*p)
|
|
||||||
{
|
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Interpret N_UNITS as # of bytes. */
|
|
||||||
count_lines = 0;
|
count_lines = 0;
|
||||||
|
|
||||||
|
if (--argc < 1) {
|
||||||
|
usage(tail_usage);
|
||||||
|
}
|
||||||
|
n_units = getNum(*(++argv));
|
||||||
|
stopit = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
forever = 1;
|
forever = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'n':
|
||||||
count_lines = 1;
|
count_lines = 1;
|
||||||
|
|
||||||
|
if (--argc < 1) {
|
||||||
|
usage(tail_usage);
|
||||||
|
}
|
||||||
|
n_units = atol(*(++argv));
|
||||||
|
stopit = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
@ -885,26 +854,11 @@ tai_main (int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error (0, 0, "unrecognized option '%c'", *p);
|
|
||||||
usage (tail_usage);
|
usage (tail_usage);
|
||||||
}
|
|
||||||
++p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Make the options we just parsed invisible to getopt. */
|
|
||||||
argv[1] = argv[0];
|
|
||||||
argv++;
|
|
||||||
argc--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_version)
|
|
||||||
{
|
|
||||||
printf ("tail - %s\n", PACKAGE_VERSION);
|
|
||||||
exit (EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (show_help)
|
|
||||||
usage (tail_usage);
|
|
||||||
|
|
||||||
if (n_units == -1)
|
if (n_units == -1)
|
||||||
n_units = DEFAULT_N_LINES;
|
n_units = DEFAULT_N_LINES;
|
||||||
@ -918,8 +872,8 @@ tai_main (int argc, char **argv)
|
|||||||
--n_units;
|
--n_units;
|
||||||
}
|
}
|
||||||
|
|
||||||
n_files = argc - optind;
|
n_files = argc;
|
||||||
file = argv + optind;
|
file = argv;
|
||||||
|
|
||||||
if (n_files > 1 && forever)
|
if (n_files > 1 && forever)
|
||||||
{
|
{
|
||||||
|
46
dd.c
46
dd.c
@ -48,54 +48,10 @@ static const char dd_usage[] =
|
|||||||
"\tcount=n\tcopy only n input blocks\n"
|
"\tcount=n\tcopy only n input blocks\n"
|
||||||
//"\tskip=n\tskip n input blocks\n"
|
//"\tskip=n\tskip n input blocks\n"
|
||||||
"\n"
|
"\n"
|
||||||
"BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
|
"BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a number with a possible multiplier.
|
|
||||||
* Returns -1 if the number format is illegal.
|
|
||||||
*/
|
|
||||||
static long getNum (const char *cp)
|
|
||||||
{
|
|
||||||
long value;
|
|
||||||
|
|
||||||
if (!isDecimal (*cp))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
value = 0;
|
|
||||||
|
|
||||||
while (isDecimal (*cp))
|
|
||||||
value = value * 10 + *cp++ - '0';
|
|
||||||
|
|
||||||
switch (*cp++) {
|
|
||||||
case 'k':
|
|
||||||
value *= 1024;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
value *= 512;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
value *= 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\0':
|
|
||||||
return value;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*cp)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern int dd_main (int argc, char **argv)
|
extern int dd_main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *inFile = NULL;
|
const char *inFile = NULL;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: hostname.c,v 1.4 1999/12/08 23:19:36 andersen Exp $
|
* $Id: hostname.c,v 1.5 1999/12/09 06:11:36 andersen Exp $
|
||||||
* Mini hostname implementation for busybox
|
* Mini hostname implementation for busybox
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
||||||
|
@ -155,6 +155,7 @@ extern void write_mtab(char* blockDevice, char* directory,
|
|||||||
char* filesystemType, long flags, char* string_flags);
|
char* filesystemType, long flags, char* string_flags);
|
||||||
extern void erase_mtab(const char * name);
|
extern void erase_mtab(const char * name);
|
||||||
extern int check_wildcard_match(const char* text, const char* pattern);
|
extern int check_wildcard_match(const char* text, const char* pattern);
|
||||||
|
extern long getNum (const char *cp);
|
||||||
|
|
||||||
|
|
||||||
#if defined BB_MTAB
|
#if defined BB_MTAB
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: hostname.c,v 1.4 1999/12/08 23:19:36 andersen Exp $
|
* $Id: hostname.c,v 1.5 1999/12/09 06:11:36 andersen Exp $
|
||||||
* Mini hostname implementation for busybox
|
* Mini hostname implementation for busybox
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: ping.c,v 1.4 1999/12/08 23:19:36 andersen Exp $
|
* $Id: ping.c,v 1.5 1999/12/09 06:11:36 andersen Exp $
|
||||||
* Mini ping implementation for busybox
|
* Mini ping implementation for busybox
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
||||||
@ -53,6 +53,7 @@
|
|||||||
#define MAXPACKET 65468
|
#define MAXPACKET 65468
|
||||||
#define MAX_DUP_CHK (8 * 128)
|
#define MAX_DUP_CHK (8 * 128)
|
||||||
#define MAXWAIT 10
|
#define MAXWAIT 10
|
||||||
|
#define PINGINTERVAL 1 /* second */
|
||||||
|
|
||||||
#define O_QUIET (1 << 0)
|
#define O_QUIET (1 << 0)
|
||||||
|
|
||||||
@ -155,8 +156,8 @@ static void sendping(int ign)
|
|||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGALRM, sendping);
|
signal(SIGALRM, sendping);
|
||||||
if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next */
|
if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */
|
||||||
alarm(1);
|
alarm(PINGINTERVAL);
|
||||||
} else { /* done, wait for the last ping to come back */
|
} else { /* done, wait for the last ping to come back */
|
||||||
/* todo, don't necessarily need to wait so long... */
|
/* todo, don't necessarily need to wait so long... */
|
||||||
signal(SIGALRM, pingstats);
|
signal(SIGALRM, pingstats);
|
||||||
@ -243,9 +244,8 @@ static void ping(char *host)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUID_BUSYBOX
|
/* drop root privs if running setuid */
|
||||||
setuid(getuid());
|
setuid(getuid());
|
||||||
#endif
|
|
||||||
|
|
||||||
memset(&pingaddr, 0, sizeof(struct sockaddr_in));
|
memset(&pingaddr, 0, sizeof(struct sockaddr_in));
|
||||||
pingaddr.sin_family = AF_INET;
|
pingaddr.sin_family = AF_INET;
|
||||||
@ -305,35 +305,31 @@ static void ping(char *host)
|
|||||||
|
|
||||||
extern int ping_main(int argc, char **argv)
|
extern int ping_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
char *thisarg;
|
||||||
|
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
options = 0;
|
options = 0;
|
||||||
/* Parse any options */
|
/* Parse any options */
|
||||||
if (argc < 1) usage(ping_usage);
|
while (argc > 1) {
|
||||||
|
if (**argv != '-') usage(ping_usage);
|
||||||
while (**argv == '-') {
|
thisarg = *argv; thisarg++;
|
||||||
while (*++(*argv))
|
switch (*thisarg) {
|
||||||
switch (**argv) {
|
case 'q': options |= O_QUIET; break;
|
||||||
case 'c':
|
case 'c':
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
if (argc < 1) usage(ping_usage);
|
pingcount = atoi(*argv);
|
||||||
pingcount = atoi(*argv);
|
break;
|
||||||
break;
|
default:
|
||||||
case 'q':
|
usage(ping_usage);
|
||||||
options |= O_QUIET;
|
}
|
||||||
break;
|
argc--; argv++;
|
||||||
default:
|
|
||||||
usage(ping_usage);
|
|
||||||
}
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
}
|
}
|
||||||
|
if (argc < 1) usage(ping_usage);
|
||||||
if (argc < 1) usage(ping_usage);
|
|
||||||
|
|
||||||
myid = getpid() & 0xFFFF;
|
myid = getpid() & 0xFFFF;
|
||||||
ping(*(argv++));
|
ping(*argv);
|
||||||
exit( TRUE);
|
exit(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
50
ping.c
50
ping.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: ping.c,v 1.4 1999/12/08 23:19:36 andersen Exp $
|
* $Id: ping.c,v 1.5 1999/12/09 06:11:36 andersen Exp $
|
||||||
* Mini ping implementation for busybox
|
* Mini ping implementation for busybox
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
* Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
|
||||||
@ -53,6 +53,7 @@
|
|||||||
#define MAXPACKET 65468
|
#define MAXPACKET 65468
|
||||||
#define MAX_DUP_CHK (8 * 128)
|
#define MAX_DUP_CHK (8 * 128)
|
||||||
#define MAXWAIT 10
|
#define MAXWAIT 10
|
||||||
|
#define PINGINTERVAL 1 /* second */
|
||||||
|
|
||||||
#define O_QUIET (1 << 0)
|
#define O_QUIET (1 << 0)
|
||||||
|
|
||||||
@ -155,8 +156,8 @@ static void sendping(int ign)
|
|||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGALRM, sendping);
|
signal(SIGALRM, sendping);
|
||||||
if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next */
|
if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */
|
||||||
alarm(1);
|
alarm(PINGINTERVAL);
|
||||||
} else { /* done, wait for the last ping to come back */
|
} else { /* done, wait for the last ping to come back */
|
||||||
/* todo, don't necessarily need to wait so long... */
|
/* todo, don't necessarily need to wait so long... */
|
||||||
signal(SIGALRM, pingstats);
|
signal(SIGALRM, pingstats);
|
||||||
@ -243,9 +244,8 @@ static void ping(char *host)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUID_BUSYBOX
|
/* drop root privs if running setuid */
|
||||||
setuid(getuid());
|
setuid(getuid());
|
||||||
#endif
|
|
||||||
|
|
||||||
memset(&pingaddr, 0, sizeof(struct sockaddr_in));
|
memset(&pingaddr, 0, sizeof(struct sockaddr_in));
|
||||||
pingaddr.sin_family = AF_INET;
|
pingaddr.sin_family = AF_INET;
|
||||||
@ -305,35 +305,31 @@ static void ping(char *host)
|
|||||||
|
|
||||||
extern int ping_main(int argc, char **argv)
|
extern int ping_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
char *thisarg;
|
||||||
|
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
options = 0;
|
options = 0;
|
||||||
/* Parse any options */
|
/* Parse any options */
|
||||||
if (argc < 1) usage(ping_usage);
|
while (argc > 1) {
|
||||||
|
if (**argv != '-') usage(ping_usage);
|
||||||
while (**argv == '-') {
|
thisarg = *argv; thisarg++;
|
||||||
while (*++(*argv))
|
switch (*thisarg) {
|
||||||
switch (**argv) {
|
case 'q': options |= O_QUIET; break;
|
||||||
case 'c':
|
case 'c':
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
if (argc < 1) usage(ping_usage);
|
pingcount = atoi(*argv);
|
||||||
pingcount = atoi(*argv);
|
break;
|
||||||
break;
|
default:
|
||||||
case 'q':
|
usage(ping_usage);
|
||||||
options |= O_QUIET;
|
}
|
||||||
break;
|
argc--; argv++;
|
||||||
default:
|
|
||||||
usage(ping_usage);
|
|
||||||
}
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
}
|
}
|
||||||
|
if (argc < 1) usage(ping_usage);
|
||||||
if (argc < 1) usage(ping_usage);
|
|
||||||
|
|
||||||
myid = getpid() & 0xFFFF;
|
myid = getpid() & 0xFFFF;
|
||||||
ping(*(argv++));
|
ping(*argv);
|
||||||
exit( TRUE);
|
exit(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
176
tail.c
176
tail.c
@ -13,35 +13,16 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
/* Can display any amount of data, unlike the Unix version, which uses
|
|
||||||
a fixed size buffer and therefore can only deliver a limited number
|
|
||||||
of lines.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-b Tail by N 512-byte blocks.
|
|
||||||
-c, --bytes=N[bkm] Tail by N bytes
|
|
||||||
[or 512-byte blocks, kilobytes, or megabytes].
|
|
||||||
-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.
|
|
||||||
-n, --lines=N Tail by N lines.
|
|
||||||
-q, --quiet, --silent Never print filename headers.
|
|
||||||
-v, --verbose Always print filename headers.
|
|
||||||
|
|
||||||
If a number (N) starts with a `+', begin printing with the Nth item
|
|
||||||
from the start of each file, instead of from the end.
|
|
||||||
|
|
||||||
Reads from standard input if no files are given or when a filename of
|
|
||||||
``-'' is encountered.
|
|
||||||
By default, filename headers are printed only more than one file
|
|
||||||
is given.
|
|
||||||
By default, prints the last 10 lines (tail -n 10).
|
|
||||||
|
|
||||||
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
|
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
|
||||||
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
|
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
|
||||||
tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */
|
tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.
|
||||||
|
|
||||||
|
Rewrote the option parser, removed locales support,
|
||||||
|
and generally busyboxed, Erik Andersen <andersen@lineo.com>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@ -49,16 +30,25 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Disable assertions. Some systems have broken assert macros. */
|
/* Disable assertions. Some systems have broken assert macros. */
|
||||||
#define NDEBUG 1
|
#define NDEBUG 1
|
||||||
|
|
||||||
|
|
||||||
static void error(int i, int errnum, char* fmt, const char *msg)
|
static void error(int i, int errnum, char* fmt, ...)
|
||||||
{
|
{
|
||||||
fprintf(stderr, fmt, msg);
|
va_list arguments;
|
||||||
perror( errnum);
|
|
||||||
|
va_start(arguments, fmt);
|
||||||
|
vfprintf(stderr, fmt, arguments);
|
||||||
|
fprintf(stderr, "\n%s\n", strerror( errnum));
|
||||||
|
va_end(arguments);
|
||||||
exit(i);
|
exit(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +59,7 @@ static void error(int i, int errnum, char* fmt, const char *msg)
|
|||||||
assert ((fd) == 1); \
|
assert ((fd) == 1); \
|
||||||
assert ((n_bytes) >= 0); \
|
assert ((n_bytes) >= 0); \
|
||||||
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
||||||
error (EXIT_FAILURE, errno, "write error", NULL); \
|
error (EXIT_FAILURE, errno, "write error"); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
@ -110,7 +100,6 @@ enum header_mode
|
|||||||
};
|
};
|
||||||
|
|
||||||
char *xmalloc ();
|
char *xmalloc ();
|
||||||
int safe_read ();
|
|
||||||
|
|
||||||
/* The name this program was run with. */
|
/* The name this program was run with. */
|
||||||
char *program_name;
|
char *program_name;
|
||||||
@ -118,33 +107,24 @@ char *program_name;
|
|||||||
/* Nonzero if we have ever read standard input. */
|
/* Nonzero if we have ever read standard input. */
|
||||||
static int have_read_stdin;
|
static int have_read_stdin;
|
||||||
|
|
||||||
/* If nonzero, display usage information and exit. */
|
|
||||||
static int show_help;
|
|
||||||
|
|
||||||
/* If nonzero, print the version on standard output then exit. */
|
|
||||||
static int show_version;
|
|
||||||
|
|
||||||
static const char tail_usage[] =
|
static const char tail_usage[] =
|
||||||
"tail [OPTION]... [FILE]...\n\
|
"tail [OPTION]... [FILE]...\n\
|
||||||
|
\n\
|
||||||
Print last 10 lines of each FILE to standard output.\n\
|
Print last 10 lines of each FILE to standard output.\n\
|
||||||
With more than one FILE, precede each with a header giving the file name.\n\
|
With more than one FILE, precede each with a header giving the file name.\n\
|
||||||
With no FILE, or when FILE is -, read standard input.\n\
|
With no FILE, or when FILE is -, read standard input.\n\
|
||||||
\n\
|
\n\
|
||||||
-c, --bytes=N output the last N bytes\n\
|
-c=N[kbm] output the last N bytes\n\
|
||||||
-f, --follow output appended data as the file grows\n\
|
-f output appended data as the file grows\n\
|
||||||
-n, --lines=N output the last N lines, instead of last 10\n\
|
-n=N output the last N lines, instead of last 10\n\
|
||||||
-q, --quiet, --silent never output headers giving file names\n\
|
-q never output headers giving file names\n\
|
||||||
-v, --verbose always output headers giving file names\n\
|
-v always output headers giving file names\n\
|
||||||
--help display this help and exit\n\
|
--help display this help and exit\n\
|
||||||
--version output version information and exit\n\
|
|
||||||
\n\
|
\n\
|
||||||
If the first character of N (the number of bytes or lines) is a `+',\n\
|
If the first character of N (bytes or lines) is a `+', output begins with \n\
|
||||||
print beginning with the Nth item from the start of each file, otherwise,\n\
|
the Nth item from the start of each file, otherwise, print the last N items\n\
|
||||||
print the last N items in the file. N may have a multiplier suffix:\n\
|
in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
|
||||||
b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\
|
|
||||||
or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\
|
|
||||||
the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\
|
|
||||||
or -c +VALUE.\n";
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_header (const char *filename, const char *comment)
|
write_header (const char *filename, const char *comment)
|
||||||
@ -184,7 +164,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
|||||||
reads will be on block boundaries, which might increase efficiency. */
|
reads will be on block boundaries, which might increase efficiency. */
|
||||||
pos -= bytes_read;
|
pos -= bytes_read;
|
||||||
lseek (fd, pos, SEEK_SET);
|
lseek (fd, pos, SEEK_SET);
|
||||||
bytes_read = safe_read (fd, buffer, bytes_read);
|
bytes_read = fullRead (fd, buffer, bytes_read);
|
||||||
if (bytes_read == -1)
|
if (bytes_read == -1)
|
||||||
{
|
{
|
||||||
error (0, errno, "%s", filename);
|
error (0, errno, "%s", filename);
|
||||||
@ -220,7 +200,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
|||||||
pos -= BUFSIZ;
|
pos -= BUFSIZ;
|
||||||
lseek (fd, pos, SEEK_SET);
|
lseek (fd, pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0);
|
while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
|
||||||
if (bytes_read == -1)
|
if (bytes_read == -1)
|
||||||
{
|
{
|
||||||
error (0, errno, "%s", filename);
|
error (0, errno, "%s", filename);
|
||||||
@ -255,7 +235,7 @@ pipe_lines (const char *filename, int fd, long int n_lines)
|
|||||||
tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER));
|
tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER));
|
||||||
|
|
||||||
/* Input is always read into a fresh buffer. */
|
/* Input is always read into a fresh buffer. */
|
||||||
while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0)
|
while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
tmp->nlines = 0;
|
tmp->nlines = 0;
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
@ -374,7 +354,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes)
|
|||||||
tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER));
|
tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER));
|
||||||
|
|
||||||
/* Input is always read into a fresh buffer. */
|
/* Input is always read into a fresh buffer. */
|
||||||
while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0)
|
while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
|
|
||||||
@ -453,7 +433,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes)
|
|||||||
char buffer[BUFSIZ];
|
char buffer[BUFSIZ];
|
||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
|
|
||||||
while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
|
while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0)
|
||||||
n_bytes -= bytes_read;
|
n_bytes -= bytes_read;
|
||||||
if (bytes_read == -1)
|
if (bytes_read == -1)
|
||||||
{
|
{
|
||||||
@ -476,7 +456,7 @@ start_lines (const char *filename, int fd, long int n_lines)
|
|||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
int bytes_to_skip = 0;
|
int bytes_to_skip = 0;
|
||||||
|
|
||||||
while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
|
while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
bytes_to_skip = 0;
|
bytes_to_skip = 0;
|
||||||
while (bytes_to_skip < bytes_read)
|
while (bytes_to_skip < bytes_read)
|
||||||
@ -509,7 +489,7 @@ dump_remainder (const char *filename, int fd)
|
|||||||
|
|
||||||
total = 0;
|
total = 0;
|
||||||
output:
|
output:
|
||||||
while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
|
while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
XWRITE (STDOUT_FILENO, buffer, bytes_read);
|
XWRITE (STDOUT_FILENO, buffer, bytes_read);
|
||||||
total += bytes_read;
|
total += bytes_read;
|
||||||
@ -731,7 +711,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
|||||||
int fd, errors;
|
int fd, errors;
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
|
|
||||||
if (!strcmp (filename, "-")
|
if (!strcmp (filename, "-"))
|
||||||
{
|
{
|
||||||
have_read_stdin = 1;
|
have_read_stdin = 1;
|
||||||
filename = "standard input";
|
filename = "standard input";
|
||||||
@ -815,16 +795,15 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
tai_main (int argc, char **argv)
|
tail_main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int stopit = 0;
|
||||||
enum header_mode header_mode = multiple_files;
|
enum header_mode header_mode = multiple_files;
|
||||||
int exit_status = 0;
|
int exit_status = 0;
|
||||||
/* If from_start, the number of items to skip before printing; otherwise,
|
/* If from_start, the number of items to skip before printing; otherwise,
|
||||||
the number of items at the end of the file to print. Initially, -1
|
the number of items at the end of the file to print. Initially, -1
|
||||||
means the value has not been set. */
|
means the value has not been set. */
|
||||||
off_t n_units = -1;
|
off_t n_units = -1;
|
||||||
long int tmp_long;
|
|
||||||
int c; /* Option character. */
|
|
||||||
int n_files;
|
int n_files;
|
||||||
char **file;
|
char **file;
|
||||||
|
|
||||||
@ -832,48 +811,38 @@ tai_main (int argc, char **argv)
|
|||||||
have_read_stdin = 0;
|
have_read_stdin = 0;
|
||||||
count_lines = 1;
|
count_lines = 1;
|
||||||
forever = forever_multiple = from_start = print_headers = 0;
|
forever = forever_multiple = from_start = print_headers = 0;
|
||||||
|
|
||||||
if (argc > 1
|
/* Parse any options */
|
||||||
&& ((argv[1][0] == '-' && ISDIGIT (argv[1][1]))
|
//fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
|
||||||
|| (argv[1][0] == '+' && (ISDIGIT (argv[1][1])
|
while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) {
|
||||||
|| argv[1][1] == 0))))
|
if (**argv == '+') {
|
||||||
{
|
from_start = 1;
|
||||||
/* Old option syntax: a dash or plus, one or more digits (zero digits
|
}
|
||||||
are acceptable with a plus), and one or more option letters. */
|
stopit = 0;
|
||||||
if (argv[1][0] == '+')
|
while (stopit == 0 && *(++(*argv))) {
|
||||||
from_start = 1;
|
switch (**argv) {
|
||||||
if (argv[1][1] != '\0')
|
|
||||||
{
|
|
||||||
strtol_error s_err;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm");
|
|
||||||
n_units = tmp_long;
|
|
||||||
if (s_err == LONGINT_OVERFLOW)
|
|
||||||
{
|
|
||||||
STRTOL_FATAL_ERROR (argv[1], "argument", s_err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a [bkm] suffix was given then count bytes, not lines. */
|
|
||||||
if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm')
|
|
||||||
count_lines = 0;
|
|
||||||
|
|
||||||
/* Parse any appended option letters. */
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
switch (*p)
|
|
||||||
{
|
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Interpret N_UNITS as # of bytes. */
|
|
||||||
count_lines = 0;
|
count_lines = 0;
|
||||||
|
|
||||||
|
if (--argc < 1) {
|
||||||
|
usage(tail_usage);
|
||||||
|
}
|
||||||
|
n_units = getNum(*(++argv));
|
||||||
|
stopit = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
forever = 1;
|
forever = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'n':
|
||||||
count_lines = 1;
|
count_lines = 1;
|
||||||
|
|
||||||
|
if (--argc < 1) {
|
||||||
|
usage(tail_usage);
|
||||||
|
}
|
||||||
|
n_units = atol(*(++argv));
|
||||||
|
stopit = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
@ -885,26 +854,11 @@ tai_main (int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error (0, 0, "unrecognized option '%c'", *p);
|
|
||||||
usage (tail_usage);
|
usage (tail_usage);
|
||||||
}
|
|
||||||
++p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Make the options we just parsed invisible to getopt. */
|
|
||||||
argv[1] = argv[0];
|
|
||||||
argv++;
|
|
||||||
argc--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_version)
|
|
||||||
{
|
|
||||||
printf ("tail - %s\n", PACKAGE_VERSION);
|
|
||||||
exit (EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (show_help)
|
|
||||||
usage (tail_usage);
|
|
||||||
|
|
||||||
if (n_units == -1)
|
if (n_units == -1)
|
||||||
n_units = DEFAULT_N_LINES;
|
n_units = DEFAULT_N_LINES;
|
||||||
@ -918,8 +872,8 @@ tai_main (int argc, char **argv)
|
|||||||
--n_units;
|
--n_units;
|
||||||
}
|
}
|
||||||
|
|
||||||
n_files = argc - optind;
|
n_files = argc;
|
||||||
file = argv + optind;
|
file = argv;
|
||||||
|
|
||||||
if (n_files > 1 && forever)
|
if (n_files > 1 && forever)
|
||||||
{
|
{
|
||||||
|
53
utility.c
53
utility.c
@ -289,7 +289,7 @@ const char *modeString(int mode)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef BB_TAR
|
#if defined BB_TAR
|
||||||
/*
|
/*
|
||||||
* Return the standard ls-like time string from a time_t
|
* Return the standard ls-like time string from a time_t
|
||||||
* This is static and so is overwritten on each call.
|
* This is static and so is overwritten on each call.
|
||||||
@ -340,8 +340,10 @@ int fullWrite(int fd, const char *buf, int len)
|
|||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined BB_TAR || defined BB_TAIL
|
||||||
/*
|
/*
|
||||||
* Read all of the supplied buffer from a file.
|
* Read all of the supplied buffer from a file.
|
||||||
* This does multiple reads as necessary.
|
* This does multiple reads as necessary.
|
||||||
@ -1018,6 +1020,55 @@ extern void whine_if_fstab_is_missing()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined BB_DD || defined BB_TAIL
|
||||||
|
/*
|
||||||
|
* Read a number with a possible multiplier.
|
||||||
|
* Returns -1 if the number format is illegal.
|
||||||
|
*/
|
||||||
|
extern long getNum (const char *cp)
|
||||||
|
{
|
||||||
|
long value;
|
||||||
|
|
||||||
|
if (!isDecimal (*cp))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
|
||||||
|
while (isDecimal (*cp))
|
||||||
|
value = value * 10 + *cp++ - '0';
|
||||||
|
|
||||||
|
switch (*cp++) {
|
||||||
|
case 'm':
|
||||||
|
value *= 1048576;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
value *= 1024;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
value *= 512;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
value *= 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\0':
|
||||||
|
return value;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*cp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* END CODE */
|
/* END CODE */
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user