aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authoraldot <aldot@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-08-28 23:31:54 +0000
committeraldot <aldot@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-08-28 23:31:54 +0000
commitd52f45a484fc7fc049ab40db9adc6ead7ea9b122 (patch)
tree2a57564b8917a983365c765d4daa83032d9f0a17 /coreutils
parent2803d256e9decd450b955c2846bf945db72bb79e (diff)
downloadbusybox-w32-d52f45a484fc7fc049ab40db9adc6ead7ea9b122.tar.gz
busybox-w32-d52f45a484fc7fc049ab40db9adc6ead7ea9b122.tar.bz2
busybox-w32-d52f45a484fc7fc049ab40db9adc6ead7ea9b122.zip
- pull from busybox_scratch: r15829:15850
Various fixes, cleanups and shrinkage: saves 952 Bytes: text data bss dec hex filename 1087742 15853 790632 1894227 1ce753 ../busybox/busybox.old 1086790 15853 790632 1893275 1ce39b busybox via: # scripts/bloat-o-meter ../busybox/busybox_unstripped.old busybox_unstripped function old new delta ipcrm_main 756 822 +66 getval - 61 +61 maybe_set_utc - 40 +40 udhcpc_main 2896 2912 +16 md5_hash_block 428 437 +9 opt 8 16 +8 qgravechar 106 110 +4 make_bitmap 292 295 +3 inflate_unzip 2056 2059 +3 add_partition 1412 1414 +2 __parsespent 156 158 +2 qrealloc 41 42 +1 format - 1 +1 catv_main 313 314 +1 watch_main 293 292 -1 varunset 81 80 -1 part 1 - -1 check_if_skip 837 836 -1 start_stop_daemon_main 840 837 -3 create_lost_and_found 175 172 -3 supress_non_delimited_lines 4 - -4 static.l 4 - -4 static.c 5 1 -4 bsd_sum_file 237 233 -4 eval2 338 332 -6 arithmetic_common 166 158 -8 cmpfunc 22 5 -17 cksum_main 294 275 -19 cmp_main 465 439 -26 dd_main 1535 1508 -27 rmmod_main 376 333 -43 cut_file 727 644 -83 ipcs_main 3809 3721 -88 cut_main 722 614 -108 date_main 1443 1263 -180 remove_ids 222 - -222 ------------------------------------------------------------------------------ (add/remove: 3/4 grow/shrink: 11/18 up/down: 217/-853) Total: -636 bytes git-svn-id: svn://busybox.net/trunk/busybox@16009 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/catv.c44
-rw-r--r--coreutils/cksum.c31
-rw-r--r--coreutils/cmp.c47
-rw-r--r--coreutils/cut.c479
-rw-r--r--coreutils/date.c260
-rw-r--r--coreutils/dd.c128
-rw-r--r--coreutils/du.c9
-rw-r--r--coreutils/expr.c406
-rw-r--r--coreutils/sum.c21
-rw-r--r--coreutils/tail.c21
-rw-r--r--coreutils/tee.c3
-rw-r--r--coreutils/watch.c21
12 files changed, 703 insertions, 767 deletions
diff --git a/coreutils/catv.c b/coreutils/catv.c
index e18203915..f8229c20e 100644
--- a/coreutils/catv.c
+++ b/coreutils/catv.c
@@ -14,49 +14,55 @@
14 14
15int catv_main(int argc, char **argv) 15int catv_main(int argc, char **argv)
16{ 16{
17 int retval = EXIT_SUCCESS, fd, flags; 17 int retval = EXIT_SUCCESS, fd;
18 unsigned long flags;
18 19
19 flags = bb_getopt_ulflags(argc, argv, "etv"); 20 flags = bb_getopt_ulflags(argc, argv, "etv");
20 flags ^= 4; 21#define CATV_OPT_e (1<<0)
21 22#define CATV_OPT_t (1<<1)
22 // Loop through files. 23#define CATV_OPT_v (1<<2)
24 flags ^= CATV_OPT_v;
23 25
24 argv += optind; 26 argv += optind;
25 do { 27 do {
26 // Read from stdin if there's nothing else to do. 28 /* Read from stdin if there's nothing else to do. */
27
28 fd = 0; 29 fd = 0;
29 if (*argv && 0>(fd = xopen(*argv, O_RDONLY))) retval = EXIT_FAILURE; 30 if (*argv && 0 > (fd = xopen(*argv, O_RDONLY)))
30 else for(;;) { 31 retval = EXIT_FAILURE;
32 else for (;;) {
31 int i, res; 33 int i, res;
32 34
33 res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1)); 35 res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1));
34 if (res < 0) retval = EXIT_FAILURE; 36 if (res < 0)
35 if (res <1) break; 37 retval = EXIT_FAILURE;
36 for (i=0; i<res; i++) { 38 if (res < 1)
37 char c=bb_common_bufsiz1[i]; 39 break;
40 for (i = 0; i < res; i++) {
41 char c = bb_common_bufsiz1[i];
38 42
39 if (c > 126 && (flags & 4)) { 43 if (c > 126 && (flags & CATV_OPT_v)) {
40 if (c == 127) { 44 if (c == 127) {
41 printf("^?"); 45 bb_printf("^?");
42 continue; 46 continue;
43 } else { 47 } else {
44 printf("M-"); 48 bb_printf("M-");
45 c -= 128; 49 c -= 128;
46 } 50 }
47 } 51 }
48 if (c < 32) { 52 if (c < 32) {
49 if (c == 10) { 53 if (c == 10) {
50 if (flags & 1) putchar('$'); 54 if (flags & CATV_OPT_e)
51 } else if (flags & (c==9 ? 2 : 4)) { 55 putchar('$');
52 printf("^%c", c+'@'); 56 } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
57 bb_printf("^%c", c+'@');
53 continue; 58 continue;
54 } 59 }
55 } 60 }
56 putchar(c); 61 putchar(c);
57 } 62 }
58 } 63 }
59 if (ENABLE_FEATURE_CLEAN_UP && fd) close(fd); 64 if (ENABLE_FEATURE_CLEAN_UP && fd)
65 close(fd);
60 } while (*++argv); 66 } while (*++argv);
61 67
62 return retval; 68 return retval;
diff --git a/coreutils/cksum.c b/coreutils/cksum.c
index 5849ddab2..9a45fd656 100644
--- a/coreutils/cksum.c
+++ b/coreutils/cksum.c
@@ -3,12 +3,13 @@
3 * cksum - calculate the CRC32 checksum of a file 3 * cksum - calculate the CRC32 checksum of a file
4 * 4 *
5 * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms 5 * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */
8 8
9#include "busybox.h" 9#include "busybox.h"
10 10
11int cksum_main(int argc, char **argv) { 11int cksum_main(int argc, char **argv)
12{
12 13
13 uint32_t *crc32_table = crc32_filltable(1); 14 uint32_t *crc32_table = crc32_filltable(1);
14 15
@@ -17,36 +18,36 @@ int cksum_main(int argc, char **argv) {
17 long length, filesize; 18 long length, filesize;
18 int bytes_read; 19 int bytes_read;
19 char *cp; 20 char *cp;
20 RESERVE_CONFIG_BUFFER(buf, BUFSIZ); 21
21 int inp_stdin = (argc == optind) ? 1 : 0; 22 int inp_stdin = (argc == optind) ? 1 : 0;
22 23
23 do { 24 do {
24 fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv); 25 fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv);
25 26
26 crc = 0; 27 crc = 0;
27 length = 0; 28 length = 0;
28 29
29 while ((bytes_read = fread(buf, 1, BUFSIZ, fp)) > 0) { 30 while ((bytes_read = fread(bb_common_bufsiz1, 1, BUFSIZ, fp)) > 0) {
30 cp = buf; 31 cp = bb_common_bufsiz1;
31 length += bytes_read; 32 length += bytes_read;
32 while (bytes_read--) 33 while (bytes_read--)
33 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL]; 34 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL];
34 } 35 }
35 36
36 filesize = length; 37 filesize = length;
37 38
38 for (; length; length >>= 8) 39 for (; length; length >>= 8)
39 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL]; 40 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL];
40 crc ^= 0xffffffffL; 41 crc ^= 0xffffffffL;
41 42
42 if (inp_stdin) { 43 if (inp_stdin) {
43 printf("%"PRIu32" %li\n", crc, filesize); 44 bb_printf("%" PRIu32 " %li\n", crc, filesize);
44 break; 45 break;
45 } 46 }
46 47
47 printf("%"PRIu32" %li %s\n", crc, filesize, *argv); 48 bb_printf("%" PRIu32 " %li %s\n", crc, filesize, *argv);
48 fclose(fp); 49 fclose(fp);
49 } while (*(argv+1)); 50 } while (*(argv + 1));
50 51
51 return EXIT_SUCCESS; 52 return EXIT_SUCCESS;
52} 53}
diff --git a/coreutils/cmp.c b/coreutils/cmp.c
index a569eb3fe..ae3f50279 100644
--- a/coreutils/cmp.c
+++ b/coreutils/cmp.c
@@ -23,7 +23,7 @@
23 23
24#include "busybox.h" 24#include "busybox.h"
25 25
26static FILE *cmp_xfopen_input(const char *filename) 26static FILE *cmp_xfopen_input(const char * const filename)
27{ 27{
28 FILE *fp; 28 FILE *fp;
29 29
@@ -40,32 +40,28 @@ static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
40static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n"; 40static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n";
41 41
42static const char opt_chars[] = "sl"; 42static const char opt_chars[] = "sl";
43 43#define CMP_OPT_s (1<<0)
44enum { 44#define CMP_OPT_l (1<<1)
45 OPT_s = 1,
46 OPT_l = 2
47};
48 45
49int cmp_main(int argc, char **argv) 46int cmp_main(int argc, char **argv)
50{ 47{
51 FILE *fp1, *fp2, *outfile = stdout; 48 FILE *fp1, *fp2, *outfile = stdout;
52 const char *filename1, *filename2; 49 const char *filename1, *filename2 = "-";
53 const char *fmt; 50 const char *fmt;
54 int c1, c2, char_pos, line_pos; 51 int c1, c2, char_pos = 0, line_pos = 1;
55 int opt_flags; 52 unsigned opt;
56 int exit_val = 0; 53 int retval = 0;
57 54
58 bb_default_error_retval = 2; /* 1 is returned if files are different. */ 55 bb_default_error_retval = 2; /* 1 is returned if files are different. */
59 56
60 opt_flags = bb_getopt_ulflags(argc, argv, opt_chars); 57 opt = bb_getopt_ulflags(argc, argv, opt_chars);
61 58
62 if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) { 59 if ((opt & (CMP_OPT_s|CMP_OPT_l))
60 || (((unsigned int)(--argc - optind)) > 1))
63 bb_show_usage(); 61 bb_show_usage();
64 }
65 62
66 fp1 = cmp_xfopen_input(filename1 = *(argv += optind)); 63 fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
67 64
68 filename2 = "-";
69 if (*++argv) { 65 if (*++argv) {
70 filename2 = *argv; 66 filename2 = *argv;
71 } 67 }
@@ -79,19 +75,17 @@ int cmp_main(int argc, char **argv)
79 return 0; 75 return 0;
80 } 76 }
81 77
82 fmt = fmt_differ; 78 if (opt & CMP_OPT_l)
83 if (opt_flags == OPT_l) {
84 fmt = fmt_l_opt; 79 fmt = fmt_l_opt;
85 } 80 else
81 fmt = fmt_differ;
86 82
87 char_pos = 0;
88 line_pos = 1;
89 do { 83 do {
90 c1 = getc(fp1); 84 c1 = getc(fp1);
91 c2 = getc(fp2); 85 c2 = getc(fp2);
92 ++char_pos; 86 ++char_pos;
93 if (c1 != c2) { /* Remember -- a read error may have occurred. */ 87 if (c1 != c2) { /* Remember: a read error may have occurred. */
94 exit_val = 1; /* But assume the files are different for now. */ 88 retval = 1; /* But assume the files are different for now. */
95 if (c2 == EOF) { 89 if (c2 == EOF) {
96 /* We know that fp1 isn't at EOF or in an error state. But to 90 /* We know that fp1 isn't at EOF or in an error state. But to
97 * save space below, things are setup to expect an EOF in fp1 91 * save space below, things are setup to expect an EOF in fp1
@@ -109,13 +103,14 @@ int cmp_main(int argc, char **argv)
109 * make sure we fflush before writing to stderr. */ 103 * make sure we fflush before writing to stderr. */
110 xfflush_stdout(); 104 xfflush_stdout();
111 } 105 }
112 if (opt_flags != OPT_s) { 106 if (!opt & CMP_OPT_s) {
113 if (opt_flags == OPT_l) { 107 if (opt & CMP_OPT_l) {
114 line_pos = c1; /* line_pos is unused in the -l case. */ 108 line_pos = c1; /* line_pos is unused in the -l case. */
115 } 109 }
116 bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2); 110 bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
117 if (opt_flags) { /* This must be -l since not -s. */ 111 if (opt) { /* This must be -l since not -s. */
118 /* If we encountered and EOF, the while check will catch it. */ 112 /* If we encountered an EOF,
113 * the while check will catch it. */
119 continue; 114 continue;
120 } 115 }
121 } 116 }
@@ -129,5 +124,5 @@ int cmp_main(int argc, char **argv)
129 xferror(fp1, filename1); 124 xferror(fp1, filename1);
130 xferror(fp2, filename2); 125 xferror(fp2, filename2);
131 126
132 bb_fflush_stdout_and_exit(exit_val); 127 bb_fflush_stdout_and_exit(retval);
133} 128}
diff --git a/coreutils/cut.c b/coreutils/cut.c
index 1b80e7e73..d88a891b0 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -4,28 +4,24 @@
4 * 4 *
5 * Copyright (C) 1999,2000,2001 by Lineo, inc. 5 * Copyright (C) 1999,2000,2001 by Lineo, inc.
6 * Written by Mark Whitley <markw@codepoet.org> 6 * Written by Mark Whitley <markw@codepoet.org>
7 * debloated by Bernhard Fischer
7 * 8 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */ 10 */
10 11
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <string.h>
15#include <limits.h>
16#include "busybox.h" 12#include "busybox.h"
17 13
18
19/* option vars */ 14/* option vars */
20static const char optstring[] = "b:c:f:d:sn"; 15static const char *const optstring = "b:c:f:d:sn";
21#define OPT_BYTE_FLGS 1 16
22#define OPT_CHAR_FLGS 2 17#define CUT_OPT_BYTE_FLGS (1<<0)
23#define OPT_FIELDS_FLGS 4 18#define CUT_OPT_CHAR_FLGS (1<<1)
24#define OPT_DELIM_FLGS 8 19#define CUT_OPT_FIELDS_FLGS (1<<2)
25#define OPT_SUPRESS_FLGS 16 20#define CUT_OPT_DELIM_FLGS (1<<3)
26static char part; /* (b)yte, (c)har, (f)ields */ 21#define CUT_OPT_SUPPRESS_FLGS (1<<4)
27static unsigned int supress_non_delimited_lines; 22static unsigned long opt;
28static char delim = '\t'; /* delimiter, default is tab */ 23
24static char delim = '\t'; /* delimiter, default is tab */
29 25
30struct cut_list { 26struct cut_list {
31 int startpos; 27 int startpos;
@@ -38,295 +34,268 @@ enum {
38 NON_RANGE = -1 34 NON_RANGE = -1
39}; 35};
40 36
41static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */ 37/* growable array holding a series of lists */
42static unsigned int nlists = 0; /* number of elements in above list */ 38static struct cut_list *cut_lists;
39static unsigned int nlists; /* number of elements in above list */
43 40
44 41
45static int cmpfunc(const void *a, const void *b) 42static int cmpfunc(const void *a, const void *b)
46{ 43{
47 struct cut_list *la = (struct cut_list *)a; 44 return (((struct cut_list *) a)->startpos -
48 struct cut_list *lb = (struct cut_list *)b; 45 ((struct cut_list *) b)->startpos);
49
50 if (la->startpos > lb->startpos)
51 return 1;
52 if (la->startpos < lb->startpos)
53 return -1;
54 return 0;
55}
56 46
47}
57 48
58/* 49static void cut_file(FILE * file)
59 * parse_lists() - parses a list and puts values into startpos and endpos.
60 * valid list formats: N, N-, N-M, -M
61 * more than one list can be separated by commas
62 */
63static void parse_lists(char *lists)
64{ 50{
65 char *ltok = NULL; 51 char *line = NULL;
66 char *ntok = NULL; 52 unsigned int linenum = 0; /* keep these zero-based to be consistent */
67 char *junk;
68 int s = 0, e = 0;
69
70 /* take apart the lists, one by one (they are separated with commas */
71 while ((ltok = strsep(&lists, ",")) != NULL) {
72
73 /* it's actually legal to pass an empty list */
74 if (strlen(ltok) == 0)
75 continue;
76
77 /* get the start pos */
78 ntok = strsep(&ltok, "-");
79 if (ntok == NULL) {
80 fprintf(stderr, "Help ntok is null for starting position! What do I do?\n");
81 } else if (strlen(ntok) == 0) {
82 s = BOL;
83 } else {
84 s = strtoul(ntok, &junk, 10);
85 if(*junk != '\0' || s < 0)
86 bb_error_msg_and_die("invalid byte or field list");
87
88 /* account for the fact that arrays are zero based, while the user
89 * expects the first char on the line to be char # 1 */
90 if (s != 0)
91 s--;
92 }
93
94 /* get the end pos */
95 ntok = strsep(&ltok, "-");
96 if (ntok == NULL) {
97 e = NON_RANGE;
98 } else if (strlen(ntok) == 0) {
99 e = EOL;
100 } else {
101 e = strtoul(ntok, &junk, 10);
102 if(*junk != '\0' || e < 0)
103 bb_error_msg_and_die("invalid byte or field list");
104 /* if the user specified and end position of 0, that means "til the
105 * end of the line */
106 if (e == 0)
107 e = INT_MAX;
108 e--; /* again, arrays are zero based, lines are 1 based */
109 if (e == s)
110 e = NON_RANGE;
111 }
112
113 /* if there's something left to tokenize, the user past an invalid list */
114 if (ltok)
115 bb_error_msg_and_die("invalid byte or field list");
116
117 /* add the new list */
118 cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
119 cut_lists[nlists-1].startpos = s;
120 cut_lists[nlists-1].endpos = e;
121 }
122
123 /* make sure we got some cut positions out of all that */
124 if (nlists == 0)
125 bb_error_msg_and_die("missing list of positions");
126
127 /* now that the lists are parsed, we need to sort them to make life easier
128 * on us when it comes time to print the chars / fields / lines */
129 qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
130 53
131} 54 /* go through every line in the file */
55 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
132 56
57 /* set up a list so we can keep track of what's been printed */
58 char * printed = xzalloc(strlen(line) * sizeof(char));
59 char * orig_line = line;
60 unsigned int cl_pos = 0;
61 int spos;
133 62
134static void cut_line_by_chars(const char *line) 63 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
135{ 64 if ((opt & (CUT_OPT_CHAR_FLGS | CUT_OPT_BYTE_FLGS))) {
136 int c, l; 65 /* print the chars specified in each cut list */
137 /* set up a list so we can keep track of what's been printed */ 66 for (; cl_pos < nlists; cl_pos++) {
138 char *printed = xzalloc(strlen(line)); 67 spos = cut_lists[cl_pos].startpos;
139 68 while (spos < strlen(line)) {
140 /* print the chars specified in each cut list */ 69 if (!printed[spos]) {
141 for (c = 0; c < nlists; c++) { 70 printed[spos] = 'X';
142 l = cut_lists[c].startpos; 71 putchar(line[spos]);
143 while (l < strlen(line)) { 72 }
144 if (!printed[l]) { 73 spos++;
145 putchar(line[l]); 74 if (spos > cut_lists[cl_pos].endpos
146 printed[l] = 'X'; 75 || cut_lists[cl_pos].endpos == NON_RANGE)
76 break;
77 }
78 }
79 } else if (delim == '\n') { /* cut by lines */
80 spos = cut_lists[cl_pos].startpos;
81
82 /* get out if we have no more lists to process or if the lines
83 * are lower than what we're interested in */
84 if (linenum < spos || cl_pos >= nlists)
85 goto next_line;
86
87 /* if the line we're looking for is lower than the one we were
88 * passed, it means we displayed it already, so move on */
89 while (spos < linenum) {
90 spos++;
91 /* go to the next list if we're at the end of this one */
92 if (spos > cut_lists[cl_pos].endpos
93 || cut_lists[cl_pos].endpos == NON_RANGE) {
94 cl_pos++;
95 /* get out if there's no more lists to process */
96 if (cl_pos >= nlists)
97 goto next_line;
98 spos = cut_lists[cl_pos].startpos;
99 /* get out if the current line is lower than the one
100 * we just became interested in */
101 if (linenum < spos)
102 goto next_line;
103 }
147 } 104 }
148 l++;
149 if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos)
150 break;
151 }
152 }
153 putchar('\n'); /* cuz we were handed a chomped line */
154 free(printed);
155}
156
157 105
158static void cut_line_by_fields(char *line) 106 /* If we made it here, it means we've found the line we're
159{ 107 * looking for, so print it */
160 int c, f;
161 int ndelim = -1; /* zero-based / one-based problem */
162 int nfields_printed = 0;
163 char *field = NULL;
164 char d[2] = { delim, 0 };
165 char *printed;
166
167 /* test the easy case first: does this line contain any delimiters? */
168 if (strchr(line, delim) == NULL) {
169 if (!supress_non_delimited_lines)
170 puts(line); 108 puts(line);
171 return; 109 goto next_line;
172 } 110 } else { /* cut by fields */
173 111 int ndelim = -1; /* zero-based / one-based problem */
174 /* set up a list so we can keep track of what's been printed */ 112 int nfields_printed = 0;
175 printed = xzalloc(strlen(line)); 113 char *field = NULL;
176 114 const char delimiter[2] = { delim, 0 };
177 /* process each list on this line, for as long as we've got a line to process */ 115
178 for (c = 0; c < nlists && line; c++) { 116 /* does this line contain any delimiters? */
179 f = cut_lists[c].startpos; 117 if (strchr(line, delim) == NULL) {
180 do { 118 if (!(opt & CUT_OPT_SUPPRESS_FLGS))
181 119 puts(line);
182 /* find the field we're looking for */ 120 goto next_line;
183 while (line && ndelim < f) {
184 field = strsep(&line, d);
185 ndelim++;
186 } 121 }
187 122
188 /* we found it, and it hasn't been printed yet */ 123 /* process each list on this line, for as long as we've got
189 if (field && ndelim == f && !printed[ndelim]) { 124 * a line to process */
190 /* if this isn't our first time through, we need to print the 125 for (; cl_pos < nlists && line; cl_pos++) {
191 * delimiter after the last field that was printed */ 126 spos = cut_lists[cl_pos].startpos;
192 if (nfields_printed > 0) 127 do {
193 putchar(delim); 128
194 fputs(field, stdout); 129 /* find the field we're looking for */
195 printed[ndelim] = 'X'; 130 while (line && ndelim < spos) {
196 nfields_printed++; 131 field = strsep(&line, delimiter);
132 ndelim++;
133 }
134
135 /* we found it, and it hasn't been printed yet */
136 if (field && ndelim == spos && !printed[ndelim]) {
137 /* if this isn't our first time through, we need to
138 * print the delimiter after the last field that was
139 * printed */
140 if (nfields_printed > 0)
141 putchar(delim);
142 fputs(field, stdout);
143 printed[ndelim] = 'X';
144 nfields_printed++; /* shouldn't overflow.. */
145 }
146
147 spos++;
148
149 /* keep going as long as we have a line to work with,
150 * this is a list, and we're not at the end of that
151 * list */
152 } while (spos <= cut_lists[cl_pos].endpos && line
153 && cut_lists[cl_pos].endpos != NON_RANGE);
197 } 154 }
198
199 f++;
200
201 /* keep going as long as we have a line to work with, this is a
202 * list, and we're not at the end of that list */
203 } while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos);
204 }
205
206 /* if we printed anything at all, we need to finish it with a newline cuz
207 * we were handed a chomped line */
208 putchar('\n');
209
210 free(printed);
211}
212
213
214static void cut_file_by_lines(const char *line, unsigned int linenum)
215{
216 static int c = 0;
217 static int l = -1;
218
219 /* I can't initialize this above cuz the "initializer isn't
220 * constant" *sigh* */
221 if (l == -1)
222 l = cut_lists[c].startpos;
223
224 /* get out if we have no more lists to process or if the lines are lower
225 * than what we're interested in */
226 if (c >= nlists || linenum < l)
227 return;
228
229 /* if the line we're looking for is lower than the one we were passed, it
230 * means we displayed it already, so move on */
231 while (l < linenum) {
232 l++;
233 /* move on to the next list if we're at the end of this one */
234 if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) {
235 c++;
236 /* get out if there's no more lists to process */
237 if (c >= nlists)
238 return;
239 l = cut_lists[c].startpos;
240 /* get out if the current line is lower than the one we just became
241 * interested in */
242 if (linenum < l)
243 return;
244 } 155 }
156 /* if we printed anything at all, we need to finish it with a
157 * newline cuz we were handed a chomped line */
158 putchar('\n');
159 next_line:
160 linenum++;
161 free(printed);
162 free(orig_line);
245 } 163 }
246
247 /* If we made it here, it means we've found the line we're looking for, so print it */
248 puts(line);
249} 164}
250 165
251 166static int getval(char *ntok)
252/*
253 * snippy-snip
254 */
255static void cut_file(FILE *file)
256{ 167{
257 char *line = NULL; 168 char *junk;
258 unsigned int linenum = 0; /* keep these zero-based to be consistent */ 169 int i = strtoul(ntok, &junk, 10);
259
260 /* go through every line in the file */
261 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
262
263 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
264 if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS)))
265 cut_line_by_chars(line);
266
267 /* cut based on fields */
268 else {
269 if (delim == '\n')
270 cut_file_by_lines(line, linenum);
271 else
272 cut_line_by_fields(line);
273 }
274 170
275 linenum++; 171 if (*junk != '\0' || i < 0)
276 free(line); 172 bb_error_msg_and_die("invalid byte or field list");
277 } 173 return i;
278} 174}
279 175
176static const char * const _op_on_field = " only when operating on fields";
280 177
281int cut_main(int argc, char **argv) 178int cut_main(int argc, char **argv)
282{ 179{
283 unsigned long opt; 180 char *sopt, *ltok;
284 char *sopt, *sdopt;
285 181
286 bb_opt_complementally = "b--bcf:c--bcf:f--bcf"; 182 bb_opt_complementally = "b--bcf:c--bcf:f--bcf";
287 opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt); 183 opt =
288 part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); 184 bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &ltok);
289 if(part == 0) 185 if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS)))
290 bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); 186 bb_error_msg_and_die
291 if(opt & BB_GETOPT_ERROR) 187 ("expected a list of bytes, characters, or fields");
188 if (opt & BB_GETOPT_ERROR)
292 bb_error_msg_and_die("only one type of list may be specified"); 189 bb_error_msg_and_die("only one type of list may be specified");
293 parse_lists(sopt); 190
294 if((opt & (OPT_DELIM_FLGS))) { 191 if ((opt & (CUT_OPT_DELIM_FLGS))) {
295 if (strlen(sdopt) > 1) { 192 if (strlen(ltok) > 1) {
296 bb_error_msg_and_die("the delimiter must be a single character"); 193 bb_error_msg_and_die("the delimiter must be a single character");
297 } 194 }
298 delim = sdopt[0]; 195 delim = ltok[0];
299 } 196 }
300 supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS;
301 197
302 /* non-field (char or byte) cutting has some special handling */ 198 /* non-field (char or byte) cutting has some special handling */
303 if (part != OPT_FIELDS_FLGS) { 199 if (!(opt & CUT_OPT_FIELDS_FLGS)) {
304 if (supress_non_delimited_lines) { 200 if (opt & CUT_OPT_SUPPRESS_FLGS) {
305 bb_error_msg_and_die("suppressing non-delimited lines makes sense" 201 bb_error_msg_and_die
306 " only when operating on fields"); 202 ("suppressing non-delimited lines makes sense%s",
203 _op_on_field);
307 } 204 }
308 if (delim != '\t') { 205 if (delim != '\t') {
309 bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); 206 bb_error_msg_and_die
207 ("a delimiter may be specified%s", _op_on_field);
310 } 208 }
311 } 209 }
312 210
211 /*
212 * parse list and put values into startpos and endpos.
213 * valid list formats: N, N-, N-M, -M
214 * more than one list can be separated by commas
215 */
216 {
217 char *ntok;
218 int s = 0, e = 0;
219
220 /* take apart the lists, one by one (they are separated with commas */
221 while ((ltok = strsep(&sopt, ",")) != NULL) {
222
223 /* it's actually legal to pass an empty list */
224 if (strlen(ltok) == 0)
225 continue;
226
227 /* get the start pos */
228 ntok = strsep(&ltok, "-");
229 if (ntok == NULL) {
230 bb_error_msg
231 ("internal error: ntok is null for start pos!?\n");
232 } else if (strlen(ntok) == 0) {
233 s = BOL;
234 } else {
235 s = getval(ntok);
236 /* account for the fact that arrays are zero based, while
237 * the user expects the first char on the line to be char #1 */
238 if (s != 0)
239 s--;
240 }
241
242 /* get the end pos */
243 ntok = strsep(&ltok, "-");
244 if (ntok == NULL) {
245 e = NON_RANGE;
246 } else if (strlen(ntok) == 0) {
247 e = EOL;
248 } else {
249 e = getval(ntok);
250 /* if the user specified and end position of 0, that means "til the
251 * end of the line */
252 if (e == 0)
253 e = EOL;
254 e--; /* again, arrays are zero based, lines are 1 based */
255 if (e == s)
256 e = NON_RANGE;
257 }
258
259 /* if there's something left to tokenize, the user passed
260 * an invalid list */
261 if (ltok)
262 bb_error_msg_and_die("invalid byte or field list");
263
264 /* add the new list */
265 cut_lists =
266 xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
267 cut_lists[nlists - 1].startpos = s;
268 cut_lists[nlists - 1].endpos = e;
269 }
270
271 /* make sure we got some cut positions out of all that */
272 if (nlists == 0)
273 bb_error_msg_and_die("missing list of positions");
274
275 /* now that the lists are parsed, we need to sort them to make life
276 * easier on us when it comes time to print the chars / fields / lines
277 */
278 qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
279 }
280
313 /* argv[(optind)..(argc-1)] should be names of file to process. If no 281 /* argv[(optind)..(argc-1)] should be names of file to process. If no
314 * files were specified or '-' was specified, take input from stdin. 282 * files were specified or '-' was specified, take input from stdin.
315 * Otherwise, we process all the files specified. */ 283 * Otherwise, we process all the files specified. */
316 if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { 284 if (argv[optind] == NULL
285 || (argv[optind][0] == '-' && argv[optind][1] == '\0')) {
317 cut_file(stdin); 286 cut_file(stdin);
318 } 287 } else {
319 else {
320 int i;
321 FILE *file; 288 FILE *file;
322 for (i = optind; i < argc; i++) { 289
323 file = bb_wfopen(argv[i], "r"); 290 for (; optind < argc; optind++) {
324 if(file) { 291 file = bb_wfopen(argv[optind], "r");
292 if (file) {
325 cut_file(file); 293 cut_file(file);
326 fclose(file); 294 fclose(file);
327 } 295 }
328 } 296 }
329 } 297 }
330 298 if (ENABLE_FEATURE_CLEAN_UP)
299 free(cut_lists);
331 return EXIT_SUCCESS; 300 return EXIT_SUCCESS;
332} 301}
diff --git a/coreutils/date.c b/coreutils/date.c
index f08392ec2..2a82e0413 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -5,14 +5,17 @@
5 * by Matthew Grant <grantma@anathoth.gen.nz> 5 * by Matthew Grant <grantma@anathoth.gen.nz>
6 * 6 *
7 * iso-format handling added by Robert Griebl <griebl@gmx.de> 7 * iso-format handling added by Robert Griebl <griebl@gmx.de>
8 * bugfixes and cleanup by Bernhard Fischer
8 * 9 *
9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
10*/ 11*/
11 12
13#include "busybox.h"
14
12/* This 'date' command supports only 2 time setting formats, 15/* This 'date' command supports only 2 time setting formats,
13 all the GNU strftime stuff (its in libc, lets use it), 16 all the GNU strftime stuff (its in libc, lets use it),
14 setting time using UTC and displaying int, as well as 17 setting time using UTC and displaying it, as well as
15 an RFC 822 complient date output for shell scripting 18 an RFC 2822 compliant date output for shell scripting
16 mail commands */ 19 mail commands */
17 20
18/* Input parsing code is always bulky - used heavy duty libc stuff as 21/* Input parsing code is always bulky - used heavy duty libc stuff as
@@ -20,13 +23,6 @@
20 23
21/* Default input handling to save surprising some people */ 24/* Default input handling to save surprising some people */
22 25
23#include <stdlib.h>
24#include <errno.h>
25#include <unistd.h>
26#include <time.h>
27#include <stdio.h>
28#include <string.h>
29#include "busybox.h"
30 26
31#define DATE_OPT_RFC2822 0x01 27#define DATE_OPT_RFC2822 0x01
32#define DATE_OPT_SET 0x02 28#define DATE_OPT_SET 0x02
@@ -36,119 +32,45 @@
36#define DATE_OPT_TIMESPEC 0x20 32#define DATE_OPT_TIMESPEC 0x20
37#define DATE_OPT_HINT 0x40 33#define DATE_OPT_HINT 0x40
38 34
39 35static void maybe_set_utc(int opt)
40static struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
41{
42 int nr;
43 char *cp;
44
45 nr = sscanf(t_string, "%2d%2d%2d%2d%d", &(tm_time->tm_mon),
46 &(tm_time->tm_mday), &(tm_time->tm_hour), &(tm_time->tm_min),
47 &(tm_time->tm_year));
48
49 if (nr < 4 || nr > 5) {
50 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
51 }
52
53 cp = strchr(t_string, '.');
54 if (cp) {
55 nr = sscanf(cp + 1, "%2d", &(tm_time->tm_sec));
56 if (nr != 1) {
57 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
58 }
59 }
60
61 /* correct for century - minor Y2K problem here? */
62 if (tm_time->tm_year >= 1900) {
63 tm_time->tm_year -= 1900;
64 }
65 /* adjust date */
66 tm_time->tm_mon -= 1;
67
68 return (tm_time);
69
70}
71
72
73/* The new stuff for LRP */
74
75static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
76{ 36{
77 struct tm t; 37 if ((opt & DATE_OPT_UTC) && putenv("TZ=UTC0") != 0)
78 38 bb_error_msg_and_die(bb_msg_memory_exhausted);
79 /* Parse input and assign appropriately to tm_time */
80
81 if (t = *tm_time, sscanf(t_string, "%d:%d:%d", &t.tm_hour, &t.tm_min,
82 &t.tm_sec) == 3) {
83 /* no adjustments needed */
84 } else if (t = *tm_time, sscanf(t_string, "%d:%d", &t.tm_hour,
85 &t.tm_min) == 2) {
86 /* no adjustments needed */
87 } else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d:%d", &t.tm_mon,
88 &t.tm_mday, &t.tm_hour,
89 &t.tm_min, &t.tm_sec) == 5) {
90 /* Adjust dates from 1-12 to 0-11 */
91 t.tm_mon -= 1;
92 } else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d", &t.tm_mon,
93 &t.tm_mday,
94 &t.tm_hour, &t.tm_min) == 4) {
95 /* Adjust dates from 1-12 to 0-11 */
96 t.tm_mon -= 1;
97 } else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d:%d", &t.tm_year,
98 &t.tm_mon, &t.tm_mday,
99 &t.tm_hour, &t.tm_min,
100 &t.tm_sec) == 6) {
101 t.tm_year -= 1900; /* Adjust years */
102 t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
103 } else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d", &t.tm_year,
104 &t.tm_mon, &t.tm_mday,
105 &t.tm_hour, &t.tm_min) == 5) {
106 t.tm_year -= 1900; /* Adjust years */
107 t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
108 } else {
109 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
110 }
111 *tm_time = t;
112 return (tm_time);
113} 39}
114 40
115int date_main(int argc, char **argv) 41int date_main(int argc, char **argv)
116{ 42{
117 char *date_str = NULL;
118 char *date_fmt = NULL;
119 int set_time;
120 int utc;
121 time_t tm; 43 time_t tm;
122 unsigned long opt;
123 struct tm tm_time; 44 struct tm tm_time;
45 unsigned long opt;
46 int ifmt = -1;
47 char *date_str = NULL;
48 char *date_fmt = NULL;
124 char *filename = NULL; 49 char *filename = NULL;
125
126 int ifmt = 0;
127 char *isofmt_arg; 50 char *isofmt_arg;
128 char *hintfmt_arg; 51 char *hintfmt_arg;
129 52
130 bb_opt_complementally = "?:d--s:s--d"; 53 bb_opt_complementally = "?:d--s:s--d"
54 USE_FEATURE_DATE_ISOFMT(":R--I:I--R");
131 opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" 55 opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:"
132 USE_FEATURE_DATE_ISOFMT("I::D:"), 56 USE_FEATURE_DATE_ISOFMT("I::D:"),
133 &date_str, &date_str, &filename 57 &date_str, &date_str, &filename
134 USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg)); 58 USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg));
135 set_time = opt & DATE_OPT_SET; 59 maybe_set_utc(opt);
136 utc = opt & DATE_OPT_UTC;
137 if (utc && putenv("TZ=UTC0") != 0) {
138 bb_error_msg_and_die(bb_msg_memory_exhausted);
139 }
140 60
141 if(ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) { 61 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) {
142 if (!isofmt_arg) { 62 if (!isofmt_arg) {
143 ifmt = 1; 63 ifmt = 0; /* default is date */
144 } else { 64 } else {
145 char *isoformats[]={"date","hours","minutes","seconds"}; 65 const char * const isoformats[] =
146 for(ifmt = 4; ifmt;) 66 {"date", "hours", "minutes", "seconds"};
147 if(!strcmp(isofmt_arg,isoformats[--ifmt])) 67
68 for (ifmt = 0; ifmt < 4; ifmt++)
69 if (!strcmp(isofmt_arg, isoformats[ifmt])) {
148 break; 70 break;
149 } 71 }
150 if (!ifmt) { 72 if (ifmt == 4) /* parse error */
151 bb_show_usage(); 73 bb_show_usage();
152 } 74 }
153 } 75 }
154 76
@@ -156,18 +78,19 @@ int date_main(int argc, char **argv)
156 if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { 78 if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) {
157 date_fmt = &argv[optind][1]; /* Skip over the '+' */ 79 date_fmt = &argv[optind][1]; /* Skip over the '+' */
158 } else if (date_str == NULL) { 80 } else if (date_str == NULL) {
159 set_time = 1; 81 opt |= DATE_OPT_SET;
160 date_str = argv[optind]; 82 date_str = argv[optind];
161 } 83 }
162 84
163 /* Now we have parsed all the information except the date format 85 /* Now we have parsed all the information except the date format
164 which depends on whether the clock is being set or read */ 86 which depends on whether the clock is being set or read */
165 87
166 if(filename) { 88 if (filename) {
167 struct stat statbuf; 89 struct stat statbuf;
168 xstat(filename,&statbuf); 90 xstat(filename, &statbuf);
169 tm=statbuf.st_mtime; 91 tm = statbuf.st_mtime;
170 } else time(&tm); 92 } else
93 time(&tm);
171 memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); 94 memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
172 /* Zero out fields - take her back to midnight! */ 95 /* Zero out fields - take her back to midnight! */
173 if (date_str != NULL) { 96 if (date_str != NULL) {
@@ -179,9 +102,64 @@ int date_main(int argc, char **argv)
179 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) { 102 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) {
180 strptime(date_str, hintfmt_arg, &tm_time); 103 strptime(date_str, hintfmt_arg, &tm_time);
181 } else if (strchr(date_str, ':') != NULL) { 104 } else if (strchr(date_str, ':') != NULL) {
182 date_conv_ftime(&tm_time, date_str); 105 /* Parse input and assign appropriately to tm_time */
106
107 if (sscanf(date_str, "%d:%d:%d", &tm_time.tm_hour, &tm_time.tm_min,
108 &tm_time.tm_sec) == 3) {
109 /* no adjustments needed */
110 } else if (sscanf(date_str, "%d:%d", &tm_time.tm_hour,
111 &tm_time.tm_min) == 2) {
112 /* no adjustments needed */
113 } else if (sscanf(date_str, "%d.%d-%d:%d:%d", &tm_time.tm_mon,
114 &tm_time.tm_mday, &tm_time.tm_hour,
115 &tm_time.tm_min, &tm_time.tm_sec) == 5) {
116 /* Adjust dates from 1-12 to 0-11 */
117 tm_time.tm_mon -= 1;
118 } else if (sscanf(date_str, "%d.%d-%d:%d", &tm_time.tm_mon,
119 &tm_time.tm_mday,
120 &tm_time.tm_hour, &tm_time.tm_min) == 4) {
121 /* Adjust dates from 1-12 to 0-11 */
122 tm_time.tm_mon -= 1;
123 } else if (sscanf(date_str, "%d.%d.%d-%d:%d:%d", &tm_time.tm_year,
124 &tm_time.tm_mon, &tm_time.tm_mday,
125 &tm_time.tm_hour, &tm_time.tm_min,
126 &tm_time.tm_sec) == 6) {
127 tm_time.tm_year -= 1900; /* Adjust years */
128 tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
129 } else if (sscanf(date_str, "%d.%d.%d-%d:%d", &tm_time.tm_year,
130 &tm_time.tm_mon, &tm_time.tm_mday,
131 &tm_time.tm_hour, &tm_time.tm_min) == 5) {
132 tm_time.tm_year -= 1900; /* Adjust years */
133 tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
134 } else {
135 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
136 }
183 } else { 137 } else {
184 date_conv_time(&tm_time, date_str); 138 int nr;
139 char *cp;
140
141 nr = sscanf(date_str, "%2d%2d%2d%2d%d", &tm_time.tm_mon,
142 &tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min,
143 &tm_time.tm_year);
144
145 if (nr < 4 || nr > 5) {
146 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
147 }
148
149 cp = strchr(date_str, '.');
150 if (cp) {
151 nr = sscanf(cp + 1, "%2d", &tm_time.tm_sec);
152 if (nr != 1) {
153 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
154 }
155 }
156
157 /* correct for century - minor Y2K problem here? */
158 if (tm_time.tm_year >= 1900) {
159 tm_time.tm_year -= 1900;
160 }
161 /* adjust date */
162 tm_time.tm_mon -= 1;
185 } 163 }
186 164
187 /* Correct any day of week and day of year etc. fields */ 165 /* Correct any day of week and day of year etc. fields */
@@ -190,12 +168,10 @@ int date_main(int argc, char **argv)
190 if (tm < 0) { 168 if (tm < 0) {
191 bb_error_msg_and_die(bb_msg_invalid_date, date_str); 169 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
192 } 170 }
193 if (utc && putenv("TZ=UTC0") != 0) { 171 maybe_set_utc(opt);
194 bb_error_msg_and_die(bb_msg_memory_exhausted);
195 }
196 172
197 /* if setting time, set it */ 173 /* if setting time, set it */
198 if (set_time && stime(&tm) < 0) { 174 if ((opt & DATE_OPT_SET) && stime(&tm) < 0) {
199 bb_perror_msg("cannot set date"); 175 bb_perror_msg("cannot set date");
200 } 176 }
201 } 177 }
@@ -203,33 +179,43 @@ int date_main(int argc, char **argv)
203 /* Display output */ 179 /* Display output */
204 180
205 /* Deal with format string */ 181 /* Deal with format string */
182
206 if (date_fmt == NULL) { 183 if (date_fmt == NULL) {
207 /* Start with the default case */ 184 int i;
208 185 date_fmt = xzalloc(32);
209 date_fmt = (opt & DATE_OPT_RFC2822 ? 186 if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) {
210 (utc ? "%a, %d %b %Y %H:%M:%S GMT" : 187 strcpy(date_fmt, "%Y-%m-%d");
211 "%a, %d %b %Y %H:%M:%S %z") : 188 if (ifmt > 0) {
212 "%a %b %e %H:%M:%S %Z %Y"); 189 i = 8;
213 190 date_fmt[i++] = 'T';
214 if (ENABLE_FEATURE_DATE_ISOFMT) { 191 date_fmt[i++] = '%';
215 if (ifmt == 4) 192 date_fmt[i++] = 'H';
216 date_fmt = utc ? "%Y-%m-%dT%H:%M:%SZ" : "%Y-%m-%dT%H:%M:%S%z"; 193 if (ifmt > 1) {
217 else if (ifmt == 3) 194 date_fmt[i++] = ':';
218 date_fmt = utc ? "%Y-%m-%dT%H:%MZ" : "%Y-%m-%dT%H:%M%z"; 195 date_fmt[i++] = '%';
219 else if (ifmt == 2) 196 date_fmt[i++] = 'M';
220 date_fmt = utc ? "%Y-%m-%dT%HZ" : "%Y-%m-%dT%H%z"; 197 }
221 else if (ifmt == 1) 198 if (ifmt > 2) {
222 date_fmt = "%Y-%m-%d"; 199 date_fmt[i++] = ':';
223 } 200 date_fmt[i++] = '%';
201 date_fmt[i++] = 'S';
202 }
203format_utc:
204 date_fmt[i++] = '%';
205 date_fmt[i] = (opt & DATE_OPT_UTC) ? 'Z' : 'z';
206 }
207 } else if (opt & DATE_OPT_RFC2822) {
208 strcpy(date_fmt, "%a, %d %b %Y %H:%M:%S ");
209 i = 22;
210 goto format_utc;
211 } else /* default case */
212 date_fmt = "%a %b %e %H:%M:%S %Z %Y";
224 } 213 }
225
226 if (*date_fmt == '\0') {
227 214
215 if (*date_fmt == '\0') {
228 /* With no format string, just print a blank line */ 216 /* With no format string, just print a blank line */
229 217 *bb_common_bufsiz1 = 0;
230 *bb_common_bufsiz1=0;
231 } else { 218 } else {
232
233 /* Handle special conversions */ 219 /* Handle special conversions */
234 220
235 if (strncmp(date_fmt, "%f", 2) == 0) { 221 if (strncmp(date_fmt, "%f", 2) == 0) {
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 052cd2902..a9536a584 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include "busybox.h" 11#include "busybox.h"
12#include <signal.h> /* For FEATURE_DD_SIGNAL_HANDLING */
12 13
13static const struct suffix_mult dd_suffixes[] = { 14static const struct suffix_mult dd_suffixes[] = {
14 { "c", 1 }, 15 { "c", 1 },
@@ -23,72 +24,72 @@ static const struct suffix_mult dd_suffixes[] = {
23 { NULL, 0 } 24 { NULL, 0 }
24}; 25};
25 26
26static size_t out_full; 27static size_t out_full, out_part, in_full, in_part;
27static size_t out_part;
28static size_t in_full;
29static size_t in_part;
30 28
31static void dd_output_status(int cur_signal) 29static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
32{ 30{
33 fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n", 31 bb_fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
34 (long)in_full, (long)in_part, 32 (long)in_full, (long)in_part,
35 (long)out_full, (long)out_part); 33 (long)out_full, (long)out_part);
36} 34}
37 35
38int dd_main(int argc, char **argv) 36int dd_main(int argc, char **argv)
39{ 37{
38#define sync_flag (1<<0)
39#define noerror (1<<1)
40#define trunc_flag (1<<2)
41#define twobufs_flag (1<<3)
42 int flags = trunc_flag;
40 size_t count = -1, oc = 0, ibs = 512, obs = 512; 43 size_t count = -1, oc = 0, ibs = 512, obs = 512;
41 ssize_t n; 44 ssize_t n;
42 off_t seek = 0, skip = 0; 45 off_t seek = 0, skip = 0;
43 int sync_flag = FALSE, noerror = FALSE, trunc_flag = TRUE, twobufs_flag = 0, 46 int oflag, ifd, ofd;
44 oflag, ifd, ofd, i;
45 const char *infile = NULL, *outfile = NULL; 47 const char *infile = NULL, *outfile = NULL;
46 char *ibuf, *obuf; 48 char *ibuf, *obuf;
47 49
48 if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) 50 if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) {
49 {
50 struct sigaction sa; 51 struct sigaction sa;
51 52
52 memset(&sa, 0, sizeof(sa)); 53 memset(&sa, 0, sizeof(sa));
53 sa.sa_handler = dd_output_status; 54 sa.sa_handler = dd_output_status;
54 sa.sa_flags = SA_RESTART; 55 sa.sa_flags = SA_RESTART;
55 sigemptyset(&sa.sa_mask); 56 sigemptyset(&sa.sa_mask);
56 sigaction(SIGUSR1, &sa, 0); 57 sigaction(SIGUSR1, &sa, 0);
57 } 58 }
58 59
59 for (i = 1; i < argc; i++) { 60 for (n = 1; n < argc; n++) {
60 if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[i], 4)) { 61 if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[n], 4)) {
61 ibs = bb_xparse_number(argv[i]+4, dd_suffixes); 62 ibs = bb_xparse_number(argv[n]+4, dd_suffixes);
62 twobufs_flag++; 63 flags |= twobufs_flag;
63 } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[i], 4)) { 64 } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[n], 4)) {
64 obs = bb_xparse_number(argv[i]+4, dd_suffixes); 65 obs = bb_xparse_number(argv[n]+4, dd_suffixes);
65 twobufs_flag++; 66 flags |= twobufs_flag;
66 } else if (!strncmp("bs=", argv[i], 3)) { 67 } else if (!strncmp("bs=", argv[n], 3))
67 ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes); 68 ibs = obs = bb_xparse_number(argv[n]+3, dd_suffixes);
68 } else if (!strncmp("count=", argv[i], 6)) 69 else if (!strncmp("count=", argv[n], 6))
69 count = bb_xparse_number(argv[i]+6, dd_suffixes); 70 count = bb_xparse_number(argv[n]+6, dd_suffixes);
70 else if (!strncmp("seek=", argv[i], 5)) 71 else if (!strncmp("seek=", argv[n], 5))
71 seek = bb_xparse_number(argv[i]+5, dd_suffixes); 72 seek = bb_xparse_number(argv[n]+5, dd_suffixes);
72 else if (!strncmp("skip=", argv[i], 5)) 73 else if (!strncmp("skip=", argv[n], 5))
73 skip = bb_xparse_number(argv[i]+5, dd_suffixes); 74 skip = bb_xparse_number(argv[n]+5, dd_suffixes);
74 else if (!strncmp("if=", argv[i], 3)) 75 else if (!strncmp("if=", argv[n], 3))
75 infile = argv[i]+3; 76 infile = argv[n]+3;
76 else if (!strncmp("of=", argv[i], 3)) 77 else if (!strncmp("of=", argv[n], 3))
77 outfile = argv[i]+3; 78 outfile = argv[n]+3;
78 else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[i], 5)) { 79 else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[n], 5)) {
79 ibuf = argv[i]+5; 80 ibuf = argv[n]+5;
80 while (1) { 81 while (1) {
81 if (!strncmp("notrunc", ibuf, 7)) { 82 if (!strncmp("notrunc", ibuf, 7)) {
82 trunc_flag = FALSE; 83 flags ^= trunc_flag;
83 ibuf += 7; 84 ibuf += 7;
84 } else if (!strncmp("sync", ibuf, 4)) { 85 } else if (!strncmp("sync", ibuf, 4)) {
85 sync_flag = TRUE; 86 flags |= sync_flag;
86 ibuf += 4; 87 ibuf += 4;
87 } else if (!strncmp("noerror", ibuf, 7)) { 88 } else if (!strncmp("noerror", ibuf, 7)) {
88 noerror = TRUE; 89 flags |= noerror;
89 ibuf += 7; 90 ibuf += 7;
90 } else { 91 } else {
91 bb_error_msg_and_die(bb_msg_invalid_arg, argv[i]+5, "conv"); 92 bb_error_msg_and_die(bb_msg_invalid_arg, argv[n]+5, "conv");
92 } 93 }
93 if (ibuf[0] == '\0') break; 94 if (ibuf[0] == '\0') break;
94 if (ibuf[0] == ',') ibuf++; 95 if (ibuf[0] == ',') ibuf++;
@@ -98,12 +99,14 @@ int dd_main(int argc, char **argv)
98 } 99 }
99 ibuf = xmalloc(ibs); 100 ibuf = xmalloc(ibs);
100 101
101 if (twobufs_flag) obuf = xmalloc(obs); 102 if (flags & twobufs_flag)
102 else obuf = ibuf; 103 obuf = xmalloc(obs);
104 else
105 obuf = ibuf;
103 106
104 if (infile != NULL) { 107 if (infile != NULL)
105 ifd = xopen(infile, O_RDONLY); 108 ifd = xopen(infile, O_RDONLY);
106 } else { 109 else {
107 ifd = STDIN_FILENO; 110 ifd = STDIN_FILENO;
108 infile = bb_msg_standard_input; 111 infile = bb_msg_standard_input;
109 } 112 }
@@ -111,20 +114,18 @@ int dd_main(int argc, char **argv)
111 if (outfile != NULL) { 114 if (outfile != NULL) {
112 oflag = O_WRONLY | O_CREAT; 115 oflag = O_WRONLY | O_CREAT;
113 116
114 if (!seek && trunc_flag) { 117 if (!seek && (flags & trunc_flag))
115 oflag |= O_TRUNC; 118 oflag |= O_TRUNC;
116 }
117 119
118 ofd = xopen3(outfile, oflag, 0666); 120 ofd = xopen3(outfile, oflag, 0666);
119 121
120 if (seek && trunc_flag) { 122 if (seek && (flags & trunc_flag)) {
121 if (ftruncate(ofd, seek * obs) < 0) { 123 if (ftruncate(ofd, seek * obs) < 0) {
122 struct stat st; 124 struct stat st;
123 125
124 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || 126 if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) ||
125 S_ISDIR (st.st_mode)) { 127 S_ISDIR(st.st_mode))
126 bb_perror_msg_and_die("%s", outfile); 128 goto die_outfile;
127 }
128 } 129 }
129 } 130 }
130 } else { 131 } else {
@@ -145,44 +146,42 @@ int dd_main(int argc, char **argv)
145 } 146 }
146 147
147 if (seek) { 148 if (seek) {
148 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) { 149 if (lseek(ofd, seek * obs, SEEK_CUR) < 0)
149 bb_perror_msg_and_die("%s", outfile); 150 goto die_outfile;
150 }
151 } 151 }
152 152
153 while (in_full + in_part != count) { 153 while (in_full + in_part != count) {
154 if (noerror) { 154 if (flags & noerror) {
155 /* Pre-zero the buffer when doing the noerror thing */ 155 /* Pre-zero the buffer when doing the noerror thing */
156 memset(ibuf, '\0', ibs); 156 memset(ibuf, '\0', ibs);
157 } 157 }
158 158
159 n = safe_read(ifd, ibuf, ibs); 159 n = safe_read(ifd, ibuf, ibs);
160 if (n == 0) { 160 if (n == 0)
161 break; 161 break;
162 }
163 if (n < 0) { 162 if (n < 0) {
164 if (noerror) { 163 if (flags & noerror) {
165 n = ibs; 164 n = ibs;
166 bb_perror_msg("%s", infile); 165 bb_perror_msg("%s", infile);
167 } else { 166 } else
168 bb_perror_msg_and_die("%s", infile); 167 bb_perror_msg_and_die("%s", infile);
169 }
170 } 168 }
171 if ((size_t)n == ibs) { 169 if ((size_t)n == ibs)
172 in_full++; 170 in_full++;
173 } else { 171 else {
174 in_part++; 172 in_part++;
175 if (sync_flag) { 173 if (sync_flag) {
176 memset(ibuf + n, '\0', ibs - n); 174 memset(ibuf + n, '\0', ibs - n);
177 n = ibs; 175 n = ibs;
178 } 176 }
179 } 177 }
180 if (twobufs_flag) { 178 if (flags & twobufs_flag) {
181 char *tmp = ibuf; 179 char *tmp = ibuf;
182 while (n) { 180 while (n) {
183 size_t d = obs - oc; 181 size_t d = obs - oc;
184 182
185 if (d > n) d = n; 183 if (d > n)
184 d = n;
186 memcpy(obuf + oc, tmp, d); 185 memcpy(obuf + oc, tmp, d);
187 n -= d; 186 n -= d;
188 tmp += d; 187 tmp += d;
@@ -195,8 +194,10 @@ int dd_main(int argc, char **argv)
195 } 194 }
196 } else { 195 } else {
197 xwrite(ofd, ibuf, n); 196 xwrite(ofd, ibuf, n);
198 if (n == ibs) out_full++; 197 if (n == ibs)
199 else out_part++; 198 out_full++;
199 else
200 out_part++;
200 } 201 }
201 } 202 }
202 203
@@ -209,6 +210,7 @@ int dd_main(int argc, char **argv)
209 } 210 }
210 211
211 if (close (ofd) < 0) { 212 if (close (ofd) < 0) {
213die_outfile:
212 bb_perror_msg_and_die("%s", outfile); 214 bb_perror_msg_and_die("%s", outfile);
213 } 215 }
214 216
diff --git a/coreutils/du.c b/coreutils/du.c
index 29427c779..3cc935553 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -23,11 +23,6 @@
23 * 4) Fixed busybox bug #1284 involving long overflow with human_readable. 23 * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
24 */ 24 */
25 25
26#include <stdlib.h>
27#include <limits.h>
28#include <unistd.h>
29#include <dirent.h>
30#include <sys/stat.h>
31#include "busybox.h" 26#include "busybox.h"
32 27
33#ifdef CONFIG_FEATURE_HUMAN_READABLE 28#ifdef CONFIG_FEATURE_HUMAN_READABLE
@@ -57,7 +52,7 @@ static int one_file_system;
57static dev_t dir_dev; 52static dev_t dir_dev;
58 53
59 54
60static void print(long size, char *filename) 55static void print(long size, const char * const filename)
61{ 56{
62 /* TODO - May not want to defer error checking here. */ 57 /* TODO - May not want to defer error checking here. */
63#ifdef CONFIG_FEATURE_HUMAN_READABLE 58#ifdef CONFIG_FEATURE_HUMAN_READABLE
@@ -73,7 +68,7 @@ static void print(long size, char *filename)
73} 68}
74 69
75/* tiny recursive du */ 70/* tiny recursive du */
76static long du(char *filename) 71static long du(const char * const filename)
77{ 72{
78 struct stat statbuf; 73 struct stat statbuf;
79 long sum; 74 long sum;
diff --git a/coreutils/expr.c b/coreutils/expr.c
index 0a1baa19d..e7fdc5f1e 100644
--- a/coreutils/expr.c
+++ b/coreutils/expr.c
@@ -37,11 +37,13 @@ typedef enum valtype TYPE;
37 37
38#if ENABLE_EXPR_MATH_SUPPORT_64 38#if ENABLE_EXPR_MATH_SUPPORT_64
39typedef int64_t arith_t; 39typedef int64_t arith_t;
40
40#define PF_REZ "ll" 41#define PF_REZ "ll"
41#define PF_REZ_TYPE (long long) 42#define PF_REZ_TYPE (long long)
42#define STRTOL(s, e, b) strtoll(s, e, b) 43#define STRTOL(s, e, b) strtoll(s, e, b)
43#else 44#else
44typedef long arith_t; 45typedef long arith_t;
46
45#define PF_REZ "l" 47#define PF_REZ "l"
46#define PF_REZ_TYPE (long) 48#define PF_REZ_TYPE (long)
47#define STRTOL(s, e, b) strtol(s, e, b) 49#define STRTOL(s, e, b) strtol(s, e, b)
@@ -49,8 +51,8 @@ typedef long arith_t;
49 51
50/* A value is.... */ 52/* A value is.... */
51struct valinfo { 53struct valinfo {
52 TYPE type; /* Which kind. */ 54 TYPE type; /* Which kind. */
53 union { /* The value itself. */ 55 union { /* The value itself. */
54 arith_t i; 56 arith_t i;
55 char *s; 57 char *s;
56 } u; 58 } u;
@@ -60,17 +62,17 @@ typedef struct valinfo VALUE;
60/* The arguments given to the program, minus the program name. */ 62/* The arguments given to the program, minus the program name. */
61static char **args; 63static char **args;
62 64
63static VALUE *docolon (VALUE *sv, VALUE *pv); 65static VALUE *docolon(VALUE * sv, VALUE * pv);
64static VALUE *eval (void); 66static VALUE *eval(void);
65static VALUE *int_value (arith_t i); 67static VALUE *int_value(arith_t i);
66static VALUE *str_value (char *s); 68static VALUE *str_value(char *s);
67static int nextarg (char *str); 69static int nextarg(char *str);
68static int null (VALUE *v); 70static int null(VALUE * v);
69static int toarith (VALUE *v); 71static int toarith(VALUE * v);
70static void freev (VALUE *v); 72static void freev(VALUE * v);
71static void tostring (VALUE *v); 73static void tostring(VALUE * v);
72 74
73int expr_main (int argc, char **argv) 75int expr_main(int argc, char **argv)
74{ 76{
75 VALUE *v; 77 VALUE *v;
76 78
@@ -80,25 +82,25 @@ int expr_main (int argc, char **argv)
80 82
81 args = argv + 1; 83 args = argv + 1;
82 84
83 v = eval (); 85 v = eval();
84 if (*args) 86 if (*args)
85 bb_error_msg_and_die ("syntax error"); 87 bb_error_msg_and_die("syntax error");
86 88
87 if (v->type == integer) 89 if (v->type == integer)
88 printf ("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); 90 bb_printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
89 else 91 else
90 puts (v->u.s); 92 puts(v->u.s);
91 93
92 exit (null (v)); 94 exit(null(v));
93} 95}
94 96
95/* Return a VALUE for I. */ 97/* Return a VALUE for I. */
96 98
97static VALUE *int_value (arith_t i) 99static VALUE *int_value(arith_t i)
98{ 100{
99 VALUE *v; 101 VALUE *v;
100 102
101 v = xmalloc (sizeof(VALUE)); 103 v = xmalloc(sizeof(VALUE));
102 v->type = integer; 104 v->type = integer;
103 v->u.i = i; 105 v->u.i = i;
104 return v; 106 return v;
@@ -106,7 +108,7 @@ static VALUE *int_value (arith_t i)
106 108
107/* Return a VALUE for S. */ 109/* Return a VALUE for S. */
108 110
109static VALUE *str_value (char *s) 111static VALUE *str_value(char *s)
110{ 112{
111 VALUE *v; 113 VALUE *v;
112 114
@@ -118,28 +120,26 @@ static VALUE *str_value (char *s)
118 120
119/* Free VALUE V, including structure components. */ 121/* Free VALUE V, including structure components. */
120 122
121static void freev (VALUE *v) 123static void freev(VALUE * v)
122{ 124{
123 if (v->type == string) 125 if (v->type == string)
124 free (v->u.s); 126 free(v->u.s);
125 free (v); 127 free(v);
126} 128}
127 129
128/* Return nonzero if V is a null-string or zero-number. */ 130/* Return nonzero if V is a null-string or zero-number. */
129 131
130static int null (VALUE *v) 132static int null(VALUE * v)
131{ 133{
132 switch (v->type) { 134 if (v->type == integer)
133 case integer: 135 return v->u.i == 0;
134 return v->u.i == 0; 136 else /* string: */
135 default: /* string: */ 137 return v->u.s[0] == '\0' || strcmp(v->u.s, "0") == 0;
136 return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
137 }
138} 138}
139 139
140/* Coerce V to a string value (can't fail). */ 140/* Coerce V to a string value (can't fail). */
141 141
142static void tostring (VALUE *v) 142static void tostring(VALUE * v)
143{ 143{
144 if (v->type == integer) { 144 if (v->type == integer) {
145 v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i); 145 v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
@@ -149,9 +149,9 @@ static void tostring (VALUE *v)
149 149
150/* Coerce V to an integer value. Return 1 on success, 0 on failure. */ 150/* Coerce V to an integer value. Return 1 on success, 0 on failure. */
151 151
152static int toarith (VALUE *v) 152static int toarith(VALUE * v)
153{ 153{
154 if(v->type == string) { 154 if (v->type == string) {
155 arith_t i; 155 arith_t i;
156 char *e; 156 char *e;
157 157
@@ -160,7 +160,7 @@ static int toarith (VALUE *v)
160 i = STRTOL(v->u.s, &e, 10); 160 i = STRTOL(v->u.s, &e, 10);
161 if ((v->u.s == e) || *e) 161 if ((v->u.s == e) || *e)
162 return 0; 162 return 0;
163 free (v->u.s); 163 free(v->u.s);
164 v->u.i = i; 164 v->u.i = i;
165 v->type = integer; 165 v->type = integer;
166 } 166 }
@@ -170,221 +170,207 @@ static int toarith (VALUE *v)
170/* Return nonzero if the next token matches STR exactly. 170/* Return nonzero if the next token matches STR exactly.
171 STR must not be NULL. */ 171 STR must not be NULL. */
172 172
173static int 173static int nextarg(char *str)
174nextarg (char *str)
175{ 174{
176 if (*args == NULL) 175 if (*args == NULL)
177 return 0; 176 return 0;
178 return strcmp (*args, str) == 0; 177 return strcmp(*args, str) == 0;
179} 178}
180 179
181/* The comparison operator handling functions. */ 180/* The comparison operator handling functions. */
182 181
183static int cmp_common (VALUE *l, VALUE *r, int op) 182static int cmp_common(VALUE * l, VALUE * r, int op)
184{ 183{
185 int cmpval; 184 int cmpval;
186 185
187 if (l->type == string || r->type == string) { 186 if (l->type == string || r->type == string) {
188 tostring (l); 187 tostring(l);
189 tostring (r); 188 tostring(r);
190 cmpval = strcmp (l->u.s, r->u.s); 189 cmpval = strcmp(l->u.s, r->u.s);
191 } 190 } else
192 else
193 cmpval = l->u.i - r->u.i; 191 cmpval = l->u.i - r->u.i;
194 switch(op) { 192 if (op == '<')
195 case '<': 193 return cmpval < 0;
196 return cmpval < 0; 194 else if (op == ('L' + 'E'))
197 case ('L'+'E'): 195 return cmpval <= 0;
198 return cmpval <= 0; 196 else if (op == '=')
199 case '=': 197 return cmpval == 0;
200 return cmpval == 0; 198 else if (op == '!')
201 case '!': 199 return cmpval != 0;
202 return cmpval != 0; 200 else if (op == '>')
203 case '>': 201 return cmpval > 0;
204 return cmpval > 0; 202 else /* >= */
205 default: /* >= */ 203 return cmpval >= 0;
206 return cmpval >= 0;
207 }
208} 204}
209 205
210/* The arithmetic operator handling functions. */ 206/* The arithmetic operator handling functions. */
211 207
212static arith_t arithmetic_common (VALUE *l, VALUE *r, int op) 208static arith_t arithmetic_common(VALUE * l, VALUE * r, int op)
213{ 209{
214 arith_t li, ri; 210 arith_t li, ri;
215 211
216 if (!toarith (l) || !toarith (r)) 212 if (!toarith(l) || !toarith(r))
217 bb_error_msg_and_die ("non-numeric argument"); 213 bb_error_msg_and_die("non-numeric argument");
218 li = l->u.i; 214 li = l->u.i;
219 ri = r->u.i; 215 ri = r->u.i;
220 if((op == '/' || op == '%') && ri == 0) 216 if ((op == '/' || op == '%') && ri == 0)
221 bb_error_msg_and_die ( "division by zero"); 217 bb_error_msg_and_die("division by zero");
222 switch(op) { 218 if (op == '+')
223 case '+':
224 return li + ri; 219 return li + ri;
225 case '-': 220 else if (op == '-')
226 return li - ri; 221 return li - ri;
227 case '*': 222 else if (op == '*')
228 return li * ri; 223 return li * ri;
229 case '/': 224 else if (op == '/')
230 return li / ri; 225 return li / ri;
231 default: 226 else
232 return li % ri; 227 return li % ri;
233 }
234} 228}
235 229
236/* Do the : operator. 230/* Do the : operator.
237 SV is the VALUE for the lhs (the string), 231 SV is the VALUE for the lhs (the string),
238 PV is the VALUE for the rhs (the pattern). */ 232 PV is the VALUE for the rhs (the pattern). */
239 233
240static VALUE *docolon (VALUE *sv, VALUE *pv) 234static VALUE *docolon(VALUE * sv, VALUE * pv)
241{ 235{
242 VALUE *v; 236 VALUE *v;
243 regex_t re_buffer; 237 regex_t re_buffer;
244 const int NMATCH = 2; 238 const int NMATCH = 2;
245 regmatch_t re_regs[NMATCH]; 239 regmatch_t re_regs[NMATCH];
246 240
247 tostring (sv); 241 tostring(sv);
248 tostring (pv); 242 tostring(pv);
249 243
250 if (pv->u.s[0] == '^') { 244 if (pv->u.s[0] == '^') {
251 fprintf (stderr, "\ 245 fprintf(stderr, "\
252warning: unportable BRE: `%s': using `^' as the first character\n\ 246warning: unportable BRE: `%s': using `^' as the first character\n\
253of a basic regular expression is not portable; it is being ignored", 247of a basic regular expression is not portable; it is being ignored", pv->u.s);
254 pv->u.s);
255 } 248 }
256 249
257 memset (&re_buffer, 0, sizeof (re_buffer)); 250 memset(&re_buffer, 0, sizeof(re_buffer));
258 memset (re_regs, 0, sizeof (*re_regs)); 251 memset(re_regs, 0, sizeof(*re_regs));
259 if( regcomp (&re_buffer, pv->u.s, 0) != 0 ) 252 if (regcomp(&re_buffer, pv->u.s, 0) != 0)
260 bb_error_msg_and_die("Invalid regular expression"); 253 bb_error_msg_and_die("Invalid regular expression");
261 254
262 /* expr uses an anchored pattern match, so check that there was a 255 /* expr uses an anchored pattern match, so check that there was a
263 * match and that the match starts at offset 0. */ 256 * match and that the match starts at offset 0. */
264 if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && 257 if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
265 re_regs[0].rm_so == 0) { 258 re_regs[0].rm_so == 0) {
266 /* Were \(...\) used? */ 259 /* Were \(...\) used? */
267 if (re_buffer.re_nsub > 0) { 260 if (re_buffer.re_nsub > 0) {
268 sv->u.s[re_regs[1].rm_eo] = '\0'; 261 sv->u.s[re_regs[1].rm_eo] = '\0';
269 v = str_value (sv->u.s + re_regs[1].rm_so); 262 v = str_value(sv->u.s + re_regs[1].rm_so);
270 } 263 } else
271 else 264 v = int_value(re_regs[0].rm_eo);
272 v = int_value (re_regs[0].rm_eo); 265 } else {
273 }
274 else {
275 /* Match failed -- return the right kind of null. */ 266 /* Match failed -- return the right kind of null. */
276 if (re_buffer.re_nsub > 0) 267 if (re_buffer.re_nsub > 0)
277 v = str_value (""); 268 v = str_value("");
278 else 269 else
279 v = int_value (0); 270 v = int_value(0);
280 } 271 }
281 return v; 272 return v;
282} 273}
283 274
284/* Handle bare operands and ( expr ) syntax. */ 275/* Handle bare operands and ( expr ) syntax. */
285 276
286static VALUE *eval7 (void) 277static VALUE *eval7(void)
287{ 278{
288 VALUE *v; 279 VALUE *v;
289 280
290 if (!*args) 281 if (!*args)
291 bb_error_msg_and_die ( "syntax error"); 282 bb_error_msg_and_die("syntax error");
292 283
293 if (nextarg ("(")) { 284 if (nextarg("(")) {
294 args++; 285 args++;
295 v = eval (); 286 v = eval();
296 if (!nextarg (")")) 287 if (!nextarg(")"))
297 bb_error_msg_and_die ( "syntax error"); 288 bb_error_msg_and_die("syntax error");
298 args++; 289 args++;
299 return v; 290 return v;
300 } 291 }
301 292
302 if (nextarg (")")) 293 if (nextarg(")"))
303 bb_error_msg_and_die ( "syntax error"); 294 bb_error_msg_and_die("syntax error");
304 295
305 return str_value (*args++); 296 return str_value(*args++);
306} 297}
307 298
308/* Handle match, substr, index, length, and quote keywords. */ 299/* Handle match, substr, index, length, and quote keywords. */
309 300
310static VALUE *eval6 (void) 301static VALUE *eval6(void)
311{ 302{
312 VALUE *l, *r, *v, *i1, *i2; 303 VALUE *l, *r, *v, *i1, *i2;
313 304
314 if (nextarg ("quote")) { 305 if (nextarg("quote")) {
315 args++; 306 args++;
316 if (!*args) 307 if (!*args)
317 bb_error_msg_and_die ( "syntax error"); 308 bb_error_msg_and_die("syntax error");
318 return str_value (*args++); 309 return str_value(*args++);
319 } 310 } else if (nextarg("length")) {
320 else if (nextarg ("length")) {
321 args++; 311 args++;
322 r = eval6 (); 312 r = eval6();
323 tostring (r); 313 tostring(r);
324 v = int_value (strlen (r->u.s)); 314 v = int_value(strlen(r->u.s));
325 freev (r); 315 freev(r);
326 return v; 316 return v;
327 } 317 } else if (nextarg("match")) {
328 else if (nextarg ("match")) {
329 args++; 318 args++;
330 l = eval6 (); 319 l = eval6();
331 r = eval6 (); 320 r = eval6();
332 v = docolon (l, r); 321 v = docolon(l, r);
333 freev (l); 322 freev(l);
334 freev (r); 323 freev(r);
335 return v; 324 return v;
336 } 325 } else if (nextarg("index")) {
337 else if (nextarg ("index")) {
338 args++; 326 args++;
339 l = eval6 (); 327 l = eval6();
340 r = eval6 (); 328 r = eval6();
341 tostring (l); 329 tostring(l);
342 tostring (r); 330 tostring(r);
343 v = int_value (strcspn (l->u.s, r->u.s) + 1); 331 v = int_value(strcspn(l->u.s, r->u.s) + 1);
344 if (v->u.i == (arith_t) strlen (l->u.s) + 1) 332 if (v->u.i == (arith_t) strlen(l->u.s) + 1)
345 v->u.i = 0; 333 v->u.i = 0;
346 freev (l); 334 freev(l);
347 freev (r); 335 freev(r);
348 return v; 336 return v;
349 } 337 } else if (nextarg("substr")) {
350 else if (nextarg ("substr")) {
351 args++; 338 args++;
352 l = eval6 (); 339 l = eval6();
353 i1 = eval6 (); 340 i1 = eval6();
354 i2 = eval6 (); 341 i2 = eval6();
355 tostring (l); 342 tostring(l);
356 if (!toarith (i1) || !toarith (i2) 343 if (!toarith(i1) || !toarith(i2)
357 || i1->u.i > (arith_t) strlen (l->u.s) 344 || i1->u.i > (arith_t) strlen(l->u.s)
358 || i1->u.i <= 0 || i2->u.i <= 0) 345 || i1->u.i <= 0 || i2->u.i <= 0)
359 v = str_value (""); 346 v = str_value("");
360 else { 347 else {
361 v = xmalloc (sizeof(VALUE)); 348 v = xmalloc(sizeof(VALUE));
362 v->type = string; 349 v->type = string;
363 v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); 350 v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
364 } 351 }
365 freev (l); 352 freev(l);
366 freev (i1); 353 freev(i1);
367 freev (i2); 354 freev(i2);
368 return v; 355 return v;
369 } 356 } else
370 else 357 return eval7();
371 return eval7 ();
372} 358}
373 359
374/* Handle : operator (pattern matching). 360/* Handle : operator (pattern matching).
375 Calls docolon to do the real work. */ 361 Calls docolon to do the real work. */
376 362
377static VALUE *eval5 (void) 363static VALUE *eval5(void)
378{ 364{
379 VALUE *l, *r, *v; 365 VALUE *l, *r, *v;
380 366
381 l = eval6 (); 367 l = eval6();
382 while (nextarg (":")) { 368 while (nextarg(":")) {
383 args++; 369 args++;
384 r = eval6 (); 370 r = eval6();
385 v = docolon (l, r); 371 v = docolon(l, r);
386 freev (l); 372 freev(l);
387 freev (r); 373 freev(r);
388 l = v; 374 l = v;
389 } 375 }
390 return l; 376 return l;
@@ -392,128 +378,126 @@ static VALUE *eval5 (void)
392 378
393/* Handle *, /, % operators. */ 379/* Handle *, /, % operators. */
394 380
395static VALUE *eval4 (void) 381static VALUE *eval4(void)
396{ 382{
397 VALUE *l, *r; 383 VALUE *l, *r;
398 int op; 384 int op;
399 arith_t val; 385 arith_t val;
400 386
401 l = eval5 (); 387 l = eval5();
402 while (1) { 388 while (1) {
403 if (nextarg ("*")) 389 if (nextarg("*"))
404 op = '*'; 390 op = '*';
405 else if (nextarg ("/")) 391 else if (nextarg("/"))
406 op = '/'; 392 op = '/';
407 else if (nextarg ("%")) 393 else if (nextarg("%"))
408 op = '%'; 394 op = '%';
409 else 395 else
410 return l; 396 return l;
411 args++; 397 args++;
412 r = eval5 (); 398 r = eval5();
413 val = arithmetic_common (l, r, op); 399 val = arithmetic_common(l, r, op);
414 freev (l); 400 freev(l);
415 freev (r); 401 freev(r);
416 l = int_value (val); 402 l = int_value(val);
417 } 403 }
418} 404}
419 405
420/* Handle +, - operators. */ 406/* Handle +, - operators. */
421 407
422static VALUE *eval3 (void) 408static VALUE *eval3(void)
423{ 409{
424 VALUE *l, *r; 410 VALUE *l, *r;
425 int op; 411 int op;
426 arith_t val; 412 arith_t val;
427 413
428 l = eval4 (); 414 l = eval4();
429 while (1) { 415 while (1) {
430 if (nextarg ("+")) 416 if (nextarg("+"))
431 op = '+'; 417 op = '+';
432 else if (nextarg ("-")) 418 else if (nextarg("-"))
433 op = '-'; 419 op = '-';
434 else 420 else
435 return l; 421 return l;
436 args++; 422 args++;
437 r = eval4 (); 423 r = eval4();
438 val = arithmetic_common (l, r, op); 424 val = arithmetic_common(l, r, op);
439 freev (l); 425 freev(l);
440 freev (r); 426 freev(r);
441 l = int_value (val); 427 l = int_value(val);
442 } 428 }
443} 429}
444 430
445/* Handle comparisons. */ 431/* Handle comparisons. */
446 432
447static VALUE *eval2 (void) 433static VALUE *eval2(void)
448{ 434{
449 VALUE *l, *r; 435 VALUE *l, *r;
450 int op; 436 int op;
451 arith_t val; 437 arith_t val;
452 438
453 l = eval3 (); 439 l = eval3();
454 while (1) { 440 while (1) {
455 if (nextarg ("<")) 441 if (nextarg("<"))
456 op = '<'; 442 op = '<';
457 else if (nextarg ("<=")) 443 else if (nextarg("<="))
458 op = 'L'+'E'; 444 op = 'L' + 'E';
459 else if (nextarg ("=") || nextarg ("==")) 445 else if (nextarg("=") || nextarg("=="))
460 op = '='; 446 op = '=';
461 else if (nextarg ("!=")) 447 else if (nextarg("!="))
462 op = '!'; 448 op = '!';
463 else if (nextarg (">=")) 449 else if (nextarg(">="))
464 op = 'G'+'E'; 450 op = 'G' + 'E';
465 else if (nextarg (">")) 451 else if (nextarg(">"))
466 op = '>'; 452 op = '>';
467 else 453 else
468 return l; 454 return l;
469 args++; 455 args++;
470 r = eval3 (); 456 r = eval3();
471 toarith (l); 457 toarith(l);
472 toarith (r); 458 toarith(r);
473 val = cmp_common (l, r, op); 459 val = cmp_common(l, r, op);
474 freev (l); 460 freev(l);
475 freev (r); 461 freev(r);
476 l = int_value (val); 462 l = int_value(val);
477 } 463 }
478} 464}
479 465
480/* Handle &. */ 466/* Handle &. */
481 467
482static VALUE *eval1 (void) 468static VALUE *eval1(void)
483{ 469{
484 VALUE *l, *r; 470 VALUE *l, *r;
485 471
486 l = eval2 (); 472 l = eval2();
487 while (nextarg ("&")) { 473 while (nextarg("&")) {
488 args++; 474 args++;
489 r = eval2 (); 475 r = eval2();
490 if (null (l) || null (r)) { 476 if (null(l) || null(r)) {
491 freev (l); 477 freev(l);
492 freev (r); 478 freev(r);
493 l = int_value (0); 479 l = int_value(0);
494 } 480 } else
495 else 481 freev(r);
496 freev (r);
497 } 482 }
498 return l; 483 return l;
499} 484}
500 485
501/* Handle |. */ 486/* Handle |. */
502 487
503static VALUE *eval (void) 488static VALUE *eval(void)
504{ 489{
505 VALUE *l, *r; 490 VALUE *l, *r;
506 491
507 l = eval1 (); 492 l = eval1();
508 while (nextarg ("|")) { 493 while (nextarg("|")) {
509 args++; 494 args++;
510 r = eval1 (); 495 r = eval1();
511 if (null (l)) { 496 if (null(l)) {
512 freev (l); 497 freev(l);
513 l = r; 498 l = r;
514 } 499 } else
515 else 500 freev(r);
516 freev (r);
517 } 501 }
518 return l; 502 return l;
519} 503}
diff --git a/coreutils/sum.c b/coreutils/sum.c
index 2edd92036..d6a76dbbc 100644
--- a/coreutils/sum.c
+++ b/coreutils/sum.c
@@ -13,12 +13,6 @@
13 * Licensed under the GPL v2, see the file LICENSE in this tarball. 13 * Licensed under the GPL v2, see the file LICENSE in this tarball.
14 */ 14 */
15 15
16#include <stdio.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20#include <unistd.h>
21
22#include "busybox.h" 16#include "busybox.h"
23 17
24/* 1 if any of the files read were the standard input */ 18/* 1 if any of the files read were the standard input */
@@ -38,14 +32,15 @@ static int bsd_sum_file(const char *file, int print_name)
38 int checksum = 0; /* The checksum mod 2^16. */ 32 int checksum = 0; /* The checksum mod 2^16. */
39 uintmax_t total_bytes = 0; /* The number of bytes. */ 33 uintmax_t total_bytes = 0; /* The number of bytes. */
40 int ch; /* Each character read. */ 34 int ch; /* Each character read. */
35 int ret = 0;
41 36
42 if (IS_STDIN(file)) { 37 if (IS_STDIN(file)) {
43 fp = stdin; 38 fp = stdin;
44 have_read_stdin = 1; 39 have_read_stdin++;
45 } else { 40 } else {
46 fp = bb_wfopen(file, "r"); 41 fp = bb_wfopen(file, "r");
47 if (fp == NULL) 42 if (fp == NULL)
48 return 0; 43 goto out;
49 } 44 }
50 45
51 while ((ch = getc(fp)) != EOF) { 46 while ((ch = getc(fp)) != EOF) {
@@ -58,21 +53,21 @@ static int bsd_sum_file(const char *file, int print_name)
58 if (ferror(fp)) { 53 if (ferror(fp)) {
59 bb_perror_msg(file); 54 bb_perror_msg(file);
60 bb_fclose_nonstdin(fp); 55 bb_fclose_nonstdin(fp);
61 return 0; 56 goto out;
62 } 57 }
63 58
64 if (bb_fclose_nonstdin(fp) == EOF) { 59 if (bb_fclose_nonstdin(fp) == EOF) {
65 bb_perror_msg(file); 60 bb_perror_msg(file);
66 return 0; 61 goto out;
67 } 62 }
68 63 ret++;
69 printf("%05d %5ju ", checksum, (total_bytes+1023)/1024); 64 printf("%05d %5ju ", checksum, (total_bytes+1023)/1024);
70 if (print_name > 1) 65 if (print_name > 1)
71 puts(file); 66 puts(file);
72 else 67 else
73 printf("\n"); 68 printf("\n");
74 69out:
75 return 1; 70 return ret;
76} 71}
77 72
78/* Calculate and print the checksum and the size in 512-byte blocks 73/* Calculate and print the checksum and the size in 512-byte blocks
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 80a66fbf5..49f1bcd6a 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -42,20 +42,25 @@ static const struct suffix_mult tail_suffixes[] = {
42 42
43static int status; 43static int status;
44 44
45static void tail_xprint_header(const char *fmt, const char *filename) 45static void tail_xbb_full_write(const char *buf, size_t len)
46{ 46{
47 /* If we get an output error, there is really no sense in continuing. */ 47 /* If we get a write error, there is really no sense in continuing. */
48 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) { 48 if (full_write(STDOUT_FILENO, buf, len) < 0)
49 bb_perror_nomsg_and_die(); 49 bb_perror_nomsg_and_die();
50 }
51} 50}
52 51
53/* len should probably be size_t */ 52static void tail_xprint_header(const char *fmt, const char *filename)
54static void tail_xbb_full_write(const char *buf, size_t len)
55{ 53{
56 /* If we get a write error, there is really no sense in continuing. */ 54#if defined __GLIBC__
57 if (full_write(STDOUT_FILENO, buf, len) < 0) 55 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
58 bb_perror_nomsg_and_die(); 56 bb_perror_nomsg_and_die();
57 }
58#else
59 int hdr_len = strlen(fmt) + strlen(filename);
60 char *hdr = xzalloc(hdr_len);
61 sprintf(hdr, filename, filename);
62 tail_xbb_full_write(hdr, hdr_len);
63#endif
59} 64}
60 65
61static ssize_t tail_read(int fd, char *buf, size_t count) 66static ssize_t tail_read(int fd, char *buf, size_t count)
diff --git a/coreutils/tee.c b/coreutils/tee.c
index 4d0e6ff85..1f59f0361 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -11,6 +11,7 @@
11/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */ 11/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
12 12
13#include "busybox.h" 13#include "busybox.h"
14#include <signal.h>
14 15
15int tee_main(int argc, char **argv) 16int tee_main(int argc, char **argv)
16{ 17{
@@ -37,7 +38,7 @@ int tee_main(int argc, char **argv)
37 38
38 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe 39 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
39 * that doesn't consume all its input. Good idea... */ 40 * that doesn't consume all its input. Good idea... */
40 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/ 41 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/
41 42
42 /* Allocate an array of FILE *'s, with one extra for a sentinal. */ 43 /* Allocate an array of FILE *'s, with one extra for a sentinal. */
43 p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2)); 44 p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));
diff --git a/coreutils/watch.c b/coreutils/watch.c
index c8b16b908..7b9c6698a 100644
--- a/coreutils/watch.c
+++ b/coreutils/watch.c
@@ -3,6 +3,7 @@
3 * Mini watch implementation for busybox 3 * Mini watch implementation for busybox
4 * 4 *
5 * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de> 5 * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de>
6 * Copyrigjt (C) Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
6 * 7 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 9 */
@@ -10,14 +11,9 @@
10/* BB_AUDIT SUSv3 N/A */ 11/* BB_AUDIT SUSv3 N/A */
11/* BB_AUDIT GNU defects -- only option -n is supported. */ 12/* BB_AUDIT GNU defects -- only option -n is supported. */
12 13
13/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
14 *
15 * Removed dependency on date_main(), added proper error checking, and
16 * reduced size.
17 */
18
19#include "busybox.h" 14#include "busybox.h"
20 15
16
21int watch_main(int argc, char **argv) 17int watch_main(int argc, char **argv)
22{ 18{
23 int width, len; 19 int width, len;
@@ -26,19 +22,18 @@ int watch_main(int argc, char **argv)
26 22
27 if (argc < 2) bb_show_usage(); 23 if (argc < 2) bb_show_usage();
28 24
29 get_terminal_width_height(1, &width, 0); 25 get_terminal_width_height(STDOUT_FILENO, &width, 0);
30 header = xzalloc(width--); 26 header = xzalloc(width--);
31 27
32 /* don't use getopt, because it permutes the arguments */ 28 /* don't use getopt, because it permutes the arguments */
33 ++argv; 29 ++argv;
34 if ((argc > 3) && !strcmp(*argv, "-n")) { 30 if ((argc > 3) && argv[0][0] == '-' && argv[0][1] == 'n') {
35 period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); 31 period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
36 argv += 2; 32 argv += 2;
37 } 33 }
38 watched_argv = argv; 34 watched_argv = argv;
39 35
40 /* create header */ 36 /* create header */
41
42 len = snprintf(header, width, "Every %ds:", period); 37 len = snprintf(header, width, "Every %ds:", period);
43 while (*argv && len<width) 38 while (*argv && len<width)
44 snprintf(header+len, width-len, " %s", *(argv++)); 39 snprintf(header+len, width-len, " %s", *(argv++));
@@ -50,11 +45,13 @@ int watch_main(int argc, char **argv)
50 time(&t); 45 time(&t);
51 thyme = ctime(&t); 46 thyme = ctime(&t);
52 len = strlen(thyme); 47 len = strlen(thyme);
53 if (len < width) header[width-len] = 0; 48 if (len < width)
54 49 header[width-len] = 0;
55 printf("\033[H\033[J%s %s\n", header, thyme); 50 bb_printf("\033[H\033[J%s %s\n", header, thyme);
56 51
57 waitpid(xspawn(watched_argv),0,0); 52 waitpid(xspawn(watched_argv),0,0);
58 sleep(period); 53 sleep(period);
59 } 54 }
55 if (ENABLE_FEATURE_CLEAN_UP)
56 free(header);
60} 57}