summaryrefslogtreecommitdiff
path: root/coreutils/tee.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-11-25 23:50:28 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-11-25 23:50:28 +0000
commit2d27e4ccbbc29d6ec1b907849984cec30f24e734 (patch)
tree9e5d35d70aa35b0a06248c5d1189e8eb274083b0 /coreutils/tee.c
parent87cd4a87e3f98dd5a1b982cfdfc4dad6800ca010 (diff)
downloadbusybox-w32-2d27e4ccbbc29d6ec1b907849984cec30f24e734.tar.gz
busybox-w32-2d27e4ccbbc29d6ec1b907849984cec30f24e734.tar.bz2
busybox-w32-2d27e4ccbbc29d6ec1b907849984cec30f24e734.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"
Diffstat (limited to 'coreutils/tee.c')
-rw-r--r--coreutils/tee.c76
1 files changed, 38 insertions, 38 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}