aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-01-09 23:00:00 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-01-09 23:00:00 +0000
commitde24bd960f3708e7aad013bd898b725fc13d15b2 (patch)
tree1ecf1b299dfdf02dbc26a4c84d95bf32fc49c328
parentd2c450ce811454fb77679d049538530d2cf54dd8 (diff)
downloadbusybox-w32-de24bd960f3708e7aad013bd898b725fc13d15b2.tar.gz
busybox-w32-de24bd960f3708e7aad013bd898b725fc13d15b2.tar.bz2
busybox-w32-de24bd960f3708e7aad013bd898b725fc13d15b2.zip
tac: handle NULs properly. +145 bytes
-rw-r--r--coreutils/tac.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/coreutils/tac.c b/coreutils/tac.c
index b1b47302f..7951be255 100644
--- a/coreutils/tac.c
+++ b/coreutils/tac.c
@@ -20,12 +20,17 @@
20 20
21/* This is a NOEXEC applet. Be very careful! */ 21/* This is a NOEXEC applet. Be very careful! */
22 22
23struct lstring {
24 int size;
25 char buf[];
26};
27
23int tac_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 28int tac_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
24int tac_main(int argc, char **argv) 29int tac_main(int argc, char **argv)
25{ 30{
26 char **name; 31 char **name;
27 FILE *f; 32 FILE *f;
28 char *line; 33 struct lstring *line = NULL;
29 llist_t *list = NULL; 34 llist_t *list = NULL;
30 int retval = EXIT_SUCCESS; 35 int retval = EXIT_SUCCESS;
31 36
@@ -38,6 +43,8 @@ int tac_main(int argc, char **argv)
38 name++; 43 name++;
39 44
40 do { 45 do {
46 int ch, i;
47
41 name--; 48 name--;
42 f = fopen_or_warn_stdin(*name); 49 f = fopen_or_warn_stdin(*name);
43 if (f == NULL) { 50 if (f == NULL) {
@@ -45,14 +52,26 @@ int tac_main(int argc, char **argv)
45 continue; 52 continue;
46 } 53 }
47 54
48 errno = 0; 55 errno = i = 0;
49 /* FIXME: NUL bytes are mishandled. */ 56 do {
50 while ((line = xmalloc_fgets(f)) != NULL) 57 ch = fgetc(f);
51 llist_add_to(&list, line); 58 if (ch != EOF) {
52 59 if (!(i & 0x7f))
53 /* xmalloc_fgets uses getc and returns NULL on error or EOF. */ 60 /* Grow on every 128th char */
54 /* It sets errno to ENOENT on EOF, but fopen_or_warn_stdin would */ 61 line = xrealloc(line, i + 0x7f + sizeof(int) + 1);
55 /* catch this error so we can filter it out here. */ 62 line->buf[i++] = ch;
63 }
64 if ((ch == '\n' || ch == EOF) && i) {
65 line = xrealloc(line, i + sizeof(int));
66 line->size = i;
67 llist_add_to(&list, line);
68 line = NULL;
69 i = 0;
70 }
71 } while (ch != EOF);
72 /* fgetc sets errno to ENOENT on EOF, but */
73 /* fopen_or_warn_stdin would catch this error */
74 /* so we can filter it out here. */
56 if (errno && errno != ENOENT) { 75 if (errno && errno != ENOENT) {
57 bb_simple_perror_msg(*name); 76 bb_simple_perror_msg(*name);
58 retval = EXIT_FAILURE; 77 retval = EXIT_FAILURE;
@@ -60,8 +79,13 @@ int tac_main(int argc, char **argv)
60 } while (name != argv); 79 } while (name != argv);
61 80
62 while (list) { 81 while (list) {
63 printf("%s", list->data); 82 line = (struct lstring *)list->data;
64 list = list->link; 83 xwrite(STDOUT_FILENO, line->buf, line->size);
84 if (ENABLE_FEATURE_CLEAN_UP) {
85 free(llist_pop(&list));
86 } else {
87 list = list->link;
88 }
65 } 89 }
66 90
67 return retval; 91 return retval;