aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-01-25 18:13:53 +0000
committerErik Andersen <andersen@codepoet.org>2000-01-25 18:13:53 +0000
commit3fe39dce5d1a0b0946878c66bbd7f694c5aa38ea (patch)
tree32b6129967a8b5c922b72843efc7fc6683287181
parentbf3a838aaca4ab34d2739438fa44d0dbb04e9862 (diff)
downloadbusybox-w32-3fe39dce5d1a0b0946878c66bbd7f694c5aa38ea.tar.gz
busybox-w32-3fe39dce5d1a0b0946878c66bbd7f694c5aa38ea.tar.bz2
busybox-w32-3fe39dce5d1a0b0946878c66bbd7f694c5aa38ea.zip
Some busybox updates. See the changelog for details if you care.
-Erik
-rw-r--r--Changelog17
-rw-r--r--applets/busybox.c4
-rw-r--r--archival/gunzip.c48
-rw-r--r--archival/gzip.c27
-rw-r--r--busybox.c4
-rw-r--r--busybox.def.h5
-rw-r--r--coreutils/head.c4
-rw-r--r--coreutils/printf.c2
-rw-r--r--coreutils/tail.c446
-rw-r--r--gunzip.c48
-rw-r--r--gzip.c27
-rw-r--r--head.c4
-rw-r--r--init.c43
-rw-r--r--init/init.c43
-rw-r--r--internal.h5
-rw-r--r--printf.c2
-rw-r--r--tail.c446
-rw-r--r--utility.c21
18 files changed, 965 insertions, 231 deletions
diff --git a/Changelog b/Changelog
index 673d1aafd..4dbb46e4f 100644
--- a/Changelog
+++ b/Changelog
@@ -15,12 +15,23 @@
15 * Optional support contributed by Ben Collins <bcollins@debian.org> 15 * Optional support contributed by Ben Collins <bcollins@debian.org>
16 for the kernel init chroot patch by Werner Almesberger, which 16 for the kernel init chroot patch by Werner Almesberger, which
17 allows init to chroot to a new device, and umount the old one. 17 allows init to chroot to a new device, and umount the old one.
18 * Fixed bug that wouldn't let one chown a symlink -- it would
19 always dereference before. -beppu
20 * Fixed a bug where init could have reference already freed memory.
21 Found and fixed by Taketoshi Sano <kgh12351@nifty.ne.jp>
22 * Several contributions from Friedrich Vedder <fwv@myrtle.lahn.de>
18 * added (and documented) "-n" option for head - 23 * added (and documented) "-n" option for head -
19 contributed Friedrich Vedder <fwv@myrtle.lahn.de>
20 * Cleanup for a number of usage messages -- also 24 * Cleanup for a number of usage messages -- also
21 contributed Friedrich Vedder <fwv@myrtle.lahn.de> 25 contributed Friedrich Vedder <fwv@myrtle.lahn.de>
22 * Fixed bug that wouldn't let one chown a symlink -- it would 26 * Cosmetic fix to busybox.c (Don't print a comma at the
23 always dereference before. -beppu 27 end of line if there are no more application names).
28 * Fixed a stupid bug in "head" option handling ("head -n" would segfault).
29 * Moved commonly used functions "xmalloc()" and "exit()"
30 to utility.c (with proper #ifdef's).
31 * Created a tiny tail implementation, removing -c, -q, -v, and making
32 tail -f work only with a single file. This reduced tail
33 from 6k to 2.4k. The bigger/more featured tail can still be
34 had by disabling BB_FEATURE_SIMPLE_TAIL in dusybox.defs.h
24 35
25 36
26 -Erik Andersen 37 -Erik Andersen
diff --git a/applets/busybox.c b/applets/busybox.c
index 67485de8d..d59b2855e 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -83,7 +83,7 @@ static const struct Applet applets[] = {
83#ifdef BB_FREE //usr/bin 83#ifdef BB_FREE //usr/bin
84 {"free", free_main}, 84 {"free", free_main},
85#endif 85#endif
86#ifdef BB_DEALLOCVT //usr/bin 86#ifdef BB_DEALLOCVT //usr/bin
87 {"deallocvt", deallocvt_main}, 87 {"deallocvt", deallocvt_main},
88#endif 88#endif
89#ifdef BB_FSCK_MINIX //sbin 89#ifdef BB_FSCK_MINIX //sbin
@@ -328,7 +328,7 @@ int busybox_main(int argc, char **argv)
328 328
329 while (a->name != 0) { 329 while (a->name != 0) {
330 col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name); 330 col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name);
331 if (col>60) { 331 if (col>60 && a->name != 0) {
332 fprintf(stderr, ",\n"); 332 fprintf(stderr, ",\n");
333 col=0; 333 col=0;
334 } 334 }
diff --git a/archival/gunzip.c b/archival/gunzip.c
index 84f5d02b7..fddcc7653 100644
--- a/archival/gunzip.c
+++ b/archival/gunzip.c
@@ -321,6 +321,9 @@ extern int save_orig_name; /* set if original name must be saved */
321#define WARN(msg) {fprintf msg ; \ 321#define WARN(msg) {fprintf msg ; \
322 if (exit_code == OK) exit_code = WARNING;} 322 if (exit_code == OK) exit_code = WARNING;}
323 323
324#define do_exit(c) exit(c)
325
326
324 /* in unzip.c */ 327 /* in unzip.c */
325extern int unzip OF((int in, int out)); 328extern int unzip OF((int in, int out));
326 329
@@ -359,7 +362,6 @@ extern void error OF((char *m));
359extern void warn OF((char *a, char *b)); 362extern void warn OF((char *a, char *b));
360extern void read_error OF((void)); 363extern void read_error OF((void));
361extern void write_error OF((void)); 364extern void write_error OF((void));
362extern voidp xmalloc OF((unsigned int size));
363 365
364 /* in inflate.c */ 366 /* in inflate.c */
365extern int inflate OF((void)); 367extern int inflate OF((void));
@@ -679,7 +681,6 @@ long header_bytes; /* number of bytes in gzip header */
679/* local functions */ 681/* local functions */
680 682
681local int get_method OF((int in)); 683local int get_method OF((int in));
682local void do_exit(int exitcode) __attribute__ ((noreturn));
683 684
684#define strequ(s1, s2) (strcmp((s1),(s2)) == 0) 685#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
685 686
@@ -927,30 +928,6 @@ local int get_method(in)
927 } 928 }
928} 929}
929 930
930
931/* ========================================================================
932 * Free all dynamically allocated variables and exit with the given code.
933 */
934local void do_exit(exitcode)
935 int exitcode;
936{
937 static int in_exit = 0;
938
939 if (in_exit) exit(exitcode);
940 in_exit = 1;
941 FREE(inbuf);
942 FREE(outbuf);
943 FREE(d_buf);
944 FREE(window);
945#ifndef MAXSEG_64K
946 FREE(tab_prefix);
947#else
948 FREE(tab_prefix0);
949 FREE(tab_prefix1);
950#endif
951 exit(exitcode);
952}
953
954/* ======================================================================== 931/* ========================================================================
955 * Signal and error handler. 932 * Signal and error handler.
956 */ 933 */
@@ -1284,13 +1261,6 @@ int strcspn(s, reject)
1284/* ======================================================================== 1261/* ========================================================================
1285 * Error handlers. 1262 * Error handlers.
1286 */ 1263 */
1287void error(m)
1288 char *m;
1289{
1290 fprintf(stderr, "\n%s\n", m);
1291 abort_gzip();
1292}
1293
1294void warn(a, b) 1264void warn(a, b)
1295 char *a, *b; /* message strings juxtaposed in output */ 1265 char *a, *b; /* message strings juxtaposed in output */
1296{ 1266{
@@ -1317,18 +1287,6 @@ void write_error()
1317 1287
1318 1288
1319/* ======================================================================== 1289/* ========================================================================
1320 * Semi-safe malloc -- never returns NULL.
1321 */
1322voidp xmalloc (size)
1323 unsigned size;
1324{
1325 voidp cp = (voidp)malloc (size);
1326
1327 if (cp == NULL) error("out of memory");
1328 return cp;
1329}
1330
1331/* ========================================================================
1332 * Table of CRC-32's of all single-byte values (made by makecrc.c) 1290 * Table of CRC-32's of all single-byte values (made by makecrc.c)
1333 */ 1291 */
1334static const ulg crc_32_tab[] = { 1292static const ulg crc_32_tab[] = {
diff --git a/archival/gzip.c b/archival/gzip.c
index 76df3ad9a..3438ee42f 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -277,7 +277,8 @@ extern int save_orig_name; /* set if original name must be saved */
277#define WARN(msg) {if (!quiet) fprintf msg ; \ 277#define WARN(msg) {if (!quiet) fprintf msg ; \
278 if (exit_code == OK) exit_code = WARNING;} 278 if (exit_code == OK) exit_code = WARNING;}
279 279
280local void do_exit(int exitcode) __attribute__ ((noreturn)); 280#define do_exit(c) exit(c)
281
281 282
282 /* in zip.c: */ 283 /* in zip.c: */
283extern int zip OF((int in, int out)); 284extern int zip OF((int in, int out));
@@ -328,7 +329,6 @@ extern void warn OF((char *a, char *b));
328extern void read_error OF((void)); 329extern void read_error OF((void));
329extern void write_error OF((void)); 330extern void write_error OF((void));
330extern void display_ratio OF((long num, long den, FILE *file)); 331extern void display_ratio OF((long num, long den, FILE *file));
331extern voidp xmalloc OF((unsigned int size));
332 332
333 /* in inflate.c */ 333 /* in inflate.c */
334extern int inflate OF((void)); 334extern int inflate OF((void));
@@ -1912,29 +1912,6 @@ int gzip_main(int argc, char ** argv)
1912 do_exit(exit_code); 1912 do_exit(exit_code);
1913} 1913}
1914 1914
1915/* ========================================================================
1916 * Free all dynamically allocated variables and exit with the given code.
1917 */
1918local void do_exit(int exitcode)
1919{
1920 static int in_exit = 0;
1921
1922 if (in_exit) exit(exitcode);
1923 in_exit = 1;
1924 if (env != NULL) free(env), env = NULL;
1925 if (args != NULL) free((char*)args), args = NULL;
1926 FREE(inbuf);
1927 FREE(outbuf);
1928 FREE(d_buf);
1929 FREE(window);
1930#ifndef MAXSEG_64K
1931 FREE(tab_prefix);
1932#else
1933 FREE(tab_prefix0);
1934 FREE(tab_prefix1);
1935#endif
1936 exit(exitcode);
1937}
1938/* trees.c -- output deflated data using Huffman coding 1915/* trees.c -- output deflated data using Huffman coding
1939 * Copyright (C) 1992-1993 Jean-loup Gailly 1916 * Copyright (C) 1992-1993 Jean-loup Gailly
1940 * This is free software; you can redistribute it and/or modify it under the 1917 * This is free software; you can redistribute it and/or modify it under the
diff --git a/busybox.c b/busybox.c
index 67485de8d..d59b2855e 100644
--- a/busybox.c
+++ b/busybox.c
@@ -83,7 +83,7 @@ static const struct Applet applets[] = {
83#ifdef BB_FREE //usr/bin 83#ifdef BB_FREE //usr/bin
84 {"free", free_main}, 84 {"free", free_main},
85#endif 85#endif
86#ifdef BB_DEALLOCVT //usr/bin 86#ifdef BB_DEALLOCVT //usr/bin
87 {"deallocvt", deallocvt_main}, 87 {"deallocvt", deallocvt_main},
88#endif 88#endif
89#ifdef BB_FSCK_MINIX //sbin 89#ifdef BB_FSCK_MINIX //sbin
@@ -328,7 +328,7 @@ int busybox_main(int argc, char **argv)
328 328
329 while (a->name != 0) { 329 while (a->name != 0) {
330 col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name); 330 col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name);
331 if (col>60) { 331 if (col>60 && a->name != 0) {
332 fprintf(stderr, ",\n"); 332 fprintf(stderr, ",\n");
333 col=0; 333 col=0;
334 } 334 }
diff --git a/busybox.def.h b/busybox.def.h
index c56f151db..8adccdc64 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -133,6 +133,11 @@
133//Enable init being called as /linuxrc 133//Enable init being called as /linuxrc
134#define BB_FEATURE_LINUXRC 134#define BB_FEATURE_LINUXRC
135// 135//
136//
137//Simple tail implementation (2k vs 6k for the full one). Still
138//provides 'tail -f' support -- but for only one file at a time.
139#define BB_FEATURE_SIMPLE_TAIL
140//
136// Enable support for loop devices in mount 141// Enable support for loop devices in mount
137#define BB_FEATURE_MOUNT_LOOP 142#define BB_FEATURE_MOUNT_LOOP
138// 143//
diff --git a/coreutils/head.c b/coreutils/head.c
index 4e58bdcd7..bc7f35429 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -61,7 +61,7 @@ head_main(int argc, char **argv)
61 switch (opt) { 61 switch (opt) {
62 case 'n': 62 case 'n':
63 tmplen = 0; 63 tmplen = 0;
64 if (i++ < argc) 64 if (++i < argc)
65 tmplen = atoi(argv[i]); 65 tmplen = atoi(argv[i]);
66 if (tmplen < 1) 66 if (tmplen < 1)
67 usage(head_usage); 67 usage(head_usage);
@@ -105,4 +105,4 @@ head_main(int argc, char **argv)
105 exit(0); 105 exit(0);
106} 106}
107 107
108/* $Id: head.c,v 1.5 2000/01/23 18:19:02 erik Exp $ */ 108/* $Id: head.c,v 1.6 2000/01/25 18:13:53 erik Exp $ */
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 02d08118b..5be3a67cb 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -121,8 +121,6 @@
121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') 121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
122#define octtobin(c) ((c) - '0') 122#define octtobin(c) ((c) - '0')
123 123
124char *xmalloc ();
125
126static double xstrtod __P ((char *s)); 124static double xstrtod __P ((char *s));
127static int print_esc __P ((char *escstart)); 125static int print_esc __P ((char *escstart));
128static int print_formatted __P ((char *format, int argc, char **argv)); 126static int print_formatted __P ((char *format, int argc, char **argv));
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 697177dc7..5198892b6 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -1,3 +1,402 @@
1#include "internal.h"
2/* This file contains _two_ implementations of tail. One is
3 * a bit more full featured, but costs 6k. The other (i.e. the
4 * SIMPLE_TAIL one) is less capable, but is good enough for about
5 * 99% of the things folks want to use tail for, and only costs 2k.
6 */
7
8
9#ifdef BB_FEATURE_SIMPLE_TAIL
10
11/* tail -- output the last part of file(s)
12 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2, or (at your option)
17 any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28 Original version by Paul Rubin <phr@ocf.berkeley.edu>.
29 Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
30 tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.
31
32 Rewrote the option parser, removed locales support,
33 and generally busyboxed, Erik Andersen <andersen@lineo.com>
34
35 Removed superfluous options and associated code ("-c", "-n", "-q").
36 Removed "tail -f" suport for multiple files.
37 Both changes by Friedrich Vedder <fwv@myrtle.lahn.de>.
38
39 */
40
41
42#include <stdio.h>
43#include <stdarg.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <fcntl.h>
47#include <ctype.h>
48
49
50#define XWRITE(fd, buffer, n_bytes) \
51 do { \
52 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
53 error("write error"); \
54 } while (0)
55
56/* Number of items to tail. */
57#define DEFAULT_N_LINES 10
58
59/* Size of atomic reads. */
60#ifndef BUFSIZ
61#define BUFSIZ (512 * 8)
62#endif
63
64/* If nonzero, read from the end of one file until killed. */
65static int forever;
66
67/* If nonzero, print filename headers. */
68static int print_headers;
69
70const char tail_usage[] =
71 "tail [OPTION] [FILE]...\n\n"
72 "Print last 10 lines of each FILE to standard output.\n"
73 "With more than one FILE, precede each with a header giving the\n"
74 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
75 "Options:\n"
76 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
77 "\t-f\t\tOutput data as the file grows. This version\n"
78 "\t\t\tof 'tail -f' supports only one file at a time.\n";
79
80
81static void write_header(const char *filename)
82{
83 static int first_file = 1;
84
85 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
86 first_file = 0;
87}
88
89/* Print the last N_LINES lines from the end of file FD.
90 Go backward through the file, reading `BUFSIZ' bytes at a time (except
91 probably the first), until we hit the start of the file or have
92 read NUMBER newlines.
93 POS starts out as the length of the file (the offset of the last
94 byte of the file + 1).
95 Return 0 if successful, 1 if an error occurred. */
96
97static int
98file_lines(const char *filename, int fd, long int n_lines, off_t pos)
99{
100 char buffer[BUFSIZ];
101 int bytes_read;
102 int i; /* Index into `buffer' for scanning. */
103
104 if (n_lines == 0)
105 return 0;
106
107 /* Set `bytes_read' to the size of the last, probably partial, buffer;
108 0 < `bytes_read' <= `BUFSIZ'. */
109 bytes_read = pos % BUFSIZ;
110 if (bytes_read == 0)
111 bytes_read = BUFSIZ;
112 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
113 reads will be on block boundaries, which might increase efficiency. */
114 pos -= bytes_read;
115 lseek(fd, pos, SEEK_SET);
116 bytes_read = fullRead(fd, buffer, bytes_read);
117 if (bytes_read == -1)
118 error("read error");
119
120 /* Count the incomplete line on files that don't end with a newline. */
121 if (bytes_read && buffer[bytes_read - 1] != '\n')
122 --n_lines;
123
124 do {
125 /* Scan backward, counting the newlines in this bufferfull. */
126 for (i = bytes_read - 1; i >= 0; i--) {
127 /* Have we counted the requested number of newlines yet? */
128 if (buffer[i] == '\n' && n_lines-- == 0) {
129 /* If this newline wasn't the last character in the buffer,
130 print the text after it. */
131 if (i != bytes_read - 1)
132 XWRITE(STDOUT_FILENO, &buffer[i + 1],
133 bytes_read - (i + 1));
134 return 0;
135 }
136 }
137 /* Not enough newlines in that bufferfull. */
138 if (pos == 0) {
139 /* Not enough lines in the file; print the entire file. */
140 lseek(fd, (off_t) 0, SEEK_SET);
141 return 0;
142 }
143 pos -= BUFSIZ;
144 lseek(fd, pos, SEEK_SET);
145 }
146 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
147 if (bytes_read == -1)
148 error("read error");
149
150 return 0;
151}
152
153/* Print the last N_LINES lines from the end of the standard input,
154 open for reading as pipe FD.
155 Buffer the text as a linked list of LBUFFERs, adding them as needed.
156 Return 0 if successful, 1 if an error occured. */
157
158static int pipe_lines(const char *filename, int fd, long int n_lines)
159{
160 struct linebuffer {
161 int nbytes, nlines;
162 char buffer[BUFSIZ];
163 struct linebuffer *next;
164 };
165 typedef struct linebuffer LBUFFER;
166 LBUFFER *first, *last, *tmp;
167 int i; /* Index into buffers. */
168 int total_lines = 0; /* Total number of newlines in all buffers. */
169 int errors = 0;
170
171 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
172 first->nbytes = first->nlines = 0;
173 first->next = NULL;
174 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
175
176 /* Input is always read into a fresh buffer. */
177 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
178 tmp->nlines = 0;
179 tmp->next = NULL;
180
181 /* Count the number of newlines just read. */
182 for (i = 0; i < tmp->nbytes; i++)
183 if (tmp->buffer[i] == '\n')
184 ++tmp->nlines;
185 total_lines += tmp->nlines;
186
187 /* If there is enough room in the last buffer read, just append the new
188 one to it. This is because when reading from a pipe, `nbytes' can
189 often be very small. */
190 if (tmp->nbytes + last->nbytes < BUFSIZ) {
191 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
192 last->nbytes += tmp->nbytes;
193 last->nlines += tmp->nlines;
194 } else {
195 /* If there's not enough room, link the new buffer onto the end of
196 the list, then either free up the oldest buffer for the next
197 read if that would leave enough lines, or else malloc a new one.
198 Some compaction mechanism is possible but probably not
199 worthwhile. */
200 last = last->next = tmp;
201 if (total_lines - first->nlines > n_lines) {
202 tmp = first;
203 total_lines -= first->nlines;
204 first = first->next;
205 } else
206 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
207 }
208 }
209 if (tmp->nbytes == -1)
210 error("read error");
211
212 free((char *) tmp);
213
214 /* This prevents a core dump when the pipe contains no newlines. */
215 if (n_lines == 0)
216 goto free_lbuffers;
217
218 /* Count the incomplete line on files that don't end with a newline. */
219 if (last->buffer[last->nbytes - 1] != '\n') {
220 ++last->nlines;
221 ++total_lines;
222 }
223
224 /* Run through the list, printing lines. First, skip over unneeded
225 buffers. */
226 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
227 total_lines -= tmp->nlines;
228
229 /* Find the correct beginning, then print the rest of the file. */
230 if (total_lines > n_lines) {
231 char *cp;
232
233 /* Skip `total_lines' - `n_lines' newlines. We made sure that
234 `total_lines' - `n_lines' <= `tmp->nlines'. */
235 cp = tmp->buffer;
236 for (i = total_lines - n_lines; i; --i)
237 while (*cp++ != '\n')
238 /* Do nothing. */ ;
239 i = cp - tmp->buffer;
240 } else
241 i = 0;
242 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
243
244 for (tmp = tmp->next; tmp; tmp = tmp->next)
245 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
246
247 free_lbuffers:
248 while (first) {
249 tmp = first->next;
250 free((char *) first);
251 first = tmp;
252 }
253 return errors;
254}
255
256/* Display file FILENAME from the current position in FD to the end.
257 If `forever' is nonzero, keep reading from the end of the file
258 until killed. Return the number of bytes read from the file. */
259
260static long dump_remainder(const char *filename, int fd)
261{
262 char buffer[BUFSIZ];
263 int bytes_read;
264 long total;
265
266 total = 0;
267 output:
268 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
269 XWRITE(STDOUT_FILENO, buffer, bytes_read);
270 total += bytes_read;
271 }
272 if (bytes_read == -1)
273 error("read error");
274 if (forever) {
275 fflush(stdout);
276 sleep(1);
277 goto output;
278 }
279
280 return total;
281}
282
283/* Output the last N_LINES lines of file FILENAME open for reading in FD.
284 Return 0 if successful, 1 if an error occurred. */
285
286static int tail_lines(const char *filename, int fd, long int n_lines)
287{
288 struct stat stats;
289 off_t length;
290
291 if (print_headers)
292 write_header(filename);
293
294 if (fstat(fd, &stats))
295 error("fstat error");
296
297 /* Use file_lines only if FD refers to a regular file with
298 its file pointer positioned at beginning of file. */
299 /* FIXME: adding the lseek conjunct is a kludge.
300 Once there's a reasonable test suite, fix the true culprit:
301 file_lines. file_lines shouldn't presume that the input
302 file pointer is initially positioned to beginning of file. */
303 if (S_ISREG(stats.st_mode)
304 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
305 length = lseek(fd, (off_t) 0, SEEK_END);
306 if (length != 0 && file_lines(filename, fd, n_lines, length))
307 return 1;
308 dump_remainder(filename, fd);
309 } else
310 return pipe_lines(filename, fd, n_lines);
311
312 return 0;
313}
314
315/* Display the last N_UNITS lines of file FILENAME.
316 "-" for FILENAME means the standard input.
317 Return 0 if successful, 1 if an error occurred. */
318
319static int tail_file(const char *filename, off_t n_units)
320{
321 int fd, errors;
322
323 if (!strcmp(filename, "-")) {
324 filename = "standard input";
325 errors = tail_lines(filename, 0, (long) n_units);
326 } else {
327 /* Not standard input. */
328 fd = open(filename, O_RDONLY);
329 if (fd == -1)
330 error("open error");
331
332 errors = tail_lines(filename, fd, (long) n_units);
333 close(fd);
334 }
335
336 return errors;
337}
338
339extern int tail_main(int argc, char **argv)
340{
341 int exit_status = 0;
342 int n_units = DEFAULT_N_LINES;
343 int n_tmp, i;
344 char opt;
345
346 forever = print_headers = 0;
347
348 /* parse argv[] */
349 for (i = 1; i < argc; i++) {
350 if (argv[i][0] == '-') {
351 opt = argv[i][1];
352 switch (opt) {
353 case 'f':
354 forever = 1;
355 break;
356 case 'n':
357 n_tmp = 0;
358 if (++i < argc)
359 n_tmp = atoi(argv[i]);
360 if (n_tmp < 1)
361 usage(tail_usage);
362 n_units = n_tmp;
363 break;
364 case '-':
365 case 'h':
366 usage(tail_usage);
367 default:
368 fprintf(stderr, "tail: invalid option -- %c\n", opt);
369 usage(tail_usage);
370 }
371 } else {
372 break;
373 }
374 }
375
376 if (i + 1 < argc) {
377 if (forever) {
378 fprintf(stderr,
379 "tail: option -f is invalid with multiple files\n");
380 usage(tail_usage);
381 }
382 print_headers = 1;
383 }
384
385 if (i >= argc) {
386 exit_status |= tail_file("-", n_units);
387 } else {
388 for (; i < argc; i++)
389 exit_status |= tail_file(argv[i], n_units);
390 }
391
392 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
393}
394
395
396#else
397// Here follows the code for the full featured tail code
398
399
1/* tail -- output the last part of file(s) 400/* tail -- output the last part of file(s)
2 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc. 401 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
3 402
@@ -42,7 +441,7 @@
42#define NDEBUG 1 441#define NDEBUG 1
43 442
44 443
45static void error(int i, int errnum, char* fmt, ...) 444static void detailed_error(int i, int errnum, char* fmt, ...)
46{ 445{
47 va_list arguments; 446 va_list arguments;
48 447
@@ -60,7 +459,7 @@ static void error(int i, int errnum, char* fmt, ...)
60 assert ((fd) == 1); \ 459 assert ((fd) == 1); \
61 assert ((n_bytes) >= 0); \ 460 assert ((n_bytes) >= 0); \
62 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ 461 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
63 error (EXIT_FAILURE, errno, "write error"); \ 462 detailed_error (EXIT_FAILURE, errno, "write error"); \
64 } \ 463 } \
65 while (0) 464 while (0)
66 465
@@ -100,8 +499,6 @@ enum header_mode
100 multiple_files, always, never 499 multiple_files, always, never
101}; 500};
102 501
103char *xmalloc ();
104
105/* The name this program was run with. */ 502/* The name this program was run with. */
106char *program_name; 503char *program_name;
107 504
@@ -168,7 +565,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
168 bytes_read = fullRead (fd, buffer, bytes_read); 565 bytes_read = fullRead (fd, buffer, bytes_read);
169 if (bytes_read == -1) 566 if (bytes_read == -1)
170 { 567 {
171 error (0, errno, "%s", filename); 568 detailed_error (0, errno, "%s", filename);
172 return 1; 569 return 1;
173 } 570 }
174 571
@@ -204,7 +601,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
204 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0); 601 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
205 if (bytes_read == -1) 602 if (bytes_read == -1)
206 { 603 {
207 error (0, errno, "%s", filename); 604 detailed_error (0, errno, "%s", filename);
208 return 1; 605 return 1;
209 } 606 }
210 return 0; 607 return 0;
@@ -276,7 +673,7 @@ pipe_lines (const char *filename, int fd, long int n_lines)
276 } 673 }
277 if (tmp->nbytes == -1) 674 if (tmp->nbytes == -1)
278 { 675 {
279 error (0, errno, "%s", filename); 676 detailed_error (0, errno, "%s", filename);
280 errors = 1; 677 errors = 1;
281 free ((char *) tmp); 678 free ((char *) tmp);
282 goto free_lbuffers; 679 goto free_lbuffers;
@@ -390,7 +787,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes)
390 } 787 }
391 if (tmp->nbytes == -1) 788 if (tmp->nbytes == -1)
392 { 789 {
393 error (0, errno, "%s", filename); 790 detailed_error (0, errno, "%s", filename);
394 errors = 1; 791 errors = 1;
395 free ((char *) tmp); 792 free ((char *) tmp);
396 goto free_cbuffers; 793 goto free_cbuffers;
@@ -438,7 +835,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes)
438 n_bytes -= bytes_read; 835 n_bytes -= bytes_read;
439 if (bytes_read == -1) 836 if (bytes_read == -1)
440 { 837 {
441 error (0, errno, "%s", filename); 838 detailed_error (0, errno, "%s", filename);
442 return 1; 839 return 1;
443 } 840 }
444 else if (n_bytes < 0) 841 else if (n_bytes < 0)
@@ -466,7 +863,7 @@ start_lines (const char *filename, int fd, long int n_lines)
466 } 863 }
467 if (bytes_read == -1) 864 if (bytes_read == -1)
468 { 865 {
469 error (0, errno, "%s", filename); 866 detailed_error (0, errno, "%s", filename);
470 return 1; 867 return 1;
471 } 868 }
472 else if (bytes_to_skip < bytes_read) 869 else if (bytes_to_skip < bytes_read)
@@ -496,7 +893,7 @@ output:
496 total += bytes_read; 893 total += bytes_read;
497 } 894 }
498 if (bytes_read == -1) 895 if (bytes_read == -1)
499 error (EXIT_FAILURE, errno, "%s", filename); 896 detailed_error (EXIT_FAILURE, errno, "%s", filename);
500 if (forever) 897 if (forever)
501 { 898 {
502 fflush (stdout); 899 fflush (stdout);
@@ -540,7 +937,7 @@ tail_forever (char **names, int nfiles)
540 continue; 937 continue;
541 if (fstat (file_descs[i], &stats) < 0) 938 if (fstat (file_descs[i], &stats) < 0)
542 { 939 {
543 error (0, errno, "%s", names[i]); 940 detailed_error (0, errno, "%s", names[i]);
544 file_descs[i] = -1; 941 file_descs[i] = -1;
545 continue; 942 continue;
546 } 943 }
@@ -590,7 +987,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
590 error, either. */ 987 error, either. */
591 if (fstat (fd, &stats)) 988 if (fstat (fd, &stats))
592 { 989 {
593 error (0, errno, "%s", filename); 990 detailed_error (0, errno, "%s", filename);
594 return 1; 991 return 1;
595 } 992 }
596 993
@@ -619,7 +1016,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
619 } 1016 }
620 else 1017 else
621 { 1018 {
622 error (0, errno, "%s", filename); 1019 detailed_error (0, errno, "%s", filename);
623 return 1; 1020 return 1;
624 } 1021 }
625 1022
@@ -656,7 +1053,7 @@ tail_lines (const char *filename, int fd, long int n_lines)
656 1053
657 if (fstat (fd, &stats)) 1054 if (fstat (fd, &stats))
658 { 1055 {
659 error (0, errno, "%s", filename); 1056 detailed_error (0, errno, "%s", filename);
660 return 1; 1057 return 1;
661 } 1058 }
662 1059
@@ -723,12 +1120,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
723 { 1120 {
724 if (fstat (0, &stats) < 0) 1121 if (fstat (0, &stats) < 0)
725 { 1122 {
726 error (0, errno, "standard input"); 1123 detailed_error (0, errno, "standard input");
727 errors = 1; 1124 errors = 1;
728 } 1125 }
729 else if (!S_ISREG (stats.st_mode)) 1126 else if (!S_ISREG (stats.st_mode))
730 { 1127 {
731 error (0, 0, 1128 detailed_error (0, 0,
732 "standard input: cannot follow end of non-regular file"); 1129 "standard input: cannot follow end of non-regular file");
733 errors = 1; 1130 errors = 1;
734 } 1131 }
@@ -749,7 +1146,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
749 { 1146 {
750 if (forever_multiple) 1147 if (forever_multiple)
751 file_descs[filenum] = -1; 1148 file_descs[filenum] = -1;
752 error (0, errno, "%s", filename); 1149 detailed_error (0, errno, "%s", filename);
753 errors = 1; 1150 errors = 1;
754 } 1151 }
755 else 1152 else
@@ -761,12 +1158,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
761 { 1158 {
762 if (fstat (fd, &stats) < 0) 1159 if (fstat (fd, &stats) < 0)
763 { 1160 {
764 error (0, errno, "%s", filename); 1161 detailed_error (0, errno, "%s", filename);
765 errors = 1; 1162 errors = 1;
766 } 1163 }
767 else if (!S_ISREG (stats.st_mode)) 1164 else if (!S_ISREG (stats.st_mode))
768 { 1165 {
769 error (0, 0, "%s: cannot follow end of non-regular file", 1166 detailed_error (0, 0, "%s: cannot follow end of non-regular file",
770 filename); 1167 filename);
771 errors = 1; 1168 errors = 1;
772 } 1169 }
@@ -785,7 +1182,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
785 { 1182 {
786 if (close (fd)) 1183 if (close (fd))
787 { 1184 {
788 error (0, errno, "%s", filename); 1185 detailed_error (0, errno, "%s", filename);
789 errors = 1; 1186 errors = 1;
790 } 1187 }
791 } 1188 }
@@ -903,8 +1300,11 @@ tail_main (int argc, char **argv)
903 } 1300 }
904 1301
905 if (have_read_stdin && close (0) < 0) 1302 if (have_read_stdin && close (0) < 0)
906 error (EXIT_FAILURE, errno, "-"); 1303 detailed_error (EXIT_FAILURE, errno, "-");
907 if (fclose (stdout) == EOF) 1304 if (fclose (stdout) == EOF)
908 error (EXIT_FAILURE, errno, "write error"); 1305 detailed_error (EXIT_FAILURE, errno, "write error");
909 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 1306 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
910} 1307}
1308
1309
1310#endif
diff --git a/gunzip.c b/gunzip.c
index 84f5d02b7..fddcc7653 100644
--- a/gunzip.c
+++ b/gunzip.c
@@ -321,6 +321,9 @@ extern int save_orig_name; /* set if original name must be saved */
321#define WARN(msg) {fprintf msg ; \ 321#define WARN(msg) {fprintf msg ; \
322 if (exit_code == OK) exit_code = WARNING;} 322 if (exit_code == OK) exit_code = WARNING;}
323 323
324#define do_exit(c) exit(c)
325
326
324 /* in unzip.c */ 327 /* in unzip.c */
325extern int unzip OF((int in, int out)); 328extern int unzip OF((int in, int out));
326 329
@@ -359,7 +362,6 @@ extern void error OF((char *m));
359extern void warn OF((char *a, char *b)); 362extern void warn OF((char *a, char *b));
360extern void read_error OF((void)); 363extern void read_error OF((void));
361extern void write_error OF((void)); 364extern void write_error OF((void));
362extern voidp xmalloc OF((unsigned int size));
363 365
364 /* in inflate.c */ 366 /* in inflate.c */
365extern int inflate OF((void)); 367extern int inflate OF((void));
@@ -679,7 +681,6 @@ long header_bytes; /* number of bytes in gzip header */
679/* local functions */ 681/* local functions */
680 682
681local int get_method OF((int in)); 683local int get_method OF((int in));
682local void do_exit(int exitcode) __attribute__ ((noreturn));
683 684
684#define strequ(s1, s2) (strcmp((s1),(s2)) == 0) 685#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
685 686
@@ -927,30 +928,6 @@ local int get_method(in)
927 } 928 }
928} 929}
929 930
930
931/* ========================================================================
932 * Free all dynamically allocated variables and exit with the given code.
933 */
934local void do_exit(exitcode)
935 int exitcode;
936{
937 static int in_exit = 0;
938
939 if (in_exit) exit(exitcode);
940 in_exit = 1;
941 FREE(inbuf);
942 FREE(outbuf);
943 FREE(d_buf);
944 FREE(window);
945#ifndef MAXSEG_64K
946 FREE(tab_prefix);
947#else
948 FREE(tab_prefix0);
949 FREE(tab_prefix1);
950#endif
951 exit(exitcode);
952}
953
954/* ======================================================================== 931/* ========================================================================
955 * Signal and error handler. 932 * Signal and error handler.
956 */ 933 */
@@ -1284,13 +1261,6 @@ int strcspn(s, reject)
1284/* ======================================================================== 1261/* ========================================================================
1285 * Error handlers. 1262 * Error handlers.
1286 */ 1263 */
1287void error(m)
1288 char *m;
1289{
1290 fprintf(stderr, "\n%s\n", m);
1291 abort_gzip();
1292}
1293
1294void warn(a, b) 1264void warn(a, b)
1295 char *a, *b; /* message strings juxtaposed in output */ 1265 char *a, *b; /* message strings juxtaposed in output */
1296{ 1266{
@@ -1317,18 +1287,6 @@ void write_error()
1317 1287
1318 1288
1319/* ======================================================================== 1289/* ========================================================================
1320 * Semi-safe malloc -- never returns NULL.
1321 */
1322voidp xmalloc (size)
1323 unsigned size;
1324{
1325 voidp cp = (voidp)malloc (size);
1326
1327 if (cp == NULL) error("out of memory");
1328 return cp;
1329}
1330
1331/* ========================================================================
1332 * Table of CRC-32's of all single-byte values (made by makecrc.c) 1290 * Table of CRC-32's of all single-byte values (made by makecrc.c)
1333 */ 1291 */
1334static const ulg crc_32_tab[] = { 1292static const ulg crc_32_tab[] = {
diff --git a/gzip.c b/gzip.c
index 76df3ad9a..3438ee42f 100644
--- a/gzip.c
+++ b/gzip.c
@@ -277,7 +277,8 @@ extern int save_orig_name; /* set if original name must be saved */
277#define WARN(msg) {if (!quiet) fprintf msg ; \ 277#define WARN(msg) {if (!quiet) fprintf msg ; \
278 if (exit_code == OK) exit_code = WARNING;} 278 if (exit_code == OK) exit_code = WARNING;}
279 279
280local void do_exit(int exitcode) __attribute__ ((noreturn)); 280#define do_exit(c) exit(c)
281
281 282
282 /* in zip.c: */ 283 /* in zip.c: */
283extern int zip OF((int in, int out)); 284extern int zip OF((int in, int out));
@@ -328,7 +329,6 @@ extern void warn OF((char *a, char *b));
328extern void read_error OF((void)); 329extern void read_error OF((void));
329extern void write_error OF((void)); 330extern void write_error OF((void));
330extern void display_ratio OF((long num, long den, FILE *file)); 331extern void display_ratio OF((long num, long den, FILE *file));
331extern voidp xmalloc OF((unsigned int size));
332 332
333 /* in inflate.c */ 333 /* in inflate.c */
334extern int inflate OF((void)); 334extern int inflate OF((void));
@@ -1912,29 +1912,6 @@ int gzip_main(int argc, char ** argv)
1912 do_exit(exit_code); 1912 do_exit(exit_code);
1913} 1913}
1914 1914
1915/* ========================================================================
1916 * Free all dynamically allocated variables and exit with the given code.
1917 */
1918local void do_exit(int exitcode)
1919{
1920 static int in_exit = 0;
1921
1922 if (in_exit) exit(exitcode);
1923 in_exit = 1;
1924 if (env != NULL) free(env), env = NULL;
1925 if (args != NULL) free((char*)args), args = NULL;
1926 FREE(inbuf);
1927 FREE(outbuf);
1928 FREE(d_buf);
1929 FREE(window);
1930#ifndef MAXSEG_64K
1931 FREE(tab_prefix);
1932#else
1933 FREE(tab_prefix0);
1934 FREE(tab_prefix1);
1935#endif
1936 exit(exitcode);
1937}
1938/* trees.c -- output deflated data using Huffman coding 1915/* trees.c -- output deflated data using Huffman coding
1939 * Copyright (C) 1992-1993 Jean-loup Gailly 1916 * Copyright (C) 1992-1993 Jean-loup Gailly
1940 * This is free software; you can redistribute it and/or modify it under the 1917 * This is free software; you can redistribute it and/or modify it under the
diff --git a/head.c b/head.c
index 4e58bdcd7..bc7f35429 100644
--- a/head.c
+++ b/head.c
@@ -61,7 +61,7 @@ head_main(int argc, char **argv)
61 switch (opt) { 61 switch (opt) {
62 case 'n': 62 case 'n':
63 tmplen = 0; 63 tmplen = 0;
64 if (i++ < argc) 64 if (++i < argc)
65 tmplen = atoi(argv[i]); 65 tmplen = atoi(argv[i]);
66 if (tmplen < 1) 66 if (tmplen < 1)
67 usage(head_usage); 67 usage(head_usage);
@@ -105,4 +105,4 @@ head_main(int argc, char **argv)
105 exit(0); 105 exit(0);
106} 106}
107 107
108/* $Id: head.c,v 1.5 2000/01/23 18:19:02 erik Exp $ */ 108/* $Id: head.c,v 1.6 2000/01/25 18:13:53 erik Exp $ */
diff --git a/init.c b/init.c
index b0a85829d..5b80cc561 100644
--- a/init.c
+++ b/init.c
@@ -488,9 +488,14 @@ static void shutdown_system(void)
488static void halt_signal(int sig) 488static void halt_signal(int sig)
489{ 489{
490 shutdown_system(); 490 shutdown_system();
491 message(CONSOLE, 491 message(CONSOLE, "The system is halted. Press %s or turn off power\r\n",
492 "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); 492 (secondConsole == NULL) /* serial console */
493 ? "Reset" : "CTRL-ALT-DEL");
493 sync(); 494 sync();
495
496 /* allow time for last message to reach serial console */
497 sleep(2);
498
494#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 499#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
495 if (sig == SIGUSR2) 500 if (sig == SIGUSR2)
496 reboot(RB_POWER_OFF); 501 reboot(RB_POWER_OFF);
@@ -505,6 +510,10 @@ static void reboot_signal(int sig)
505 shutdown_system(); 510 shutdown_system();
506 message(CONSOLE, "Please stand by while rebooting the system.\r\n"); 511 message(CONSOLE, "Please stand by while rebooting the system.\r\n");
507 sync(); 512 sync();
513
514 /* allow time for last message to reach serial console */
515 sleep(2);
516
508 reboot(RB_AUTOBOOT); 517 reboot(RB_AUTOBOOT);
509 exit(0); 518 exit(0);
510} 519}
@@ -580,7 +589,9 @@ static void check_chroot(int sig)
580 /* execute init in the (hopefully) new root */ 589 /* execute init in the (hopefully) new root */
581 execve("/sbin/init",argv_init,envp_init); 590 execve("/sbin/init",argv_init,envp_init);
582 591
583 message(CONSOLE, "ERROR: Could not exec new init. Hit ctrl+alt+delete to reboot.\r\n"); 592 message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
593 (secondConsole == NULL) /* serial console */
594 ? "Reset" : "CTRL-ALT-DEL");
584 return; 595 return;
585} 596}
586#endif /* BB_FEATURE_INIT_CHROOT */ 597#endif /* BB_FEATURE_INIT_CHROOT */
@@ -592,11 +603,14 @@ void new_initAction (initActionEnum action,
592{ 603{
593 initAction* newAction; 604 initAction* newAction;
594 605
606 if (*cons == '\0')
607 cons = console;
608
595 /* If BusyBox detects that a serial console is in use, 609 /* If BusyBox detects that a serial console is in use,
596 * then entries containing non-empty id fields will _not_ be run. 610 * then entries not refering to the console or null devices will _not_ be run.
597 * The exception to this rule is the null device. 611 * The exception to this rule is the null device.
598 */ 612 */
599 if (secondConsole == NULL && (*cons != '\0' || strncmp(cons, "null", 4))) 613 if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
600 return; 614 return;
601 615
602 newAction = calloc ((size_t)(1), sizeof(initAction)); 616 newAction = calloc ((size_t)(1), sizeof(initAction));
@@ -608,10 +622,7 @@ void new_initAction (initActionEnum action,
608 initActionList = newAction; 622 initActionList = newAction;
609 strncpy( newAction->process, process, 255); 623 strncpy( newAction->process, process, 255);
610 newAction->action = action; 624 newAction->action = action;
611 if (*cons != '\0') { 625 strncpy(newAction->console, cons, 255);
612 strncpy(newAction->console, cons, 255);
613 } else
614 strncpy(newAction->console, console, 255);
615 newAction->pid = 0; 626 newAction->pid = 0;
616// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", 627// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
617// newAction->process, newAction->action, newAction->console); 628// newAction->process, newAction->action, newAction->console);
@@ -620,9 +631,13 @@ void new_initAction (initActionEnum action,
620void delete_initAction (initAction *action) 631void delete_initAction (initAction *action)
621{ 632{
622 initAction *a, *b=NULL; 633 initAction *a, *b=NULL;
623 for( a=initActionList ; a; b=a, a=a->nextPtr) { 634 for( a=initActionList ; a ; b=a, a=a->nextPtr) {
624 if (a == action && b != NULL) { 635 if (a == action) {
625 b->nextPtr=a->nextPtr; 636 if (b==NULL) {
637 initActionList=a->nextPtr;
638 } else {
639 b->nextPtr=a->nextPtr;
640 }
626 free( a); 641 free( a);
627 break; 642 break;
628 } 643 }
@@ -805,8 +820,8 @@ extern int init_main(int argc, char **argv)
805 /* Ask first then start a shell on tty2 */ 820 /* Ask first then start a shell on tty2 */
806 if (secondConsole != NULL) 821 if (secondConsole != NULL)
807 new_initAction( ASKFIRST, SHELL, secondConsole); 822 new_initAction( ASKFIRST, SHELL, secondConsole);
808 /* Ask first then start a shell on tty1 */ 823 /* Start a shell on tty1 */
809 new_initAction( ASKFIRST, SHELL, console); 824 new_initAction( RESPAWN, SHELL, console);
810 } else { 825 } else {
811 /* Not in single user mode -- see what inittab says */ 826 /* Not in single user mode -- see what inittab says */
812 827
diff --git a/init/init.c b/init/init.c
index b0a85829d..5b80cc561 100644
--- a/init/init.c
+++ b/init/init.c
@@ -488,9 +488,14 @@ static void shutdown_system(void)
488static void halt_signal(int sig) 488static void halt_signal(int sig)
489{ 489{
490 shutdown_system(); 490 shutdown_system();
491 message(CONSOLE, 491 message(CONSOLE, "The system is halted. Press %s or turn off power\r\n",
492 "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); 492 (secondConsole == NULL) /* serial console */
493 ? "Reset" : "CTRL-ALT-DEL");
493 sync(); 494 sync();
495
496 /* allow time for last message to reach serial console */
497 sleep(2);
498
494#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 499#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
495 if (sig == SIGUSR2) 500 if (sig == SIGUSR2)
496 reboot(RB_POWER_OFF); 501 reboot(RB_POWER_OFF);
@@ -505,6 +510,10 @@ static void reboot_signal(int sig)
505 shutdown_system(); 510 shutdown_system();
506 message(CONSOLE, "Please stand by while rebooting the system.\r\n"); 511 message(CONSOLE, "Please stand by while rebooting the system.\r\n");
507 sync(); 512 sync();
513
514 /* allow time for last message to reach serial console */
515 sleep(2);
516
508 reboot(RB_AUTOBOOT); 517 reboot(RB_AUTOBOOT);
509 exit(0); 518 exit(0);
510} 519}
@@ -580,7 +589,9 @@ static void check_chroot(int sig)
580 /* execute init in the (hopefully) new root */ 589 /* execute init in the (hopefully) new root */
581 execve("/sbin/init",argv_init,envp_init); 590 execve("/sbin/init",argv_init,envp_init);
582 591
583 message(CONSOLE, "ERROR: Could not exec new init. Hit ctrl+alt+delete to reboot.\r\n"); 592 message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
593 (secondConsole == NULL) /* serial console */
594 ? "Reset" : "CTRL-ALT-DEL");
584 return; 595 return;
585} 596}
586#endif /* BB_FEATURE_INIT_CHROOT */ 597#endif /* BB_FEATURE_INIT_CHROOT */
@@ -592,11 +603,14 @@ void new_initAction (initActionEnum action,
592{ 603{
593 initAction* newAction; 604 initAction* newAction;
594 605
606 if (*cons == '\0')
607 cons = console;
608
595 /* If BusyBox detects that a serial console is in use, 609 /* If BusyBox detects that a serial console is in use,
596 * then entries containing non-empty id fields will _not_ be run. 610 * then entries not refering to the console or null devices will _not_ be run.
597 * The exception to this rule is the null device. 611 * The exception to this rule is the null device.
598 */ 612 */
599 if (secondConsole == NULL && (*cons != '\0' || strncmp(cons, "null", 4))) 613 if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
600 return; 614 return;
601 615
602 newAction = calloc ((size_t)(1), sizeof(initAction)); 616 newAction = calloc ((size_t)(1), sizeof(initAction));
@@ -608,10 +622,7 @@ void new_initAction (initActionEnum action,
608 initActionList = newAction; 622 initActionList = newAction;
609 strncpy( newAction->process, process, 255); 623 strncpy( newAction->process, process, 255);
610 newAction->action = action; 624 newAction->action = action;
611 if (*cons != '\0') { 625 strncpy(newAction->console, cons, 255);
612 strncpy(newAction->console, cons, 255);
613 } else
614 strncpy(newAction->console, console, 255);
615 newAction->pid = 0; 626 newAction->pid = 0;
616// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", 627// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
617// newAction->process, newAction->action, newAction->console); 628// newAction->process, newAction->action, newAction->console);
@@ -620,9 +631,13 @@ void new_initAction (initActionEnum action,
620void delete_initAction (initAction *action) 631void delete_initAction (initAction *action)
621{ 632{
622 initAction *a, *b=NULL; 633 initAction *a, *b=NULL;
623 for( a=initActionList ; a; b=a, a=a->nextPtr) { 634 for( a=initActionList ; a ; b=a, a=a->nextPtr) {
624 if (a == action && b != NULL) { 635 if (a == action) {
625 b->nextPtr=a->nextPtr; 636 if (b==NULL) {
637 initActionList=a->nextPtr;
638 } else {
639 b->nextPtr=a->nextPtr;
640 }
626 free( a); 641 free( a);
627 break; 642 break;
628 } 643 }
@@ -805,8 +820,8 @@ extern int init_main(int argc, char **argv)
805 /* Ask first then start a shell on tty2 */ 820 /* Ask first then start a shell on tty2 */
806 if (secondConsole != NULL) 821 if (secondConsole != NULL)
807 new_initAction( ASKFIRST, SHELL, secondConsole); 822 new_initAction( ASKFIRST, SHELL, secondConsole);
808 /* Ask first then start a shell on tty1 */ 823 /* Start a shell on tty1 */
809 new_initAction( ASKFIRST, SHELL, console); 824 new_initAction( RESPAWN, SHELL, console);
810 } else { 825 } else {
811 /* Not in single user mode -- see what inittab says */ 826 /* Not in single user mode -- see what inittab says */
812 827
diff --git a/internal.h b/internal.h
index b77feabad..500a63e62 100644
--- a/internal.h
+++ b/internal.h
@@ -175,6 +175,11 @@ extern int check_wildcard_match(const char* text, const char* pattern);
175extern long getNum (const char *cp); 175extern long getNum (const char *cp);
176extern pid_t findInitPid(); 176extern pid_t findInitPid();
177 177
178#if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL
179extern void *xmalloc (size_t size);
180extern void error(char *msg);
181#endif
182
178#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT) 183#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT)
179extern int vdprintf(int d, const char *format, va_list ap); 184extern int vdprintf(int d, const char *format, va_list ap);
180#endif 185#endif
diff --git a/printf.c b/printf.c
index 02d08118b..5be3a67cb 100644
--- a/printf.c
+++ b/printf.c
@@ -121,8 +121,6 @@
121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') 121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
122#define octtobin(c) ((c) - '0') 122#define octtobin(c) ((c) - '0')
123 123
124char *xmalloc ();
125
126static double xstrtod __P ((char *s)); 124static double xstrtod __P ((char *s));
127static int print_esc __P ((char *escstart)); 125static int print_esc __P ((char *escstart));
128static int print_formatted __P ((char *format, int argc, char **argv)); 126static int print_formatted __P ((char *format, int argc, char **argv));
diff --git a/tail.c b/tail.c
index 697177dc7..5198892b6 100644
--- a/tail.c
+++ b/tail.c
@@ -1,3 +1,402 @@
1#include "internal.h"
2/* This file contains _two_ implementations of tail. One is
3 * a bit more full featured, but costs 6k. The other (i.e. the
4 * SIMPLE_TAIL one) is less capable, but is good enough for about
5 * 99% of the things folks want to use tail for, and only costs 2k.
6 */
7
8
9#ifdef BB_FEATURE_SIMPLE_TAIL
10
11/* tail -- output the last part of file(s)
12 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2, or (at your option)
17 any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28 Original version by Paul Rubin <phr@ocf.berkeley.edu>.
29 Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
30 tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.
31
32 Rewrote the option parser, removed locales support,
33 and generally busyboxed, Erik Andersen <andersen@lineo.com>
34
35 Removed superfluous options and associated code ("-c", "-n", "-q").
36 Removed "tail -f" suport for multiple files.
37 Both changes by Friedrich Vedder <fwv@myrtle.lahn.de>.
38
39 */
40
41
42#include <stdio.h>
43#include <stdarg.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <fcntl.h>
47#include <ctype.h>
48
49
50#define XWRITE(fd, buffer, n_bytes) \
51 do { \
52 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
53 error("write error"); \
54 } while (0)
55
56/* Number of items to tail. */
57#define DEFAULT_N_LINES 10
58
59/* Size of atomic reads. */
60#ifndef BUFSIZ
61#define BUFSIZ (512 * 8)
62#endif
63
64/* If nonzero, read from the end of one file until killed. */
65static int forever;
66
67/* If nonzero, print filename headers. */
68static int print_headers;
69
70const char tail_usage[] =
71 "tail [OPTION] [FILE]...\n\n"
72 "Print last 10 lines of each FILE to standard output.\n"
73 "With more than one FILE, precede each with a header giving the\n"
74 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
75 "Options:\n"
76 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
77 "\t-f\t\tOutput data as the file grows. This version\n"
78 "\t\t\tof 'tail -f' supports only one file at a time.\n";
79
80
81static void write_header(const char *filename)
82{
83 static int first_file = 1;
84
85 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
86 first_file = 0;
87}
88
89/* Print the last N_LINES lines from the end of file FD.
90 Go backward through the file, reading `BUFSIZ' bytes at a time (except
91 probably the first), until we hit the start of the file or have
92 read NUMBER newlines.
93 POS starts out as the length of the file (the offset of the last
94 byte of the file + 1).
95 Return 0 if successful, 1 if an error occurred. */
96
97static int
98file_lines(const char *filename, int fd, long int n_lines, off_t pos)
99{
100 char buffer[BUFSIZ];
101 int bytes_read;
102 int i; /* Index into `buffer' for scanning. */
103
104 if (n_lines == 0)
105 return 0;
106
107 /* Set `bytes_read' to the size of the last, probably partial, buffer;
108 0 < `bytes_read' <= `BUFSIZ'. */
109 bytes_read = pos % BUFSIZ;
110 if (bytes_read == 0)
111 bytes_read = BUFSIZ;
112 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
113 reads will be on block boundaries, which might increase efficiency. */
114 pos -= bytes_read;
115 lseek(fd, pos, SEEK_SET);
116 bytes_read = fullRead(fd, buffer, bytes_read);
117 if (bytes_read == -1)
118 error("read error");
119
120 /* Count the incomplete line on files that don't end with a newline. */
121 if (bytes_read && buffer[bytes_read - 1] != '\n')
122 --n_lines;
123
124 do {
125 /* Scan backward, counting the newlines in this bufferfull. */
126 for (i = bytes_read - 1; i >= 0; i--) {
127 /* Have we counted the requested number of newlines yet? */
128 if (buffer[i] == '\n' && n_lines-- == 0) {
129 /* If this newline wasn't the last character in the buffer,
130 print the text after it. */
131 if (i != bytes_read - 1)
132 XWRITE(STDOUT_FILENO, &buffer[i + 1],
133 bytes_read - (i + 1));
134 return 0;
135 }
136 }
137 /* Not enough newlines in that bufferfull. */
138 if (pos == 0) {
139 /* Not enough lines in the file; print the entire file. */
140 lseek(fd, (off_t) 0, SEEK_SET);
141 return 0;
142 }
143 pos -= BUFSIZ;
144 lseek(fd, pos, SEEK_SET);
145 }
146 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
147 if (bytes_read == -1)
148 error("read error");
149
150 return 0;
151}
152
153/* Print the last N_LINES lines from the end of the standard input,
154 open for reading as pipe FD.
155 Buffer the text as a linked list of LBUFFERs, adding them as needed.
156 Return 0 if successful, 1 if an error occured. */
157
158static int pipe_lines(const char *filename, int fd, long int n_lines)
159{
160 struct linebuffer {
161 int nbytes, nlines;
162 char buffer[BUFSIZ];
163 struct linebuffer *next;
164 };
165 typedef struct linebuffer LBUFFER;
166 LBUFFER *first, *last, *tmp;
167 int i; /* Index into buffers. */
168 int total_lines = 0; /* Total number of newlines in all buffers. */
169 int errors = 0;
170
171 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
172 first->nbytes = first->nlines = 0;
173 first->next = NULL;
174 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
175
176 /* Input is always read into a fresh buffer. */
177 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
178 tmp->nlines = 0;
179 tmp->next = NULL;
180
181 /* Count the number of newlines just read. */
182 for (i = 0; i < tmp->nbytes; i++)
183 if (tmp->buffer[i] == '\n')
184 ++tmp->nlines;
185 total_lines += tmp->nlines;
186
187 /* If there is enough room in the last buffer read, just append the new
188 one to it. This is because when reading from a pipe, `nbytes' can
189 often be very small. */
190 if (tmp->nbytes + last->nbytes < BUFSIZ) {
191 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
192 last->nbytes += tmp->nbytes;
193 last->nlines += tmp->nlines;
194 } else {
195 /* If there's not enough room, link the new buffer onto the end of
196 the list, then either free up the oldest buffer for the next
197 read if that would leave enough lines, or else malloc a new one.
198 Some compaction mechanism is possible but probably not
199 worthwhile. */
200 last = last->next = tmp;
201 if (total_lines - first->nlines > n_lines) {
202 tmp = first;
203 total_lines -= first->nlines;
204 first = first->next;
205 } else
206 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
207 }
208 }
209 if (tmp->nbytes == -1)
210 error("read error");
211
212 free((char *) tmp);
213
214 /* This prevents a core dump when the pipe contains no newlines. */
215 if (n_lines == 0)
216 goto free_lbuffers;
217
218 /* Count the incomplete line on files that don't end with a newline. */
219 if (last->buffer[last->nbytes - 1] != '\n') {
220 ++last->nlines;
221 ++total_lines;
222 }
223
224 /* Run through the list, printing lines. First, skip over unneeded
225 buffers. */
226 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
227 total_lines -= tmp->nlines;
228
229 /* Find the correct beginning, then print the rest of the file. */
230 if (total_lines > n_lines) {
231 char *cp;
232
233 /* Skip `total_lines' - `n_lines' newlines. We made sure that
234 `total_lines' - `n_lines' <= `tmp->nlines'. */
235 cp = tmp->buffer;
236 for (i = total_lines - n_lines; i; --i)
237 while (*cp++ != '\n')
238 /* Do nothing. */ ;
239 i = cp - tmp->buffer;
240 } else
241 i = 0;
242 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
243
244 for (tmp = tmp->next; tmp; tmp = tmp->next)
245 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
246
247 free_lbuffers:
248 while (first) {
249 tmp = first->next;
250 free((char *) first);
251 first = tmp;
252 }
253 return errors;
254}
255
256/* Display file FILENAME from the current position in FD to the end.
257 If `forever' is nonzero, keep reading from the end of the file
258 until killed. Return the number of bytes read from the file. */
259
260static long dump_remainder(const char *filename, int fd)
261{
262 char buffer[BUFSIZ];
263 int bytes_read;
264 long total;
265
266 total = 0;
267 output:
268 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
269 XWRITE(STDOUT_FILENO, buffer, bytes_read);
270 total += bytes_read;
271 }
272 if (bytes_read == -1)
273 error("read error");
274 if (forever) {
275 fflush(stdout);
276 sleep(1);
277 goto output;
278 }
279
280 return total;
281}
282
283/* Output the last N_LINES lines of file FILENAME open for reading in FD.
284 Return 0 if successful, 1 if an error occurred. */
285
286static int tail_lines(const char *filename, int fd, long int n_lines)
287{
288 struct stat stats;
289 off_t length;
290
291 if (print_headers)
292 write_header(filename);
293
294 if (fstat(fd, &stats))
295 error("fstat error");
296
297 /* Use file_lines only if FD refers to a regular file with
298 its file pointer positioned at beginning of file. */
299 /* FIXME: adding the lseek conjunct is a kludge.
300 Once there's a reasonable test suite, fix the true culprit:
301 file_lines. file_lines shouldn't presume that the input
302 file pointer is initially positioned to beginning of file. */
303 if (S_ISREG(stats.st_mode)
304 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
305 length = lseek(fd, (off_t) 0, SEEK_END);
306 if (length != 0 && file_lines(filename, fd, n_lines, length))
307 return 1;
308 dump_remainder(filename, fd);
309 } else
310 return pipe_lines(filename, fd, n_lines);
311
312 return 0;
313}
314
315/* Display the last N_UNITS lines of file FILENAME.
316 "-" for FILENAME means the standard input.
317 Return 0 if successful, 1 if an error occurred. */
318
319static int tail_file(const char *filename, off_t n_units)
320{
321 int fd, errors;
322
323 if (!strcmp(filename, "-")) {
324 filename = "standard input";
325 errors = tail_lines(filename, 0, (long) n_units);
326 } else {
327 /* Not standard input. */
328 fd = open(filename, O_RDONLY);
329 if (fd == -1)
330 error("open error");
331
332 errors = tail_lines(filename, fd, (long) n_units);
333 close(fd);
334 }
335
336 return errors;
337}
338
339extern int tail_main(int argc, char **argv)
340{
341 int exit_status = 0;
342 int n_units = DEFAULT_N_LINES;
343 int n_tmp, i;
344 char opt;
345
346 forever = print_headers = 0;
347
348 /* parse argv[] */
349 for (i = 1; i < argc; i++) {
350 if (argv[i][0] == '-') {
351 opt = argv[i][1];
352 switch (opt) {
353 case 'f':
354 forever = 1;
355 break;
356 case 'n':
357 n_tmp = 0;
358 if (++i < argc)
359 n_tmp = atoi(argv[i]);
360 if (n_tmp < 1)
361 usage(tail_usage);
362 n_units = n_tmp;
363 break;
364 case '-':
365 case 'h':
366 usage(tail_usage);
367 default:
368 fprintf(stderr, "tail: invalid option -- %c\n", opt);
369 usage(tail_usage);
370 }
371 } else {
372 break;
373 }
374 }
375
376 if (i + 1 < argc) {
377 if (forever) {
378 fprintf(stderr,
379 "tail: option -f is invalid with multiple files\n");
380 usage(tail_usage);
381 }
382 print_headers = 1;
383 }
384
385 if (i >= argc) {
386 exit_status |= tail_file("-", n_units);
387 } else {
388 for (; i < argc; i++)
389 exit_status |= tail_file(argv[i], n_units);
390 }
391
392 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
393}
394
395
396#else
397// Here follows the code for the full featured tail code
398
399
1/* tail -- output the last part of file(s) 400/* tail -- output the last part of file(s)
2 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc. 401 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
3 402
@@ -42,7 +441,7 @@
42#define NDEBUG 1 441#define NDEBUG 1
43 442
44 443
45static void error(int i, int errnum, char* fmt, ...) 444static void detailed_error(int i, int errnum, char* fmt, ...)
46{ 445{
47 va_list arguments; 446 va_list arguments;
48 447
@@ -60,7 +459,7 @@ static void error(int i, int errnum, char* fmt, ...)
60 assert ((fd) == 1); \ 459 assert ((fd) == 1); \
61 assert ((n_bytes) >= 0); \ 460 assert ((n_bytes) >= 0); \
62 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ 461 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
63 error (EXIT_FAILURE, errno, "write error"); \ 462 detailed_error (EXIT_FAILURE, errno, "write error"); \
64 } \ 463 } \
65 while (0) 464 while (0)
66 465
@@ -100,8 +499,6 @@ enum header_mode
100 multiple_files, always, never 499 multiple_files, always, never
101}; 500};
102 501
103char *xmalloc ();
104
105/* The name this program was run with. */ 502/* The name this program was run with. */
106char *program_name; 503char *program_name;
107 504
@@ -168,7 +565,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
168 bytes_read = fullRead (fd, buffer, bytes_read); 565 bytes_read = fullRead (fd, buffer, bytes_read);
169 if (bytes_read == -1) 566 if (bytes_read == -1)
170 { 567 {
171 error (0, errno, "%s", filename); 568 detailed_error (0, errno, "%s", filename);
172 return 1; 569 return 1;
173 } 570 }
174 571
@@ -204,7 +601,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
204 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0); 601 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
205 if (bytes_read == -1) 602 if (bytes_read == -1)
206 { 603 {
207 error (0, errno, "%s", filename); 604 detailed_error (0, errno, "%s", filename);
208 return 1; 605 return 1;
209 } 606 }
210 return 0; 607 return 0;
@@ -276,7 +673,7 @@ pipe_lines (const char *filename, int fd, long int n_lines)
276 } 673 }
277 if (tmp->nbytes == -1) 674 if (tmp->nbytes == -1)
278 { 675 {
279 error (0, errno, "%s", filename); 676 detailed_error (0, errno, "%s", filename);
280 errors = 1; 677 errors = 1;
281 free ((char *) tmp); 678 free ((char *) tmp);
282 goto free_lbuffers; 679 goto free_lbuffers;
@@ -390,7 +787,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes)
390 } 787 }
391 if (tmp->nbytes == -1) 788 if (tmp->nbytes == -1)
392 { 789 {
393 error (0, errno, "%s", filename); 790 detailed_error (0, errno, "%s", filename);
394 errors = 1; 791 errors = 1;
395 free ((char *) tmp); 792 free ((char *) tmp);
396 goto free_cbuffers; 793 goto free_cbuffers;
@@ -438,7 +835,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes)
438 n_bytes -= bytes_read; 835 n_bytes -= bytes_read;
439 if (bytes_read == -1) 836 if (bytes_read == -1)
440 { 837 {
441 error (0, errno, "%s", filename); 838 detailed_error (0, errno, "%s", filename);
442 return 1; 839 return 1;
443 } 840 }
444 else if (n_bytes < 0) 841 else if (n_bytes < 0)
@@ -466,7 +863,7 @@ start_lines (const char *filename, int fd, long int n_lines)
466 } 863 }
467 if (bytes_read == -1) 864 if (bytes_read == -1)
468 { 865 {
469 error (0, errno, "%s", filename); 866 detailed_error (0, errno, "%s", filename);
470 return 1; 867 return 1;
471 } 868 }
472 else if (bytes_to_skip < bytes_read) 869 else if (bytes_to_skip < bytes_read)
@@ -496,7 +893,7 @@ output:
496 total += bytes_read; 893 total += bytes_read;
497 } 894 }
498 if (bytes_read == -1) 895 if (bytes_read == -1)
499 error (EXIT_FAILURE, errno, "%s", filename); 896 detailed_error (EXIT_FAILURE, errno, "%s", filename);
500 if (forever) 897 if (forever)
501 { 898 {
502 fflush (stdout); 899 fflush (stdout);
@@ -540,7 +937,7 @@ tail_forever (char **names, int nfiles)
540 continue; 937 continue;
541 if (fstat (file_descs[i], &stats) < 0) 938 if (fstat (file_descs[i], &stats) < 0)
542 { 939 {
543 error (0, errno, "%s", names[i]); 940 detailed_error (0, errno, "%s", names[i]);
544 file_descs[i] = -1; 941 file_descs[i] = -1;
545 continue; 942 continue;
546 } 943 }
@@ -590,7 +987,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
590 error, either. */ 987 error, either. */
591 if (fstat (fd, &stats)) 988 if (fstat (fd, &stats))
592 { 989 {
593 error (0, errno, "%s", filename); 990 detailed_error (0, errno, "%s", filename);
594 return 1; 991 return 1;
595 } 992 }
596 993
@@ -619,7 +1016,7 @@ tail_bytes (const char *filename, int fd, off_t n_bytes)
619 } 1016 }
620 else 1017 else
621 { 1018 {
622 error (0, errno, "%s", filename); 1019 detailed_error (0, errno, "%s", filename);
623 return 1; 1020 return 1;
624 } 1021 }
625 1022
@@ -656,7 +1053,7 @@ tail_lines (const char *filename, int fd, long int n_lines)
656 1053
657 if (fstat (fd, &stats)) 1054 if (fstat (fd, &stats))
658 { 1055 {
659 error (0, errno, "%s", filename); 1056 detailed_error (0, errno, "%s", filename);
660 return 1; 1057 return 1;
661 } 1058 }
662 1059
@@ -723,12 +1120,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
723 { 1120 {
724 if (fstat (0, &stats) < 0) 1121 if (fstat (0, &stats) < 0)
725 { 1122 {
726 error (0, errno, "standard input"); 1123 detailed_error (0, errno, "standard input");
727 errors = 1; 1124 errors = 1;
728 } 1125 }
729 else if (!S_ISREG (stats.st_mode)) 1126 else if (!S_ISREG (stats.st_mode))
730 { 1127 {
731 error (0, 0, 1128 detailed_error (0, 0,
732 "standard input: cannot follow end of non-regular file"); 1129 "standard input: cannot follow end of non-regular file");
733 errors = 1; 1130 errors = 1;
734 } 1131 }
@@ -749,7 +1146,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
749 { 1146 {
750 if (forever_multiple) 1147 if (forever_multiple)
751 file_descs[filenum] = -1; 1148 file_descs[filenum] = -1;
752 error (0, errno, "%s", filename); 1149 detailed_error (0, errno, "%s", filename);
753 errors = 1; 1150 errors = 1;
754 } 1151 }
755 else 1152 else
@@ -761,12 +1158,12 @@ tail_file (const char *filename, off_t n_units, int filenum)
761 { 1158 {
762 if (fstat (fd, &stats) < 0) 1159 if (fstat (fd, &stats) < 0)
763 { 1160 {
764 error (0, errno, "%s", filename); 1161 detailed_error (0, errno, "%s", filename);
765 errors = 1; 1162 errors = 1;
766 } 1163 }
767 else if (!S_ISREG (stats.st_mode)) 1164 else if (!S_ISREG (stats.st_mode))
768 { 1165 {
769 error (0, 0, "%s: cannot follow end of non-regular file", 1166 detailed_error (0, 0, "%s: cannot follow end of non-regular file",
770 filename); 1167 filename);
771 errors = 1; 1168 errors = 1;
772 } 1169 }
@@ -785,7 +1182,7 @@ tail_file (const char *filename, off_t n_units, int filenum)
785 { 1182 {
786 if (close (fd)) 1183 if (close (fd))
787 { 1184 {
788 error (0, errno, "%s", filename); 1185 detailed_error (0, errno, "%s", filename);
789 errors = 1; 1186 errors = 1;
790 } 1187 }
791 } 1188 }
@@ -903,8 +1300,11 @@ tail_main (int argc, char **argv)
903 } 1300 }
904 1301
905 if (have_read_stdin && close (0) < 0) 1302 if (have_read_stdin && close (0) < 0)
906 error (EXIT_FAILURE, errno, "-"); 1303 detailed_error (EXIT_FAILURE, errno, "-");
907 if (fclose (stdout) == EOF) 1304 if (fclose (stdout) == EOF)
908 error (EXIT_FAILURE, errno, "write error"); 1305 detailed_error (EXIT_FAILURE, errno, "write error");
909 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 1306 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
910} 1307}
1308
1309
1310#endif
diff --git a/utility.c b/utility.c
index 4b67ce9b7..8139f38d9 100644
--- a/utility.c
+++ b/utility.c
@@ -175,7 +175,7 @@ copyFile( const char *srcName, const char *destName,
175 } 175 }
176 } else if (S_ISFIFO(srcStatBuf.st_mode)) { 176 } else if (S_ISFIFO(srcStatBuf.st_mode)) {
177 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName); 177 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
178 if (mkfifo(destName, 644)) { 178 if (mkfifo(destName, 0644)) {
179 perror(destName); 179 perror(destName);
180 return (FALSE); 180 return (FALSE);
181 } 181 }
@@ -406,7 +406,6 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int depthFir
406 else 406 else
407 status = lstat(fileName, &statbuf); 407 status = lstat(fileName, &statbuf);
408 408
409 status = lstat(fileName, &statbuf);
410 if (status < 0) { 409 if (status < 0) {
411 perror(fileName); 410 perror(fileName);
412 return (FALSE); 411 return (FALSE);
@@ -1118,6 +1117,24 @@ findInitPid()
1118} 1117}
1119#endif 1118#endif
1120 1119
1120#if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL
1121extern void *xmalloc (size_t size)
1122{
1123 void *cp = malloc (size);
1124
1125 if (cp == NULL) {
1126 error("out of memory");
1127 }
1128 return cp;
1129}
1130
1131extern void error(char *msg)
1132{
1133 fprintf(stderr, "\n%s\n", msg);
1134 exit(1);
1135}
1136#endif
1137
1121#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT) 1138#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT)
1122extern int vdprintf(int d, const char *format, va_list ap) 1139extern int vdprintf(int d, const char *format, va_list ap)
1123{ 1140{