aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-11-25 23:50:28 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-11-25 23:50:28 +0000
commita0f78c266b49e283f862a642ede1cc1ed439162a (patch)
tree9e5d35d70aa35b0a06248c5d1189e8eb274083b0
parent4250ba3f536c66fa7caeb4e2a7110e69f69925de (diff)
downloadbusybox-w32-a0f78c266b49e283f862a642ede1cc1ed439162a.tar.gz
busybox-w32-a0f78c266b49e283f862a642ede1cc1ed439162a.tar.bz2
busybox-w32-a0f78c266b49e283f862a642ede1cc1ed439162a.zip
tee: fix bug: argv[-1] is a no-no!
bb_full_fd_action: optimize die_if_ferror: "<applet>: filename" isn't a good err msg, add "..I/O error" git-svn-id: svn://busybox.net/trunk/busybox@16669 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--coreutils/tee.c76
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/copyfd.c47
-rw-r--r--libbb/xfuncs.c4
4 files changed, 71 insertions, 58 deletions
diff --git a/coreutils/tee.c b/coreutils/tee.c
index 06c94aba6..640a231ef 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -17,67 +17,66 @@ int tee_main(int argc, char **argv)
17{ 17{
18 const char *mode = "w\0a"; 18 const char *mode = "w\0a";
19 FILE **files; 19 FILE **files;
20 FILE **p; 20 FILE **fp;
21 char **filenames; 21 char **names;
22 char **np;
22 int flags; 23 int flags;
23 int retval = EXIT_SUCCESS; 24 int retval = EXIT_SUCCESS;
24#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO 25#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
25 ssize_t c; 26 ssize_t c;
26# define buf bb_common_bufsiz1 27# define buf bb_common_bufsiz1
27#else 28#else
28 int c; 29 int c;
29#endif 30#endif
30
31 flags = getopt32(argc, argv, "ia"); /* 'a' must be 2nd */ 31 flags = getopt32(argc, argv, "ia"); /* 'a' must be 2nd */
32 argc -= optind;
33 argv += optind;
32 34
33 mode += (flags & 2); /* Since 'a' is the 2nd option... */ 35 mode += (flags & 2); /* Since 'a' is the 2nd option... */
34 36
35 if (flags & 1) { 37 if (flags & 1) {
36 signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction.*/ 38 signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. */
37 } 39 }
38
39 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe 40 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
40 * that doesn't consume all its input. Good idea... */ 41 * that doesn't consume all its input. Good idea... */
41 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/ 42 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction. */
42 43
43 /* Allocate an array of FILE *'s, with one extra for a sentinal. */ 44 /* Allocate an array of FILE *'s, with one extra for a sentinal. */
44 p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2)); 45 fp = files = xzalloc(sizeof(FILE *) * (argc + 2));
45 *p = stdout; 46 np = names = argv - 1;
46 argv += optind - 1;
47 filenames = argv - 1;
48 *filenames = (char *) bb_msg_standard_input; /* for later */
49 goto GOT_NEW_FILE;
50 47
48 files[0] = stdout;
49 goto GOT_NEW_FILE;
51 do { 50 do {
52 if ((*p = fopen_or_warn(*argv, mode)) == NULL) { 51 *fp = fopen_or_warn(*argv, mode);
52 if (*fp == NULL) {
53 retval = EXIT_FAILURE; 53 retval = EXIT_FAILURE;
54 continue; 54 continue;
55 } 55 }
56 filenames[(int)(p - files)] = *argv; 56 *np = *argv++;
57 GOT_NEW_FILE: 57 GOT_NEW_FILE:
58 setbuf(*p, NULL); /* tee must not buffer output. */ 58 setbuf(*fp++, NULL); /* tee must not buffer output. */
59 ++p; 59 np++;
60 } while (*++argv); 60 } while (*argv);
61 61 /* names[0] will be filled later */
62 *p = NULL; /* Store the sentinal value. */ 62
63 63#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
64#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
65 while ((c = safe_read(STDIN_FILENO, buf, BUFSIZ)) > 0) { 64 while ((c = safe_read(STDIN_FILENO, buf, BUFSIZ)) > 0) {
66 for (p=files ; *p ; p++) { 65 fp = files;
67 fwrite(buf, 1, c, *p); 66 do
68 } 67 fwrite(buf, 1, c, *fp++);
68 while (*fp);
69 } 69 }
70 70 if (c < 0) { /* Make sure read errors are signaled. */
71 if (c < 0) { /* Make sure read errors are signaled. */
72 retval = EXIT_FAILURE; 71 retval = EXIT_FAILURE;
73 } 72 }
74
75#else 73#else
76 setvbuf(stdout, NULL, _IONBF, 0); 74 setvbuf(stdout, NULL, _IONBF, 0);
77 while ((c = getchar()) != EOF) { 75 while ((c = getchar()) != EOF) {
78 for (p=files ; *p ; p++) { 76 fp = files;
79 putc(c, *p); 77 do
80 } 78 putc(c, *fp++);
79 while (*fp);
81 } 80 }
82#endif 81#endif
83 82
@@ -87,14 +86,15 @@ int tee_main(int argc, char **argv)
87 * setting the first entry to stdin and checking stdout error 86 * setting the first entry to stdin and checking stdout error
88 * status with fflush_stdout_and_exit()... although fflush()ing 87 * status with fflush_stdout_and_exit()... although fflush()ing
89 * is unnecessary here. */ 88 * is unnecessary here. */
90 89 np = names;
91 p = files; 90 fp = files;
92 *p = stdin; 91 names[0] = (char *) bb_msg_standard_input;
93 do { /* Now check for (input and) output errors. */ 92 files[0] = stdin;
93 do { /* Now check for input and output errors. */
94 /* Checking ferror should be sufficient, but we may want to fclose. 94 /* Checking ferror should be sufficient, but we may want to fclose.
95 * If we do, remember not to close stdin! */ 95 * If we do, remember not to close stdin! */
96 die_if_ferror(*p, filenames[(int)(p - files)]); 96 die_if_ferror(*fp++, *np++);
97 } while (*++p); 97 } while (*fp);
98 98
99 fflush_stdout_and_exit(retval); 99 fflush_stdout_and_exit(retval);
100} 100}
diff --git a/include/libbb.h b/include/libbb.h
index 5cba27932..61e379423 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -271,7 +271,7 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *sizep);
271 271
272extern ssize_t safe_write(int fd, const void *buf, size_t count); 272extern ssize_t safe_write(int fd, const void *buf, size_t count);
273extern ssize_t full_write(int fd, const void *buf, size_t count); 273extern ssize_t full_write(int fd, const void *buf, size_t count);
274extern void xwrite(int fd, void *buf, size_t count); 274extern void xwrite(int fd, const void *buf, size_t count);
275 275
276/* Reads and prints to stdout till eof, then closes FILE. Exits on error: */ 276/* Reads and prints to stdout till eof, then closes FILE. Exits on error: */
277extern void xprint_and_close_file(FILE *file); 277extern void xprint_and_close_file(FILE *file);
diff --git a/libbb/copyfd.c b/libbb/copyfd.c
index 601c51ce4..c6b886647 100644
--- a/libbb/copyfd.c
+++ b/libbb/copyfd.c
@@ -25,37 +25,50 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
25{ 25{
26 int status = -1; 26 int status = -1;
27 off_t total = 0; 27 off_t total = 0;
28 RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); 28 RESERVE_CONFIG_BUFFER(buffer, BUFSIZ);
29 29
30 if (src_fd < 0) goto out; 30 if (src_fd < 0) goto out;
31 while (!size || total < size) {
32 ssize_t wr, rd;
33 31
34 rd = safe_read(src_fd, buffer, 32 if (!size) {
35 (!size || size - total > BUFSIZ) ? BUFSIZ : size - total); 33 size = BUFSIZ;
34 status = 1; /* copy until eof */
35 }
36
37 while (1) {
38 ssize_t rd;
36 39
37 if (rd > 0) { 40 rd = safe_read(src_fd, buffer, size > BUFSIZ ? BUFSIZ : size);
38 /* A -1 dst_fd means we need to fake it... */ 41
39 wr = (dst_fd < 0) ? rd : full_write(dst_fd, buffer, rd); 42 if (!rd) { /* eof - all done. */
43 status = 0;
44 break;
45 }
46 if (rd < 0) {
47 bb_perror_msg(bb_msg_read_error);
48 break;
49 }
50 /* dst_fd == -1 is a fake, else... */
51 if (dst_fd >= 0) {
52 ssize_t wr = full_write(dst_fd, buffer, rd);
40 if (wr < rd) { 53 if (wr < rd) {
41 bb_perror_msg(bb_msg_write_error); 54 bb_perror_msg(bb_msg_write_error);
42 break; 55 break;
43 } 56 }
44 total += wr; 57 }
45 if (total == size) status = 0; 58 total += rd;
46 } else if (rd < 0) { 59 if (status < 0) {
47 bb_perror_msg(bb_msg_read_error); 60 size -= rd;
48 break; 61 if (!size) {
49 } else { /* eof - all done. */ 62 status = 0;
50 status = 0; 63 break;
51 break; 64 }
52 } 65 }
53 } 66 }
54 67
55out: 68out:
56 RELEASE_CONFIG_BUFFER(buffer); 69 RELEASE_CONFIG_BUFFER(buffer);
57 70
58 return status ? status : total; 71 return status ? -1 : total;
59} 72}
60 73
61 74
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 1dbd7521b..773e718b8 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -124,7 +124,7 @@ int ndelay_on(int fd)
124} 124}
125 125
126// Die with an error message if we can't write the entire buffer. 126// Die with an error message if we can't write the entire buffer.
127void xwrite(int fd, void *buf, size_t count) 127void xwrite(int fd, const void *buf, size_t count)
128{ 128{
129 if (count) { 129 if (count) {
130 ssize_t size = full_write(fd, buf, count); 130 ssize_t size = full_write(fd, buf, count);
@@ -146,7 +146,7 @@ off_t xlseek(int fd, off_t offset, int whence)
146void die_if_ferror(FILE *fp, const char *fn) 146void die_if_ferror(FILE *fp, const char *fn)
147{ 147{
148 if (ferror(fp)) { 148 if (ferror(fp)) {
149 bb_error_msg_and_die("%s", fn); 149 bb_error_msg_and_die("%s: I/O error", fn);
150 } 150 }
151} 151}
152 152