Some busybox updates. See the changelog for details if you care.
-Erik
This commit is contained in:
parent
bf3a838aac
commit
3fe39dce5d
19
Changelog
19
Changelog
@ -15,12 +15,23 @@
|
||||
* Optional support contributed by Ben Collins <bcollins@debian.org>
|
||||
for the kernel init chroot patch by Werner Almesberger, which
|
||||
allows init to chroot to a new device, and umount the old one.
|
||||
* added (and documented) "-n" option for head -
|
||||
contributed Friedrich Vedder <fwv@myrtle.lahn.de>
|
||||
* Cleanup for a number of usage messages -- also
|
||||
contributed Friedrich Vedder <fwv@myrtle.lahn.de>
|
||||
* Fixed bug that wouldn't let one chown a symlink -- it would
|
||||
always dereference before. -beppu
|
||||
* Fixed a bug where init could have reference already freed memory.
|
||||
Found and fixed by Taketoshi Sano <kgh12351@nifty.ne.jp>
|
||||
* Several contributions from Friedrich Vedder <fwv@myrtle.lahn.de>
|
||||
* added (and documented) "-n" option for head -
|
||||
* Cleanup for a number of usage messages -- also
|
||||
contributed Friedrich Vedder <fwv@myrtle.lahn.de>
|
||||
* Cosmetic fix to busybox.c (Don't print a comma at the
|
||||
end of line if there are no more application names).
|
||||
* Fixed a stupid bug in "head" option handling ("head -n" would segfault).
|
||||
* Moved commonly used functions "xmalloc()" and "exit()"
|
||||
to utility.c (with proper #ifdef's).
|
||||
* Created a tiny tail implementation, removing -c, -q, -v, and making
|
||||
tail -f work only with a single file. This reduced tail
|
||||
from 6k to 2.4k. The bigger/more featured tail can still be
|
||||
had by disabling BB_FEATURE_SIMPLE_TAIL in dusybox.defs.h
|
||||
|
||||
|
||||
-Erik Andersen
|
||||
|
@ -83,7 +83,7 @@ static const struct Applet applets[] = {
|
||||
#ifdef BB_FREE //usr/bin
|
||||
{"free", free_main},
|
||||
#endif
|
||||
#ifdef BB_DEALLOCVT //usr/bin
|
||||
#ifdef BB_DEALLOCVT //usr/bin
|
||||
{"deallocvt", deallocvt_main},
|
||||
#endif
|
||||
#ifdef BB_FSCK_MINIX //sbin
|
||||
@ -328,7 +328,7 @@ int busybox_main(int argc, char **argv)
|
||||
|
||||
while (a->name != 0) {
|
||||
col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name);
|
||||
if (col>60) {
|
||||
if (col>60 && a->name != 0) {
|
||||
fprintf(stderr, ",\n");
|
||||
col=0;
|
||||
}
|
||||
|
@ -321,6 +321,9 @@ extern int save_orig_name; /* set if original name must be saved */
|
||||
#define WARN(msg) {fprintf msg ; \
|
||||
if (exit_code == OK) exit_code = WARNING;}
|
||||
|
||||
#define do_exit(c) exit(c)
|
||||
|
||||
|
||||
/* in unzip.c */
|
||||
extern int unzip OF((int in, int out));
|
||||
|
||||
@ -359,7 +362,6 @@ extern void error OF((char *m));
|
||||
extern void warn OF((char *a, char *b));
|
||||
extern void read_error OF((void));
|
||||
extern void write_error OF((void));
|
||||
extern voidp xmalloc OF((unsigned int size));
|
||||
|
||||
/* in inflate.c */
|
||||
extern int inflate OF((void));
|
||||
@ -679,7 +681,6 @@ long header_bytes; /* number of bytes in gzip header */
|
||||
/* local functions */
|
||||
|
||||
local int get_method OF((int in));
|
||||
local void do_exit(int exitcode) __attribute__ ((noreturn));
|
||||
|
||||
#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
|
||||
|
||||
@ -927,30 +928,6 @@ local int get_method(in)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
* Free all dynamically allocated variables and exit with the given code.
|
||||
*/
|
||||
local void do_exit(exitcode)
|
||||
int exitcode;
|
||||
{
|
||||
static int in_exit = 0;
|
||||
|
||||
if (in_exit) exit(exitcode);
|
||||
in_exit = 1;
|
||||
FREE(inbuf);
|
||||
FREE(outbuf);
|
||||
FREE(d_buf);
|
||||
FREE(window);
|
||||
#ifndef MAXSEG_64K
|
||||
FREE(tab_prefix);
|
||||
#else
|
||||
FREE(tab_prefix0);
|
||||
FREE(tab_prefix1);
|
||||
#endif
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Signal and error handler.
|
||||
*/
|
||||
@ -1284,13 +1261,6 @@ int strcspn(s, reject)
|
||||
/* ========================================================================
|
||||
* Error handlers.
|
||||
*/
|
||||
void error(m)
|
||||
char *m;
|
||||
{
|
||||
fprintf(stderr, "\n%s\n", m);
|
||||
abort_gzip();
|
||||
}
|
||||
|
||||
void warn(a, b)
|
||||
char *a, *b; /* message strings juxtaposed in output */
|
||||
{
|
||||
@ -1316,18 +1286,6 @@ void write_error()
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
* Semi-safe malloc -- never returns NULL.
|
||||
*/
|
||||
voidp xmalloc (size)
|
||||
unsigned size;
|
||||
{
|
||||
voidp cp = (voidp)malloc (size);
|
||||
|
||||
if (cp == NULL) error("out of memory");
|
||||
return cp;
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Table of CRC-32's of all single-byte values (made by makecrc.c)
|
||||
*/
|
||||
|
@ -277,7 +277,8 @@ extern int save_orig_name; /* set if original name must be saved */
|
||||
#define WARN(msg) {if (!quiet) fprintf msg ; \
|
||||
if (exit_code == OK) exit_code = WARNING;}
|
||||
|
||||
local void do_exit(int exitcode) __attribute__ ((noreturn));
|
||||
#define do_exit(c) exit(c)
|
||||
|
||||
|
||||
/* in zip.c: */
|
||||
extern int zip OF((int in, int out));
|
||||
@ -328,7 +329,6 @@ extern void warn OF((char *a, char *b));
|
||||
extern void read_error OF((void));
|
||||
extern void write_error OF((void));
|
||||
extern void display_ratio OF((long num, long den, FILE *file));
|
||||
extern voidp xmalloc OF((unsigned int size));
|
||||
|
||||
/* in inflate.c */
|
||||
extern int inflate OF((void));
|
||||
@ -1912,29 +1912,6 @@ int gzip_main(int argc, char ** argv)
|
||||
do_exit(exit_code);
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Free all dynamically allocated variables and exit with the given code.
|
||||
*/
|
||||
local void do_exit(int exitcode)
|
||||
{
|
||||
static int in_exit = 0;
|
||||
|
||||
if (in_exit) exit(exitcode);
|
||||
in_exit = 1;
|
||||
if (env != NULL) free(env), env = NULL;
|
||||
if (args != NULL) free((char*)args), args = NULL;
|
||||
FREE(inbuf);
|
||||
FREE(outbuf);
|
||||
FREE(d_buf);
|
||||
FREE(window);
|
||||
#ifndef MAXSEG_64K
|
||||
FREE(tab_prefix);
|
||||
#else
|
||||
FREE(tab_prefix0);
|
||||
FREE(tab_prefix1);
|
||||
#endif
|
||||
exit(exitcode);
|
||||
}
|
||||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1992-1993 Jean-loup Gailly
|
||||
* This is free software; you can redistribute it and/or modify it under the
|
||||
|
@ -83,7 +83,7 @@ static const struct Applet applets[] = {
|
||||
#ifdef BB_FREE //usr/bin
|
||||
{"free", free_main},
|
||||
#endif
|
||||
#ifdef BB_DEALLOCVT //usr/bin
|
||||
#ifdef BB_DEALLOCVT //usr/bin
|
||||
{"deallocvt", deallocvt_main},
|
||||
#endif
|
||||
#ifdef BB_FSCK_MINIX //sbin
|
||||
@ -328,7 +328,7 @@ int busybox_main(int argc, char **argv)
|
||||
|
||||
while (a->name != 0) {
|
||||
col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name);
|
||||
if (col>60) {
|
||||
if (col>60 && a->name != 0) {
|
||||
fprintf(stderr, ",\n");
|
||||
col=0;
|
||||
}
|
||||
|
@ -133,6 +133,11 @@
|
||||
//Enable init being called as /linuxrc
|
||||
#define BB_FEATURE_LINUXRC
|
||||
//
|
||||
//
|
||||
//Simple tail implementation (2k vs 6k for the full one). Still
|
||||
//provides 'tail -f' support -- but for only one file at a time.
|
||||
#define BB_FEATURE_SIMPLE_TAIL
|
||||
//
|
||||
// Enable support for loop devices in mount
|
||||
#define BB_FEATURE_MOUNT_LOOP
|
||||
//
|
||||
|
@ -61,7 +61,7 @@ head_main(int argc, char **argv)
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
tmplen = 0;
|
||||
if (i++ < argc)
|
||||
if (++i < argc)
|
||||
tmplen = atoi(argv[i]);
|
||||
if (tmplen < 1)
|
||||
usage(head_usage);
|
||||
@ -105,4 +105,4 @@ head_main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* $Id: head.c,v 1.5 2000/01/23 18:19:02 erik Exp $ */
|
||||
/* $Id: head.c,v 1.6 2000/01/25 18:13:53 erik Exp $ */
|
||||
|
@ -121,8 +121,6 @@
|
||||
#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
|
||||
#define octtobin(c) ((c) - '0')
|
||||
|
||||
char *xmalloc ();
|
||||
|
||||
static double xstrtod __P ((char *s));
|
||||
static int print_esc __P ((char *escstart));
|
||||
static int print_formatted __P ((char *format, int argc, char **argv));
|
||||
|
446
coreutils/tail.c
446
coreutils/tail.c
@ -1,3 +1,402 @@
|
||||
#include "internal.h"
|
||||
/* This file contains _two_ implementations of tail. One is
|
||||
* a bit more full featured, but costs 6k. The other (i.e. the
|
||||
* SIMPLE_TAIL one) is less capable, but is good enough for about
|
||||
* 99% of the things folks want to use tail for, and only costs 2k.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef BB_FEATURE_SIMPLE_TAIL
|
||||
|
||||
/* tail -- output the last part of file(s)
|
||||
Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
|
||||
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
|
||||
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>
|
||||
|
||||
Removed superfluous options and associated code ("-c", "-n", "-q").
|
||||
Removed "tail -f" suport for multiple files.
|
||||
Both changes by Friedrich Vedder <fwv@myrtle.lahn.de>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define XWRITE(fd, buffer, n_bytes) \
|
||||
do { \
|
||||
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
||||
error("write error"); \
|
||||
} while (0)
|
||||
|
||||
/* Number of items to tail. */
|
||||
#define DEFAULT_N_LINES 10
|
||||
|
||||
/* Size of atomic reads. */
|
||||
#ifndef BUFSIZ
|
||||
#define BUFSIZ (512 * 8)
|
||||
#endif
|
||||
|
||||
/* If nonzero, read from the end of one file until killed. */
|
||||
static int forever;
|
||||
|
||||
/* If nonzero, print filename headers. */
|
||||
static int print_headers;
|
||||
|
||||
const char tail_usage[] =
|
||||
"tail [OPTION] [FILE]...\n\n"
|
||||
"Print last 10 lines of each FILE to standard output.\n"
|
||||
"With more than one FILE, precede each with a header giving the\n"
|
||||
"file name. With no FILE, or when FILE is -, read standard input.\n\n"
|
||||
"Options:\n"
|
||||
"\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
|
||||
"\t-f\t\tOutput data as the file grows. This version\n"
|
||||
"\t\t\tof 'tail -f' supports only one file at a time.\n";
|
||||
|
||||
|
||||
static void write_header(const char *filename)
|
||||
{
|
||||
static int first_file = 1;
|
||||
|
||||
printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
|
||||
first_file = 0;
|
||||
}
|
||||
|
||||
/* Print the last N_LINES lines from the end of file FD.
|
||||
Go backward through the file, reading `BUFSIZ' bytes at a time (except
|
||||
probably the first), until we hit the start of the file or have
|
||||
read NUMBER newlines.
|
||||
POS starts out as the length of the file (the offset of the last
|
||||
byte of the file + 1).
|
||||
Return 0 if successful, 1 if an error occurred. */
|
||||
|
||||
static int
|
||||
file_lines(const char *filename, int fd, long int n_lines, off_t pos)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
int bytes_read;
|
||||
int i; /* Index into `buffer' for scanning. */
|
||||
|
||||
if (n_lines == 0)
|
||||
return 0;
|
||||
|
||||
/* Set `bytes_read' to the size of the last, probably partial, buffer;
|
||||
0 < `bytes_read' <= `BUFSIZ'. */
|
||||
bytes_read = pos % BUFSIZ;
|
||||
if (bytes_read == 0)
|
||||
bytes_read = BUFSIZ;
|
||||
/* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
|
||||
reads will be on block boundaries, which might increase efficiency. */
|
||||
pos -= bytes_read;
|
||||
lseek(fd, pos, SEEK_SET);
|
||||
bytes_read = fullRead(fd, buffer, bytes_read);
|
||||
if (bytes_read == -1)
|
||||
error("read error");
|
||||
|
||||
/* Count the incomplete line on files that don't end with a newline. */
|
||||
if (bytes_read && buffer[bytes_read - 1] != '\n')
|
||||
--n_lines;
|
||||
|
||||
do {
|
||||
/* Scan backward, counting the newlines in this bufferfull. */
|
||||
for (i = bytes_read - 1; i >= 0; i--) {
|
||||
/* Have we counted the requested number of newlines yet? */
|
||||
if (buffer[i] == '\n' && n_lines-- == 0) {
|
||||
/* If this newline wasn't the last character in the buffer,
|
||||
print the text after it. */
|
||||
if (i != bytes_read - 1)
|
||||
XWRITE(STDOUT_FILENO, &buffer[i + 1],
|
||||
bytes_read - (i + 1));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Not enough newlines in that bufferfull. */
|
||||
if (pos == 0) {
|
||||
/* Not enough lines in the file; print the entire file. */
|
||||
lseek(fd, (off_t) 0, SEEK_SET);
|
||||
return 0;
|
||||
}
|
||||
pos -= BUFSIZ;
|
||||
lseek(fd, pos, SEEK_SET);
|
||||
}
|
||||
while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
|
||||
if (bytes_read == -1)
|
||||
error("read error");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print the last N_LINES lines from the end of the standard input,
|
||||
open for reading as pipe FD.
|
||||
Buffer the text as a linked list of LBUFFERs, adding them as needed.
|
||||
Return 0 if successful, 1 if an error occured. */
|
||||
|
||||
static int pipe_lines(const char *filename, int fd, long int n_lines)
|
||||
{
|
||||
struct linebuffer {
|
||||
int nbytes, nlines;
|
||||
char buffer[BUFSIZ];
|
||||
struct linebuffer *next;
|
||||
};
|
||||
typedef struct linebuffer LBUFFER;
|
||||
LBUFFER *first, *last, *tmp;
|
||||
int i; /* Index into buffers. */
|
||||
int total_lines = 0; /* Total number of newlines in all buffers. */
|
||||
int errors = 0;
|
||||
|
||||
first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
|
||||
first->nbytes = first->nlines = 0;
|
||||
first->next = NULL;
|
||||
tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
|
||||
|
||||
/* Input is always read into a fresh buffer. */
|
||||
while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
|
||||
tmp->nlines = 0;
|
||||
tmp->next = NULL;
|
||||
|
||||
/* Count the number of newlines just read. */
|
||||
for (i = 0; i < tmp->nbytes; i++)
|
||||
if (tmp->buffer[i] == '\n')
|
||||
++tmp->nlines;
|
||||
total_lines += tmp->nlines;
|
||||
|
||||
/* If there is enough room in the last buffer read, just append the new
|
||||
one to it. This is because when reading from a pipe, `nbytes' can
|
||||
often be very small. */
|
||||
if (tmp->nbytes + last->nbytes < BUFSIZ) {
|
||||
memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
|
||||
last->nbytes += tmp->nbytes;
|
||||
last->nlines += tmp->nlines;
|
||||
} else {
|
||||
/* If there's not enough room, link the new buffer onto the end of
|
||||
the list, then either free up the oldest buffer for the next
|
||||
read if that would leave enough lines, or else malloc a new one.
|
||||
Some compaction mechanism is possible but probably not
|
||||
worthwhile. */
|
||||
last = last->next = tmp;
|
||||
if (total_lines - first->nlines > n_lines) {
|
||||
tmp = first;
|
||||
total_lines -= first->nlines;
|
||||
first = first->next;
|
||||
} else
|
||||
tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
|
||||
}
|
||||
}
|
||||
if (tmp->nbytes == -1)
|
||||
error("read error");
|
||||
|
||||
free((char *) tmp);
|
||||
|
||||
/* This prevents a core dump when the pipe contains no newlines. */
|
||||
if (n_lines == 0)
|
||||
goto free_lbuffers;
|
||||
|
||||
/* Count the incomplete line on files that don't end with a newline. */
|
||||
if (last->buffer[last->nbytes - 1] != '\n') {
|
||||
++last->nlines;
|
||||
++total_lines;
|
||||
}
|
||||
|
||||
/* Run through the list, printing lines. First, skip over unneeded
|
||||
buffers. */
|
||||
for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
|
||||
total_lines -= tmp->nlines;
|
||||
|
||||
/* Find the correct beginning, then print the rest of the file. */
|
||||
if (total_lines > n_lines) {
|
||||
char *cp;
|
||||
|
||||
/* Skip `total_lines' - `n_lines' newlines. We made sure that
|
||||
`total_lines' - `n_lines' <= `tmp->nlines'. */
|
||||
cp = tmp->buffer;
|
||||
for (i = total_lines - n_lines; i; --i)
|
||||
while (*cp++ != '\n')
|
||||
/* Do nothing. */ ;
|
||||
i = cp - tmp->buffer;
|
||||
} else
|
||||
i = 0;
|
||||
XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
|
||||
|
||||
for (tmp = tmp->next; tmp; tmp = tmp->next)
|
||||
XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
|
||||
|
||||
free_lbuffers:
|
||||
while (first) {
|
||||
tmp = first->next;
|
||||
free((char *) first);
|
||||
first = tmp;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/* Display file FILENAME from the current position in FD to the end.
|
||||
If `forever' is nonzero, keep reading from the end of the file
|
||||
until killed. Return the number of bytes read from the file. */
|
||||
|
||||
static long dump_remainder(const char *filename, int fd)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
int bytes_read;
|
||||
long total;
|
||||
|
||||
total = 0;
|
||||
output:
|
||||
while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
|
||||
XWRITE(STDOUT_FILENO, buffer, bytes_read);
|
||||
total += bytes_read;
|
||||
}
|
||||
if (bytes_read == -1)
|
||||
error("read error");
|
||||
if (forever) {
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
goto output;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Output the last N_LINES lines of file FILENAME open for reading in FD.
|
||||
Return 0 if successful, 1 if an error occurred. */
|
||||
|
||||
static int tail_lines(const char *filename, int fd, long int n_lines)
|
||||
{
|
||||
struct stat stats;
|
||||
off_t length;
|
||||
|
||||
if (print_headers)
|
||||
write_header(filename);
|
||||
|
||||
if (fstat(fd, &stats))
|
||||
error("fstat error");
|
||||
|
||||
/* Use file_lines only if FD refers to a regular file with
|
||||
its file pointer positioned at beginning of file. */
|
||||
/* FIXME: adding the lseek conjunct is a kludge.
|
||||
Once there's a reasonable test suite, fix the true culprit:
|
||||
file_lines. file_lines shouldn't presume that the input
|
||||
file pointer is initially positioned to beginning of file. */
|
||||
if (S_ISREG(stats.st_mode)
|
||||
&& lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
|
||||
length = lseek(fd, (off_t) 0, SEEK_END);
|
||||
if (length != 0 && file_lines(filename, fd, n_lines, length))
|
||||
return 1;
|
||||
dump_remainder(filename, fd);
|
||||
} else
|
||||
return pipe_lines(filename, fd, n_lines);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Display the last N_UNITS lines of file FILENAME.
|
||||
"-" for FILENAME means the standard input.
|
||||
Return 0 if successful, 1 if an error occurred. */
|
||||
|
||||
static int tail_file(const char *filename, off_t n_units)
|
||||
{
|
||||
int fd, errors;
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
filename = "standard input";
|
||||
errors = tail_lines(filename, 0, (long) n_units);
|
||||
} else {
|
||||
/* Not standard input. */
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd == -1)
|
||||
error("open error");
|
||||
|
||||
errors = tail_lines(filename, fd, (long) n_units);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
extern int tail_main(int argc, char **argv)
|
||||
{
|
||||
int exit_status = 0;
|
||||
int n_units = DEFAULT_N_LINES;
|
||||
int n_tmp, i;
|
||||
char opt;
|
||||
|
||||
forever = print_headers = 0;
|
||||
|
||||
/* parse argv[] */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
opt = argv[i][1];
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
forever = 1;
|
||||
break;
|
||||
case 'n':
|
||||
n_tmp = 0;
|
||||
if (++i < argc)
|
||||
n_tmp = atoi(argv[i]);
|
||||
if (n_tmp < 1)
|
||||
usage(tail_usage);
|
||||
n_units = n_tmp;
|
||||
break;
|
||||
case '-':
|
||||
case 'h':
|
||||
usage(tail_usage);
|
||||
default:
|
||||
fprintf(stderr, "tail: invalid option -- %c\n", opt);
|
||||
usage(tail_usage);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i + 1 < argc) {
|
||||
if (forever) {
|
||||
fprintf(stderr,
|
||||
"tail: option -f is invalid with multiple files\n");
|
||||
usage(tail_usage);
|
||||
}
|
||||
print_headers = 1;
|
||||
}
|
||||
|
||||
if (i >= argc) {
|
||||
exit_status |= tail_file("-", n_units);
|
||||
} else {
|
||||
for (; i < argc; i++)
|
||||
exit_status |= tail_file(argv[i], n_units);
|
||||
}
|
||||
|
||||
exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
// Here follows the code for the full featured tail code
|
||||
|
||||
|
||||
/* tail -- output the last part of file(s)
|
||||
Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
|
||||
|
||||
@ -42,7 +441,7 @@
|
||||
#define NDEBUG 1
|
||||
|
||||
|
||||
static void error(int i, int errnum, char* fmt, ...)
|
||||
static void detailed_error(int i, int errnum, char* fmt, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
|
||||
@ -60,7 +459,7 @@ static void error(int i, int errnum, char* fmt, ...)
|
||||
assert ((fd) == 1); \
|
||||
assert ((n_bytes) >= 0); \
|
||||
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
||||
error (EXIT_FAILURE, errno, "write error"); \
|
||||
detailed_error (EXIT_FAILURE, errno, "write error"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
@ -100,8 +499,6 @@ enum header_mode
|
||||
multiple_files, always, never
|
||||
};
|
||||
|
||||
char *xmalloc ();
|
||||
|
||||
/* The name this program was run with. */
|
||||
char *program_name;
|
||||
|
||||
@ -168,7 +565,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
||||
bytes_read = fullRead (fd, buffer, bytes_read);
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -204,7 +601,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
||||
while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -276,7 +673,7 @@ pipe_lines (const char *filename, int fd, long int n_lines)
|
||||
}
|
||||
if (tmp->nbytes == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
free ((char *) tmp);
|
||||
goto free_lbuffers;
|
||||
@ -390,7 +787,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
}
|
||||
if (tmp->nbytes == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
free ((char *) tmp);
|
||||
goto free_cbuffers;
|
||||
@ -438,7 +835,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
n_bytes -= bytes_read;
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
else if (n_bytes < 0)
|
||||
@ -466,7 +863,7 @@ start_lines (const char *filename, int fd, long int n_lines)
|
||||
}
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
else if (bytes_to_skip < bytes_read)
|
||||
@ -496,7 +893,7 @@ output:
|
||||
total += bytes_read;
|
||||
}
|
||||
if (bytes_read == -1)
|
||||
error (EXIT_FAILURE, errno, "%s", filename);
|
||||
detailed_error (EXIT_FAILURE, errno, "%s", filename);
|
||||
if (forever)
|
||||
{
|
||||
fflush (stdout);
|
||||
@ -540,7 +937,7 @@ tail_forever (char **names, int nfiles)
|
||||
continue;
|
||||
if (fstat (file_descs[i], &stats) < 0)
|
||||
{
|
||||
error (0, errno, "%s", names[i]);
|
||||
detailed_error (0, errno, "%s", names[i]);
|
||||
file_descs[i] = -1;
|
||||
continue;
|
||||
}
|
||||
@ -590,7 +987,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
error, either. */
|
||||
if (fstat (fd, &stats))
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -619,7 +1016,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -656,7 +1053,7 @@ tail_lines (const char *filename, int fd, long int n_lines)
|
||||
|
||||
if (fstat (fd, &stats))
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -723,12 +1120,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (fstat (0, &stats) < 0)
|
||||
{
|
||||
error (0, errno, "standard input");
|
||||
detailed_error (0, errno, "standard input");
|
||||
errors = 1;
|
||||
}
|
||||
else if (!S_ISREG (stats.st_mode))
|
||||
{
|
||||
error (0, 0,
|
||||
detailed_error (0, 0,
|
||||
"standard input: cannot follow end of non-regular file");
|
||||
errors = 1;
|
||||
}
|
||||
@ -749,7 +1146,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (forever_multiple)
|
||||
file_descs[filenum] = -1;
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
}
|
||||
else
|
||||
@ -761,12 +1158,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (fstat (fd, &stats) < 0)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
}
|
||||
else if (!S_ISREG (stats.st_mode))
|
||||
{
|
||||
error (0, 0, "%s: cannot follow end of non-regular file",
|
||||
detailed_error (0, 0, "%s: cannot follow end of non-regular file",
|
||||
filename);
|
||||
errors = 1;
|
||||
}
|
||||
@ -785,7 +1182,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (close (fd))
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
}
|
||||
}
|
||||
@ -903,8 +1300,11 @@ tail_main (int argc, char **argv)
|
||||
}
|
||||
|
||||
if (have_read_stdin && close (0) < 0)
|
||||
error (EXIT_FAILURE, errno, "-");
|
||||
detailed_error (EXIT_FAILURE, errno, "-");
|
||||
if (fclose (stdout) == EOF)
|
||||
error (EXIT_FAILURE, errno, "write error");
|
||||
detailed_error (EXIT_FAILURE, errno, "write error");
|
||||
exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
48
gunzip.c
48
gunzip.c
@ -321,6 +321,9 @@ extern int save_orig_name; /* set if original name must be saved */
|
||||
#define WARN(msg) {fprintf msg ; \
|
||||
if (exit_code == OK) exit_code = WARNING;}
|
||||
|
||||
#define do_exit(c) exit(c)
|
||||
|
||||
|
||||
/* in unzip.c */
|
||||
extern int unzip OF((int in, int out));
|
||||
|
||||
@ -359,7 +362,6 @@ extern void error OF((char *m));
|
||||
extern void warn OF((char *a, char *b));
|
||||
extern void read_error OF((void));
|
||||
extern void write_error OF((void));
|
||||
extern voidp xmalloc OF((unsigned int size));
|
||||
|
||||
/* in inflate.c */
|
||||
extern int inflate OF((void));
|
||||
@ -679,7 +681,6 @@ long header_bytes; /* number of bytes in gzip header */
|
||||
/* local functions */
|
||||
|
||||
local int get_method OF((int in));
|
||||
local void do_exit(int exitcode) __attribute__ ((noreturn));
|
||||
|
||||
#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
|
||||
|
||||
@ -927,30 +928,6 @@ local int get_method(in)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
* Free all dynamically allocated variables and exit with the given code.
|
||||
*/
|
||||
local void do_exit(exitcode)
|
||||
int exitcode;
|
||||
{
|
||||
static int in_exit = 0;
|
||||
|
||||
if (in_exit) exit(exitcode);
|
||||
in_exit = 1;
|
||||
FREE(inbuf);
|
||||
FREE(outbuf);
|
||||
FREE(d_buf);
|
||||
FREE(window);
|
||||
#ifndef MAXSEG_64K
|
||||
FREE(tab_prefix);
|
||||
#else
|
||||
FREE(tab_prefix0);
|
||||
FREE(tab_prefix1);
|
||||
#endif
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Signal and error handler.
|
||||
*/
|
||||
@ -1284,13 +1261,6 @@ int strcspn(s, reject)
|
||||
/* ========================================================================
|
||||
* Error handlers.
|
||||
*/
|
||||
void error(m)
|
||||
char *m;
|
||||
{
|
||||
fprintf(stderr, "\n%s\n", m);
|
||||
abort_gzip();
|
||||
}
|
||||
|
||||
void warn(a, b)
|
||||
char *a, *b; /* message strings juxtaposed in output */
|
||||
{
|
||||
@ -1316,18 +1286,6 @@ void write_error()
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
* Semi-safe malloc -- never returns NULL.
|
||||
*/
|
||||
voidp xmalloc (size)
|
||||
unsigned size;
|
||||
{
|
||||
voidp cp = (voidp)malloc (size);
|
||||
|
||||
if (cp == NULL) error("out of memory");
|
||||
return cp;
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Table of CRC-32's of all single-byte values (made by makecrc.c)
|
||||
*/
|
||||
|
27
gzip.c
27
gzip.c
@ -277,7 +277,8 @@ extern int save_orig_name; /* set if original name must be saved */
|
||||
#define WARN(msg) {if (!quiet) fprintf msg ; \
|
||||
if (exit_code == OK) exit_code = WARNING;}
|
||||
|
||||
local void do_exit(int exitcode) __attribute__ ((noreturn));
|
||||
#define do_exit(c) exit(c)
|
||||
|
||||
|
||||
/* in zip.c: */
|
||||
extern int zip OF((int in, int out));
|
||||
@ -328,7 +329,6 @@ extern void warn OF((char *a, char *b));
|
||||
extern void read_error OF((void));
|
||||
extern void write_error OF((void));
|
||||
extern void display_ratio OF((long num, long den, FILE *file));
|
||||
extern voidp xmalloc OF((unsigned int size));
|
||||
|
||||
/* in inflate.c */
|
||||
extern int inflate OF((void));
|
||||
@ -1912,29 +1912,6 @@ int gzip_main(int argc, char ** argv)
|
||||
do_exit(exit_code);
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Free all dynamically allocated variables and exit with the given code.
|
||||
*/
|
||||
local void do_exit(int exitcode)
|
||||
{
|
||||
static int in_exit = 0;
|
||||
|
||||
if (in_exit) exit(exitcode);
|
||||
in_exit = 1;
|
||||
if (env != NULL) free(env), env = NULL;
|
||||
if (args != NULL) free((char*)args), args = NULL;
|
||||
FREE(inbuf);
|
||||
FREE(outbuf);
|
||||
FREE(d_buf);
|
||||
FREE(window);
|
||||
#ifndef MAXSEG_64K
|
||||
FREE(tab_prefix);
|
||||
#else
|
||||
FREE(tab_prefix0);
|
||||
FREE(tab_prefix1);
|
||||
#endif
|
||||
exit(exitcode);
|
||||
}
|
||||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1992-1993 Jean-loup Gailly
|
||||
* This is free software; you can redistribute it and/or modify it under the
|
||||
|
4
head.c
4
head.c
@ -61,7 +61,7 @@ head_main(int argc, char **argv)
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
tmplen = 0;
|
||||
if (i++ < argc)
|
||||
if (++i < argc)
|
||||
tmplen = atoi(argv[i]);
|
||||
if (tmplen < 1)
|
||||
usage(head_usage);
|
||||
@ -105,4 +105,4 @@ head_main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* $Id: head.c,v 1.5 2000/01/23 18:19:02 erik Exp $ */
|
||||
/* $Id: head.c,v 1.6 2000/01/25 18:13:53 erik Exp $ */
|
||||
|
43
init.c
43
init.c
@ -488,9 +488,14 @@ static void shutdown_system(void)
|
||||
static void halt_signal(int sig)
|
||||
{
|
||||
shutdown_system();
|
||||
message(CONSOLE,
|
||||
"The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
|
||||
message(CONSOLE, "The system is halted. Press %s or turn off power\r\n",
|
||||
(secondConsole == NULL) /* serial console */
|
||||
? "Reset" : "CTRL-ALT-DEL");
|
||||
sync();
|
||||
|
||||
/* allow time for last message to reach serial console */
|
||||
sleep(2);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
|
||||
if (sig == SIGUSR2)
|
||||
reboot(RB_POWER_OFF);
|
||||
@ -505,6 +510,10 @@ static void reboot_signal(int sig)
|
||||
shutdown_system();
|
||||
message(CONSOLE, "Please stand by while rebooting the system.\r\n");
|
||||
sync();
|
||||
|
||||
/* allow time for last message to reach serial console */
|
||||
sleep(2);
|
||||
|
||||
reboot(RB_AUTOBOOT);
|
||||
exit(0);
|
||||
}
|
||||
@ -580,7 +589,9 @@ static void check_chroot(int sig)
|
||||
/* execute init in the (hopefully) new root */
|
||||
execve("/sbin/init",argv_init,envp_init);
|
||||
|
||||
message(CONSOLE, "ERROR: Could not exec new init. Hit ctrl+alt+delete to reboot.\r\n");
|
||||
message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
|
||||
(secondConsole == NULL) /* serial console */
|
||||
? "Reset" : "CTRL-ALT-DEL");
|
||||
return;
|
||||
}
|
||||
#endif /* BB_FEATURE_INIT_CHROOT */
|
||||
@ -592,11 +603,14 @@ void new_initAction (initActionEnum action,
|
||||
{
|
||||
initAction* newAction;
|
||||
|
||||
if (*cons == '\0')
|
||||
cons = console;
|
||||
|
||||
/* If BusyBox detects that a serial console is in use,
|
||||
* then entries containing non-empty id fields will _not_ be run.
|
||||
* then entries not refering to the console or null devices will _not_ be run.
|
||||
* The exception to this rule is the null device.
|
||||
*/
|
||||
if (secondConsole == NULL && (*cons != '\0' || strncmp(cons, "null", 4)))
|
||||
if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
|
||||
return;
|
||||
|
||||
newAction = calloc ((size_t)(1), sizeof(initAction));
|
||||
@ -608,10 +622,7 @@ void new_initAction (initActionEnum action,
|
||||
initActionList = newAction;
|
||||
strncpy( newAction->process, process, 255);
|
||||
newAction->action = action;
|
||||
if (*cons != '\0') {
|
||||
strncpy(newAction->console, cons, 255);
|
||||
} else
|
||||
strncpy(newAction->console, console, 255);
|
||||
strncpy(newAction->console, cons, 255);
|
||||
newAction->pid = 0;
|
||||
// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
|
||||
// newAction->process, newAction->action, newAction->console);
|
||||
@ -620,9 +631,13 @@ void new_initAction (initActionEnum action,
|
||||
void delete_initAction (initAction *action)
|
||||
{
|
||||
initAction *a, *b=NULL;
|
||||
for( a=initActionList ; a; b=a, a=a->nextPtr) {
|
||||
if (a == action && b != NULL) {
|
||||
b->nextPtr=a->nextPtr;
|
||||
for( a=initActionList ; a ; b=a, a=a->nextPtr) {
|
||||
if (a == action) {
|
||||
if (b==NULL) {
|
||||
initActionList=a->nextPtr;
|
||||
} else {
|
||||
b->nextPtr=a->nextPtr;
|
||||
}
|
||||
free( a);
|
||||
break;
|
||||
}
|
||||
@ -805,8 +820,8 @@ extern int init_main(int argc, char **argv)
|
||||
/* Ask first then start a shell on tty2 */
|
||||
if (secondConsole != NULL)
|
||||
new_initAction( ASKFIRST, SHELL, secondConsole);
|
||||
/* Ask first then start a shell on tty1 */
|
||||
new_initAction( ASKFIRST, SHELL, console);
|
||||
/* Start a shell on tty1 */
|
||||
new_initAction( RESPAWN, SHELL, console);
|
||||
} else {
|
||||
/* Not in single user mode -- see what inittab says */
|
||||
|
||||
|
43
init/init.c
43
init/init.c
@ -488,9 +488,14 @@ static void shutdown_system(void)
|
||||
static void halt_signal(int sig)
|
||||
{
|
||||
shutdown_system();
|
||||
message(CONSOLE,
|
||||
"The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
|
||||
message(CONSOLE, "The system is halted. Press %s or turn off power\r\n",
|
||||
(secondConsole == NULL) /* serial console */
|
||||
? "Reset" : "CTRL-ALT-DEL");
|
||||
sync();
|
||||
|
||||
/* allow time for last message to reach serial console */
|
||||
sleep(2);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
|
||||
if (sig == SIGUSR2)
|
||||
reboot(RB_POWER_OFF);
|
||||
@ -505,6 +510,10 @@ static void reboot_signal(int sig)
|
||||
shutdown_system();
|
||||
message(CONSOLE, "Please stand by while rebooting the system.\r\n");
|
||||
sync();
|
||||
|
||||
/* allow time for last message to reach serial console */
|
||||
sleep(2);
|
||||
|
||||
reboot(RB_AUTOBOOT);
|
||||
exit(0);
|
||||
}
|
||||
@ -580,7 +589,9 @@ static void check_chroot(int sig)
|
||||
/* execute init in the (hopefully) new root */
|
||||
execve("/sbin/init",argv_init,envp_init);
|
||||
|
||||
message(CONSOLE, "ERROR: Could not exec new init. Hit ctrl+alt+delete to reboot.\r\n");
|
||||
message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
|
||||
(secondConsole == NULL) /* serial console */
|
||||
? "Reset" : "CTRL-ALT-DEL");
|
||||
return;
|
||||
}
|
||||
#endif /* BB_FEATURE_INIT_CHROOT */
|
||||
@ -592,11 +603,14 @@ void new_initAction (initActionEnum action,
|
||||
{
|
||||
initAction* newAction;
|
||||
|
||||
if (*cons == '\0')
|
||||
cons = console;
|
||||
|
||||
/* If BusyBox detects that a serial console is in use,
|
||||
* then entries containing non-empty id fields will _not_ be run.
|
||||
* then entries not refering to the console or null devices will _not_ be run.
|
||||
* The exception to this rule is the null device.
|
||||
*/
|
||||
if (secondConsole == NULL && (*cons != '\0' || strncmp(cons, "null", 4)))
|
||||
if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
|
||||
return;
|
||||
|
||||
newAction = calloc ((size_t)(1), sizeof(initAction));
|
||||
@ -608,10 +622,7 @@ void new_initAction (initActionEnum action,
|
||||
initActionList = newAction;
|
||||
strncpy( newAction->process, process, 255);
|
||||
newAction->action = action;
|
||||
if (*cons != '\0') {
|
||||
strncpy(newAction->console, cons, 255);
|
||||
} else
|
||||
strncpy(newAction->console, console, 255);
|
||||
strncpy(newAction->console, cons, 255);
|
||||
newAction->pid = 0;
|
||||
// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
|
||||
// newAction->process, newAction->action, newAction->console);
|
||||
@ -620,9 +631,13 @@ void new_initAction (initActionEnum action,
|
||||
void delete_initAction (initAction *action)
|
||||
{
|
||||
initAction *a, *b=NULL;
|
||||
for( a=initActionList ; a; b=a, a=a->nextPtr) {
|
||||
if (a == action && b != NULL) {
|
||||
b->nextPtr=a->nextPtr;
|
||||
for( a=initActionList ; a ; b=a, a=a->nextPtr) {
|
||||
if (a == action) {
|
||||
if (b==NULL) {
|
||||
initActionList=a->nextPtr;
|
||||
} else {
|
||||
b->nextPtr=a->nextPtr;
|
||||
}
|
||||
free( a);
|
||||
break;
|
||||
}
|
||||
@ -805,8 +820,8 @@ extern int init_main(int argc, char **argv)
|
||||
/* Ask first then start a shell on tty2 */
|
||||
if (secondConsole != NULL)
|
||||
new_initAction( ASKFIRST, SHELL, secondConsole);
|
||||
/* Ask first then start a shell on tty1 */
|
||||
new_initAction( ASKFIRST, SHELL, console);
|
||||
/* Start a shell on tty1 */
|
||||
new_initAction( RESPAWN, SHELL, console);
|
||||
} else {
|
||||
/* Not in single user mode -- see what inittab says */
|
||||
|
||||
|
@ -175,6 +175,11 @@ extern int check_wildcard_match(const char* text, const char* pattern);
|
||||
extern long getNum (const char *cp);
|
||||
extern pid_t findInitPid();
|
||||
|
||||
#if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL
|
||||
extern void *xmalloc (size_t size);
|
||||
extern void error(char *msg);
|
||||
#endif
|
||||
|
||||
#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT)
|
||||
extern int vdprintf(int d, const char *format, va_list ap);
|
||||
#endif
|
||||
|
2
printf.c
2
printf.c
@ -121,8 +121,6 @@
|
||||
#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
|
||||
#define octtobin(c) ((c) - '0')
|
||||
|
||||
char *xmalloc ();
|
||||
|
||||
static double xstrtod __P ((char *s));
|
||||
static int print_esc __P ((char *escstart));
|
||||
static int print_formatted __P ((char *format, int argc, char **argv));
|
||||
|
446
tail.c
446
tail.c
@ -1,3 +1,402 @@
|
||||
#include "internal.h"
|
||||
/* This file contains _two_ implementations of tail. One is
|
||||
* a bit more full featured, but costs 6k. The other (i.e. the
|
||||
* SIMPLE_TAIL one) is less capable, but is good enough for about
|
||||
* 99% of the things folks want to use tail for, and only costs 2k.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef BB_FEATURE_SIMPLE_TAIL
|
||||
|
||||
/* tail -- output the last part of file(s)
|
||||
Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
|
||||
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
|
||||
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>
|
||||
|
||||
Removed superfluous options and associated code ("-c", "-n", "-q").
|
||||
Removed "tail -f" suport for multiple files.
|
||||
Both changes by Friedrich Vedder <fwv@myrtle.lahn.de>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define XWRITE(fd, buffer, n_bytes) \
|
||||
do { \
|
||||
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
||||
error("write error"); \
|
||||
} while (0)
|
||||
|
||||
/* Number of items to tail. */
|
||||
#define DEFAULT_N_LINES 10
|
||||
|
||||
/* Size of atomic reads. */
|
||||
#ifndef BUFSIZ
|
||||
#define BUFSIZ (512 * 8)
|
||||
#endif
|
||||
|
||||
/* If nonzero, read from the end of one file until killed. */
|
||||
static int forever;
|
||||
|
||||
/* If nonzero, print filename headers. */
|
||||
static int print_headers;
|
||||
|
||||
const char tail_usage[] =
|
||||
"tail [OPTION] [FILE]...\n\n"
|
||||
"Print last 10 lines of each FILE to standard output.\n"
|
||||
"With more than one FILE, precede each with a header giving the\n"
|
||||
"file name. With no FILE, or when FILE is -, read standard input.\n\n"
|
||||
"Options:\n"
|
||||
"\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
|
||||
"\t-f\t\tOutput data as the file grows. This version\n"
|
||||
"\t\t\tof 'tail -f' supports only one file at a time.\n";
|
||||
|
||||
|
||||
static void write_header(const char *filename)
|
||||
{
|
||||
static int first_file = 1;
|
||||
|
||||
printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
|
||||
first_file = 0;
|
||||
}
|
||||
|
||||
/* Print the last N_LINES lines from the end of file FD.
|
||||
Go backward through the file, reading `BUFSIZ' bytes at a time (except
|
||||
probably the first), until we hit the start of the file or have
|
||||
read NUMBER newlines.
|
||||
POS starts out as the length of the file (the offset of the last
|
||||
byte of the file + 1).
|
||||
Return 0 if successful, 1 if an error occurred. */
|
||||
|
||||
static int
|
||||
file_lines(const char *filename, int fd, long int n_lines, off_t pos)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
int bytes_read;
|
||||
int i; /* Index into `buffer' for scanning. */
|
||||
|
||||
if (n_lines == 0)
|
||||
return 0;
|
||||
|
||||
/* Set `bytes_read' to the size of the last, probably partial, buffer;
|
||||
0 < `bytes_read' <= `BUFSIZ'. */
|
||||
bytes_read = pos % BUFSIZ;
|
||||
if (bytes_read == 0)
|
||||
bytes_read = BUFSIZ;
|
||||
/* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
|
||||
reads will be on block boundaries, which might increase efficiency. */
|
||||
pos -= bytes_read;
|
||||
lseek(fd, pos, SEEK_SET);
|
||||
bytes_read = fullRead(fd, buffer, bytes_read);
|
||||
if (bytes_read == -1)
|
||||
error("read error");
|
||||
|
||||
/* Count the incomplete line on files that don't end with a newline. */
|
||||
if (bytes_read && buffer[bytes_read - 1] != '\n')
|
||||
--n_lines;
|
||||
|
||||
do {
|
||||
/* Scan backward, counting the newlines in this bufferfull. */
|
||||
for (i = bytes_read - 1; i >= 0; i--) {
|
||||
/* Have we counted the requested number of newlines yet? */
|
||||
if (buffer[i] == '\n' && n_lines-- == 0) {
|
||||
/* If this newline wasn't the last character in the buffer,
|
||||
print the text after it. */
|
||||
if (i != bytes_read - 1)
|
||||
XWRITE(STDOUT_FILENO, &buffer[i + 1],
|
||||
bytes_read - (i + 1));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Not enough newlines in that bufferfull. */
|
||||
if (pos == 0) {
|
||||
/* Not enough lines in the file; print the entire file. */
|
||||
lseek(fd, (off_t) 0, SEEK_SET);
|
||||
return 0;
|
||||
}
|
||||
pos -= BUFSIZ;
|
||||
lseek(fd, pos, SEEK_SET);
|
||||
}
|
||||
while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
|
||||
if (bytes_read == -1)
|
||||
error("read error");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print the last N_LINES lines from the end of the standard input,
|
||||
open for reading as pipe FD.
|
||||
Buffer the text as a linked list of LBUFFERs, adding them as needed.
|
||||
Return 0 if successful, 1 if an error occured. */
|
||||
|
||||
static int pipe_lines(const char *filename, int fd, long int n_lines)
|
||||
{
|
||||
struct linebuffer {
|
||||
int nbytes, nlines;
|
||||
char buffer[BUFSIZ];
|
||||
struct linebuffer *next;
|
||||
};
|
||||
typedef struct linebuffer LBUFFER;
|
||||
LBUFFER *first, *last, *tmp;
|
||||
int i; /* Index into buffers. */
|
||||
int total_lines = 0; /* Total number of newlines in all buffers. */
|
||||
int errors = 0;
|
||||
|
||||
first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
|
||||
first->nbytes = first->nlines = 0;
|
||||
first->next = NULL;
|
||||
tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
|
||||
|
||||
/* Input is always read into a fresh buffer. */
|
||||
while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
|
||||
tmp->nlines = 0;
|
||||
tmp->next = NULL;
|
||||
|
||||
/* Count the number of newlines just read. */
|
||||
for (i = 0; i < tmp->nbytes; i++)
|
||||
if (tmp->buffer[i] == '\n')
|
||||
++tmp->nlines;
|
||||
total_lines += tmp->nlines;
|
||||
|
||||
/* If there is enough room in the last buffer read, just append the new
|
||||
one to it. This is because when reading from a pipe, `nbytes' can
|
||||
often be very small. */
|
||||
if (tmp->nbytes + last->nbytes < BUFSIZ) {
|
||||
memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
|
||||
last->nbytes += tmp->nbytes;
|
||||
last->nlines += tmp->nlines;
|
||||
} else {
|
||||
/* If there's not enough room, link the new buffer onto the end of
|
||||
the list, then either free up the oldest buffer for the next
|
||||
read if that would leave enough lines, or else malloc a new one.
|
||||
Some compaction mechanism is possible but probably not
|
||||
worthwhile. */
|
||||
last = last->next = tmp;
|
||||
if (total_lines - first->nlines > n_lines) {
|
||||
tmp = first;
|
||||
total_lines -= first->nlines;
|
||||
first = first->next;
|
||||
} else
|
||||
tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
|
||||
}
|
||||
}
|
||||
if (tmp->nbytes == -1)
|
||||
error("read error");
|
||||
|
||||
free((char *) tmp);
|
||||
|
||||
/* This prevents a core dump when the pipe contains no newlines. */
|
||||
if (n_lines == 0)
|
||||
goto free_lbuffers;
|
||||
|
||||
/* Count the incomplete line on files that don't end with a newline. */
|
||||
if (last->buffer[last->nbytes - 1] != '\n') {
|
||||
++last->nlines;
|
||||
++total_lines;
|
||||
}
|
||||
|
||||
/* Run through the list, printing lines. First, skip over unneeded
|
||||
buffers. */
|
||||
for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
|
||||
total_lines -= tmp->nlines;
|
||||
|
||||
/* Find the correct beginning, then print the rest of the file. */
|
||||
if (total_lines > n_lines) {
|
||||
char *cp;
|
||||
|
||||
/* Skip `total_lines' - `n_lines' newlines. We made sure that
|
||||
`total_lines' - `n_lines' <= `tmp->nlines'. */
|
||||
cp = tmp->buffer;
|
||||
for (i = total_lines - n_lines; i; --i)
|
||||
while (*cp++ != '\n')
|
||||
/* Do nothing. */ ;
|
||||
i = cp - tmp->buffer;
|
||||
} else
|
||||
i = 0;
|
||||
XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
|
||||
|
||||
for (tmp = tmp->next; tmp; tmp = tmp->next)
|
||||
XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
|
||||
|
||||
free_lbuffers:
|
||||
while (first) {
|
||||
tmp = first->next;
|
||||
free((char *) first);
|
||||
first = tmp;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/* Display file FILENAME from the current position in FD to the end.
|
||||
If `forever' is nonzero, keep reading from the end of the file
|
||||
until killed. Return the number of bytes read from the file. */
|
||||
|
||||
static long dump_remainder(const char *filename, int fd)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
int bytes_read;
|
||||
long total;
|
||||
|
||||
total = 0;
|
||||
output:
|
||||
while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
|
||||
XWRITE(STDOUT_FILENO, buffer, bytes_read);
|
||||
total += bytes_read;
|
||||
}
|
||||
if (bytes_read == -1)
|
||||
error("read error");
|
||||
if (forever) {
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
goto output;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Output the last N_LINES lines of file FILENAME open for reading in FD.
|
||||
Return 0 if successful, 1 if an error occurred. */
|
||||
|
||||
static int tail_lines(const char *filename, int fd, long int n_lines)
|
||||
{
|
||||
struct stat stats;
|
||||
off_t length;
|
||||
|
||||
if (print_headers)
|
||||
write_header(filename);
|
||||
|
||||
if (fstat(fd, &stats))
|
||||
error("fstat error");
|
||||
|
||||
/* Use file_lines only if FD refers to a regular file with
|
||||
its file pointer positioned at beginning of file. */
|
||||
/* FIXME: adding the lseek conjunct is a kludge.
|
||||
Once there's a reasonable test suite, fix the true culprit:
|
||||
file_lines. file_lines shouldn't presume that the input
|
||||
file pointer is initially positioned to beginning of file. */
|
||||
if (S_ISREG(stats.st_mode)
|
||||
&& lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
|
||||
length = lseek(fd, (off_t) 0, SEEK_END);
|
||||
if (length != 0 && file_lines(filename, fd, n_lines, length))
|
||||
return 1;
|
||||
dump_remainder(filename, fd);
|
||||
} else
|
||||
return pipe_lines(filename, fd, n_lines);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Display the last N_UNITS lines of file FILENAME.
|
||||
"-" for FILENAME means the standard input.
|
||||
Return 0 if successful, 1 if an error occurred. */
|
||||
|
||||
static int tail_file(const char *filename, off_t n_units)
|
||||
{
|
||||
int fd, errors;
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
filename = "standard input";
|
||||
errors = tail_lines(filename, 0, (long) n_units);
|
||||
} else {
|
||||
/* Not standard input. */
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd == -1)
|
||||
error("open error");
|
||||
|
||||
errors = tail_lines(filename, fd, (long) n_units);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
extern int tail_main(int argc, char **argv)
|
||||
{
|
||||
int exit_status = 0;
|
||||
int n_units = DEFAULT_N_LINES;
|
||||
int n_tmp, i;
|
||||
char opt;
|
||||
|
||||
forever = print_headers = 0;
|
||||
|
||||
/* parse argv[] */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
opt = argv[i][1];
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
forever = 1;
|
||||
break;
|
||||
case 'n':
|
||||
n_tmp = 0;
|
||||
if (++i < argc)
|
||||
n_tmp = atoi(argv[i]);
|
||||
if (n_tmp < 1)
|
||||
usage(tail_usage);
|
||||
n_units = n_tmp;
|
||||
break;
|
||||
case '-':
|
||||
case 'h':
|
||||
usage(tail_usage);
|
||||
default:
|
||||
fprintf(stderr, "tail: invalid option -- %c\n", opt);
|
||||
usage(tail_usage);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i + 1 < argc) {
|
||||
if (forever) {
|
||||
fprintf(stderr,
|
||||
"tail: option -f is invalid with multiple files\n");
|
||||
usage(tail_usage);
|
||||
}
|
||||
print_headers = 1;
|
||||
}
|
||||
|
||||
if (i >= argc) {
|
||||
exit_status |= tail_file("-", n_units);
|
||||
} else {
|
||||
for (; i < argc; i++)
|
||||
exit_status |= tail_file(argv[i], n_units);
|
||||
}
|
||||
|
||||
exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
// Here follows the code for the full featured tail code
|
||||
|
||||
|
||||
/* tail -- output the last part of file(s)
|
||||
Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
|
||||
|
||||
@ -42,7 +441,7 @@
|
||||
#define NDEBUG 1
|
||||
|
||||
|
||||
static void error(int i, int errnum, char* fmt, ...)
|
||||
static void detailed_error(int i, int errnum, char* fmt, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
|
||||
@ -60,7 +459,7 @@ static void error(int i, int errnum, char* fmt, ...)
|
||||
assert ((fd) == 1); \
|
||||
assert ((n_bytes) >= 0); \
|
||||
if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
|
||||
error (EXIT_FAILURE, errno, "write error"); \
|
||||
detailed_error (EXIT_FAILURE, errno, "write error"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
@ -100,8 +499,6 @@ enum header_mode
|
||||
multiple_files, always, never
|
||||
};
|
||||
|
||||
char *xmalloc ();
|
||||
|
||||
/* The name this program was run with. */
|
||||
char *program_name;
|
||||
|
||||
@ -168,7 +565,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
||||
bytes_read = fullRead (fd, buffer, bytes_read);
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -204,7 +601,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
|
||||
while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -276,7 +673,7 @@ pipe_lines (const char *filename, int fd, long int n_lines)
|
||||
}
|
||||
if (tmp->nbytes == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
free ((char *) tmp);
|
||||
goto free_lbuffers;
|
||||
@ -390,7 +787,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
}
|
||||
if (tmp->nbytes == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
free ((char *) tmp);
|
||||
goto free_cbuffers;
|
||||
@ -438,7 +835,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
n_bytes -= bytes_read;
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
else if (n_bytes < 0)
|
||||
@ -466,7 +863,7 @@ start_lines (const char *filename, int fd, long int n_lines)
|
||||
}
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
else if (bytes_to_skip < bytes_read)
|
||||
@ -496,7 +893,7 @@ output:
|
||||
total += bytes_read;
|
||||
}
|
||||
if (bytes_read == -1)
|
||||
error (EXIT_FAILURE, errno, "%s", filename);
|
||||
detailed_error (EXIT_FAILURE, errno, "%s", filename);
|
||||
if (forever)
|
||||
{
|
||||
fflush (stdout);
|
||||
@ -540,7 +937,7 @@ tail_forever (char **names, int nfiles)
|
||||
continue;
|
||||
if (fstat (file_descs[i], &stats) < 0)
|
||||
{
|
||||
error (0, errno, "%s", names[i]);
|
||||
detailed_error (0, errno, "%s", names[i]);
|
||||
file_descs[i] = -1;
|
||||
continue;
|
||||
}
|
||||
@ -590,7 +987,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
error, either. */
|
||||
if (fstat (fd, &stats))
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -619,7 +1016,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -656,7 +1053,7 @@ tail_lines (const char *filename, int fd, long int n_lines)
|
||||
|
||||
if (fstat (fd, &stats))
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -723,12 +1120,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (fstat (0, &stats) < 0)
|
||||
{
|
||||
error (0, errno, "standard input");
|
||||
detailed_error (0, errno, "standard input");
|
||||
errors = 1;
|
||||
}
|
||||
else if (!S_ISREG (stats.st_mode))
|
||||
{
|
||||
error (0, 0,
|
||||
detailed_error (0, 0,
|
||||
"standard input: cannot follow end of non-regular file");
|
||||
errors = 1;
|
||||
}
|
||||
@ -749,7 +1146,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (forever_multiple)
|
||||
file_descs[filenum] = -1;
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
}
|
||||
else
|
||||
@ -761,12 +1158,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (fstat (fd, &stats) < 0)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
}
|
||||
else if (!S_ISREG (stats.st_mode))
|
||||
{
|
||||
error (0, 0, "%s: cannot follow end of non-regular file",
|
||||
detailed_error (0, 0, "%s: cannot follow end of non-regular file",
|
||||
filename);
|
||||
errors = 1;
|
||||
}
|
||||
@ -785,7 +1182,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
|
||||
{
|
||||
if (close (fd))
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
detailed_error (0, errno, "%s", filename);
|
||||
errors = 1;
|
||||
}
|
||||
}
|
||||
@ -903,8 +1300,11 @@ tail_main (int argc, char **argv)
|
||||
}
|
||||
|
||||
if (have_read_stdin && close (0) < 0)
|
||||
error (EXIT_FAILURE, errno, "-");
|
||||
detailed_error (EXIT_FAILURE, errno, "-");
|
||||
if (fclose (stdout) == EOF)
|
||||
error (EXIT_FAILURE, errno, "write error");
|
||||
detailed_error (EXIT_FAILURE, errno, "write error");
|
||||
exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
21
utility.c
21
utility.c
@ -175,7 +175,7 @@ copyFile( const char *srcName, const char *destName,
|
||||
}
|
||||
} else if (S_ISFIFO(srcStatBuf.st_mode)) {
|
||||
//fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
|
||||
if (mkfifo(destName, 644)) {
|
||||
if (mkfifo(destName, 0644)) {
|
||||
perror(destName);
|
||||
return (FALSE);
|
||||
}
|
||||
@ -406,7 +406,6 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int depthFir
|
||||
else
|
||||
status = lstat(fileName, &statbuf);
|
||||
|
||||
status = lstat(fileName, &statbuf);
|
||||
if (status < 0) {
|
||||
perror(fileName);
|
||||
return (FALSE);
|
||||
@ -1118,6 +1117,24 @@ findInitPid()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL
|
||||
extern void *xmalloc (size_t size)
|
||||
{
|
||||
void *cp = malloc (size);
|
||||
|
||||
if (cp == NULL) {
|
||||
error("out of memory");
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
extern void error(char *msg)
|
||||
{
|
||||
fprintf(stderr, "\n%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT)
|
||||
extern int vdprintf(int d, const char *format, va_list ap)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user