aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/Config.in41
-rw-r--r--coreutils/basename.c35
-rw-r--r--coreutils/cal.c484
-rw-r--r--coreutils/cat.c60
-rw-r--r--coreutils/chgrp.c60
-rw-r--r--coreutils/chmod.c85
-rw-r--r--coreutils/chown.c104
-rw-r--r--coreutils/chroot.c50
-rw-r--r--coreutils/cmp.c156
-rw-r--r--coreutils/cp.c130
-rw-r--r--coreutils/cut.c23
-rw-r--r--coreutils/date.c22
-rw-r--r--coreutils/dd.c47
-rw-r--r--coreutils/df.c185
-rw-r--r--coreutils/dirname.c14
-rw-r--r--coreutils/dos2unix.c20
-rw-r--r--coreutils/du.c227
-rw-r--r--coreutils/echo.c133
-rw-r--r--coreutils/env.c52
-rw-r--r--coreutils/expr.c24
-rw-r--r--coreutils/false.c3
-rw-r--r--coreutils/head.c154
-rw-r--r--coreutils/hostid.c12
-rw-r--r--coreutils/id.c76
-rw-r--r--coreutils/length.c14
-rw-r--r--coreutils/libcoreutils/Makefile30
-rw-r--r--coreutils/libcoreutils/Makefile.in32
-rw-r--r--coreutils/libcoreutils/coreutils.h12
-rw-r--r--coreutils/libcoreutils/cp_mv_stat.c45
-rw-r--r--coreutils/libcoreutils/getopt_mk_fifo_nod.c45
-rw-r--r--coreutils/libcoreutils/xgetoptfile_sort_uniq.c38
-rw-r--r--coreutils/ln.c163
-rw-r--r--coreutils/logname.c29
-rw-r--r--coreutils/ls.c557
-rw-r--r--coreutils/md5sum.c38
-rw-r--r--coreutils/mkdir.c58
-rw-r--r--coreutils/mkfifo.c53
-rw-r--r--coreutils/mknod.c94
-rw-r--r--coreutils/mv.c203
-rw-r--r--coreutils/od.c203
-rw-r--r--coreutils/printf.c2
-rw-r--r--coreutils/pwd.c16
-rw-r--r--coreutils/realpath.c20
-rw-r--r--coreutils/rm.c67
-rw-r--r--coreutils/rmdir.c105
-rw-r--r--coreutils/sha1sum.c4
-rw-r--r--coreutils/sleep.c65
-rw-r--r--coreutils/sort.c98
-rw-r--r--coreutils/stty.c493
-rw-r--r--coreutils/sync.c8
-rw-r--r--coreutils/tail.c396
-rw-r--r--coreutils/tee.c115
-rw-r--r--coreutils/test.c12
-rw-r--r--coreutils/touch.c67
-rw-r--r--coreutils/tr.c10
-rw-r--r--coreutils/true.c3
-rw-r--r--coreutils/tty.c44
-rw-r--r--coreutils/uname.c38
-rw-r--r--coreutils/uniq.c126
-rw-r--r--coreutils/usleep.c16
-rw-r--r--coreutils/uudecode.c26
-rw-r--r--coreutils/uuencode.c38
-rw-r--r--coreutils/watch.c91
-rw-r--r--coreutils/wc.c325
-rw-r--r--coreutils/who.c6
-rw-r--r--coreutils/whoami.c11
-rw-r--r--coreutils/yes.c45
67 files changed, 3275 insertions, 2783 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index 5b9996d5b..9f5c379a3 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -111,17 +111,31 @@ config CONFIG_DOS2UNIX
111 Please submit a patch to add help text for this item. 111 Please submit a patch to add help text for this item.
112 112
113config CONFIG_DU 113config CONFIG_DU
114 bool "du" 114 bool "du (default blocksize of 512 bytes)"
115 default n 115 default n
116 help 116 help
117 Please submit a patch to add help text for this item. 117 Please submit a patch to add help text for this item.
118 118
119config CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
120 bool " Use a default blocksize of 1024 bytes (1K)"
121 default y
122 depends on CONFIG_DU
123 help
124 Please submit a patch to add help text for this item.
125
119config CONFIG_ECHO 126config CONFIG_ECHO
120 bool "echo" 127 bool "echo (basic SUSv3 version taking no options"
121 default n 128 default n
122 help 129 help
123 Please submit a patch to add help text for this item. 130 Please submit a patch to add help text for this item.
124 131
132config CONFIG_FEATURE_FANCY_ECHO
133 bool " Enable echo options (-n and -e)"
134 default y
135 depends on CONFIG_ECHO
136 help
137 Please submit a patch to add help text for this item.
138
125config CONFIG_ENV 139config CONFIG_ENV
126 bool "env" 140 bool "env"
127 default n 141 default n
@@ -154,6 +168,13 @@ config CONFIG_HEAD
154 help 168 help
155 Please submit a patch to add help text for this item. 169 Please submit a patch to add help text for this item.
156 170
171config CONFIG_FEATURE_FANCY_HEAD
172 bool " Enable head options (-c, -q, and -v)"
173 default n
174 depends on CONFIG_HEAD
175 help
176 Please submit a patch to add help text for this item.
177
157config CONFIG_HOSTID 178config CONFIG_HOSTID
158 bool "hostid" 179 bool "hostid"
159 default n 180 default n
@@ -313,8 +334,15 @@ config CONFIG_SHA1SUM
313 Compute and check SHA1 message digest 334 Compute and check SHA1 message digest
314 335
315config CONFIG_SLEEP 336config CONFIG_SLEEP
316 bool "sleep" 337 bool "sleep (single integer arg with no suffix)"
338 default n
339 help
340 Please submit a patch to add help text for this item.
341
342config CONFIG_FEATURE_FANCY_SLEEP
343 bool " Enable multiple integer args and optional time suffixes"
317 default n 344 default n
345 depends on CONFIG_SLEEP
318 help 346 help
319 Please submit a patch to add help text for this item. 347 Please submit a patch to add help text for this item.
320 348
@@ -369,6 +397,13 @@ config CONFIG_TEE
369 help 397 help
370 Please submit a patch to add help text for this item. 398 Please submit a patch to add help text for this item.
371 399
400config CONFIG_FEATURE_TEE_USE_BLOCK_IO
401 bool " Enable block i/o (larger/faster) instead of byte i/o."
402 default n
403 depends on CONFIG_TEE
404 help
405 Please submit a patch to add help text for this item.
406
372if CONFIG_ASH || CONFIG_HUSH || CONFIG_LASH || CONFIG_MSH 407if CONFIG_ASH || CONFIG_HUSH || CONFIG_LASH || CONFIG_MSH
373 config CONFIG_TEST 408 config CONFIG_TEST
374 default y 409 default y
diff --git a/coreutils/basename.c b/coreutils/basename.c
index bdbcec17a..71bb9b3bd 100644
--- a/coreutils/basename.c
+++ b/coreutils/basename.c
@@ -21,32 +21,43 @@
21 * 21 *
22 */ 22 */
23 23
24/* getopt not needed */ 24/* BB_AUDIT SUSv3 compliant */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
26
27
28/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
29 *
30 * Changes:
31 * 1) Now checks for too many args. Need at least one and at most two.
32 * 2) Don't check for options, as per SUSv3.
33 * 3) Save some space by using strcmp(). Calling strncmp() here was silly.
34 */
25 35
26#include <stdlib.h> 36#include <stdlib.h>
27#include "busybox.h" 37#include <stdio.h>
28#include <string.h> 38#include <string.h>
39#include "busybox.h"
29 40
30extern int basename_main(int argc, char **argv) 41extern int basename_main(int argc, char **argv)
31{ 42{
32 int m, n; 43 size_t m, n;
33 char *s; 44 char *s;
34 45
35 if ((argc < 2) || (**(argv + 1) == '-')) { 46 if (((unsigned int)(argc-2)) >= 2) {
36 show_usage(); 47 bb_show_usage();
37 } 48 }
38 49
39 argv++; 50 s = bb_get_last_path_component(*++argv);
40
41 s = get_last_path_component(*argv);
42 51
43 if (argc>2) { 52 if (*++argv) {
44 argv++;
45 n = strlen(*argv); 53 n = strlen(*argv);
46 m = strlen(s); 54 m = strlen(s);
47 if (m>n && strncmp(s+m-n, *argv, n)==0) 55 if ((m > n) && ((strcmp)(s+m-n, *argv) == 0)) {
48 s[m-n] = '\0'; 56 s[m-n] = '\0';
57 }
49 } 58 }
59
50 puts(s); 60 puts(s);
51 return EXIT_SUCCESS; 61
62 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
52} 63}
diff --git a/coreutils/cal.c b/coreutils/cal.c
index ab631576a..ed480dd78 100644
--- a/coreutils/cal.c
+++ b/coreutils/cal.c
@@ -1,3 +1,14 @@
1/* NOTE:
2 *
3 * Apparently, all "Steven J. Merrifield" did was grab the util-linux cal applet,
4 * spend maybe 5 minutes integrating it into busybox, slapped a copyright on it,
5 * and submitted it. I certainly saw no evidence of any attempt at size reduction.
6 * Not only do I consider his copyright below meaningless, I also consider his
7 * actions shameful.
8 *
9 * Manuel Novoa III (mjn3@codepoet.org)
10 */
11
1/* 12/*
2 * Calendar implementation for busybox 13 * Calendar implementation for busybox
3 * 14 *
@@ -20,7 +31,16 @@
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * 32 *
22*/ 33*/
23 34
35/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */
36/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect. The upstream
37 * BB_AUDIT BUG: version in util-linux seems to be broken as well. */
38/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */
39
40/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
41 *
42 * Major size reduction... over 50% (>1.5k) on i386.
43 */
24 44
25#include <sys/types.h> 45#include <sys/types.h>
26#include <ctype.h> 46#include <ctype.h>
@@ -46,44 +66,30 @@
46#define MAXDAYS 42 /* max slots in a month array */ 66#define MAXDAYS 42 /* max slots in a month array */
47#define SPACE -1 /* used in day array */ 67#define SPACE -1 /* used in day array */
48 68
49static int days_in_month[2][13] = { 69static const char days_in_month[] = {
50 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 70 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
51 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
52}; 71};
53 72
54int sep1752[MAXDAYS] = { 73static const char sep1752[] = {
55 SPACE, SPACE, 1, 2, 14, 15, 16, 74 1, 2, 14, 15, 16,
56 17, 18, 19, 20, 21, 22, 23, 75 17, 18, 19, 20, 21, 22, 23,
57 24, 25, 26, 27, 28, 29, 30, 76 24, 25, 26, 27, 28, 29, 30
58 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
59 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
60 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
61}, j_sep1752[MAXDAYS] = {
62 SPACE, SPACE, 245, 246, 258, 259, 260,
63 261, 262, 263, 264, 265, 266, 267,
64 268, 269, 270, 271, 272, 273, 274,
65 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
66 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
67 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
68}, empty[MAXDAYS] = {
69 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
70 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
71 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
72 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
73 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
74 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
75}; 77};
76 78
77char *month_names[12]; 79static int julian;
78
79char day_headings[] = " ";
80char j_day_headings[] = " ";
81 80
82/* leap year -- account for gregorian reformation in 1752 */ 81/* leap year -- account for gregorian reformation in 1752 */
83#define leap_year(yr) \ 82#define leap_year(yr) \
84 ((yr) <= 1752 ? !((yr) % 4) : \ 83 ((yr) <= 1752 ? !((yr) % 4) : \
85 (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400)) 84 (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
86 85
86static int is_leap_year(int year)
87{
88 return leap_year(year);
89}
90#undef leap_year
91#define leap_year(yr) is_leap_year(yr)
92
87/* number of centuries since 1700, not inclusive */ 93/* number of centuries since 1700, not inclusive */
88#define centuries_since_1700(yr) \ 94#define centuries_since_1700(yr) \
89 ((yr) > 1700 ? (yr) / 100 - 17 : 0) 95 ((yr) > 1700 ? (yr) / 100 - 17 : 0)
@@ -96,178 +102,129 @@ char j_day_headings[] = " ";
96#define leap_years_since_year_1(yr) \ 102#define leap_years_since_year_1(yr) \
97 ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) 103 ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
98 104
99int julian; 105static void center __P((char *, int, int));
100void ascii_day __P((char *, int)); 106static void day_array __P((int, int, int *));
101void center __P((char *, int, int)); 107static void trim_trailing_spaces_and_print __P((char *));
102void day_array __P((int, int, int *)); 108
103int day_in_week __P((int, int, int)); 109static void blank_string(char *buf, size_t buflen);
104int day_in_year __P((int, int, int)); 110static char *build_row(char *p, int *dp);
105void j_yearly __P((int)); 111
106void monthly __P((int, int)); 112#define DAY_LEN 3 /* 3 spaces per day */
107void trim_trailing_spaces __P((char *)); 113#define J_DAY_LEN (DAY_LEN + 1)
108void yearly __P((int)); 114#define WEEK_LEN 20 /* 7 * 3 - one space at the end */
115#define J_WEEK_LEN (WEEK_LEN + 7)
116#define HEAD_SEP 2 /* spaces between day headings */
109 117
110int cal_main(int argc, char **argv) 118int cal_main(int argc, char **argv)
111{ 119{
112 struct tm *local_time; 120 struct tm *local_time;
113 static struct tm zero_tm; 121 struct tm zero_tm;
114 time_t now; 122 time_t now;
115 int ch, month, year, yflag, i; 123 int month, year, flags, i;
124 char *month_names[12];
125 char day_headings[28]; /* 28 for julian, 21 for nonjulian */
116 char buf[40]; 126 char buf[40];
117 127
118#ifdef CONFIG_LOCALE_SUPPORT 128#ifdef CONFIG_LOCALE_SUPPORT
119 setlocale(LC_TIME, ""); 129 setlocale(LC_TIME, "");
120#endif 130#endif
121 131
122 yflag = 0; 132 flags = bb_getopt_ulflags(argc, argv, "jy");
123 while ((ch = getopt(argc, argv, "jy")) != -1) 133
124 switch(ch) { 134 julian = flags & 1;
125 case 'j': 135
126 julian = 1;
127 break;
128 case 'y':
129 yflag = 1;
130 break;
131 default:
132 show_usage();
133 }
134 argc -= optind;
135 argv += optind; 136 argv += optind;
136 137
137 month = 0; 138 month = 0;
138 switch(argc) { 139
139 case 2: 140 if ((argc -= optind) > 2) {
140 if ((month = atoi(*argv++)) < 1 || month > 12) 141 bb_show_usage();
141 error_msg_and_die("Illegal month value: use 1-12"); 142 }
142 /* FALLTHROUGH */ 143
143 case 1: 144 if (!argc) {
144 if ((year = atoi(*argv)) < 1 || year > 9999)
145 error_msg_and_die("Illegal year value: use 1-9999");
146 break;
147 case 0:
148 time(&now); 145 time(&now);
149 local_time = localtime(&now); 146 local_time = localtime(&now);
150 year = local_time->tm_year + 1900; 147 year = local_time->tm_year + 1900;
151 if (!yflag) 148 if (!(flags & 2)) {
152 month = local_time->tm_mon + 1; 149 month = local_time->tm_mon + 1;
153 break; 150 }
154 default: 151 } else {
155 show_usage(); 152 if (argc == 2) {
153 month = bb_xgetularg10_bnd(*argv++, 1, 12);
154 }
155 year = bb_xgetularg10_bnd(*argv, 1, 9999);
156 } 156 }
157 157
158 for (i = 0; i < 12; i++) { 158 blank_string(day_headings, sizeof(day_headings) - 7 + 7*julian);
159
160 i = 0;
161 do {
159 zero_tm.tm_mon = i; 162 zero_tm.tm_mon = i;
160 strftime(buf, sizeof(buf), "%B", &zero_tm); 163 strftime(buf, sizeof(buf), "%B", &zero_tm);
161 month_names[i] = xstrdup(buf); 164 month_names[i] = bb_xstrdup(buf);
162 }
163 for (i = 0; i < 7; i++) {
164 zero_tm.tm_wday = i;
165 strftime(buf, sizeof(buf), "%a", &zero_tm);
166 strncpy(day_headings + i * 3, buf, 2);
167 strncpy(j_day_headings + i * 4 + 1, buf, 2);
168 }
169
170 if (month)
171 monthly(month, year);
172 else if (julian)
173 j_yearly(year);
174 else
175 yearly(year);
176 exit(0);
177}
178 165
179#define DAY_LEN 3 /* 3 spaces per day */ 166 if (i < 7) {
180#define J_DAY_LEN 4 /* 4 spaces per day */ 167 zero_tm.tm_wday = i;
181#define WEEK_LEN 20 /* 7 * 3 - one space at the end */ 168 strftime(buf, sizeof(buf), "%a", &zero_tm);
182#define J_WEEK_LEN 27 /* 7 * 4 - one space at the end */ 169 strncpy(day_headings + i * (3+julian) + julian, buf, 2);
183#define HEAD_SEP 2 /* spaces between day headings */
184#define J_HEAD_SEP 2
185
186void monthly(int month, int year)
187{
188 int col, row, len, days[MAXDAYS];
189 char *p, lineout[30];
190
191 day_array(month, year, days);
192 len = sprintf(lineout, "%s %d", month_names[month - 1], year);
193 printf("%*s%s\n%s\n",
194 ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "",
195 lineout, julian ? j_day_headings : day_headings);
196 for (row = 0; row < 6; row++) {
197 for (col = 0, p = lineout; col < 7; col++,
198 p += julian ? J_DAY_LEN : DAY_LEN)
199 ascii_day(p, days[row * 7 + col]);
200 *p = '\0';
201 trim_trailing_spaces(lineout);
202 printf("%s\n", lineout);
203 }
204}
205
206void j_yearly(int year)
207{
208 int col, *dp, i, month, row, which_cal;
209 int days[12][MAXDAYS];
210 char *p, lineout[80];
211
212 sprintf(lineout, "%d", year);
213 center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
214 printf("\n\n");
215 for (i = 0; i < 12; i++)
216 day_array(i + 1, year, days[i]);
217 memset(lineout, ' ', sizeof(lineout) - 1);
218 lineout[sizeof(lineout) - 1] = '\0';
219 for (month = 0; month < 12; month += 2) {
220 center(month_names[month], J_WEEK_LEN, J_HEAD_SEP);
221 center(month_names[month + 1], J_WEEK_LEN, 0);
222 printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
223 j_day_headings);
224 for (row = 0; row < 6; row++) {
225 for (which_cal = 0; which_cal < 2; which_cal++) {
226 p = lineout + which_cal * (J_WEEK_LEN + 2);
227 dp = &days[month + which_cal][row * 7];
228 for (col = 0; col < 7; col++, p += J_DAY_LEN)
229 ascii_day(p, *dp++);
230 }
231 *p = '\0';
232 trim_trailing_spaces(lineout);
233 printf("%s\n", lineout);
234 } 170 }
235 } 171 } while (++i < 12);
236 printf("\n"); 172
237} 173 if (month) {
238 174 int row, len, days[MAXDAYS];
239void yearly(int year) 175 int *dp = days;
240{ 176 char lineout[30];
241 int col, *dp, i, month, row, which_cal; 177
242 int days[12][MAXDAYS]; 178 day_array(month, year, dp);
243 char *p, lineout[80]; 179 len = sprintf(lineout, "%s %d", month_names[month - 1], year);
244 180 bb_printf("%*s%s\n%s\n",
245 sprintf(lineout, "%d", year); 181 ((7*julian + WEEK_LEN) - len) / 2, "",
246 center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0); 182 lineout, day_headings);
247 printf("\n\n");
248 for (i = 0; i < 12; i++)
249 day_array(i + 1, year, days[i]);
250 memset(lineout, ' ', sizeof(lineout) - 1);
251 lineout[sizeof(lineout) - 1] = '\0';
252 for (month = 0; month < 12; month += 3) {
253 center(month_names[month], WEEK_LEN, HEAD_SEP);
254 center(month_names[month + 1], WEEK_LEN, HEAD_SEP);
255 center(month_names[month + 2], WEEK_LEN, 0);
256 printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
257 "", day_headings, HEAD_SEP, "", day_headings);
258 for (row = 0; row < 6; row++) { 183 for (row = 0; row < 6; row++) {
259 for (which_cal = 0; which_cal < 3; which_cal++) { 184 build_row(lineout, dp)[0] = '\0';
260 p = lineout + which_cal * (WEEK_LEN + 2); 185 dp += 7;
261 dp = &days[month + which_cal][row * 7]; 186 trim_trailing_spaces_and_print(lineout);
262 for (col = 0; col < 7; col++, p += DAY_LEN) 187 }
263 ascii_day(p, *dp++); 188 } else {
189 int row, which_cal, week_len, days[12][MAXDAYS];
190 int *dp;
191 char lineout[80];
192
193 sprintf(lineout, "%d", year);
194 center(lineout,
195 (WEEK_LEN * 3 + HEAD_SEP * 2)
196 + julian * (J_WEEK_LEN * 2 + HEAD_SEP
197 - (WEEK_LEN * 3 + HEAD_SEP * 2)),
198 0);
199 puts("\n"); /* two \n's */
200 for (i = 0; i < 12; i++) {
201 day_array(i + 1, year, days[i]);
202 }
203 blank_string(lineout, sizeof(lineout));
204 week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN);
205 for (month = 0; month < 12; month += 3-julian) {
206 center(month_names[month], week_len, HEAD_SEP);
207 if (!julian) {
208 center(month_names[month + 1], week_len, HEAD_SEP);
209 }
210 center(month_names[month + 2 - julian], week_len, 0);
211 bb_printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings);
212 if (!julian) {
213 bb_printf("%*s%s", HEAD_SEP, "", day_headings);
214 }
215 putchar('\n');
216 for (row = 0; row < (6*7); row += 7) {
217 for (which_cal = 0; which_cal < 3-julian; which_cal++) {
218 dp = days[month + which_cal] + row;
219 build_row(lineout + which_cal * (week_len + 2), dp);
220 }
221 /* blank_string took care of nul termination. */
222 trim_trailing_spaces_and_print(lineout);
264 } 223 }
265 *p = '\0';
266 trim_trailing_spaces(lineout);
267 printf("%s\n", lineout);
268 } 224 }
269 } 225 }
270 printf("\n"); 226
227 bb_fflush_stdout_and_exit(0);
271} 228}
272 229
273/* 230/*
@@ -277,118 +234,129 @@ void yearly(int year)
277 * out end to end. You would have 42 numbers or spaces. This routine 234 * out end to end. You would have 42 numbers or spaces. This routine
278 * builds that array for any month from Jan. 1 through Dec. 9999. 235 * builds that array for any month from Jan. 1 through Dec. 9999.
279 */ 236 */
280void day_array(int month, int year, int *days) 237static void day_array(int month, int year, int *days)
281{ 238{
239 long temp;
240 int i;
241 int j_offset;
282 int day, dw, dm; 242 int day, dw, dm;
283 243
244 memset(days, SPACE, MAXDAYS * sizeof(int));
245
284 if ((month == 9) && (year == 1752)) { 246 if ((month == 9) && (year == 1752)) {
285 memmove(days, 247 j_offset = julian * 244;
286 julian ? j_sep1752 : sep1752, MAXDAYS * sizeof(int)); 248 i = 0;
249 do {
250 days[i+2] = sep1752[i] + j_offset;
251 } while (++i < sizeof(sep1752));
252
287 return; 253 return;
288 } 254 }
289 memmove(days, empty, MAXDAYS * sizeof(int));
290 dm = days_in_month[leap_year(year)][month];
291 dw = day_in_week(1, month, year);
292 day = julian ? day_in_year(1, month, year) : 1;
293 while (dm--)
294 days[dw++] = day++;
295}
296 255
297/* 256 /* day_in_year
298 * day_in_year -- 257 * return the 1 based day number within the year
299 * return the 1 based day number within the year 258 */
300 */ 259 day = 1;
301int day_in_year(int day, int month, int year) 260 if ((month > 2) && leap_year(year)) {
302{ 261 ++day;
303 int i, leap; 262 }
304
305 leap = leap_year(year);
306 for (i = 1; i < month; i++)
307 day += days_in_month[leap][i];
308 return (day);
309}
310 263
311/* 264 i = month;
312 * day_in_week 265 while (i) {
313 * return the 0 based day number for any date from 1 Jan. 1 to 266 day += days_in_month[--i];
314 * 31 Dec. 9999. Assumes the Gregorian reformation eliminates 267 }
315 * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
316 * missing days.
317 */
318int day_in_week(int day, int month, int year)
319{
320 long temp;
321 268
269 /* day_in_week
270 * return the 0 based day number for any date from 1 Jan. 1 to
271 * 31 Dec. 9999. Assumes the Gregorian reformation eliminates
272 * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
273 * missing days.
274 */
275 dw = THURSDAY;
322 temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) 276 temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
323 + day_in_year(day, month, year); 277 + day;
324 if (temp < FIRST_MISSING_DAY) 278 if (temp < FIRST_MISSING_DAY) {
325 return ((temp - 1 + SATURDAY) % 7); 279 dw = ((temp - 1 + SATURDAY) % 7);
326 if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) 280 } else if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) {
327 return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); 281 dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
328 return (THURSDAY); 282 }
283
284 if (!julian) {
285 day = 1;
286 }
287
288 dm = days_in_month[month];
289 if ((month == 2) && leap_year(year)) {
290 ++dm;
291 }
292
293 while (dm) {
294 days[dw++] = day++;
295 --dm;
296 }
329} 297}
330 298
331void ascii_day(char *p, int day) 299static void trim_trailing_spaces_and_print(char *s)
332{ 300{
333 int display, val; 301 char *p = s;
334 static char *aday[] = { 302
335 "", 303 while (*p) {
336 " 1", " 2", " 3", " 4", " 5", " 6", " 7", 304 ++p;
337 " 8", " 9", "10", "11", "12", "13", "14",
338 "15", "16", "17", "18", "19", "20", "21",
339 "22", "23", "24", "25", "26", "27", "28",
340 "29", "30", "31",
341 };
342
343 if (day == SPACE) {
344 memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
345 return;
346 } 305 }
347 if (julian) { 306 while (p > s) {
348 if ((val = day / 100) != 0) { 307 --p;
349 day %= 100; 308 if (!(isspace)(*p)) { /* We want the function... not the inline. */
350 *p++ = val + '0'; 309 p[1] = '\0';
351 display = 1; 310 break;
352 } else {
353 *p++ = ' ';
354 display = 0;
355 } 311 }
356 val = day / 10;
357 if (val || display)
358 *p++ = val + '0';
359 else
360 *p++ = ' ';
361 *p++ = day % 10 + '0';
362 } else {
363 *p++ = aday[day][0];
364 *p++ = aday[day][1];
365 } 312 }
366 *p = ' '; 313
314 puts(s);
367} 315}
368 316
369void trim_trailing_spaces(char *s) 317static void center(char *str, int len, int separate)
370{ 318{
371 char *p; 319 int n = strlen(str);
320 len -= n;
321 bb_printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, "");
322}
372 323
373 for (p = s; *p; ++p) 324static void blank_string(char *buf, size_t buflen)
374 continue; 325{
375 while (p > s && (--p, isspace(*p))) 326 memset(buf, ' ', buflen);
376 continue; 327 buf[buflen-1] = '\0';
377 if (p > s)
378 ++p;
379 *p = '\0';
380} 328}
381 329
382void center(char *str, int len, int separate) 330static char *build_row(char *p, int *dp)
383{ 331{
332 int col, val, day;
333
334 memset(p, ' ', (julian + DAY_LEN) * 7);
335
336 col = 0;
337 do {
338 if ((day = *dp++) != SPACE) {
339 if (julian) {
340 *++p;
341 if (day >= 100) {
342 *p = '0';
343 p[-1] = (day / 100) + '0';
344 day %= 100;
345 }
346 }
347 if ((val = day / 10) > 0) {
348 *p = val + '0';
349 }
350 *++p = day % 10 + '0';
351 p += 2;
352 } else {
353 p += DAY_LEN + julian;
354 }
355 } while (++col < 7);
384 356
385 len -= strlen(str); 357 return p;
386 printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
387 if (separate)
388 printf("%*s", separate, "");
389} 358}
390 359
391
392/* 360/*
393 * Copyright (c) 1989, 1993, 1994 361 * Copyright (c) 1989, 1993, 1994
394 * The Regents of the University of California. All rights reserved. 362 * The Regents of the University of California. All rights reserved.
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 33f15da71..865275767 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -1,9 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini Cat implementation for busybox 3 * cat implementation for busybox
4 * 4 *
5 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -21,33 +20,48 @@
21 * 20 *
22 */ 21 */
23 22
23/* BB_AUDIT SUSv3 compliant */
24/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
25
26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27 *
28 * This is a new implementation of 'cat' which aims to be SUSv3 compliant.
29 *
30 * Changes from the previous implementation include:
31 * 1) Multiple '-' args are accepted as required by SUSv3. The previous
32 * implementation would close stdin and segfault on a subsequent '-'.
33 * 2) The '-u' options is required by SUSv3. Note that the specified
34 * behavior for '-u' is done by default, so all we need do is accept
35 * the option.
36 */
37
24#include <stdlib.h> 38#include <stdlib.h>
25#include <string.h> 39#include <stdio.h>
40#include <unistd.h>
26#include "busybox.h" 41#include "busybox.h"
27 42
28extern int cat_main(int argc, char **argv) 43extern int cat_main(int argc, char **argv)
29{ 44{
30 int status = EXIT_SUCCESS; 45 FILE *f;
46 int retval = EXIT_SUCCESS;
31 47
32 if (argc == 1) { 48 bb_getopt_ulflags(argc, argv, "u");
33 print_file(stdin); 49
34 return status; 50 argv += optind;
51 if (!*argv) {
52 *--argv = "-";
35 } 53 }
36 54
37 while (--argc > 0) { 55 do {
38 if(!(strcmp(*++argv, "-"))) { 56 if ((f = bb_wfopen_input(*argv)) != NULL) {
39 print_file(stdin); 57 int r = bb_copyfd(fileno(f), STDOUT_FILENO, 0);
40 } else if (! print_file_by_name(*argv)) { 58 bb_fclose_nonstdin(f);
41 status = EXIT_FAILURE; 59 if (r >= 0) {
60 continue;
61 }
42 } 62 }
43 } 63 retval = EXIT_FAILURE;
44 return status; 64 } while (*++argv);
45}
46 65
47/* 66 return retval;
48Local Variables: 67}
49c-file-style: "linux"
50c-basic-offset: 4
51tab-width: 4
52End:
53*/
diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c
index 968b448c0..f5e5d29f1 100644
--- a/coreutils/chgrp.c
+++ b/coreutils/chgrp.c
@@ -21,9 +21,12 @@
21 * 21 *
22 */ 22 */
23 23
24#include <stdio.h> 24/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
25/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
26/* BB_AUDIT Note: gnu chgrp does not support -H, -L, or -P. */
27/* http://www.opengroup.org/onlinepubs/007904975/utilities/chgrp.html */
28
25#include <stdlib.h> 29#include <stdlib.h>
26#include <string.h>
27#include <unistd.h> 30#include <unistd.h>
28#include "busybox.h" 31#include "busybox.h"
29 32
@@ -32,53 +35,46 @@
32#define lchown chown 35#define lchown chown
33#endif 36#endif
34 37
35
36static long gid;
37
38static int fileAction(const char *fileName, struct stat *statbuf, void* junk) 38static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
39{ 39{
40 if (lchown(fileName, statbuf->st_uid, (gid == -1) ? statbuf->st_gid : gid) == 0) { 40 if (lchown(fileName, statbuf->st_uid, *((long *) junk)) == 0) {
41 return (TRUE); 41 return (TRUE);
42 } 42 }
43 perror(fileName); 43 bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */
44 return (FALSE); 44 return (FALSE);
45} 45}
46 46
47int chgrp_main(int argc, char **argv) 47int chgrp_main(int argc, char **argv)
48{ 48{
49 int opt; 49 long gid;
50 int recursiveFlag = FALSE; 50 int recursiveFlag;;
51 char *p=NULL; 51 int retval = EXIT_SUCCESS;
52 char *p;
52 53
53 /* do normal option parsing */ 54 recursiveFlag = bb_getopt_ulflags(argc, argv, "R");
54 while ((opt = getopt(argc, argv, "R")) > 0) { 55
55 switch (opt) { 56 if (argc - optind < 2) {
56 case 'R': 57 bb_show_usage();
57 recursiveFlag = TRUE;
58 break;
59 default:
60 show_usage();
61 }
62 } 58 }
63 59
64 if (argc > optind && argc > 2 && argv[optind]) { 60 argv += optind;
65 /* Find the selected group */ 61
66 gid = strtoul(argv[optind], &p, 10); /* maybe it's already numeric */ 62 /* Find the selected group */
67 if (argv[optind] == p) 63 gid = strtoul(*argv, &p, 10); /* maybe it's already numeric */
68 gid = my_getgrnam(argv[optind]); 64 if (*p || (p == *argv)) { /* trailing chars or nonnumeric */
69 } else { 65 gid = my_getgrnam(*argv);
70 error_msg_and_die(too_few_args);
71 } 66 }
67 ++argv;
72 68
73 /* Ok, ready to do the deed now */ 69 /* Ok, ready to do the deed now */
74 while (++optind < argc) { 70 do {
75 if (! recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, 71 if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE,
76 fileAction, fileAction, NULL)) { 72 fileAction, fileAction, &gid)) {
77 return EXIT_FAILURE; 73 retval = EXIT_FAILURE;
78 } 74 }
79 } 75 } while (*++argv);
80 return EXIT_SUCCESS;
81 76
77 return retval;
82} 78}
83 79
84/* 80/*
diff --git a/coreutils/chmod.c b/coreutils/chmod.c
index ba80e020a..28c98552a 100644
--- a/coreutils/chmod.c
+++ b/coreutils/chmod.c
@@ -24,67 +24,84 @@
24 * 24 *
25 */ 25 */
26 26
27/* BB_AUDIT SUSv3 compliant */
28/* BB_AUDIT GNU defects - unsupported options -c, -f, -v, and long options. */
29/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
30
27#include <stdio.h> 31#include <stdio.h>
28#include <stdlib.h> 32#include <stdlib.h>
29#include <string.h> 33#include <string.h>
30#include <unistd.h> 34#include <unistd.h>
31#include <getopt.h> 35#include <sys/stat.h>
32#include "busybox.h" 36#include "busybox.h"
33 37
34static int fileAction(const char *fileName, struct stat *statbuf, void* junk) 38static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
35{ 39{
36 if (!parse_mode((char *)junk, &(statbuf->st_mode))) 40 if (!bb_parse_mode((char *)junk, &(statbuf->st_mode)))
37 error_msg_and_die( "unknown mode: %s", (char *)junk); 41 bb_error_msg_and_die( "unknown mode: %s", (char *)junk);
38 if (chmod(fileName, statbuf->st_mode) == 0) 42 if (chmod(fileName, statbuf->st_mode) == 0)
39 return (TRUE); 43 return (TRUE);
40 perror(fileName); 44 bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */
41 return (FALSE); 45 return (FALSE);
42} 46}
43 47
44int chmod_main(int argc, char **argv) 48int chmod_main(int argc, char **argv)
45{ 49{
46 int opt; 50 int retval = EXIT_SUCCESS;
47 int recursiveFlag = FALSE; 51 int recursiveFlag = FALSE;
48 int modeind = 0; /* Index of the mode argument in `argv'. */ 52 int count;
49 char *smode; 53 char *smode;
50 static const char chmod_modes[] = "Rrwxstugoa,+-="; 54 char **p;
55 char *p0;
56 char opt = '-';
51 57
52 /* do normal option parsing */ 58 ++argv;
53 while (1) { 59 count = 0;
54 int thisind = optind ? optind : 1;
55 60
56 opt = getopt(argc, argv, chmod_modes); 61 for (p = argv ; *p ; p++) {
57 if (opt == EOF) 62 p0 = p[0];
58 break; 63 if (p0[0] == opt) {
59 smode = strchr(chmod_modes, opt); 64 if ((p0[1] == '-') && !p0[2]) {
60 if(smode == NULL) 65 opt = 0; /* Disable further option processing. */
61 show_usage(); 66 continue;
62 if(smode == chmod_modes) { /* 'R' */ 67 }
63 recursiveFlag = TRUE; 68 if (p0[1] == 'R') {
64 } else { 69 char *s = p0 + 2;
65 if (modeind != 0 && modeind != thisind) 70 while (*s == 'R') {
66 show_usage(); 71 ++s;
67 modeind = thisind; 72 }
73 if (*s) {
74 bb_show_usage();
75 }
76 recursiveFlag = TRUE;
77 continue;
78 }
79 if (count) {
80 bb_show_usage();
81 }
68 } 82 }
83 argv[count] = p0;
84 ++count;
69 } 85 }
70 86
71 if (modeind == 0) 87 argv[count] = NULL;
72 modeind = optind++;
73 88
74 opt = optind; 89 if (count < 2) {
75 if (opt >= argc) { 90 bb_show_usage();
76 error_msg_and_die(too_few_args);
77 } 91 }
78 92
79 smode = argv[modeind]; 93 smode = *argv;
94 ++argv;
95
80 /* Ok, ready to do the deed now */ 96 /* Ok, ready to do the deed now */
81 for (; opt < argc; opt++) { 97 do {
82 if (! recursive_action (argv[opt], recursiveFlag, FALSE, FALSE, fileAction, 98 if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE,
83 fileAction, smode)) { 99 fileAction, fileAction, smode)) {
84 return EXIT_FAILURE; 100 retval = EXIT_FAILURE;
85 } 101 }
86 } 102 } while (*++argv);
87 return EXIT_SUCCESS; 103
104 return retval;
88} 105}
89 106
90/* 107/*
diff --git a/coreutils/chown.c b/coreutils/chown.c
index 4e766a90b..3e983cfa6 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -21,10 +21,14 @@
21 * 21 *
22 */ 22 */
23 23
24#include <stdio.h> 24/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
25/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
26/* BB_AUDIT Note: gnu chown does not support -H, -L, or -P. */
27/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
28
25#include <stdlib.h> 29#include <stdlib.h>
26#include <string.h>
27#include <unistd.h> 30#include <unistd.h>
31#include <string.h>
28#include "busybox.h" 32#include "busybox.h"
29 33
30/* Don't use lchown for libc5 or glibc older then 2.1.x */ 34/* Don't use lchown for libc5 or glibc older then 2.1.x */
@@ -42,65 +46,67 @@ static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
42 if (chown_func(fileName, uid, (gid == -1) ? statbuf->st_gid : gid) == 0) { 46 if (chown_func(fileName, uid, (gid == -1) ? statbuf->st_gid : gid) == 0) {
43 return (TRUE); 47 return (TRUE);
44 } 48 }
45 perror(fileName); 49 bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */
46 return (FALSE); 50 return (FALSE);
47} 51}
48 52
53#define FLAG_R 1
54#define FLAG_h 2
55
56static unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *))
57{
58 unsigned long r;
59 char *p;
60
61 r = strtoul(s, &p, 10);
62 if (*p || (s == p)) {
63 r = my_getxxnam(s);
64 }
65
66 return r;
67}
68
49int chown_main(int argc, char **argv) 69int chown_main(int argc, char **argv)
50{ 70{
51 int opt; 71 int flags;
52 int recursiveFlag = FALSE, 72 int retval = EXIT_SUCCESS;
53 noderefFlag = FALSE; 73 char *groupName;
54 char *groupName=NULL; 74
55 char *p=NULL; 75 flags = bb_getopt_ulflags(argc, argv, "Rh");
56 76
57 /* do normal option parsing */ 77 if (flags & FLAG_h) chown_func = lchown;
58 while ((opt = getopt(argc, argv, "Rh")) > 0) { 78
59 switch (opt) { 79 if (argc - optind < 2) {
60 case 'R': 80 bb_show_usage();
61 recursiveFlag = TRUE;
62 break;
63 case 'h':
64 noderefFlag = TRUE;
65 break;
66 default:
67 show_usage();
68 }
69 } 81 }
70 82
71 if (noderefFlag) chown_func = lchown; 83 argv += optind;
72 84
73 if (argc > optind && argc > 2 && argv[optind]) { 85 /* First, check if there is a group name here */
74 /* First, check if there is a group name here */ 86 if ((groupName = strchr(*argv, '.')) == NULL) {
75 groupName = strchr(argv[optind], '.'); 87 groupName = strchr(*argv, ':');
76 if (groupName == NULL) 88 }
77 groupName = strchr(argv[optind], ':'); 89
78 if (groupName) { 90 gid = -1;
79 *groupName++ = '\0'; 91 if (groupName) {
80 gid = strtoul(groupName, &p, 10); 92 *groupName++ = '\0';
81 if (groupName == p) 93 gid = get_ug_id(groupName, my_getgrnam);
82 gid = my_getgrnam(groupName);
83 } else {
84 gid = -1;
85 }
86 /* Now check for the username */
87 uid = strtoul(argv[optind], &p, 10); /* Is is numeric? */
88 if (argv[optind] == p) {
89 uid = my_getpwnam(argv[optind]);
90 }
91 } else {
92 error_msg_and_die(too_few_args);
93 } 94 }
94 95
96 /* Now check for the username */
97 uid = get_ug_id(*argv, my_getpwnam);
98
99 ++argv;
100
95 /* Ok, ready to do the deed now */ 101 /* Ok, ready to do the deed now */
96 while (++optind < argc) { 102 do {
97 if (! recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, 103 if (! recursive_action (*argv, (flags & FLAG_R), FALSE, FALSE,
98 fileAction, fileAction, NULL)) { 104 fileAction, fileAction, NULL)) {
99 return EXIT_FAILURE; 105 retval = EXIT_FAILURE;
100 } 106 }
101 } 107 } while (*++argv);
102 return EXIT_SUCCESS;
103 108
109 return retval;
104} 110}
105 111
106/* 112/*
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index ba3e5f864..01e4d564c 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -21,6 +21,8 @@
21 * 21 *
22 */ 22 */
23 23
24/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
25
24#include <stdlib.h> 26#include <stdlib.h>
25#include <stdio.h> 27#include <stdio.h>
26#include <unistd.h> 28#include <unistd.h>
@@ -29,46 +31,24 @@
29 31
30int chroot_main(int argc, char **argv) 32int chroot_main(int argc, char **argv)
31{ 33{
32 char *prog; 34 if (argc < 2) {
33 35 bb_show_usage();
34 if ((argc < 2) || (**(argv + 1) == '-')) {
35 show_usage();
36 } 36 }
37 argc--;
38 argv++;
39 37
38 ++argv;
40 if (chroot(*argv) || (chdir("/"))) { 39 if (chroot(*argv) || (chdir("/"))) {
41 perror_msg_and_die("cannot change root directory to %s", *argv); 40 bb_perror_msg_and_die("cannot change root directory to %s", *argv);
42 } 41 }
43 42
44 argc--; 43 ++argv;
45 argv++; 44 if (argc == 2) {
46 if (argc >= 1) { 45 argv -= 2;
47 prog = *argv; 46 if (!(*argv = getenv("SHELL"))) {
48 execvp(*argv, argv); 47 *argv = (char *) "/bin/sh";
49 } else { 48 }
50#if defined shell_main && defined CONFIG_FEATURE_SH_STANDALONE_SHELL 49 argv[1] = (char *) "-i";
51 char shell[] = "/bin/sh";
52 char *shell_argv[2] = { shell, NULL };
53 applet_name = shell;
54 shell_main(1, shell_argv);
55 return EXIT_SUCCESS;
56#else
57 prog = getenv("SHELL");
58 if (!prog)
59 prog = "/bin/sh";
60 execlp(prog, prog, NULL);
61#endif
62 } 50 }
63 perror_msg_and_die("cannot execute %s", prog);
64 51
52 execvp(*argv, argv);
53 bb_perror_msg_and_die("cannot execute %s", *argv);
65} 54}
66
67
68/*
69Local Variables:
70c-file-style: "linux"
71c-basic-offset: 4
72tab-width: 4
73End:
74*/
diff --git a/coreutils/cmp.c b/coreutils/cmp.c
index 07bf3be92..43dbc842f 100644
--- a/coreutils/cmp.c
+++ b/coreutils/cmp.c
@@ -20,59 +20,133 @@
20 * 20 *
21 */ 21 */
22 22
23/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */
24/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */
25
26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27 *
28 * Original version majorly reworked for SUSv3 compliance, bug fixes, and
29 * size optimizations. Changes include:
30 * 1) Now correctly distingusishes between errors and actual file differences.
31 * 2) Proper handling of '-' args.
32 * 3) Actual error checking of i/o.
33 * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format
34 * in the '-l' case.
35 */
36
23#include <stdio.h> 37#include <stdio.h>
24#include <string.h>
25#include <errno.h>
26#include <stdlib.h> 38#include <stdlib.h>
27#include <getopt.h> 39#include <unistd.h>
28#include "busybox.h" 40#include "busybox.h"
29 41
42static FILE *cmp_xfopen_input(const char *filename)
43{
44 FILE *fp;
45
46 if ((fp = bb_wfopen_input(filename)) != NULL) {
47 return fp;
48 }
49
50 exit(bb_default_error_retval); /* We already output an error message. */
51}
52
53static const char fmt_eof[] = "cmp: EOF on %s\n";
54static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
55#if 0
56static const char fmt_l_opt[] = "%.0s%.0s%d %o %o\n"; /* SUSv3 format */
57#else
58static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n"; /* nicer gnu format */
59#endif
60
61static const char opt_chars[] = "sl";
62
63enum {
64 OPT_s = 1,
65 OPT_l = 2
66};
67
30int cmp_main(int argc, char **argv) 68int cmp_main(int argc, char **argv)
31{ 69{
32 FILE *fp1 = NULL, *fp2 = stdin; 70 FILE *fp1, *fp2, *outfile = stdout;
33 char *filename1, *filename2 = "-"; 71 const char *filename1, *filename2;
34 int c, c1, c2, char_pos = 1, line_pos = 1, silent = FALSE; 72 const char *fmt;
35 73 int c1, c2, char_pos, line_pos;
36 while ((c = getopt(argc, argv, "s")) != EOF) { 74 int opt_flags;
37 switch (c) { 75 int exit_val = 0;
38 case 's': 76
39 silent = TRUE; 77 bb_default_error_retval = 2; /* 1 is returned if files are different. */
40 break; 78
41 default: 79 opt_flags = bb_getopt_ulflags(argc, argv, opt_chars);
42 show_usage(); 80
43 } 81 if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) {
82 bb_show_usage();
44 } 83 }
45 84
46 filename1 = argv[optind]; 85 fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
47 switch (argc - optind) { 86
48 case 2: 87 filename2 = "-";
49 fp2 = xfopen(filename2 = argv[optind + 1], "r"); 88 if (*++argv) {
50 case 1: 89 filename2 = *argv;
51 fp1 = xfopen(filename1, "r");
52 break;
53 default:
54 show_usage();
55 } 90 }
91 fp2 = cmp_xfopen_input(filename2);
56 92
93 if (fp1 == fp2) { /* Paranioa check... stdin == stdin? */
94 /* Note that we don't bother reading stdin. Neither does gnu wc.
95 * But perhaps we should, so that other apps down the chain don't
96 * get the input. Consider 'echo hello | (cmp - - && cat -)'.
97 */
98 return 0;
99 }
100
101 fmt = fmt_differ;
102 if (opt_flags == OPT_l) {
103 fmt = fmt_l_opt;
104 }
105
106 char_pos = 0;
107 line_pos = 1;
57 do { 108 do {
58 c1 = fgetc(fp1); 109 c1 = getc(fp1);
59 c2 = fgetc(fp2); 110 c2 = getc(fp2);
60 if (c1 != c2) { 111 ++char_pos;
61 if (silent) 112 if (c1 != c2) { /* Remember -- a read error may have occurred. */
62 return EXIT_FAILURE; 113 exit_val = 1; /* But assume the files are different for now. */
63 if (c1 == EOF) 114 if (c2 == EOF) {
64 printf("EOF on %s\n", filename1); 115 /* We know that fp1 isn't at EOF or in an error state. But to
65 else if (c2 == EOF) 116 * save space below, things are setup to expect an EOF in fp1
66 printf("EOF on %s\n", filename2); 117 * if an EOF occurred. So, swap things around.
67 else 118 */
68 printf("%s %s differ: char %d, line %d\n", filename1, filename2, 119 fp1 = fp2;
69 char_pos, line_pos); 120 filename1 = filename2;
70 return EXIT_FAILURE; 121 c1 = c2;
122 }
123 if (c1 == EOF) {
124 bb_xferror(fp1, filename1);
125 fmt = fmt_eof; /* Well, no error, so it must really be EOF. */
126 outfile = stderr;
127 /* There may have been output to stdout (option -l), so
128 * make sure we fflush before writing to stderr. */
129 bb_xfflush_stdout();
130 }
131 if (opt_flags != OPT_s) {
132 if (opt_flags == OPT_l) {
133 line_pos = c1; /* line_pos is unused in the -l case. */
134 }
135 bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
136 if (opt_flags) { /* This must be -l since not -s. */
137 /* If we encountered and EOF, the while check will catch it. */
138 continue;
139 }
140 }
141 break;
142 }
143 if (c1 == '\n') {
144 ++line_pos;
71 } 145 }
72 char_pos++;
73 if (c1 == '\n')
74 line_pos++;
75 } while (c1 != EOF); 146 } while (c1 != EOF);
76 147
77 return EXIT_SUCCESS; 148 bb_xferror(fp1, filename1);
149 bb_xferror(fp2, filename2);
150
151 bb_fflush_stdout_and_exit(exit_val);
78} 152}
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 8f8fe5ed3..c5dd31ec3 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -2,7 +2,6 @@
2/* 2/*
3 * Mini cp implementation for busybox 3 * Mini cp implementation for busybox
4 * 4 *
5 *
6 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -21,6 +20,15 @@
21 * 20 *
22 */ 21 */
23 22
23/* BB_AUDIT SUSv3 defects - unsupported options -H, -L, and -P. */
24/* BB_AUDIT GNU defects - only extension options supported are -a and -d. */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */
26
27/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
28 *
29 * Size reduction.
30 */
31
24#include <sys/types.h> 32#include <sys/types.h>
25#include <sys/stat.h> 33#include <sys/stat.h>
26#include <unistd.h> 34#include <unistd.h>
@@ -29,86 +37,76 @@
29#include <errno.h> 37#include <errno.h>
30#include <dirent.h> 38#include <dirent.h>
31#include <stdlib.h> 39#include <stdlib.h>
32 40#include <assert.h>
33#include "busybox.h" 41#include "busybox.h"
42#include "libcoreutils/coreutils.h"
43
44static const char cp_opts[] = "pdRfia"; /* WARNING!! ORDER IS IMPORTANT!! */
34 45
35extern int cp_main(int argc, char **argv) 46extern int cp_main(int argc, char **argv)
36{ 47{
48 struct stat source_stat;
49 struct stat dest_stat;
50 const char *last;
51 const char *dest;
52 int s_flags;
53 int d_flags;
54 int flags;
37 int status = 0; 55 int status = 0;
38 int opt;
39 int flags = FILEUTILS_DEREFERENCE;
40 int i;
41 56
42 while ((opt = getopt(argc, argv, "adfipR")) != -1) 57 /* Since these are enums, #if tests will not work. So use assert()s. */
43 switch (opt) { 58 assert(FILEUTILS_PRESERVE_STATUS == 1);
44 case 'a': 59 assert(FILEUTILS_DEREFERENCE == 2);
45 flags |= FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR; 60 assert(FILEUTILS_RECUR == 4);
46 /* fallthrough */ 61 assert(FILEUTILS_FORCE == 8);
47 case 'd': 62 assert(FILEUTILS_INTERACTIVE == 16);
48 flags &= ~FILEUTILS_DEREFERENCE;
49 break;
50 case 'f':
51 flags |= FILEUTILS_FORCE;
52 break;
53 case 'i':
54 flags |= FILEUTILS_INTERACTIVE;
55 break;
56 case 'p':
57 flags |= FILEUTILS_PRESERVE_STATUS;
58 break;
59 case 'R':
60 flags |= FILEUTILS_RECUR;
61 break;
62 default:
63 show_usage();
64 }
65
66 if (optind + 2 > argc)
67 show_usage();
68 63
69 /* If there are only two arguments and... */ 64 flags = bb_getopt_ulflags(argc, argv, cp_opts);
70 if (optind + 2 == argc) {
71 struct stat source_stat;
72 struct stat dest_stat;
73 int source_exists = 1;
74 int dest_exists = 1;
75 65
76 if ((!(flags & FILEUTILS_DEREFERENCE) && 66 if (flags & 32) {
77 lstat(argv[optind], &source_stat) < 0) || 67 flags |= (FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR | FILEUTILS_DEREFERENCE);
78 ((flags & FILEUTILS_DEREFERENCE) && 68 }
79 stat(argv[optind], &source_stat))) { 69
80 if (errno != ENOENT) 70 flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */
81 perror_msg_and_die("unable to stat `%s'", argv[optind]); 71
82 source_exists = 0; 72 if (optind + 2 > argc) {
83 } 73 bb_show_usage();
74 }
75
76 last = argv[argc - 1];
77 argv += optind;
84 78
85 if (stat(argv[optind + 1], &dest_stat) < 0) { 79 /* If there are only two arguments and... */
86 if (errno != ENOENT) 80 if (optind + 2 == argc) {
87 perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); 81 s_flags = cp_mv_stat2(*argv, &source_stat,
88 dest_exists = 0; 82 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
83 if ((s_flags < 0) || ((d_flags = cp_mv_stat(last, &dest_stat)) < 0)) {
84 exit(EXIT_FAILURE);
89 } 85 }
90
91 /* ...if neither is a directory or... */ 86 /* ...if neither is a directory or... */
92 if (((!source_exists || !S_ISDIR(source_stat.st_mode)) && 87 if ( !((s_flags | d_flags) & 2) ||
93 (!dest_exists || !S_ISDIR(dest_stat.st_mode))) || 88 /* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */
94 /* ...recursing, the first is a directory, and the 89 /* ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) */
95 * second doesn't exist, then... */ 90 /* Simplify the above since FILEUTILS_RECUR >> 1 == 2. */
96 ((flags & FILEUTILS_RECUR) && S_ISDIR(source_stat.st_mode) && 91 ((((flags & FILEUTILS_RECUR) >> 1) & s_flags) && !d_flags)
97 !dest_exists)) { 92 ) {
98 /* ...do a simple copy. */ 93 /* ...do a simple copy. */
99 if (copy_file(argv[optind], argv[optind + 1], flags) < 0) 94 dest = last;
100 status = 1; 95 goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */
101 return status;
102 } 96 }
103 } 97 }
104 98
105 for (i = optind; i < argc - 1; i++) { 99 do {
106 char *dest = concat_path_file(argv[argc - 1], 100 dest = concat_path_file(last, bb_get_last_path_component(*argv));
107 get_last_path_component(argv[i])); 101 DO_COPY:
108 if (copy_file(argv[i], dest, flags) < 0) 102 if (copy_file(*argv, dest, flags) < 0) {
109 status = 1; 103 status = 1;
110 free(dest); 104 }
111 } 105 if (*++argv == last) {
106 break;
107 }
108 free((void *) dest);
109 } while (1);
112 110
113 return status; 111 exit(status);
114} 112}
diff --git a/coreutils/cut.c b/coreutils/cut.c
index 3ed264870..c24cf6611 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -92,7 +92,7 @@ static void parse_lists(char *lists)
92 } else { 92 } else {
93 s = strtoul(ntok, &junk, 10); 93 s = strtoul(ntok, &junk, 10);
94 if(*junk != '\0' || s < 0) 94 if(*junk != '\0' || s < 0)
95 error_msg_and_die("invalid byte or field list"); 95 bb_error_msg_and_die("invalid byte or field list");
96 96
97 /* account for the fact that arrays are zero based, while the user 97 /* account for the fact that arrays are zero based, while the user
98 * expects the first char on the line to be char # 1 */ 98 * expects the first char on the line to be char # 1 */
@@ -109,7 +109,7 @@ static void parse_lists(char *lists)
109 } else { 109 } else {
110 e = strtoul(ntok, &junk, 10); 110 e = strtoul(ntok, &junk, 10);
111 if(*junk != '\0' || e < 0) 111 if(*junk != '\0' || e < 0)
112 error_msg_and_die("invalid byte or field list"); 112 bb_error_msg_and_die("invalid byte or field list");
113 /* if the user specified and end position of 0, that means "til the 113 /* if the user specified and end position of 0, that means "til the
114 * end of the line */ 114 * end of the line */
115 if (e == 0) 115 if (e == 0)
@@ -121,7 +121,7 @@ static void parse_lists(char *lists)
121 121
122 /* if there's something left to tokenize, the user past an invalid list */ 122 /* if there's something left to tokenize, the user past an invalid list */
123 if (ltok) 123 if (ltok)
124 error_msg_and_die("invalid byte or field list"); 124 bb_error_msg_and_die("invalid byte or field list");
125 125
126 /* add the new list */ 126 /* add the new list */
127 cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); 127 cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
@@ -131,7 +131,7 @@ static void parse_lists(char *lists)
131 131
132 /* make sure we got some cut positions out of all that */ 132 /* make sure we got some cut positions out of all that */
133 if (nlists == 0) 133 if (nlists == 0)
134 error_msg_and_die("missing list of positions"); 134 bb_error_msg_and_die("missing list of positions");
135 135
136 /* now that the lists are parsed, we need to sort them to make life easier 136 /* now that the lists are parsed, we need to sort them to make life easier
137 * on us when it comes time to print the chars / fields / lines */ 137 * on us when it comes time to print the chars / fields / lines */
@@ -267,8 +267,7 @@ static void cut_file(FILE *file)
267 unsigned int linenum = 0; /* keep these zero-based to be consistent */ 267 unsigned int linenum = 0; /* keep these zero-based to be consistent */
268 268
269 /* go through every line in the file */ 269 /* go through every line in the file */
270 while ((line = get_line_from_file(file)) != NULL) { 270 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
271 chomp(line);
272 271
273 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ 272 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
274 if (part == 'c' || part == 'b') 273 if (part == 'c' || part == 'b')
@@ -299,14 +298,14 @@ extern int cut_main(int argc, char **argv)
299 case 'f': 298 case 'f':
300 /* make sure they didn't ask for two types of lists */ 299 /* make sure they didn't ask for two types of lists */
301 if (part != 0) { 300 if (part != 0) {
302 error_msg_and_die("only one type of list may be specified"); 301 bb_error_msg_and_die("only one type of list may be specified");
303 } 302 }
304 part = (char)opt; 303 part = (char)opt;
305 parse_lists(optarg); 304 parse_lists(optarg);
306 break; 305 break;
307 case 'd': 306 case 'd':
308 if (strlen(optarg) > 1) { 307 if (strlen(optarg) > 1) {
309 error_msg_and_die("the delimiter must be a single character"); 308 bb_error_msg_and_die("the delimiter must be a single character");
310 } 309 }
311 delim = optarg[0]; 310 delim = optarg[0];
312 break; 311 break;
@@ -320,17 +319,17 @@ extern int cut_main(int argc, char **argv)
320 } 319 }
321 320
322 if (part == 0) { 321 if (part == 0) {
323 error_msg_and_die("you must specify a list of bytes, characters, or fields"); 322 bb_error_msg_and_die("you must specify a list of bytes, characters, or fields");
324 } 323 }
325 324
326 /* non-field (char or byte) cutting has some special handling */ 325 /* non-field (char or byte) cutting has some special handling */
327 if (part != 'f') { 326 if (part != 'f') {
328 if (supress_non_delimited_lines) { 327 if (supress_non_delimited_lines) {
329 error_msg_and_die("suppressing non-delimited lines makes sense" 328 bb_error_msg_and_die("suppressing non-delimited lines makes sense"
330 " only when operating on fields"); 329 " only when operating on fields");
331 } 330 }
332 if (delim != '\t' && part != 'f') { 331 if (delim != '\t' && part != 'f') {
333 error_msg_and_die("a delimiter may be specified only when operating on fields"); 332 bb_error_msg_and_die("a delimiter may be specified only when operating on fields");
334 } 333 }
335 } 334 }
336 335
@@ -344,7 +343,7 @@ extern int cut_main(int argc, char **argv)
344 int i; 343 int i;
345 FILE *file; 344 FILE *file;
346 for (i = optind; i < argc; i++) { 345 for (i = optind; i < argc; i++) {
347 file = wfopen(argv[i], "r"); 346 file = bb_wfopen(argv[i], "r");
348 if(file) { 347 if(file) {
349 cut_file(file); 348 cut_file(file);
350 fclose(file); 349 fclose(file);
diff --git a/coreutils/date.c b/coreutils/date.c
index d68c04a8d..afbedb90d 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -53,7 +53,7 @@ static struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
53 &(tm_time->tm_year)); 53 &(tm_time->tm_year));
54 54
55 if (nr < 4 || nr > 5) { 55 if (nr < 4 || nr > 5) {
56 error_msg_and_die(invalid_date, t_string); 56 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
57 } 57 }
58 58
59 /* correct for century - minor Y2K problem here? */ 59 /* correct for century - minor Y2K problem here? */
@@ -108,7 +108,7 @@ static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
108 t.tm_year -= 1900; /* Adjust years */ 108 t.tm_year -= 1900; /* Adjust years */
109 t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 109 t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
110 } else { 110 } else {
111 error_msg_and_die(invalid_date, t_string); 111 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
112 } 112 }
113 *tm_time = t; 113 *tm_time = t;
114 return (tm_time); 114 return (tm_time);
@@ -145,25 +145,25 @@ int date_main(int argc, char **argv)
145 case 's': 145 case 's':
146 set_time = 1; 146 set_time = 1;
147 if ((date_str != NULL) || ((date_str = optarg) == NULL)) { 147 if ((date_str != NULL) || ((date_str = optarg) == NULL)) {
148 show_usage(); 148 bb_show_usage();
149 } 149 }
150 break; 150 break;
151 case 'u': 151 case 'u':
152 utc = 1; 152 utc = 1;
153 if (putenv("TZ=UTC0") != 0) 153 if (putenv("TZ=UTC0") != 0)
154 error_msg_and_die(memory_exhausted); 154 bb_error_msg_and_die(bb_msg_memory_exhausted);
155 break; 155 break;
156 case 'd': 156 case 'd':
157 use_arg = 1; 157 use_arg = 1;
158 if ((date_str != NULL) || ((date_str = optarg) == NULL)) 158 if ((date_str != NULL) || ((date_str = optarg) == NULL))
159 show_usage(); 159 bb_show_usage();
160 break; 160 break;
161#ifdef CONFIG_FEATURE_DATE_ISOFMT 161#ifdef CONFIG_FEATURE_DATE_ISOFMT
162 case 'I': 162 case 'I':
163 if (!optarg) 163 if (!optarg)
164 ifmt = 1; 164 ifmt = 1;
165 else { 165 else {
166 int ifmt_len = xstrlen(optarg); 166 int ifmt_len = bb_strlen(optarg);
167 167
168 if ((ifmt_len <= 4) 168 if ((ifmt_len <= 4)
169 && (strncmp(optarg, "date", ifmt_len) == 0)) { 169 && (strncmp(optarg, "date", ifmt_len) == 0)) {
@@ -180,11 +180,11 @@ int date_main(int argc, char **argv)
180 } 180 }
181 } 181 }
182 if (ifmt) { 182 if (ifmt) {
183 break; /* else show_usage(); */ 183 break; /* else bb_show_usage(); */
184 } 184 }
185#endif 185#endif
186 default: 186 default:
187 show_usage(); 187 bb_show_usage();
188 } 188 }
189 } 189 }
190 190
@@ -220,15 +220,15 @@ int date_main(int argc, char **argv)
220 /* Correct any day of week and day of year etc. fields */ 220 /* Correct any day of week and day of year etc. fields */
221 tm = mktime(&tm_time); 221 tm = mktime(&tm_time);
222 if (tm < 0) { 222 if (tm < 0) {
223 error_msg_and_die(invalid_date, date_str); 223 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
224 } 224 }
225 if (utc && (putenv("TZ=UTC0") != 0)) { 225 if (utc && (putenv("TZ=UTC0") != 0)) {
226 error_msg_and_die(memory_exhausted); 226 bb_error_msg_and_die(bb_msg_memory_exhausted);
227 } 227 }
228 228
229 /* if setting time, set it */ 229 /* if setting time, set it */
230 if (set_time && (stime(&tm) < 0)) { 230 if (set_time && (stime(&tm) < 0)) {
231 perror_msg("cannot set date"); 231 bb_perror_msg("cannot set date");
232 } 232 }
233 } 233 }
234 234
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 8c7272b5c..11508614f 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -62,19 +62,19 @@ int dd_main(int argc, char **argv)
62 int ifd; 62 int ifd;
63 int ofd; 63 int ofd;
64 int i; 64 int i;
65 char *infile = NULL; 65 const char *infile = NULL;
66 char *outfile = NULL; 66 const char *outfile = NULL;
67 char *buf; 67 char *buf;
68 68
69 for (i = 1; i < argc; i++) { 69 for (i = 1; i < argc; i++) {
70 if (strncmp("bs=", argv[i], 3) == 0) 70 if (strncmp("bs=", argv[i], 3) == 0)
71 bs = parse_number(argv[i]+3, dd_suffixes); 71 bs = bb_xparse_number(argv[i]+3, dd_suffixes);
72 else if (strncmp("count=", argv[i], 6) == 0) 72 else if (strncmp("count=", argv[i], 6) == 0)
73 count = parse_number(argv[i]+6, dd_suffixes); 73 count = bb_xparse_number(argv[i]+6, dd_suffixes);
74 else if (strncmp("seek=", argv[i], 5) == 0) 74 else if (strncmp("seek=", argv[i], 5) == 0)
75 seek = parse_number(argv[i]+5, dd_suffixes); 75 seek = bb_xparse_number(argv[i]+5, dd_suffixes);
76 else if (strncmp("skip=", argv[i], 5) == 0) 76 else if (strncmp("skip=", argv[i], 5) == 0)
77 skip = parse_number(argv[i]+5, dd_suffixes); 77 skip = bb_xparse_number(argv[i]+5, dd_suffixes);
78 else if (strncmp("if=", argv[i], 3) == 0) 78 else if (strncmp("if=", argv[i], 3) == 0)
79 infile = argv[i]+3; 79 infile = argv[i]+3;
80 else if (strncmp("of=", argv[i], 3) == 0) 80 else if (strncmp("of=", argv[i], 3) == 0)
@@ -92,7 +92,7 @@ int dd_main(int argc, char **argv)
92 noerror = TRUE; 92 noerror = TRUE;
93 buf += 7; 93 buf += 7;
94 } else { 94 } else {
95 error_msg_and_die("invalid conversion `%s'", argv[i]+5); 95 bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5);
96 } 96 }
97 if (buf[0] == '\0') 97 if (buf[0] == '\0')
98 break; 98 break;
@@ -100,18 +100,18 @@ int dd_main(int argc, char **argv)
100 buf++; 100 buf++;
101 } 101 }
102 } else 102 } else
103 show_usage(); 103 bb_show_usage();
104 } 104 }
105 105
106 buf = xmalloc(bs); 106 buf = xmalloc(bs);
107 107
108 if (infile != NULL) { 108 if (infile != NULL) {
109 if ((ifd = open(infile, O_RDONLY)) < 0) { 109 if ((ifd = open(infile, O_RDONLY)) < 0) {
110 perror_msg_and_die("%s", infile); 110 bb_perror_msg_and_die("%s", infile);
111 } 111 }
112 } else { 112 } else {
113 ifd = STDIN_FILENO; 113 ifd = STDIN_FILENO;
114 infile = "standard input"; 114 infile = bb_msg_standard_input;
115 } 115 }
116 116
117 if (outfile != NULL) { 117 if (outfile != NULL) {
@@ -122,7 +122,7 @@ int dd_main(int argc, char **argv)
122 } 122 }
123 123
124 if ((ofd = open(outfile, oflag, 0666)) < 0) { 124 if ((ofd = open(outfile, oflag, 0666)) < 0) {
125 perror_msg_and_die("%s", outfile); 125 bb_perror_msg_and_die("%s", outfile);
126 } 126 }
127 127
128 if (seek && trunc) { 128 if (seek && trunc) {
@@ -131,24 +131,24 @@ int dd_main(int argc, char **argv)
131 131
132 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || 132 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
133 S_ISDIR (st.st_mode)) { 133 S_ISDIR (st.st_mode)) {
134 perror_msg_and_die("%s", outfile); 134 bb_perror_msg_and_die("%s", outfile);
135 } 135 }
136 } 136 }
137 } 137 }
138 } else { 138 } else {
139 ofd = STDOUT_FILENO; 139 ofd = STDOUT_FILENO;
140 outfile = "standard output"; 140 outfile = bb_msg_standard_output;
141 } 141 }
142 142
143 if (skip) { 143 if (skip) {
144 if (lseek(ifd, skip * bs, SEEK_CUR) < 0) { 144 if (lseek(ifd, skip * bs, SEEK_CUR) < 0) {
145 perror_msg_and_die("%s", infile); 145 bb_perror_msg_and_die("%s", infile);
146 } 146 }
147 } 147 }
148 148
149 if (seek) { 149 if (seek) {
150 if (lseek(ofd, seek * bs, SEEK_CUR) < 0) { 150 if (lseek(ofd, seek * bs, SEEK_CUR) < 0) {
151 perror_msg_and_die("%s", outfile); 151 bb_perror_msg_and_die("%s", outfile);
152 } 152 }
153 } 153 }
154 154
@@ -161,9 +161,9 @@ int dd_main(int argc, char **argv)
161 if (n < 0) { 161 if (n < 0) {
162 if (noerror) { 162 if (noerror) {
163 n = bs; 163 n = bs;
164 perror_msg("%s", infile); 164 bb_perror_msg("%s", infile);
165 } else { 165 } else {
166 perror_msg_and_die("%s", infile); 166 bb_perror_msg_and_die("%s", infile);
167 } 167 }
168 } 168 }
169 if (n == 0) { 169 if (n == 0) {
@@ -178,9 +178,9 @@ int dd_main(int argc, char **argv)
178 memset(buf + n, '\0', bs - n); 178 memset(buf + n, '\0', bs - n);
179 n = bs; 179 n = bs;
180 } 180 }
181 n = full_write(ofd, buf, n); 181 n = bb_full_write(ofd, buf, n);
182 if (n < 0) { 182 if (n < 0) {
183 perror_msg_and_die("%s", outfile); 183 bb_perror_msg_and_die("%s", outfile);
184 } 184 }
185 if (n == bs) { 185 if (n == bs) {
186 out_full++; 186 out_full++;
@@ -190,15 +190,16 @@ int dd_main(int argc, char **argv)
190 } 190 }
191 191
192 if (close (ifd) < 0) { 192 if (close (ifd) < 0) {
193 perror_msg_and_die("%s", infile); 193 bb_perror_msg_and_die("%s", infile);
194 } 194 }
195 195
196 if (close (ofd) < 0) { 196 if (close (ofd) < 0) {
197 perror_msg_and_die("%s", outfile); 197 bb_perror_msg_and_die("%s", outfile);
198 } 198 }
199 199
200 fprintf(stderr, "%ld+%ld records in\n", (long)in_full, (long)in_part); 200 fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
201 fprintf(stderr, "%ld+%ld records out\n", (long)out_full, (long)out_part); 201 (long)in_full, (long)in_part,
202 (long)out_full, (long)out_part);
202 203
203 return EXIT_SUCCESS; 204 return EXIT_SUCCESS;
204} 205}
diff --git a/coreutils/df.c b/coreutils/df.c
index 0e9e5d61a..7d007a003 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -22,74 +22,45 @@
22 * 22 *
23 */ 23 */
24 24
25/* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing. Also blocksize. */
26/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */
27
28/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
29 *
30 * Size reduction. Removed floating point dependency. Added error checking
31 * on output. Output stats on 0-sized filesystems if specificly listed on
32 * the command line. Properly round *-blocks, Used, and Available quantities.
33 */
34
25#include <stdio.h> 35#include <stdio.h>
26#include <stdlib.h> 36#include <stdlib.h>
27#include <string.h> 37#include <string.h>
38#include <unistd.h>
28#include <mntent.h> 39#include <mntent.h>
29#include <sys/vfs.h> 40#include <sys/vfs.h>
30#include <getopt.h>
31#include "busybox.h" 41#include "busybox.h"
32 42
33extern const char mtab_file[]; /* Defined in utility.c */ 43#ifndef CONFIG_FEATURE_HUMAN_READABLE
34#ifdef CONFIG_FEATURE_HUMAN_READABLE 44static long kscale(long b, long bs)
35static unsigned long df_disp_hr = KILOBYTE; 45{
46 return ( b * (long long) bs + KILOBYTE/2 ) / KILOBYTE;
47}
36#endif 48#endif
37 49
38static int do_df(char *device, const char *mount_point) 50extern int df_main(int argc, char **argv)
39{ 51{
40 struct statfs s;
41 long blocks_used; 52 long blocks_used;
42 long blocks_percent_used; 53 long blocks_percent_used;
43
44 if (statfs(mount_point, &s) != 0) {
45 perror_msg("%s", mount_point);
46 return FALSE;
47 }
48
49 if (s.f_blocks > 0) {
50 blocks_used = s.f_blocks - s.f_bfree;
51 if(blocks_used == 0)
52 blocks_percent_used = 0;
53 else {
54 blocks_percent_used = (long)
55 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
56 }
57 if (strcmp(device, "/dev/root") == 0) {
58 /* Adjusts device to be the real root device,
59 * or leaves device alone if it can't find it */
60 device = find_real_root_device_name(device);
61 if(device==NULL)
62 return FALSE;
63 }
64#ifdef CONFIG_FEATURE_HUMAN_READABLE 54#ifdef CONFIG_FEATURE_HUMAN_READABLE
65 printf("%-20s %9s ", device, 55 unsigned long df_disp_hr = KILOBYTE;
66 make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
67
68 printf("%9s ",
69 make_human_readable_str( (s.f_blocks - s.f_bfree), s.f_bsize, df_disp_hr));
70
71 printf("%9s %3ld%% %s\n",
72 make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
73 blocks_percent_used, mount_point);
74#else
75 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
76 device,
77 (long) (s.f_blocks * (s.f_bsize / (double)KILOBYTE)),
78 (long) ((s.f_blocks - s.f_bfree)*(s.f_bsize/(double)KILOBYTE)),
79 (long) (s.f_bavail * (s.f_bsize / (double)KILOBYTE)),
80 blocks_percent_used, mount_point);
81#endif 56#endif
82 }
83
84 return TRUE;
85}
86
87extern int df_main(int argc, char **argv)
88{
89 int status = EXIT_SUCCESS; 57 int status = EXIT_SUCCESS;
90 int opt = 0; 58 int opt;
91 int i = 0; 59 FILE *mount_table;
92 char disp_units_hdr[80] = "1k-blocks"; /* default display is kilobytes */ 60 struct mntent *mount_entry;
61 struct statfs s;
62 static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */;
63 const char *disp_units_hdr = hdr_1k;
93 64
94 while ((opt = getopt(argc, argv, "k" 65 while ((opt = getopt(argc, argv, "k"
95#ifdef CONFIG_FEATURE_HUMAN_READABLE 66#ifdef CONFIG_FEATURE_HUMAN_READABLE
@@ -101,52 +72,106 @@ extern int df_main(int argc, char **argv)
101#ifdef CONFIG_FEATURE_HUMAN_READABLE 72#ifdef CONFIG_FEATURE_HUMAN_READABLE
102 case 'h': 73 case 'h':
103 df_disp_hr = 0; 74 df_disp_hr = 0;
104 strcpy(disp_units_hdr, " Size"); 75 disp_units_hdr = " Size";
105 break; 76 break;
106 case 'm': 77 case 'm':
107 df_disp_hr = MEGABYTE; 78 df_disp_hr = MEGABYTE;
108 strcpy(disp_units_hdr, "1M-blocks"); 79 disp_units_hdr = "1M-blocks";
109 break; 80 break;
110#endif 81#endif
111 case 'k': 82 case 'k':
112 /* default display is kilobytes */ 83 /* default display is kilobytes */
84#ifdef CONFIG_FEATURE_HUMAN_READABLE
85 df_disp_hr = KILOBYTE;
86 disp_units_hdr = hdr_1k;
87#endif
113 break; 88 break;
114 default: 89 default:
115 show_usage(); 90 bb_show_usage();
116 } 91 }
117 } 92 }
118 93
119 printf("%-20s %-14s %s %s %s %s\n", "Filesystem", disp_units_hdr, 94 bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n",
120 "Used", "Available", "Use%", "Mounted on"); 95 "", disp_units_hdr);
121 96
122 if(optind < argc) { 97 mount_table = NULL;
123 struct mntent *mount_entry; 98 argv += optind;
124 for(i = optind; i < argc; i++) 99 if (optind >= argc) {
125 { 100 if (!(mount_table = setmntent(bb_path_mtab_file, "r"))) {
126 if ((mount_entry = find_mount_point(argv[i], mtab_file)) == 0) { 101 bb_perror_msg_and_die(bb_path_mtab_file);
127 error_msg("%s: can't find mount point.", argv[i]);
128 status = EXIT_FAILURE;
129 } else if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir))
130 status = EXIT_FAILURE;
131 } 102 }
132 } else { 103 }
133 FILE *mount_table;
134 struct mntent *mount_entry;
135 104
136 mount_table = setmntent(mtab_file, "r"); 105 do {
137 if (mount_table == 0) { 106 const char *device;
138 perror_msg("%s", mtab_file); 107 const char *mount_point;
139 return EXIT_FAILURE;
140 }
141 108
142 while ((mount_entry = getmntent(mount_table))) { 109 if (mount_table) {
143 if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir)) 110 if (!(mount_entry = getmntent(mount_table))) {
111 endmntent(mount_table);
112 break;
113 }
114 } else {
115 if (!(mount_point = *argv++)) {
116 break;
117 }
118 if (!(mount_entry = find_mount_point(mount_point, bb_path_mtab_file))) {
119 bb_error_msg("%s: can't find mount point.", mount_point);
120 SET_ERROR:
144 status = EXIT_FAILURE; 121 status = EXIT_FAILURE;
122 continue;
123 }
145 } 124 }
146 endmntent(mount_table);
147 }
148 125
149 return status; 126 device = mount_entry->mnt_fsname;
127 mount_point = mount_entry->mnt_dir;
128
129 if (statfs(mount_point, &s) != 0) {
130 bb_perror_msg("%s", mount_point);
131 goto SET_ERROR;
132 }
133
134 if ((s.f_blocks > 0) || !mount_table){
135 blocks_used = s.f_blocks - s.f_bfree;
136 blocks_percent_used = 0;
137 if (blocks_used + s.f_bavail) {
138 blocks_percent_used = (((long long) blocks_used) * 100
139 + (blocks_used + s.f_bavail)/2
140 ) / (blocks_used + s.f_bavail);
141 }
142
143 if (strcmp(device, "/dev/root") == 0) {
144 /* Adjusts device to be the real root device,
145 * or leaves device alone if it can't find it */
146 if ((device = find_real_root_device_name(device)) != NULL) {
147 goto SET_ERROR;
148 }
149 }
150
151#ifdef CONFIG_FEATURE_HUMAN_READABLE
152 bb_printf("%-21s%9s ", device,
153 make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
154
155 bb_printf("%9s ",
156 make_human_readable_str( (s.f_blocks - s.f_bfree),
157 s.f_bsize, df_disp_hr));
158
159 bb_printf("%9s %3ld%% %s\n",
160 make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
161 blocks_percent_used, mount_point);
162#else
163 bb_printf("%-21s%9ld %9ld %9ld %3ld%% %s\n",
164 device,
165 kscale(s.f_blocks, s.f_bsize),
166 kscale(s.f_blocks-s.f_bfree, s.f_bsize),
167 kscale(s.f_bavail, s.f_bsize),
168 blocks_percent_used, mount_point);
169#endif
170 }
171
172 } while (1);
173
174 bb_fflush_stdout_and_exit(status);
150} 175}
151 176
152/* 177/*
diff --git a/coreutils/dirname.c b/coreutils/dirname.c
index 387233789..4c6115e66 100644
--- a/coreutils/dirname.c
+++ b/coreutils/dirname.c
@@ -21,20 +21,20 @@
21 * 21 *
22 */ 22 */
23 23
24/* getopt not needed */ 24/* BB_AUDIT SUSv3 compliant */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/dirname.html */
25 26
26#include <stdio.h> 27#include <stdio.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include <string.h>
29#include "busybox.h" 29#include "busybox.h"
30 30
31extern int dirname_main(int argc, char **argv) 31extern int dirname_main(int argc, char **argv)
32{ 32{
33 if ((argc < 2) || (**(argv + 1) == '-')) 33 if (argc != 2) {
34 show_usage(); 34 bb_show_usage();
35 argv++; 35 }
36 36
37 puts (dirname (argv[0])); 37 puts(dirname(argv[1]));
38 38
39 return EXIT_SUCCESS; 39 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
40} 40}
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c
index b1d0a9d70..c28e6a8b9 100644
--- a/coreutils/dos2unix.c
+++ b/coreutils/dos2unix.c
@@ -35,6 +35,10 @@
35#include <sys/time.h> 35#include <sys/time.h>
36#include "busybox.h" 36#include "busybox.h"
37 37
38#define CT_AUTO 0
39#define CT_UNIX2DOS 1
40#define CT_DOS2UNIX 2
41
38/* We are making a lame pseudo-random string generator here. in 42/* We are making a lame pseudo-random string generator here. in
39 * convert(), each pass through the while loop will add more and more 43 * convert(), each pass through the while loop will add more and more
40 * stuff into value, which is _supposed_ to wrap. We don't care about 44 * stuff into value, which is _supposed_ to wrap. We don't care about
@@ -55,15 +59,13 @@ static int convert(char *fn, int ConvType)
55 FILE *in = stdin, *out = stdout; 59 FILE *in = stdin, *out = stdout;
56 60
57 if (fn != NULL) { 61 if (fn != NULL) {
58 if ((in = wfopen(fn, "rw")) == NULL) { 62 in = bb_xfopen(fn, "rw");
59 return -1;
60 }
61 safe_strncpy(tempFn, fn, sizeof(tempFn)); 63 safe_strncpy(tempFn, fn, sizeof(tempFn));
62 c = strlen(tempFn); 64 c = strlen(tempFn);
63 tempFn[c] = '.'; 65 tempFn[c] = '.';
64 while(1) { 66 while(1) {
65 if (c >=BUFSIZ) 67 if (c >=BUFSIZ)
66 error_msg_and_die("unique name not found"); 68 bb_error_msg_and_die("unique name not found");
67 /* Get some semi random stuff to try and make a 69 /* Get some semi random stuff to try and make a
68 * random filename based (and in the same dir as) 70 * random filename based (and in the same dir as)
69 * the input file... */ 71 * the input file... */
@@ -92,7 +94,7 @@ static int convert(char *fn, int ConvType)
92 // file is alredy in DOS format so it is not necessery to touch it 94 // file is alredy in DOS format so it is not necessery to touch it
93 remove(tempFn); 95 remove(tempFn);
94 if (fclose(in) < 0 || fclose(out) < 0) { 96 if (fclose(in) < 0 || fclose(out) < 0) {
95 perror_msg(NULL); 97 bb_perror_nomsg();
96 return -2; 98 return -2;
97 } 99 }
98 return 0; 100 return 0;
@@ -106,7 +108,7 @@ static int convert(char *fn, int ConvType)
106 // file is alredy in UNIX format so it is not necessery to touch it 108 // file is alredy in UNIX format so it is not necessery to touch it
107 remove(tempFn); 109 remove(tempFn);
108 if ((fclose(in) < 0) || (fclose(out) < 0)) { 110 if ((fclose(in) < 0) || (fclose(out) < 0)) {
109 perror_msg(NULL); 111 bb_perror_nomsg();
110 return -2; 112 return -2;
111 } 113 }
112 return 0; 114 return 0;
@@ -137,7 +139,7 @@ static int convert(char *fn, int ConvType)
137 139
138 if (fn != NULL) { 140 if (fn != NULL) {
139 if (fclose(in) < 0 || fclose(out) < 0) { 141 if (fclose(in) < 0 || fclose(out) < 0) {
140 perror_msg(NULL); 142 bb_perror_nomsg();
141 remove(tempFn); 143 remove(tempFn);
142 return -2; 144 return -2;
143 } 145 }
@@ -146,7 +148,7 @@ static int convert(char *fn, int ConvType)
146 * should be true since we put them into the same directory 148 * should be true since we put them into the same directory
147 * so we _should_ be ok, but you never know... */ 149 * so we _should_ be ok, but you never know... */
148 if (rename(tempFn, fn) < 0) { 150 if (rename(tempFn, fn) < 0) {
149 perror_msg("unable to rename '%s' as '%s'", tempFn, fn); 151 bb_perror_msg("unable to rename '%s' as '%s'", tempFn, fn);
150 return -1; 152 return -1;
151 } 153 }
152 } 154 }
@@ -177,7 +179,7 @@ int dos2unix_main(int argc, char *argv[])
177 ConvType = CT_DOS2UNIX; 179 ConvType = CT_DOS2UNIX;
178 break; 180 break;
179 default: 181 default:
180 show_usage(); 182 bb_show_usage();
181 } 183 }
182 } 184 }
183 185
diff --git a/coreutils/du.c b/coreutils/du.c
index 2e49b2147..702a9aa14 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -22,45 +22,65 @@
22 * 22 *
23 */ 23 */
24 24
25#include <sys/types.h> 25/* BB_AUDIT SUSv3 compliant (unless default blocksize set to 1k) */
26#include <fcntl.h> 26/* http://www.opengroup.org/onlinepubs/007904975/utilities/du.html */
27#include <dirent.h> 27
28#include <stdio.h> 28/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
29 *
30 * Mostly rewritten for SUSv3 compliance and to fix bugs/defects.
31 * 1) Added support for SUSv3 -a, -H, -L, gnu -c, and (busybox) -d options.
32 * The -d option allows setting of max depth (similar to gnu --max-depth).
33 * 2) Fixed incorrect size calculations for links and directories, especially
34 * when errors occurred. Calculates sizes should now match gnu du output.
35 * 3) Added error checking of output.
36 * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
37 */
38
29#include <stdlib.h> 39#include <stdlib.h>
30#include <getopt.h> 40#include <limits.h>
31#include <string.h> 41#include <unistd.h>
32#include <errno.h> 42#include <dirent.h>
43#include <sys/stat.h>
33#include "busybox.h" 44#include "busybox.h"
34 45
35
36#ifdef CONFIG_FEATURE_HUMAN_READABLE 46#ifdef CONFIG_FEATURE_HUMAN_READABLE
47# ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
37static unsigned long disp_hr = KILOBYTE; 48static unsigned long disp_hr = KILOBYTE;
49# else
50static unsigned long disp_hr = 512;
51# endif
52#elif defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
53static unsigned int disp_k = 1;
54#else
55static unsigned int disp_k; /* bss inits to 0 */
38#endif 56#endif
39 57
40static int du_depth /*= 0*/; 58static int max_print_depth = INT_MAX;
41static int count_hardlinks /*= 0*/; 59static int count_hardlinks = INT_MAX;
42static int one_file_system /*= 0*/; 60
61static int status
62#if EXIT_SUCCESS == 0
63 = EXIT_SUCCESS
64#endif
65 ;
66static int print_files;
67static int slink_depth;
68static int du_depth;
69static int one_file_system;
43static dev_t dir_dev; 70static dev_t dir_dev;
44 71
45static void (*print) (long, char *);
46 72
47static void print_normal(long size, char *filename) 73static void print(long size, char *filename)
48{ 74{
75 /* TODO - May not want to defer error checking here. */
49#ifdef CONFIG_FEATURE_HUMAN_READABLE 76#ifdef CONFIG_FEATURE_HUMAN_READABLE
50 printf("%s\t%s\n", make_human_readable_str(size << 10, 1, disp_hr), 77 bb_printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr),
51 filename); 78 filename);
52#else 79#else
53 printf("%ld\t%s\n", size, filename); 80 bb_printf("%ld\t%s\n", size >> disp_k, filename);
54#endif 81#endif
55} 82}
56 83
57static void print_summary(long size, char *filename)
58{
59 if (du_depth == 1) {
60 print_normal(size, filename);
61 }
62}
63
64/* tiny recursive du */ 84/* tiny recursive du */
65static long du(char *filename) 85static long du(char *filename)
66{ 86{
@@ -68,23 +88,43 @@ static long du(char *filename)
68 long sum; 88 long sum;
69 89
70 if ((lstat(filename, &statbuf)) != 0) { 90 if ((lstat(filename, &statbuf)) != 0) {
71 perror_msg("%s", filename); 91 bb_perror_msg("%s", filename);
92 status = EXIT_FAILURE;
72 return 0; 93 return 0;
73 } 94 }
74 if (du_depth == 0)
75 dir_dev = statbuf.st_dev;
76 else if (one_file_system && dir_dev != statbuf.st_dev)
77 return 0;
78 95
79 du_depth++; 96 if (one_file_system) {
80 sum = (statbuf.st_blocks >> 1); 97 if (du_depth == 0) {
98 dir_dev = statbuf.st_dev;
99 } else if (dir_dev != statbuf.st_dev) {
100 return 0;
101 }
102 }
103
104 sum = statbuf.st_blocks;
81 105
82 /* Don't add in stuff pointed to by symbolic links */
83 if (S_ISLNK(statbuf.st_mode)) { 106 if (S_ISLNK(statbuf.st_mode)) {
84 sum = 0L; 107 if (slink_depth > du_depth) { /* -H or -L */
85 if (du_depth == 1) { 108 if ((stat(filename, &statbuf)) != 0) {
109 bb_perror_msg("%s", filename);
110 status = EXIT_FAILURE;
111 return 0;
112 }
113 sum = statbuf.st_blocks;
114 if (slink_depth == 1) {
115 slink_depth = INT_MAX; /* Convert -H to -L. */
116 }
86 } 117 }
87 } 118 }
119
120 if (statbuf.st_nlink > count_hardlinks) {
121 /* Add files/directories with links only once */
122 if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
123 return 0;
124 }
125 add_to_ino_dev_hashtable(&statbuf, NULL);
126 }
127
88 if (S_ISDIR(statbuf.st_mode)) { 128 if (S_ISDIR(statbuf.st_mode)) {
89 DIR *dir; 129 DIR *dir;
90 struct dirent *entry; 130 struct dirent *entry;
@@ -92,8 +132,9 @@ static long du(char *filename)
92 132
93 dir = opendir(filename); 133 dir = opendir(filename);
94 if (!dir) { 134 if (!dir) {
95 du_depth--; 135 bb_perror_msg("%s", filename);
96 return 0; 136 status = EXIT_FAILURE;
137 return sum;
97 } 138 }
98 139
99 newfile = last_char_is(filename, '/'); 140 newfile = last_char_is(filename, '/');
@@ -103,54 +144,86 @@ static long du(char *filename)
103 while ((entry = readdir(dir))) { 144 while ((entry = readdir(dir))) {
104 char *name = entry->d_name; 145 char *name = entry->d_name;
105 146
106 if ((strcmp(name, "..") == 0) 147 if ((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2]))) {
107 || (strcmp(name, ".") == 0)) {
108 continue; 148 continue;
109 } 149 }
110 newfile = concat_path_file(filename, name); 150 newfile = concat_path_file(filename, name);
151 ++du_depth;
111 sum += du(newfile); 152 sum += du(newfile);
153 --du_depth;
112 free(newfile); 154 free(newfile);
113 } 155 }
114 closedir(dir); 156 closedir(dir);
157 } else if (du_depth > print_files) {
158 return sum;
159 }
160 if (du_depth <= max_print_depth) {
115 print(sum, filename); 161 print(sum, filename);
116 } else if (statbuf.st_nlink > 1 && !count_hardlinks) {
117 /* Add files with hard links only once */
118 if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
119 sum = 0L;
120 if (du_depth == 1)
121 print(sum, filename);
122 } else {
123 add_to_ino_dev_hashtable(&statbuf, NULL);
124 }
125 } 162 }
126 du_depth--;
127 return sum; 163 return sum;
128} 164}
129 165
130int du_main(int argc, char **argv) 166int du_main(int argc, char **argv)
131{ 167{
132 int status = EXIT_SUCCESS; 168 long total;
133 int i; 169 int slink_depth_save;
170 int print_final_total = 0;
134 int c; 171 int c;
135 172
136 /* default behaviour */ 173#ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
137 print = print_normal; 174 if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */
175#ifdef CONFIG_FEATURE_HUMAN_READABLE
176 disp_hr = 512;
177#else
178 disp_k = 0;
179#endif
180 }
181#endif
182
183 /* Note: SUSv3 specifies that -a and -s options can not be used together
184 * in strictly conforming applications. However, it also says that some
185 * du implementations may produce output when -a and -s are used together.
186 * gnu du exits with an error code in this case. We choose to simply
187 * ignore -a. This is consistent with -s being equivalent to -d 0.
188 */
138 189
139 /* parse argv[] */ 190 while ((c = getopt(argc, argv, "aHkLsx" "d:" "lc"
140 while ((c = getopt(argc, argv, "slx"
141#ifdef CONFIG_FEATURE_HUMAN_READABLE 191#ifdef CONFIG_FEATURE_HUMAN_READABLE
142 "hm" 192 "hm"
143#endif 193#endif
144 "k")) != EOF) { 194 )) > 0) {
145 switch (c) { 195 switch (c) {
196 case 'a':
197 print_files = INT_MAX;
198 break;
199 case 'H':
200 slink_depth = 1;
201 break;
202 case 'k':
203#ifdef CONFIG_FEATURE_HUMAN_READABLE
204 disp_hr = KILOBYTE;
205#elif !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
206 disp_k = 1;
207#endif
208 break;
209 case 'L':
210 slink_depth = INT_MAX;
211 break;
146 case 's': 212 case 's':
147 print = print_summary; 213 max_print_depth = 0;
214 break;
215 case 'x':
216 one_file_system = 1;
217 break;
218
219 case 'd':
220 max_print_depth = bb_xgetularg10_bnd(optarg, 0, INT_MAX);
148 break; 221 break;
149 case 'l': 222 case 'l':
150 count_hardlinks = 1; 223 count_hardlinks = 1;
151 break; 224 break;
152 case 'x': 225 case 'c':
153 one_file_system = 1; 226 print_final_total = 1;
154 break; 227 break;
155#ifdef CONFIG_FEATURE_HUMAN_READABLE 228#ifdef CONFIG_FEATURE_HUMAN_READABLE
156 case 'h': 229 case 'h':
@@ -160,37 +233,31 @@ int du_main(int argc, char **argv)
160 disp_hr = MEGABYTE; 233 disp_hr = MEGABYTE;
161 break; 234 break;
162#endif 235#endif
163 case 'k':
164 break;
165 default: 236 default:
166 show_usage(); 237 bb_show_usage();
167 } 238 }
168 } 239 }
169 240
170 /* go through remaining args (if any) */ 241 /* go through remaining args (if any) */
242 argv += optind;
171 if (optind >= argc) { 243 if (optind >= argc) {
172 if (du(".") == 0) 244 *--argv = ".";
173 status = EXIT_FAILURE; 245 if (slink_depth == 1) {
174 } else { 246 slink_depth = 0;
175 long sum;
176
177 for (i = optind; i < argc; i++) {
178 sum = du(argv[i]);
179 if (is_directory(argv[i], FALSE, NULL) == FALSE) {
180 print_normal(sum, argv[i]);
181 }
182 reset_ino_dev_hashtable();
183 } 247 }
184 } 248 }
185 249
186 return status; 250 slink_depth_save = slink_depth;
187} 251 total = 0;
252 do {
253 total += du(*argv);
254 slink_depth = slink_depth_save;
255 } while (*++argv);
256 reset_ino_dev_hashtable();
188 257
189/* $Id: du.c,v 1.55 2002/08/23 07:28:45 aaronl Exp $ */ 258 if (print_final_total) {
190/* 259 print(total, "total");
191Local Variables: 260 }
192c-file-style: "linux" 261
193c-basic-offset: 4 262 bb_fflush_stdout_and_exit(status);
194tab-width: 4 263}
195End:
196*/
diff --git a/coreutils/echo.c b/coreutils/echo.c
index 31c031528..b600a1fbd 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -22,94 +22,107 @@
22 * Original copyright notice is retained at the end of this file. 22 * Original copyright notice is retained at the end of this file.
23 */ 23 */
24 24
25/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
26/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
27
28/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
29 *
30 * Because of behavioral differences, implemented configureable SUSv3
31 * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs.
32 * 1) In handling '\c' escape, the previous version only suppressed the
33 * trailing newline. SUSv3 specifies _no_ output after '\c'.
34 * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
35 * The previous version version did not allow 4-digit octals.
36 */
37
25#include <stdio.h> 38#include <stdio.h>
26#include <string.h> 39#include <string.h>
27#include <stdlib.h> 40#include <stdlib.h>
28#include "busybox.h" 41#include "busybox.h"
29 42
30extern int 43extern int echo_main(int argc, char** argv)
31echo_main(int argc, char** argv)
32{ 44{
33 int nflag = 0; 45#ifndef CONFIG_FEATURE_FANCY_ECHO
46#define eflag '\\'
47 ++argv;
48#else
49 const char *p;
50 int nflag = 1;
34 int eflag = 0; 51 int eflag = 0;
35 52
36 /* Skip argv[0]. */ 53 while (*++argv && (**argv == '-')) {
37 argc--; 54 /* If it appears that we are handling options, then make sure
38 argv++;
39
40 while (argc > 0 && *argv[0] == '-')
41 {
42 register char *temp;
43 register int ix;
44
45 /*
46 * If it appears that we are handling options, then make sure
47 * that all of the options specified are actually valid. 55 * that all of the options specified are actually valid.
48 * Otherwise, the string should just be echoed. 56 * Otherwise, the string should just be echoed.
49 */ 57 */
50 temp = argv[0] + 1; 58
51 59 if (!*(p = *argv + 1)) { /* A single '-', so echo it. */
52 for (ix = 0; temp[ix]; ix++)
53 {
54 if (strrchr("neE", temp[ix]) == 0)
55 goto just_echo;
56 }
57
58 if (!*temp)
59 goto just_echo; 60 goto just_echo;
61 }
60 62
61 /* 63 do {
62 * All of the options in temp are valid options to echo. 64 if (strrchr("neE", *p) == 0) {
63 * Handle them.
64 */
65 while (*temp)
66 {
67 if (*temp == 'n')
68 nflag = 1;
69 else if (*temp == 'e')
70 eflag = 1;
71 else if (*temp == 'E')
72 eflag = 0;
73 else
74 goto just_echo; 65 goto just_echo;
66 }
67 } while (*++p);
75 68
76 temp++; 69 /* All of the options in this arg are valid, so handle them. */
77 } 70 p = *argv + 1;
78 argc--; 71 do {
79 argv++; 72 if (*p == 'n') {
73 nflag = 0;
74 } else if (*p == 'e') {
75 eflag = '\\';
76 } else {
77 eflag = 0;
78 }
79 } while (*++p);
80 } 80 }
81 81
82just_echo: 82just_echo:
83 while (argc > 0) { 83#endif
84 const char *arg = argv[0]; 84 while (*argv) {
85 register int c; 85 register int c;
86 86
87 while ((c = *arg++)) { 87 while ((c = *(*argv)++)) {
88 88 if (c == eflag) { /* Check for escape seq. */
89 /* Check for escape sequence. */ 89 if (**argv == 'c') {
90 if (c == '\\' && eflag && *arg) { 90 /* '\c' means cancel newline and
91 if (*arg == 'c') { 91 * ignore all subsequent chars. */
92 /* '\c' means cancel newline. */ 92 goto DONE;
93 nflag = 1; 93 }
94 arg++; 94#ifndef CONFIG_FEATURE_FANCY_ECHO
95 continue; 95 /* SUSv3 specifies that octal escapes must begin with '0'. */
96 } else { 96 if (((unsigned int)(**argv - '1')) >= 7)
97 c = process_escape_sequence(&arg); 97#endif
98 {
99 /* Since SUSv3 mandates a first digit of 0, 4-digit octals
100 * of the form \0### are accepted. */
101 if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) {
102 (*argv)++;
103 }
104 /* bb_process_escape_sequence can handle nul correctly */
105 c = bb_process_escape_sequence((const char **) argv);
98 } 106 }
99 } 107 }
100
101 putchar(c); 108 putchar(c);
102 } 109 }
103 argc--; 110
104 argv++; 111 if (*++argv) {
105 if (argc > 0)
106 putchar(' '); 112 putchar(' ');
113 }
107 } 114 }
108 if (!nflag) 115
116#ifdef CONFIG_FEATURE_FANCY_ECHO
117 if (nflag) {
109 putchar('\n'); 118 putchar('\n');
110 fflush(stdout); 119 }
120#else
121 putchar('\n');
122#endif
111 123
112 return EXIT_SUCCESS; 124DONE:
125 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
113} 126}
114 127
115/*- 128/*-
diff --git a/coreutils/env.c b/coreutils/env.c
index 8bb690b72..db13b3aed 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -24,50 +24,66 @@
24 * Modified for BusyBox by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> 24 * Modified for BusyBox by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
25 */ 25 */
26 26
27/* BB_AUDIT SUSv3 compliant */
28/* http://www.opengroup.org/onlinepubs/007904975/utilities/env.html */
29
30/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
31 *
32 * Fixed bug involving exit return codes if execvp fails. Also added
33 * output error checking.
34 */
35
27#include <stdio.h> 36#include <stdio.h>
28#include <string.h> 37#include <string.h>
29#include <getopt.h>
30#include <stdlib.h> 38#include <stdlib.h>
39#include <errno.h>
31#include <unistd.h> 40#include <unistd.h>
32#include "busybox.h" 41#include "busybox.h"
33 42
34extern int env_main(int argc, char** argv) 43extern int env_main(int argc, char** argv)
35{ 44{
36 char **ep, *p; 45 char **ep, *p;
37 char *cleanenv[1]; 46 char *cleanenv[1] = { NULL };
38 int ignore_environment = 0;
39 int ch; 47 int ch;
40 48
41 while ((ch = getopt(argc, argv, "+iu:")) != -1) { 49 while ((ch = getopt(argc, argv, "iu:")) > 0) {
42 switch(ch) { 50 switch(ch) {
43 case 'i': 51 case 'i':
44 ignore_environment = 1; 52 environ = cleanenv;
45 break; 53 break;
46 case 'u': 54 case 'u':
47 unsetenv(optarg); 55 unsetenv(optarg);
48 break; 56 break;
49 default: 57 default:
50 show_usage(); 58 bb_show_usage();
51 } 59 }
52 } 60 }
53 if (optind != argc && !strcmp(argv[optind], "-")) { 61
54 ignore_environment = 1; 62 argv += optind;
55 argv++; 63
56 } 64 if (*argv && (argv[0][0] == '-') && !argv[0][1]) {
57 if (ignore_environment) {
58 environ = cleanenv; 65 environ = cleanenv;
59 cleanenv[0] = NULL; 66 ++argv;
60 } 67 }
61 for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) 68
62 if (putenv(*argv) < 0) 69 while (*argv && ((p = strchr(*argv, '=')) != NULL)) {
63 perror_msg_and_die("%s", *argv); 70 if (putenv(*argv) < 0) {
71 bb_perror_msg_and_die("putenv");
72 }
73 ++argv;
74 }
75
64 if (*argv) { 76 if (*argv) {
65 execvp(*argv, argv); 77 execvp(*argv, argv);
66 perror_msg_and_die("%s", *argv); 78 bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
79 return (errno == ENOENT) ? 127 : 126; /* SUSv3-mandated exit codes. */
67 } 80 }
68 for (ep = environ; *ep; ep++) 81
82 for (ep = environ; *ep; ep++) {
69 puts(*ep); 83 puts(*ep);
70 return 0; 84 }
85
86 bb_fflush_stdout_and_exit(0);
71} 87}
72 88
73/* 89/*
diff --git a/coreutils/expr.c b/coreutils/expr.c
index 55ae3a969..ecba825d5 100644
--- a/coreutils/expr.c
+++ b/coreutils/expr.c
@@ -78,14 +78,14 @@ int expr_main (int argc, char **argv)
78 VALUE *v; 78 VALUE *v;
79 79
80 if (argc == 1) { 80 if (argc == 1) {
81 error_msg_and_die("too few arguments"); 81 bb_error_msg_and_die("too few arguments");
82 } 82 }
83 83
84 args = argv + 1; 84 args = argv + 1;
85 85
86 v = eval (); 86 v = eval ();
87 if (*args) 87 if (*args)
88 error_msg_and_die ("syntax error"); 88 bb_error_msg_and_die ("syntax error");
89 89
90 if (v->type == integer) 90 if (v->type == integer)
91 printf ("%d\n", v->u.i); 91 printf ("%d\n", v->u.i);
@@ -147,7 +147,7 @@ static int null (VALUE *v)
147static void tostring (VALUE *v) 147static void tostring (VALUE *v)
148{ 148{
149 if (v->type == integer) { 149 if (v->type == integer) {
150 bb_asprintf (&(v->u.s), "%d", v->u.i); 150 bb_xasprintf (&(v->u.s), "%d", v->u.i);
151 v->type = string; 151 v->type = string;
152 } 152 }
153} 153}
@@ -216,7 +216,7 @@ static \
216int name (VALUE *l, VALUE *r) \ 216int name (VALUE *l, VALUE *r) \
217{ \ 217{ \
218 if (!toarith (l) || !toarith (r)) \ 218 if (!toarith (l) || !toarith (r)) \
219 error_msg_and_die ("non-numeric argument"); \ 219 bb_error_msg_and_die ("non-numeric argument"); \
220 return l->u.i op r->u.i; \ 220 return l->u.i op r->u.i; \
221} 221}
222 222
@@ -224,9 +224,9 @@ int name (VALUE *l, VALUE *r) \
224static int name (VALUE *l, VALUE *r) \ 224static int name (VALUE *l, VALUE *r) \
225{ \ 225{ \
226 if (!toarith (l) || !toarith (r)) \ 226 if (!toarith (l) || !toarith (r)) \
227 error_msg_and_die ( "non-numeric argument"); \ 227 bb_error_msg_and_die ( "non-numeric argument"); \
228 if (r->u.i == 0) \ 228 if (r->u.i == 0) \
229 error_msg_and_die ( "division by zero"); \ 229 bb_error_msg_and_die ( "division by zero"); \
230 return l->u.i op r->u.i; \ 230 return l->u.i op r->u.i; \
231} 231}
232 232
@@ -270,7 +270,7 @@ of a basic regular expression is not portable; it is being ignored",
270 re_syntax_options = RE_SYNTAX_POSIX_BASIC; 270 re_syntax_options = RE_SYNTAX_POSIX_BASIC;
271 errmsg = re_compile_pattern (pv->u.s, len, &re_buffer); 271 errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
272 if (errmsg) { 272 if (errmsg) {
273 error_msg_and_die("%s", errmsg); 273 bb_error_msg_and_die("%s", errmsg);
274 } 274 }
275 275
276 len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs); 276 len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
@@ -301,19 +301,19 @@ static VALUE *eval7 (void)
301 VALUE *v; 301 VALUE *v;
302 302
303 if (!*args) 303 if (!*args)
304 error_msg_and_die ( "syntax error"); 304 bb_error_msg_and_die ( "syntax error");
305 305
306 if (nextarg ("(")) { 306 if (nextarg ("(")) {
307 args++; 307 args++;
308 v = eval (); 308 v = eval ();
309 if (!nextarg (")")) 309 if (!nextarg (")"))
310 error_msg_and_die ( "syntax error"); 310 bb_error_msg_and_die ( "syntax error");
311 args++; 311 args++;
312 return v; 312 return v;
313 } 313 }
314 314
315 if (nextarg (")")) 315 if (nextarg (")"))
316 error_msg_and_die ( "syntax error"); 316 bb_error_msg_and_die ( "syntax error");
317 317
318 return str_value (*args++); 318 return str_value (*args++);
319} 319}
@@ -327,7 +327,7 @@ static VALUE *eval6 (void)
327 if (nextarg ("quote")) { 327 if (nextarg ("quote")) {
328 args++; 328 args++;
329 if (!*args) 329 if (!*args)
330 error_msg_and_die ( "syntax error"); 330 bb_error_msg_and_die ( "syntax error");
331 return str_value (*args++); 331 return str_value (*args++);
332 } 332 }
333 else if (nextarg ("length")) { 333 else if (nextarg ("length")) {
@@ -373,7 +373,7 @@ static VALUE *eval6 (void)
373 else { 373 else {
374 v = xmalloc (sizeof(VALUE)); 374 v = xmalloc (sizeof(VALUE));
375 v->type = string; 375 v->type = string;
376 v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); 376 v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
377 } 377 }
378 freev (l); 378 freev (l);
379 freev (i1); 379 freev (i1);
diff --git a/coreutils/false.c b/coreutils/false.c
index 96b18498a..c17de7693 100644
--- a/coreutils/false.c
+++ b/coreutils/false.c
@@ -21,7 +21,8 @@
21 * 21 *
22 */ 22 */
23 23
24/* getopt not needed */ 24/* BB_AUDIT SUSv3 compliant */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/false.html */
25 26
26#include <stdlib.h> 27#include <stdlib.h>
27#include "busybox.h" 28#include "busybox.h"
diff --git a/coreutils/head.c b/coreutils/head.c
index ad21e1b95..dab4de11b 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -1,9 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini head implementation for busybox 3 * head implementation for busybox
4 * 4 *
5 * Copyright (C) 1999 by Lineo, inc. and John Beppu 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -21,82 +20,119 @@
21 * 20 *
22 */ 21 */
23 22
23/* BB_AUDIT SUSv3 compliant */
24/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
26
24#include <stdio.h> 27#include <stdio.h>
25#include <getopt.h>
26#include <stdlib.h> 28#include <stdlib.h>
27#include <string.h> 29#include <limits.h>
28#include <ctype.h> 30#include <ctype.h>
31#include <unistd.h>
29#include "busybox.h" 32#include "busybox.h"
30 33
31static int head(int len, FILE *fp) 34static const char head_opts[] =
32{ 35 "n:"
33 int i; 36#ifdef CONFIG_FEATURE_FANCY_HEAD
34 char *input; 37 "c:qv"
38#endif
39 ;
35 40
36 for (i = 0; i < len; i++) { 41static const char header_fmt_str[] = "\n==> %s <==\n";
37 if ((input = get_line_from_file(fp)) == NULL)
38 break;
39 fputs(input, stdout);
40 free(input);
41 }
42 return 0;
43}
44 42
45/* BusyBoxed head(1) */
46int head_main(int argc, char **argv) 43int head_main(int argc, char **argv)
47{ 44{
45 unsigned long count = 10;
46 unsigned long i;
47#ifdef CONFIG_FEATURE_FANCY_HEAD
48 int count_bytes = 0;
49 int header_threshhold = 1;
50#endif
51
48 FILE *fp; 52 FILE *fp;
49 int need_headers, opt, len = 10, status = EXIT_SUCCESS; 53 const char *fmt;
54 char *p;
55 int opt;
56 int c;
57 int retval = EXIT_SUCCESS;
50 58
51 if (( argc >= 2 ) && ( argv [1][0] == '-' ) && isdigit ( argv [1][1] )) { 59 /* Allow legacy syntax of an initial numeric option without -n. */
52 len = atoi ( &argv [1][1] ); 60 if ((argc > 1) && (argv[1][0] == '-')
53 optind = 2; 61 /* && (isdigit)(argv[1][1]) */
62 && (((unsigned int)(argv[1][1] - '0')) <= 9)
63 ) {
64 --argc;
65 ++argv;
66 p = (*argv) + 1;
67 goto GET_COUNT;
54 } 68 }
55 69
56 /* parse argv[] */ 70 while ((opt = getopt(argc, argv, head_opts)) > 0) {
57 while ((opt = getopt(argc, argv, "n:")) > 0) { 71 switch(opt) {
58 switch (opt) { 72#ifdef CONFIG_FEATURE_FANCY_HEAD
59 case 'n': 73 case 'q':
60 len = atoi(optarg); 74 header_threshhold = INT_MAX;
61 if (len >= 0) 75 break;
76 case 'v':
77 header_threshhold = -1;
62 break; 78 break;
63 /* fallthrough */ 79 case 'c':
64 default: 80 count_bytes = 1;
65 show_usage(); 81 /* fall through */
82#endif
83 case 'n':
84 p = optarg;
85 GET_COUNT:
86 count = bb_xgetularg10(p);
87 break;
88 default:
89 bb_show_usage();
66 } 90 }
67 } 91 }
68 92
69 /* get rest of argv[] or stdin if nothing's left */ 93 argv += optind;
70 if (argv[optind] == NULL) { 94 if (!*argv) {
71 head(len, stdin); 95 *--argv = "-";
72 return status; 96 }
73 }
74 97
75 need_headers = optind != (argc - 1); 98 fmt = header_fmt_str + 1;
76 while (argv[optind]) { 99#ifdef CONFIG_FEATURE_FANCY_HEAD
77 if (strcmp(argv[optind], "-") == 0) { 100 if (argc - optind <= header_threshhold) {
78 fp = stdin; 101 header_threshhold = 0;
79 argv[optind] = "standard input"; 102 }
80 } else { 103#else
81 if ((fp = wfopen(argv[optind], "r")) == NULL) 104 if (argc <= optind + 1) {
82 status = EXIT_FAILURE; 105 fmt += 11;
83 } 106 }
84 if (fp) { 107 /* Now define some things here to avoid #ifdefs in the code below.
85 if (need_headers) { 108 * These should optimize out of the if conditions below. */
86 printf("==> %s <==\n", argv[optind]); 109#define header_threshhold 1
110#define count_bytes 0
111#endif
112
113 do {
114 if ((fp = bb_wfopen_input(*argv)) != NULL) {
115 if (fp == stdin) {
116 *argv = (char *) bb_msg_standard_input;
87 } 117 }
88 head(len, fp); 118 if (header_threshhold) {
89 if (ferror(fp)) { 119 bb_printf(fmt, *argv);
90 perror_msg("%s", argv[optind]);
91 status = EXIT_FAILURE;
92 } 120 }
93 if (optind < argc - 1) 121 i = count;
94 putchar('\n'); 122 while (i && ((c = getc(fp)) != EOF)) {
95 if (fp != stdin) 123 if (count_bytes || (c == '\n')) {
96 fclose(fp); 124 --i;
125 }
126 putchar(c);
127 }
128 if (bb_fclose_nonstdin(fp)) {
129 bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
130 retval = EXIT_FAILURE;
131 }
132 bb_xferror_stdout();
97 } 133 }
98 optind++; 134 fmt = header_fmt_str;
99 } 135 } while (*++argv);
100 136
101 return status; 137 bb_fflush_stdout_and_exit(retval);
102} 138}
diff --git a/coreutils/hostid.c b/coreutils/hostid.c
index 68a2cc659..917dc223e 100644
--- a/coreutils/hostid.c
+++ b/coreutils/hostid.c
@@ -20,13 +20,19 @@
20 * 20 *
21 */ 21 */
22 22
23#include <stdio.h> 23/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
24
24#include <stdlib.h> 25#include <stdlib.h>
25#include <unistd.h> 26#include <unistd.h>
26#include "busybox.h" 27#include "busybox.h"
27 28
28extern int hostid_main(int argc, char **argv) 29extern int hostid_main(int argc, char **argv)
29{ 30{
30 printf("%lx\n", gethostid()); 31 if (argc > 1) {
31 return EXIT_SUCCESS; 32 bb_show_usage();
33 }
34
35 bb_printf("%lx\n", gethostid());
36
37 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
32} 38}
diff --git a/coreutils/id.c b/coreutils/id.c
index c7f61532d..9b2d60dc7 100644
--- a/coreutils/id.c
+++ b/coreutils/id.c
@@ -20,6 +20,8 @@
20 * 20 *
21 */ 21 */
22 22
23/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
24
23#include "busybox.h" 25#include "busybox.h"
24#include <stdio.h> 26#include <stdio.h>
25#include <unistd.h> 27#include <unistd.h>
@@ -27,70 +29,58 @@
27#include <string.h> 29#include <string.h>
28#include <sys/types.h> 30#include <sys/types.h>
29 31
32#define NO_GROUP 1
33#define NO_USER 2
34#define PRINT_REAL 4
35#define NAME_NOT_NUMBER 8
36
30extern int id_main(int argc, char **argv) 37extern int id_main(int argc, char **argv)
31{ 38{
32 int no_user = 0, no_group = 0, print_real = 0;
33 int name_not_number = 0;
34 char user[9], group[9]; 39 char user[9], group[9];
35 long gid;
36 long pwnam, grnam; 40 long pwnam, grnam;
37 int opt; 41 int uid, gid;
42 int flags;
38 43
39 gid = 0; 44 flags = bb_getopt_ulflags(argc, argv, "ugrn");
40 45
41 while ((opt = getopt(argc, argv, "ugrn")) > 0) { 46 if (((flags & (NO_USER | NO_GROUP)) == (NO_USER | NO_GROUP))
42 switch (opt) { 47 || (argc > optind + 1)
43 case 'u': 48 ) {
44 no_group++; 49 bb_show_usage();
45 break;
46 case 'g':
47 no_user++;
48 break;
49 case 'r':
50 print_real++;
51 break;
52 case 'n':
53 name_not_number++;
54 break;
55 default:
56 show_usage();
57 }
58 } 50 }
59 51
60 if (no_user && no_group) show_usage();
61
62 if (argv[optind] == NULL) { 52 if (argv[optind] == NULL) {
63 if (print_real) { 53 if (flags & PRINT_REAL) {
64 my_getpwuid(user, getuid()); 54 uid = getuid();
65 my_getgrgid(group, getgid()); 55 gid = getgid();
66 } else { 56 } else {
67 my_getpwuid(user, geteuid()); 57 uid = geteuid();
68 my_getgrgid(group, getegid()); 58 gid = getegid();
69 } 59 }
60 my_getpwuid(user, uid);
70 } else { 61 } else {
71 safe_strncpy(user, argv[optind], sizeof(user)); 62 safe_strncpy(user, argv[optind], sizeof(user));
72 gid = my_getpwnamegid(user); 63 gid = my_getpwnamegid(user);
73 my_getgrgid(group, gid);
74 } 64 }
65 my_getgrgid(group, gid);
75 66
76 pwnam=my_getpwnam(user); 67 pwnam=my_getpwnam(user);
77 grnam=my_getgrnam(group); 68 grnam=my_getgrnam(group);
78 69
79 if (no_group) { 70 if (flags & (NO_GROUP | NO_USER)) {
80 if(name_not_number) 71 char *s = group;
81 puts(user); 72 if (flags & NO_GROUP) {
82 else 73 s = user;
83 printf("%ld\n", pwnam); 74 grnam = pwnam;
84 } else if (no_user) { 75 }
85 if(name_not_number) 76 if (flags & NAME_NOT_NUMBER) {
86 puts(group); 77 puts(s);
87 else 78 } else {
88 printf("%ld\n", grnam); 79 printf("%ld\n", grnam);
80 }
89 } else { 81 } else {
90 printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group); 82 printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group);
91 } 83 }
92 return(0);
93}
94 84
95 85 bb_fflush_stdout_and_exit(0);
96/* END CODE */ 86}
diff --git a/coreutils/length.c b/coreutils/length.c
index 73becd28a..bce43ab3f 100644
--- a/coreutils/length.c
+++ b/coreutils/length.c
@@ -1,4 +1,7 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2
3/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */
4
2#include <stdlib.h> 5#include <stdlib.h>
3#include <string.h> 6#include <string.h>
4#include <stdio.h> 7#include <stdio.h>
@@ -6,8 +9,11 @@
6 9
7extern int length_main(int argc, char **argv) 10extern int length_main(int argc, char **argv)
8{ 11{
9 if (argc != 2 || **(argv + 1) == '-') 12 if ((argc != 2) || (**(++argv) == '-')) {
10 show_usage(); 13 bb_show_usage();
11 printf("%lu\n", (long)strlen(argv[1])); 14 }
12 return EXIT_SUCCESS; 15
16 bb_printf("%lu\n", (unsigned long)strlen(*argv));
17
18 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
13} 19}
diff --git a/coreutils/libcoreutils/Makefile b/coreutils/libcoreutils/Makefile
new file mode 100644
index 000000000..59ec24ed9
--- /dev/null
+++ b/coreutils/libcoreutils/Makefile
@@ -0,0 +1,30 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2002 Erik Andersen <andersee@debian.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20TOPDIR:= ../../
21LIBCOREUTILS_DIR:=./
22include $(TOPDIR).config
23include $(TOPDIR)Rules.mak
24include Makefile.in
25all: $(libraries-y)
26-include $(TOPDIR).depend
27
28clean:
29 rm -f *.o *.a $(AR_TARGET)
30
diff --git a/coreutils/libcoreutils/Makefile.in b/coreutils/libcoreutils/Makefile.in
new file mode 100644
index 000000000..47391dd49
--- /dev/null
+++ b/coreutils/libcoreutils/Makefile.in
@@ -0,0 +1,32 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2002 Erik Andersen <andersee@debian.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20LIBCOREUTILS_AR:=libcoreutils.a
21ifndef $(LIBCOREUTILS_DIR)
22LIBCOREUTILS_DIR:=$(TOPDIR)coreutils/libcoreutils/
23endif
24
25LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c xgetoptfile_sort_uniq.c
26
27LIBCOREUTILS_OBJS=$(patsubst %.c,$(LIBCOREUTILS_DIR)%.o, $(LIBCOREUTILS_SRC))
28
29libraries-y+=$(LIBCOREUTILS_DIR)$(LIBCOREUTILS_AR)
30
31$(LIBCOREUTILS_DIR)$(LIBCOREUTILS_AR): $(LIBCOREUTILS_OBJS)
32 $(AR) -ro $@ $(LIBCOREUTILS_OBJS)
diff --git a/coreutils/libcoreutils/coreutils.h b/coreutils/libcoreutils/coreutils.h
new file mode 100644
index 000000000..eabca8204
--- /dev/null
+++ b/coreutils/libcoreutils/coreutils.h
@@ -0,0 +1,12 @@
1#ifndef COREUTILS_H
2#define COREUTILS_H 1
3
4typedef int (*stat_func)(const char *fn, struct stat *ps);
5
6extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf);
7extern int cp_mv_stat(const char *fn, struct stat *fn_stat);
8
9extern mode_t getopt_mk_fifo_nod(int argc, char **argv);
10extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode);
11
12#endif
diff --git a/coreutils/libcoreutils/cp_mv_stat.c b/coreutils/libcoreutils/cp_mv_stat.c
new file mode 100644
index 000000000..5a70b0221
--- /dev/null
+++ b/coreutils/libcoreutils/cp_mv_stat.c
@@ -0,0 +1,45 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * coreutils utility routine
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <errno.h>
24#include <sys/stat.h>
25#include "libbb.h"
26#include "coreutils.h"
27
28extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf)
29{
30 if (sf(fn, fn_stat) < 0) {
31 if (errno != ENOENT) {
32 bb_perror_msg("unable to stat `%s'", fn);
33 return -1;
34 }
35 return 0;
36 } else if (S_ISDIR(fn_stat->st_mode)) {
37 return 3;
38 }
39 return 1;
40}
41
42extern int cp_mv_stat(const char *fn, struct stat *fn_stat)
43{
44 return cp_mv_stat2(fn, fn_stat, stat);
45}
diff --git a/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/coreutils/libcoreutils/getopt_mk_fifo_nod.c
new file mode 100644
index 000000000..0872bdcf0
--- /dev/null
+++ b/coreutils/libcoreutils/getopt_mk_fifo_nod.c
@@ -0,0 +1,45 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * coreutils utility routine
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <unistd.h>
26#include "libbb.h"
27#include "coreutils.h"
28
29extern mode_t getopt_mk_fifo_nod(int argc, char **argv)
30{
31 mode_t mode = 0666;
32 int opt;
33
34 while ((opt = getopt(argc, argv, "m:")) > 0) {
35 if (opt == 'm') {
36 mode = 0666;
37 if (bb_parse_mode(optarg, &mode)) {
38 umask(0);
39 continue;
40 }
41 }
42 bb_show_usage();
43 }
44 return mode;
45}
diff --git a/coreutils/libcoreutils/xgetoptfile_sort_uniq.c b/coreutils/libcoreutils/xgetoptfile_sort_uniq.c
new file mode 100644
index 000000000..a63daf97b
--- /dev/null
+++ b/coreutils/libcoreutils/xgetoptfile_sort_uniq.c
@@ -0,0 +1,38 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * coreutils utility routine
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <stdio.h>
24#include <unistd.h>
25#include "libbb.h"
26#include "coreutils.h"
27
28extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode)
29{
30 const char *n;
31
32 if ((n = *argv) != NULL) {
33 if ((*n != '-') || n[1]) {
34 return bb_xfopen(n, mode);
35 }
36 }
37 return (*mode == 'r') ? stdin : stdout;
38}
diff --git a/coreutils/ln.c b/coreutils/ln.c
index 427ffcc6e..2edece104 100644
--- a/coreutils/ln.c
+++ b/coreutils/ln.c
@@ -21,113 +21,86 @@
21 * 21 *
22 */ 22 */
23 23
24#include <stdio.h> 24/* BB_AUDIT SUSv3 compliant */
25#include <dirent.h> 25/* BB_AUDIT GNU options missing: -b, -d, -F, -i, -S, and -v. */
26#include <string.h> 26/* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
27
28/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
29 *
30 * Fixed bug involving -n option. Essentially, -n was always in effect.
31 */
32
27#include <stdlib.h> 33#include <stdlib.h>
28#include <errno.h>
29#include <unistd.h> 34#include <unistd.h>
30#include "busybox.h" 35#include "busybox.h"
31 36
37#define LN_SYMLINK 1
38#define LN_FORCE 2
39#define LN_NODEREFERENCE 4
32 40
33static const int LN_SYMLINK = 1; 41extern int ln_main(int argc, char **argv)
34static const int LN_FORCE = 2;
35static const int LN_NODEREFERENCE = 4;
36
37/*
38 * linkDestName is where the link points to,
39 * linkSrcName is the name of the link to be created.
40 */
41static int fs_link(const char *link_destname, const char *link_srcname,
42 const int flag)
43{ 42{
44 int status; 43 int status = EXIT_SUCCESS;
45 int src_is_dir; 44 int flag;
46 char *src_name = 0; 45 char *last;
46 char *src_name;
47 const char *src; 47 const char *src;
48 int (*link_func)(const char *, const char *);
48 49
49 if (link_destname==NULL) 50 flag = bb_getopt_ulflags(argc, argv, "sfn");
50 return(FALSE); 51
51 52 if (argc == optind) {
52 if (link_srcname==NULL) 53 bb_show_usage();
53 src = link_destname;
54 else
55 src = link_srcname;
56
57 if (flag&LN_NODEREFERENCE)
58 src_is_dir = is_directory(src, TRUE, NULL);
59 else
60 src_is_dir = is_directory(src, FALSE, NULL);
61
62 if ((src_is_dir==TRUE)&&((flag&LN_NODEREFERENCE)==0)) {
63 char* srcdir_name;
64
65 srcdir_name = xstrdup(link_destname);
66 src_name = concat_path_file(src, get_last_path_component(srcdir_name));
67 src = src_name;
68 free(srcdir_name);
69 } 54 }
70 55
71 if (flag&LN_FORCE) 56 last = argv[argc - 1];
72 unlink(src); 57 argv += optind;
73 58
74 if (flag&LN_SYMLINK) 59 if (argc == optind + 1) {
75 status = symlink(link_destname, src); 60 *--argv = last;
76 else 61 last = bb_get_last_path_component(bb_xstrdup(last));
77 status = link(link_destname, src);
78
79 if (status != 0) {
80 perror_msg(src);
81 status = FALSE;
82 } else {
83 status = TRUE;
84 } 62 }
85 free(src_name);
86 return status;
87}
88 63
89extern int ln_main(int argc, char **argv) 64 do {
90{ 65 src_name = 0;
91 int status = EXIT_SUCCESS; 66 src = last;
92 int flag = 0; 67
93 int opt; 68 if (is_directory(src,
94 69 (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
95 /* Parse any options */ 70 NULL)) {
96 while ((opt=getopt(argc, argv, "sfn")) != -1) { 71 src_name = bb_xstrdup(*argv);
97 switch(opt) { 72 src = concat_path_file(src, bb_get_last_path_component(src_name));
98 case 's': 73 free(src_name);
99 flag |= LN_SYMLINK; 74 src_name = (char *)src;
100 break;
101 case 'f':
102 flag |= LN_FORCE;
103 break;
104 case 'n':
105 flag |= LN_NODEREFERENCE;
106 break;
107 default:
108 show_usage();
109 } 75 }
110 } 76
111 if (optind > (argc-1)) { 77 if (flag & LN_FORCE) {
112 show_usage(); 78 unlink(src);
113 } 79 }
114 if (optind == (argc-1)) { 80
115 if (fs_link(argv[optind], 81 link_func = link;
116 get_last_path_component(argv[optind]), flag)==FALSE) 82 if (flag & LN_SYMLINK) {
117 status = EXIT_FAILURE; 83 link_func = symlink;
118 } 84 }
119 while(optind<(argc-1)) { 85
120 if (fs_link(argv[optind], argv[argc-1], flag)==FALSE) 86 if (link_func(*argv, src) != 0) {
121 status = EXIT_FAILURE; 87 bb_perror_msg(src);
122 optind++; 88 status = EXIT_FAILURE;;
123 } 89 }
90
91 free(src_name);
92
93 } while ((++argv)[1]);
94
124 return status; 95 return status;
125} 96}
126 97
127/* 98
128Local Variables: 99
129c-file-style: "linux" 100
130c-basic-offset: 4 101
131tab-width: 4 102
132End: 103
133*/ 104
105
106
diff --git a/coreutils/logname.c b/coreutils/logname.c
index 3e10fba6f..9cedff027 100644
--- a/coreutils/logname.c
+++ b/coreutils/logname.c
@@ -20,6 +20,19 @@
20 * 20 *
21 */ 21 */
22 22
23/* BB_AUDIT SUSv3 compliant */
24/* http://www.opengroup.org/onlinepubs/007904975/utilities/logname.html */
25
26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27 *
28 * SUSv3 specifies the string used is that returned from getlogin().
29 * The previous implementation used getpwuid() for geteuid(), which
30 * is _not_ the same. Erik apparently made this change almost 3 years
31 * ago to avoid failing when no utmp was available. However, the
32 * correct course of action wrt SUSv3 for a failing getlogin() is
33 * a dianostic message and an error return.
34 */
35
23#include <stdio.h> 36#include <stdio.h>
24#include <stdlib.h> 37#include <stdlib.h>
25#include <unistd.h> 38#include <unistd.h>
@@ -27,14 +40,16 @@
27 40
28extern int logname_main(int argc, char **argv) 41extern int logname_main(int argc, char **argv)
29{ 42{
30 char user[9]; 43 const char *p;
31 44
32 if (argc > 1) 45 if (argc > 1) {
33 show_usage(); 46 bb_show_usage();
47 }
34 48
35 if (my_getpwuid(user, geteuid())) { 49 if ((p = getlogin()) != NULL) {
36 puts(user); 50 puts(p);
37 return EXIT_SUCCESS; 51 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
38 } 52 }
39 error_msg_and_die("no login name"); 53
54 bb_perror_msg_and_die("getlogin");
40} 55}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 64ec0fee6..4a4956611 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -73,58 +73,76 @@ enum {
73#endif 73#endif
74 74
75/* what is the overall style of the listing */ 75/* what is the overall style of the listing */
76enum { 76#define STYLE_AUTO (0)
77 STYLE_AUTO = 0, 77#define STYLE_COLUMNS (1U<<21) /* fill columns */
78 STYLE_LONG = 1, /* one record per line, extended info */ 78#define STYLE_LONG (2U<<21) /* one record per line, extended info */
79 STYLE_SINGLE = 2, /* one record per line */ 79#define STYLE_SINGLE (3U<<21) /* one record per line */
80 STYLE_COLUMNS = 3 /* fill columns */ 80
81}; 81#define STYLE_MASK STYLE_SINGLE
82#define STYLE_ONE_RECORD_FLAG STYLE_LONG
82 83
83/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ 84/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */
84/* what file information will be listed */ 85/* what file information will be listed */
85#define LIST_INO (1<<0) 86#define LIST_INO (1U<<0)
86#define LIST_BLOCKS (1<<1) 87#define LIST_BLOCKS (1U<<1)
87#define LIST_MODEBITS (1<<2) 88#define LIST_MODEBITS (1U<<2)
88#define LIST_NLINKS (1<<3) 89#define LIST_NLINKS (1U<<3)
89#define LIST_ID_NAME (1<<4) 90#define LIST_ID_NAME (1U<<4)
90#define LIST_ID_NUMERIC (1<<5) 91#define LIST_ID_NUMERIC (1U<<5)
91#define LIST_SIZE (1<<6) 92#define LIST_SIZE (1U<<6)
92#define LIST_DEV (1<<7) 93#define LIST_DEV (1U<<7)
93#define LIST_DATE_TIME (1<<8) 94#define LIST_DATE_TIME (1U<<8)
94#define LIST_FULLTIME (1<<9) 95#define LIST_FULLTIME (1U<<9)
95#define LIST_FILENAME (1<<10) 96#define LIST_FILENAME (1U<<10)
96#define LIST_SYMLINK (1<<11) 97#define LIST_SYMLINK (1U<<11)
97#define LIST_FILETYPE (1<<12) 98#define LIST_FILETYPE (1U<<12)
98#define LIST_EXEC (1<<13) 99#define LIST_EXEC (1U<<13)
100
101#define LIST_MASK ((LIST_EXEC << 1) - 1)
99 102
100/* what files will be displayed */ 103/* what files will be displayed */
101#define DISP_NORMAL (0) /* show normal filenames */ 104/* TODO -- We may be able to make DISP_NORMAL 0 to save a bit slot. */
102#define DISP_DIRNAME (1<<0) /* 2 or more items? label directories */ 105#define DISP_NORMAL (1U<<14) /* show normal filenames */
103#define DISP_HIDDEN (1<<1) /* show filenames starting with . */ 106#define DISP_DIRNAME (1U<<15) /* 2 or more items? label directories */
104#define DISP_DOT (1<<2) /* show . and .. */ 107#define DISP_HIDDEN (1U<<16) /* show filenames starting with . */
105#define DISP_NOLIST (1<<3) /* show directory as itself, not contents */ 108#define DISP_DOT (1U<<17) /* show . and .. */
106#define DISP_RECURSIVE (1<<4) /* show directory and everything below it */ 109#define DISP_NOLIST (1U<<18) /* show directory as itself, not contents */
107#define DISP_ROWS (1<<5) /* print across rows */ 110#define DISP_RECURSIVE (1U<<19) /* show directory and everything below it */
111#define DISP_ROWS (1U<<20) /* print across rows */
112
113#define DISP_MASK (((DISP_ROWS << 1) - 1) & ~(DISP_NORMAL - 1))
108 114
109#ifdef CONFIG_FEATURE_LS_SORTFILES 115#ifdef CONFIG_FEATURE_LS_SORTFILES
110/* how will the files be sorted */ 116/* how will the files be sorted */
111static const int SORT_FORWARD = 0; /* sort in reverse order */ 117#define SORT_ORDER_FORWARD 0 /* sort in reverse order */
112static const int SORT_REVERSE = 1; /* sort in reverse order */ 118#define SORT_ORDER_REVERSE (1U<<27) /* sort in reverse order */
113static const int SORT_NAME = 2; /* sort by file name */ 119
114static const int SORT_SIZE = 3; /* sort by file size */ 120#define SORT_NAME 0 /* sort by file name */
115static const int SORT_ATIME = 4; /* sort by last access time */ 121#define SORT_SIZE (1U<<28) /* sort by file size */
116static const int SORT_CTIME = 5; /* sort by last change time */ 122#define SORT_ATIME (2U<<28) /* sort by last access time */
117static const int SORT_MTIME = 6; /* sort by last modification time */ 123#define SORT_CTIME (3U<<28) /* sort by last change time */
118static const int SORT_VERSION = 7; /* sort by version */ 124#define SORT_MTIME (4U<<28) /* sort by last modification time */
119static const int SORT_EXT = 8; /* sort by file name extension */ 125#define SORT_VERSION (5U<<28) /* sort by version */
120static const int SORT_DIR = 9; /* sort by file or directory */ 126#define SORT_EXT (6U<<28) /* sort by file name extension */
127#define SORT_DIR (7U<<28) /* sort by file or directory */
128
129#define SORT_MASK (7U<<28)
121#endif 130#endif
122 131
123#ifdef CONFIG_FEATURE_LS_TIMESTAMPS 132#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
124/* which of the three times will be used */ 133/* which of the three times will be used */
125static const int TIME_MOD = 0; 134#define TIME_MOD 0
126static const int TIME_CHANGE = 1; 135#define TIME_CHANGE (1U<<23)
127static const int TIME_ACCESS = 2; 136#define TIME_ACCESS (1U<<24)
137
138#define TIME_MASK (3U<<23)
139#endif
140
141#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
142#define FOLLOW_LINKS (1U<<25)
143#endif
144#ifdef CONFIG_FEATURE_HUMAN_READABLE
145#define LS_DISP_HR (1U<<26)
128#endif 146#endif
129 147
130#define LIST_SHORT (LIST_FILENAME) 148#define LIST_SHORT (LIST_FILENAME)
@@ -133,9 +151,9 @@ static const int TIME_ACCESS = 2;
133 LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK) 151 LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK)
134#define LIST_ILONG (LIST_INO | LIST_LONG) 152#define LIST_ILONG (LIST_INO | LIST_LONG)
135 153
136static const int SPLIT_DIR = 0; 154#define SPLIT_DIR 1
137static const int SPLIT_FILE = 1; 155#define SPLIT_FILE 0
138static const int SPLIT_SUBDIR = 2; 156#define SPLIT_SUBDIR 2
139 157
140#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) 158#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
141#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) 159#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
@@ -169,20 +187,7 @@ static struct dnode **list_dir(const char *);
169static struct dnode **dnalloc(int); 187static struct dnode **dnalloc(int);
170static int list_single(struct dnode *); 188static int list_single(struct dnode *);
171 189
172static unsigned int disp_opts; 190static unsigned int all_fmt;
173static unsigned int style_fmt;
174static unsigned int list_fmt;
175
176#ifdef CONFIG_FEATURE_LS_SORTFILES
177static unsigned int sort_opts;
178static unsigned int sort_order;
179#endif
180#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
181static unsigned int time_fmt;
182#endif
183#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
184static unsigned int follow_links = FALSE;
185#endif
186 191
187#ifdef CONFIG_FEATURE_AUTOWIDTH 192#ifdef CONFIG_FEATURE_AUTOWIDTH
188static unsigned short terminal_width = TERMINAL_WIDTH; 193static unsigned short terminal_width = TERMINAL_WIDTH;
@@ -194,26 +199,22 @@ static unsigned short tabstops = COLUMN_GAP;
194 199
195static int status = EXIT_SUCCESS; 200static int status = EXIT_SUCCESS;
196 201
197#ifdef CONFIG_FEATURE_HUMAN_READABLE
198static unsigned long ls_disp_hr = 0;
199#endif
200
201static struct dnode *my_stat(char *fullname, char *name) 202static struct dnode *my_stat(char *fullname, char *name)
202{ 203{
203 struct stat dstat; 204 struct stat dstat;
204 struct dnode *cur; 205 struct dnode *cur;
205 206
206#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS 207#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
207 if (follow_links) { 208 if (all_fmt & FOLLOW_LINKS) {
208 if (stat(fullname, &dstat)) { 209 if (stat(fullname, &dstat)) {
209 perror_msg("%s", fullname); 210 bb_perror_msg("%s", fullname);
210 status = EXIT_FAILURE; 211 status = EXIT_FAILURE;
211 return 0; 212 return 0;
212 } 213 }
213 } else 214 } else
214#endif 215#endif
215 if (lstat(fullname, &dstat)) { 216 if (lstat(fullname, &dstat)) {
216 perror_msg("%s", fullname); 217 bb_perror_msg("%s", fullname);
217 status = EXIT_FAILURE; 218 status = EXIT_FAILURE;
218 return 0; 219 return 0;
219 } 220 }
@@ -253,9 +254,9 @@ static char bgcolor(mode_t mode)
253#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR) 254#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR)
254static char append_char(mode_t mode) 255static char append_char(mode_t mode)
255{ 256{
256 if (!(list_fmt & LIST_FILETYPE)) 257 if (!(all_fmt & LIST_FILETYPE))
257 return '\0'; 258 return '\0';
258 if ((list_fmt & LIST_EXEC) && S_ISREG(mode) 259 if ((all_fmt & LIST_EXEC) && S_ISREG(mode)
259 && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) 260 && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
260 return '*'; 261 return '*';
261 return APPCHAR(mode); 262 return APPCHAR(mode);
@@ -263,13 +264,11 @@ static char append_char(mode_t mode)
263#endif 264#endif
264 265
265/*----------------------------------------------------------------------*/ 266/*----------------------------------------------------------------------*/
266static int is_subdir(struct dnode *dn)
267{
268 return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 &&
269 strcmp(dn->name, "..") != 0);
270}
271 267
272static int countdirs(struct dnode **dn, int nfiles) 268#define countdirs(A,B) count_dirs((A), (B), 1)
269#define countsubdirs(A,B) count_dirs((A), (B), 0)
270
271static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
273{ 272{
274 int i, dirs; 273 int i, dirs;
275 274
@@ -277,25 +276,17 @@ static int countdirs(struct dnode **dn, int nfiles)
277 return (0); 276 return (0);
278 dirs = 0; 277 dirs = 0;
279 for (i = 0; i < nfiles; i++) { 278 for (i = 0; i < nfiles; i++) {
280 if (S_ISDIR(dn[i]->dstat.st_mode)) 279 if (S_ISDIR(dn[i]->dstat.st_mode)
280 && (notsubdirs
281 || ((dn[i]->name[0] != '.')
282 || (dn[i]->name[1]
283 && ((dn[i]->name[1] != '.')
284 || dn[i]->name[2])))))
281 dirs++; 285 dirs++;
282 } 286 }
283 return (dirs); 287 return (dirs);
284} 288}
285 289
286static int countsubdirs(struct dnode **dn, int nfiles)
287{
288 int i, subdirs;
289
290 if (dn == NULL || nfiles < 1)
291 return 0;
292 subdirs = 0;
293 for (i = 0; i < nfiles; i++)
294 if (is_subdir(dn[i]))
295 subdirs++;
296 return subdirs;
297}
298
299static int countfiles(struct dnode **dnp) 290static int countfiles(struct dnode **dnp)
300{ 291{
301 int nfiles; 292 int nfiles;
@@ -364,18 +355,18 @@ static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
364 355
365 /* copy the entrys into the file or dir array */ 356 /* copy the entrys into the file or dir array */
366 for (d = i = 0; i < nfiles; i++) { 357 for (d = i = 0; i < nfiles; i++) {
367 if (which == SPLIT_DIR) { 358 if (S_ISDIR(dn[i]->dstat.st_mode)) {
368 if (S_ISDIR(dn[i]->dstat.st_mode)) { 359 if (which & (SPLIT_DIR|SPLIT_SUBDIR)) {
369 dnp[d++] = dn[i]; 360 if ((which & SPLIT_DIR)
370 } /* else skip the file */ 361 || ((dn[i]->name[0] != '.')
371 } else if (which == SPLIT_SUBDIR) { 362 || (dn[i]->name[1]
372 if (is_subdir(dn[i])) { 363 && ((dn[i]->name[1] != '.')
373 dnp[d++] = dn[i]; 364 || dn[i]->name[2])))) {
374 } /* else skip the file or dir */ 365 dnp[d++] = dn[i];
375 } else { 366 }
376 if (!(S_ISDIR(dn[i]->dstat.st_mode))) { 367 }
377 dnp[d++] = dn[i]; 368 } else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) {
378 } /* else skip the dir */ 369 dnp[d++] = dn[i];
379 } 370 }
380 } 371 }
381 return (dnp); 372 return (dnp);
@@ -385,29 +376,24 @@ static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
385#ifdef CONFIG_FEATURE_LS_SORTFILES 376#ifdef CONFIG_FEATURE_LS_SORTFILES
386static int sortcmp(struct dnode *d1, struct dnode *d2) 377static int sortcmp(struct dnode *d1, struct dnode *d2)
387{ 378{
388 int cmp, dif; 379 unsigned int sort_opts = all_fmt & SORT_MASK;
380 int dif;
389 381
390 cmp = 0; 382 dif = 0; /* assume SORT_NAME */
391 if (sort_opts == SORT_SIZE) { 383 if (sort_opts == SORT_SIZE) {
392 dif = (int) (d1->dstat.st_size - d2->dstat.st_size); 384 dif = (int) (d2->dstat.st_size - d1->dstat.st_size);
393 } else if (sort_opts == SORT_ATIME) { 385 } else if (sort_opts == SORT_ATIME) {
394 dif = (int) (d1->dstat.st_atime - d2->dstat.st_atime); 386 dif = (int) (d2->dstat.st_atime - d1->dstat.st_atime);
395 } else if (sort_opts == SORT_CTIME) { 387 } else if (sort_opts == SORT_CTIME) {
396 dif = (int) (d1->dstat.st_ctime - d2->dstat.st_ctime); 388 dif = (int) (d2->dstat.st_ctime - d1->dstat.st_ctime);
397 } else if (sort_opts == SORT_MTIME) { 389 } else if (sort_opts == SORT_MTIME) {
398 dif = (int) (d1->dstat.st_mtime - d2->dstat.st_mtime); 390 dif = (int) (d2->dstat.st_mtime - d1->dstat.st_mtime);
399 } else if (sort_opts == SORT_DIR) { 391 } else if (sort_opts == SORT_DIR) {
400 dif = S_ISDIR(d1->dstat.st_mode) - S_ISDIR(d2->dstat.st_mode); 392 dif = S_ISDIR(d2->dstat.st_mode) - S_ISDIR(d1->dstat.st_mode);
401 /* } else if (sort_opts == SORT_VERSION) { */ 393 /* } else if (sort_opts == SORT_VERSION) { */
402 /* } else if (sort_opts == SORT_EXT) { */ 394 /* } else if (sort_opts == SORT_EXT) { */
403 } else { /* assume SORT_NAME */
404 dif = 0;
405 } 395 }
406 396
407 if (dif > 0)
408 cmp = -1;
409 if (dif < 0)
410 cmp = 1;
411 if (dif == 0) { 397 if (dif == 0) {
412 /* sort by name- may be a tie_breaker for time or size cmp */ 398 /* sort by name- may be a tie_breaker for time or size cmp */
413#ifdef CONFIG_LOCALE_SUPPORT 399#ifdef CONFIG_LOCALE_SUPPORT
@@ -415,16 +401,12 @@ static int sortcmp(struct dnode *d1, struct dnode *d2)
415#else 401#else
416 dif = strcmp(d1->name, d2->name); 402 dif = strcmp(d1->name, d2->name);
417#endif 403#endif
418 if (dif > 0)
419 cmp = 1;
420 if (dif < 0)
421 cmp = -1;
422 } 404 }
423 405
424 if (sort_order == SORT_REVERSE) { 406 if (all_fmt & SORT_ORDER_REVERSE) {
425 cmp = -1 * cmp; 407 dif = -dif;
426 } 408 }
427 return (cmp); 409 return (dif);
428} 410}
429 411
430/*----------------------------------------------------------------------*/ 412/*----------------------------------------------------------------------*/
@@ -463,20 +445,17 @@ static void showfiles(struct dnode **dn, int nfiles)
463 if (dn == NULL || nfiles < 1) 445 if (dn == NULL || nfiles < 1)
464 return; 446 return;
465 447
466 switch (style_fmt) { 448 if (all_fmt & STYLE_ONE_RECORD_FLAG) {
467 case STYLE_LONG: /* one record per line, extended info */
468 case STYLE_SINGLE: /* one record per line */
469 ncols = 1; 449 ncols = 1;
470 break; 450 } else {
471 default: 451 /* find the longest file name- use that as the column width */
472 /* find the longest file name- use that as the column width */ 452 for (i = 0; i < nfiles; i++) {
473 for (i = 0; i < nfiles; i++) {
474 int len = strlen(dn[i]->name) + 453 int len = strlen(dn[i]->name) +
475 ((list_fmt & LIST_INO) ? 8 : 0) + 454 ((all_fmt & LIST_INO) ? 8 : 0) +
476 ((list_fmt & LIST_BLOCKS) ? 5 : 0); 455 ((all_fmt & LIST_BLOCKS) ? 5 : 0);
477 if (column_width < len) 456 if (column_width < len)
478 column_width = len; 457 column_width = len;
479 } 458 }
480 column_width += tabstops; 459 column_width += tabstops;
481 ncols = (int) (terminal_width / column_width); 460 ncols = (int) (terminal_width / column_width);
482 } 461 }
@@ -494,7 +473,7 @@ static void showfiles(struct dnode **dn, int nfiles)
494 for (nc = 0; nc < ncols; nc++) { 473 for (nc = 0; nc < ncols; nc++) {
495 /* reach into the array based on the column and row */ 474 /* reach into the array based on the column and row */
496 i = (nc * nrows) + row; /* assume display by column */ 475 i = (nc * nrows) + row; /* assume display by column */
497 if (disp_opts & DISP_ROWS) 476 if (all_fmt & DISP_ROWS)
498 i = (row * ncols) + nc; /* display across row */ 477 i = (row * ncols) + nc; /* display across row */
499 if (i < nfiles) { 478 if (i < nfiles) {
500 if (column > 0) { 479 if (column > 0) {
@@ -528,7 +507,7 @@ static void showdirs(struct dnode **dn, int ndirs)
528 return; 507 return;
529 508
530 for (i = 0; i < ndirs; i++) { 509 for (i = 0; i < ndirs; i++) {
531 if (disp_opts & (DISP_DIRNAME | DISP_RECURSIVE)) { 510 if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
532 printf("\n%s:\n", dn[i]->fullname); 511 printf("\n%s:\n", dn[i]->fullname);
533 } 512 }
534 subdnp = list_dir(dn[i]->fullname); 513 subdnp = list_dir(dn[i]->fullname);
@@ -540,7 +519,7 @@ static void showdirs(struct dnode **dn, int ndirs)
540#endif 519#endif
541 showfiles(subdnp, nfiles); 520 showfiles(subdnp, nfiles);
542#ifdef CONFIG_FEATURE_LS_RECURSIVE 521#ifdef CONFIG_FEATURE_LS_RECURSIVE
543 if (disp_opts & DISP_RECURSIVE) { 522 if (all_fmt & DISP_RECURSIVE) {
544 /* recursive- list the sub-dirs */ 523 /* recursive- list the sub-dirs */
545 dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR); 524 dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR);
546 dndirs = countsubdirs(subdnp, nfiles); 525 dndirs = countsubdirs(subdnp, nfiles);
@@ -573,7 +552,7 @@ static struct dnode **list_dir(const char *path)
573 nfiles = 0; 552 nfiles = 0;
574 dir = opendir(path); 553 dir = opendir(path);
575 if (dir == NULL) { 554 if (dir == NULL) {
576 perror_msg("%s", path); 555 bb_perror_msg("%s", path);
577 status = EXIT_FAILURE; 556 status = EXIT_FAILURE;
578 return (NULL); /* could not open the dir */ 557 return (NULL); /* could not open the dir */
579 } 558 }
@@ -585,9 +564,9 @@ static struct dnode **list_dir(const char *path)
585 if ((entry->d_name[1] == 0 || ( 564 if ((entry->d_name[1] == 0 || (
586 entry->d_name[1] == '.' 565 entry->d_name[1] == '.'
587 && entry->d_name[2] == 0)) 566 && entry->d_name[2] == 0))
588 && !(disp_opts & DISP_DOT)) 567 && !(all_fmt & DISP_DOT))
589 continue; 568 continue;
590 if (!(disp_opts & DISP_HIDDEN)) 569 if (!(all_fmt & DISP_HIDDEN))
591 continue; 570 continue;
592 } 571 }
593 fullname = concat_path_file(path, entry->d_name); 572 fullname = concat_path_file(path, entry->d_name);
@@ -636,9 +615,9 @@ static int list_single(struct dnode *dn)
636 615
637#ifdef CONFIG_FEATURE_LS_TIMESTAMPS 616#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
638 ttime = dn->dstat.st_mtime; /* the default time */ 617 ttime = dn->dstat.st_mtime; /* the default time */
639 if (time_fmt & TIME_ACCESS) 618 if (all_fmt & TIME_ACCESS)
640 ttime = dn->dstat.st_atime; 619 ttime = dn->dstat.st_atime;
641 if (time_fmt & TIME_CHANGE) 620 if (all_fmt & TIME_CHANGE)
642 ttime = dn->dstat.st_ctime; 621 ttime = dn->dstat.st_ctime;
643 filetime = ctime(&ttime); 622 filetime = ctime(&ttime);
644#endif 623#endif
@@ -647,7 +626,7 @@ static int list_single(struct dnode *dn)
647#endif 626#endif
648 627
649 for (i = 0; i <= 31; i++) { 628 for (i = 0; i <= 31; i++) {
650 switch (list_fmt & (1 << i)) { 629 switch (all_fmt & (1 << i)) {
651 case LIST_INO: 630 case LIST_INO:
652 column += printf("%7ld ", (long int) dn->dstat.st_ino); 631 column += printf("%7ld ", (long int) dn->dstat.st_ino);
653 break; 632 break;
@@ -659,7 +638,7 @@ static int list_single(struct dnode *dn)
659#endif 638#endif
660 break; 639 break;
661 case LIST_MODEBITS: 640 case LIST_MODEBITS:
662 column += printf("%-10s ", (char *) mode_string(dn->dstat.st_mode)); 641 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
663 break; 642 break;
664 case LIST_NLINKS: 643 case LIST_NLINKS:
665 column += printf("%4ld ", (long) dn->dstat.st_nlink); 644 column += printf("%4ld ", (long) dn->dstat.st_nlink);
@@ -683,7 +662,7 @@ static int list_single(struct dnode *dn)
683 (int) MINOR(dn->dstat.st_rdev)); 662 (int) MINOR(dn->dstat.st_rdev));
684 } else { 663 } else {
685#ifdef CONFIG_FEATURE_HUMAN_READABLE 664#ifdef CONFIG_FEATURE_HUMAN_READABLE
686 if (ls_disp_hr == TRUE) { 665 if (all_fmt & LS_DISP_HR) {
687 column += printf("%9s ", 666 column += printf("%9s ",
688 make_human_readable_str(dn->dstat.st_size, 1, 0)); 667 make_human_readable_str(dn->dstat.st_size, 1, 0));
689 } else 668 } else
@@ -700,7 +679,7 @@ static int list_single(struct dnode *dn)
700#ifdef CONFIG_FEATURE_LS_TIMESTAMPS 679#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
701 case LIST_FULLTIME: 680 case LIST_FULLTIME:
702 case LIST_DATE_TIME: 681 case LIST_DATE_TIME:
703 if (list_fmt & LIST_FULLTIME) { 682 if (all_fmt & LIST_FULLTIME) {
704 printf("%24.24s ", filetime); 683 printf("%24.24s ", filetime);
705 column += 25; 684 column += 25;
706 break; 685 break;
@@ -774,47 +753,8 @@ static int list_single(struct dnode *dn)
774} 753}
775 754
776/*----------------------------------------------------------------------*/ 755/*----------------------------------------------------------------------*/
777extern int ls_main(int argc, char **argv)
778{
779 struct dnode **dnf, **dnd;
780 int dnfiles, dndirs;
781 struct dnode *dn, *cur, **dnp;
782 int i, nfiles;
783 int opt;
784 int oi, ac;
785 char **av;
786
787#ifdef CONFIG_FEATURE_AUTOWIDTH
788 struct winsize win = { 0, 0, 0, 0 };
789#endif
790
791 disp_opts = DISP_NORMAL;
792 style_fmt = STYLE_AUTO;
793 list_fmt = LIST_SHORT;
794#ifdef CONFIG_FEATURE_LS_SORTFILES
795 sort_opts = SORT_NAME;
796 sort_order = SORT_FORWARD;
797#endif
798#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
799 time_fmt = TIME_MOD;
800#endif
801#ifdef CONFIG_FEATURE_AUTOWIDTH
802 ioctl(fileno(stdout), TIOCGWINSZ, &win);
803 if (win.ws_col > 0)
804 terminal_width = win.ws_col - 1;
805#endif
806 nfiles = 0;
807 756
808#ifdef CONFIG_FEATURE_LS_COLOR 757static const char ls_opts[] = "1AaCdgilnsx"
809 if (isatty(fileno(stdout)))
810 show_color = 1;
811#endif
812
813 /* process options */
814 while ((opt = getopt(argc, argv, "1AaCdgilnsx"
815#ifdef CONFIG_FEATURE_AUTOWIDTH
816 "T:w:"
817#endif
818#ifdef CONFIG_FEATURE_LS_FILETYPES 758#ifdef CONFIG_FEATURE_LS_FILETYPES
819 "Fp" 759 "Fp"
820#endif 760#endif
@@ -825,7 +765,7 @@ extern int ls_main(int argc, char **argv)
825 "rSvX" 765 "rSvX"
826#endif 766#endif
827#ifdef CONFIG_FEATURE_LS_TIMESTAMPS 767#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
828 "cetu" 768 "ecut"
829#endif 769#endif
830#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS 770#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
831 "L" 771 "L"
@@ -833,141 +773,180 @@ extern int ls_main(int argc, char **argv)
833#ifdef CONFIG_FEATURE_HUMAN_READABLE 773#ifdef CONFIG_FEATURE_HUMAN_READABLE
834 "h" 774 "h"
835#endif 775#endif
836 "k")) > 0) { 776 "k"
837 switch (opt) { 777#ifdef CONFIG_FEATURE_AUTOWIDTH
838 case '1': 778 "T:w:"
839 style_fmt = STYLE_SINGLE;
840 list_fmt = LIST_SHORT;
841 break;
842 case 'A':
843 disp_opts |= DISP_HIDDEN;
844 break;
845 case 'a':
846 disp_opts |= DISP_HIDDEN | DISP_DOT;
847 break;
848 case 'C':
849 style_fmt = STYLE_COLUMNS;
850 list_fmt = LIST_SHORT;
851 break;
852 case 'd':
853 disp_opts |= DISP_NOLIST;
854 break;
855 case 'g': /* ignore -- for ftp servers */
856 break;
857 case 'i':
858 list_fmt |= LIST_INO;
859 break;
860 case 'l':
861 style_fmt = STYLE_LONG;
862 list_fmt |= LIST_LONG;
863#ifdef CONFIG_FEATURE_HUMAN_READABLE
864 ls_disp_hr = FALSE;
865#endif 779#endif
866 break; 780 ;
867 case 'n': 781
868 list_fmt |= LIST_ID_NUMERIC; 782#define LIST_MASK_TRIGGER LIST_SHORT
869 break; 783#define STYLE_MASK_TRIGGER STYLE_MASK
870 case 's': 784#define SORT_MASK_TRIGGER SORT_MASK
871 list_fmt |= LIST_BLOCKS; 785#define DISP_MASK_TRIGGER DISP_ROWS
872 break; 786#define TIME_MASK_TRIGGER TIME_MASK
873 case 'x': 787
874 disp_opts = DISP_ROWS; 788static const unsigned opt_flags[] = {
875 break; 789 LIST_SHORT | STYLE_SINGLE, /* 1 */
790 DISP_HIDDEN, /* A */
791 DISP_HIDDEN | DISP_DOT, /* a */
792 LIST_SHORT | STYLE_COLUMNS, /* C */
793 DISP_NOLIST, /* d */
794 0, /* g - ingored */
795 LIST_INO, /* i */
796 LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */
797 LIST_ID_NUMERIC, /* n */
798 LIST_BLOCKS, /* s */
799 DISP_ROWS, /* x */
876#ifdef CONFIG_FEATURE_LS_FILETYPES 800#ifdef CONFIG_FEATURE_LS_FILETYPES
877 case 'F': 801 LIST_FILETYPE | LIST_EXEC, /* F */
878 list_fmt |= LIST_FILETYPE | LIST_EXEC; 802 LIST_FILETYPE, /* p */
879 break;
880 case 'p':
881 list_fmt |= LIST_FILETYPE;
882 break;
883#endif 803#endif
884#ifdef CONFIG_FEATURE_LS_RECURSIVE 804#ifdef CONFIG_FEATURE_LS_RECURSIVE
885 case 'R': 805 DISP_RECURSIVE, /* R */
886 disp_opts |= DISP_RECURSIVE;
887 break;
888#endif 806#endif
889#ifdef CONFIG_FEATURE_LS_SORTFILES 807#ifdef CONFIG_FEATURE_LS_SORTFILES
890 case 'r': 808 SORT_ORDER_REVERSE, /* r */
891 sort_order |= SORT_REVERSE; 809 SORT_SIZE, /* S */
892 break; 810 SORT_VERSION, /* v */
893 case 'S': 811 SORT_EXT, /* v */
894 sort_opts = SORT_SIZE;
895 break;
896 case 'v':
897 sort_opts = SORT_VERSION;
898 break;
899 case 'X':
900 sort_opts = SORT_EXT;
901 break;
902#endif 812#endif
903#ifdef CONFIG_FEATURE_LS_TIMESTAMPS 813#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
904 case 'e': 814 LIST_FULLTIME, /* e */
905 list_fmt |= LIST_FULLTIME;
906 break;
907 case 'c':
908 time_fmt = TIME_CHANGE;
909#ifdef CONFIG_FEATURE_LS_SORTFILES 815#ifdef CONFIG_FEATURE_LS_SORTFILES
910 sort_opts = SORT_CTIME; 816 TIME_CHANGE | SORT_CTIME, /* c */
817#else
818 TIME_CHANGE, /* c */
911#endif 819#endif
912 break;
913 case 'u':
914 time_fmt = TIME_ACCESS;
915#ifdef CONFIG_FEATURE_LS_SORTFILES 820#ifdef CONFIG_FEATURE_LS_SORTFILES
916 sort_opts = SORT_ATIME; 821 TIME_ACCESS | SORT_ATIME, /* u */
822#else
823 TIME_ACCESS, /* u */
917#endif 824#endif
918 break;
919 case 't':
920#ifdef CONFIG_FEATURE_LS_SORTFILES 825#ifdef CONFIG_FEATURE_LS_SORTFILES
921 sort_opts = SORT_MTIME; 826 SORT_MTIME, /* t */
827#else
828 0, /* t - ignored -- is this correct? */
922#endif 829#endif
923 break;
924#endif 830#endif
925#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS 831#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
926 case 'L': 832 FOLLOW_LINKS, /* L */
927 follow_links = TRUE; 833#endif
928 break; 834#ifdef CONFIG_FEATURE_HUMAN_READABLE
835LS_DISP_HR, /* h */
836#endif
837 0, /* k - ingored */
838};
839
840
841/*----------------------------------------------------------------------*/
842
843extern int ls_main(int argc, char **argv)
844{
845 struct dnode **dnf, **dnd;
846 int dnfiles, dndirs;
847 struct dnode *dn, *cur, **dnp;
848 int i, nfiles;
849 int opt;
850 int oi, ac;
851 char **av;
852
853#ifdef CONFIG_FEATURE_AUTOWIDTH
854 struct winsize win = { 0, 0, 0, 0 };
855#endif
856
857 all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO
858#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
859 | TIME_MOD
860#endif
861#ifdef CONFIG_FEATURE_LS_SORTFILES
862 | SORT_NAME | SORT_ORDER_FORWARD
863#endif
864 ;
865#ifdef CONFIG_FEATURE_AUTOWIDTH
866 ioctl(fileno(stdout), TIOCGWINSZ, &win);
867 if (win.ws_col > 0)
868 terminal_width = win.ws_col - 1;
869#endif
870 nfiles = 0;
871
872#ifdef CONFIG_FEATURE_LS_COLOR
873 if (isatty(fileno(stdout)))
874 show_color = 1;
929#endif 875#endif
876
877 /* process options */
878 while ((opt = getopt(argc, argv, ls_opts)) > 0) {
930#ifdef CONFIG_FEATURE_AUTOWIDTH 879#ifdef CONFIG_FEATURE_AUTOWIDTH
931 case 'T': 880 if (opt == 'T') {
932 tabstops = atoi(optarg); 881 tabstops = atoi(optarg);
933 break; 882 continue;
934 case 'w': 883 }
884 if (opt == 'w') {
935 terminal_width = atoi(optarg); 885 terminal_width = atoi(optarg);
936 break; 886 continue;
887 }
888 if (opt == ':') {
889 goto print_usage_message;
890 }
937#endif 891#endif
892 {
893 unsigned int flags;
894 const char *p = strchr(ls_opts, opt);
895 if (!p) { /* shouldn't be necessary */
896 goto print_usage_message;
897 }
898 flags = opt_flags[(int)(p - ls_opts)];
899 if (flags & LIST_MASK_TRIGGER) {
900 all_fmt &= ~LIST_MASK;
901 }
902 if (flags & STYLE_MASK_TRIGGER) {
903 all_fmt &= ~STYLE_MASK;
904 }
905 if (flags & SORT_MASK_TRIGGER) {
906 all_fmt &= ~SORT_MASK;
907 }
908 if (flags & DISP_MASK_TRIGGER) {
909 all_fmt &= ~DISP_MASK;
910 }
911 if (flags & TIME_MASK_TRIGGER) {
912 all_fmt &= ~TIME_MASK;
913 }
938#ifdef CONFIG_FEATURE_HUMAN_READABLE 914#ifdef CONFIG_FEATURE_HUMAN_READABLE
939 case 'h': 915 if (opt == 'l') {
940 ls_disp_hr = TRUE; 916 all_fmt &= ~LS_DISP_HR;
941 break; 917 }
942#endif 918#endif
943 case 'k': 919 all_fmt |= flags;
944 break;
945 default:
946 goto print_usage_message;
947 } 920 }
948 } 921 }
949 922
923
950 /* sort out which command line options take precedence */ 924 /* sort out which command line options take precedence */
951#ifdef CONFIG_FEATURE_LS_RECURSIVE 925#ifdef CONFIG_FEATURE_LS_RECURSIVE
952 if (disp_opts & DISP_NOLIST) 926 if (all_fmt & DISP_NOLIST)
953 disp_opts &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ 927 all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */
954#endif 928#endif
955#if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES) 929#if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES)
956 if (time_fmt & TIME_CHANGE) 930 if (all_fmt & TIME_CHANGE)
957 sort_opts = SORT_CTIME; 931 all_fmt = (all_fmt & ~SORT_MASK) | SORT_CTIME;
958 if (time_fmt & TIME_ACCESS) 932 if (all_fmt & TIME_ACCESS)
959 sort_opts = SORT_ATIME; 933 all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
960#endif 934#endif
961 if (style_fmt != STYLE_LONG) /* only for long list */ 935 if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */
962 list_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC); 936 all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC);
963#ifdef CONFIG_FEATURE_LS_USERNAME 937#ifdef CONFIG_FEATURE_LS_USERNAME
964 if (style_fmt == STYLE_LONG && (list_fmt & LIST_ID_NUMERIC)) 938 if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
965 list_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ 939 all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */
966#endif 940#endif
967 941
968 /* choose a display format */ 942 /* choose a display format */
969 if (style_fmt == STYLE_AUTO) 943 if ((all_fmt & STYLE_MASK) == STYLE_AUTO)
970 style_fmt = isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE; 944#if STYLE_AUTO != 0
945 all_fmt = (all_fmt & ~STYLE_MASK)
946 | (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
947#else
948 all_fmt |= (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
949#endif
971 950
972 /* 951 /*
973 * when there are no cmd line args we have to supply a default "." arg. 952 * when there are no cmd line args we have to supply a default "." arg.
@@ -979,7 +958,7 @@ extern int ls_main(int argc, char **argv)
979 ac = argc - optind; /* how many cmd line args are left */ 958 ac = argc - optind; /* how many cmd line args are left */
980 if (ac < 1) { 959 if (ac < 1) {
981 av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *))); 960 av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *)));
982 av[0] = xstrdup("."); 961 av[0] = bb_xstrdup(".");
983 ac = 1; 962 ac = 1;
984 } else { 963 } else {
985 av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *))); 964 av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *)));
@@ -990,12 +969,12 @@ extern int ls_main(int argc, char **argv)
990 969
991 /* now, everything is in the av array */ 970 /* now, everything is in the av array */
992 if (ac > 1) 971 if (ac > 1)
993 disp_opts |= DISP_DIRNAME; /* 2 or more items? label directories */ 972 all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */
994 973
995 /* stuff the command line file names into an dnode array */ 974 /* stuff the command line file names into an dnode array */
996 dn = NULL; 975 dn = NULL;
997 for (oi = 0; oi < ac; oi++) { 976 for (oi = 0; oi < ac; oi++) {
998 char *fullname = xstrdup(av[oi]); 977 char *fullname = bb_xstrdup(av[oi]);
999 978
1000 cur = my_stat(fullname, fullname); 979 cur = my_stat(fullname, fullname);
1001 if (!cur) 980 if (!cur)
@@ -1015,7 +994,7 @@ extern int ls_main(int argc, char **argv)
1015 } 994 }
1016 995
1017 996
1018 if (disp_opts & DISP_NOLIST) { 997 if (all_fmt & DISP_NOLIST) {
1019#ifdef CONFIG_FEATURE_LS_SORTFILES 998#ifdef CONFIG_FEATURE_LS_SORTFILES
1020 shellsort(dnp, nfiles); 999 shellsort(dnp, nfiles);
1021#endif 1000#endif
@@ -1042,5 +1021,5 @@ extern int ls_main(int argc, char **argv)
1042 return (status); 1021 return (status);
1043 1022
1044 print_usage_message: 1023 print_usage_message:
1045 show_usage(); 1024 bb_show_usage();
1046} 1025}
diff --git a/coreutils/md5sum.c b/coreutils/md5sum.c
index f5be4486c..c1480cd32 100644
--- a/coreutils/md5sum.c
+++ b/coreutils/md5sum.c
@@ -770,13 +770,13 @@ static int md5_file(const char *filename,
770 have_read_stdin = 1; 770 have_read_stdin = 1;
771 fp = stdin; 771 fp = stdin;
772 } else { 772 } else {
773 fp = wfopen(filename, "r"); 773 fp = bb_wfopen(filename, "r");
774 if (fp == NULL) 774 if (fp == NULL)
775 return FALSE; 775 return FALSE;
776 } 776 }
777 777
778 if (md5_stream(fp, md5_result)) { 778 if (md5_stream(fp, md5_result)) {
779 perror_msg("%s", filename); 779 bb_perror_msg("%s", filename);
780 780
781 if (fp != stdin) 781 if (fp != stdin)
782 fclose(fp); 782 fclose(fp);
@@ -784,7 +784,7 @@ static int md5_file(const char *filename,
784 } 784 }
785 785
786 if (fp != stdin && fclose(fp) == EOF) { 786 if (fp != stdin && fclose(fp) == EOF) {
787 perror_msg("%s", filename); 787 bb_perror_msg("%s", filename);
788 return FALSE; 788 return FALSE;
789 } 789 }
790 790
@@ -805,7 +805,7 @@ static int md5_check(const char *checkfile_name)
805 have_read_stdin = 1; 805 have_read_stdin = 1;
806 checkfile_stream = stdin; 806 checkfile_stream = stdin;
807 } else { 807 } else {
808 checkfile_stream = wfopen(checkfile_name, "r"); 808 checkfile_stream = bb_wfopen(checkfile_name, "r");
809 if (checkfile_stream == NULL) 809 if (checkfile_stream == NULL)
810 return FALSE; 810 return FALSE;
811 } 811 }
@@ -836,7 +836,7 @@ static int md5_check(const char *checkfile_name)
836 if (split_3(line, line_length, &md5num, &filename) 836 if (split_3(line, line_length, &md5num, &filename)
837 || !hex_digits(md5num)) { 837 || !hex_digits(md5num)) {
838 if (warn) { 838 if (warn) {
839 error_msg("%s: %lu: improperly formatted MD5 checksum line", 839 bb_error_msg("%s: %lu: improperly formatted MD5 checksum line",
840 checkfile_name, (unsigned long) line_number); 840 checkfile_name, (unsigned long) line_number);
841 } 841 }
842 } else { 842 } else {
@@ -881,18 +881,18 @@ static int md5_check(const char *checkfile_name)
881 while (!feof(checkfile_stream) && !ferror(checkfile_stream)); 881 while (!feof(checkfile_stream) && !ferror(checkfile_stream));
882 882
883 if (ferror(checkfile_stream)) { 883 if (ferror(checkfile_stream)) {
884 error_msg("%s: read error", checkfile_name); 884 bb_error_msg("%s: read error", checkfile_name);
885 return FALSE; 885 return FALSE;
886 } 886 }
887 887
888 if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) { 888 if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
889 perror_msg("md5sum: %s", checkfile_name); 889 bb_perror_msg("md5sum: %s", checkfile_name);
890 return FALSE; 890 return FALSE;
891 } 891 }
892 892
893 if (n_properly_formated_lines == 0) { 893 if (n_properly_formated_lines == 0) {
894 /* Warn if no tests are found. */ 894 /* Warn if no tests are found. */
895 error_msg("%s: no properly formatted MD5 checksum lines found", 895 bb_error_msg("%s: no properly formatted MD5 checksum lines found",
896 checkfile_name); 896 checkfile_name);
897 return FALSE; 897 return FALSE;
898 } else { 898 } else {
@@ -901,13 +901,13 @@ static int md5_check(const char *checkfile_name)
901 - n_open_or_read_failures); 901 - n_open_or_read_failures);
902 902
903 if (n_open_or_read_failures > 0) { 903 if (n_open_or_read_failures > 0) {
904 error_msg("WARNING: %d of %d listed files could not be read", 904 bb_error_msg("WARNING: %d of %d listed files could not be read",
905 n_open_or_read_failures, n_properly_formated_lines); 905 n_open_or_read_failures, n_properly_formated_lines);
906 return FALSE; 906 return FALSE;
907 } 907 }
908 908
909 if (n_mismatched_checksums > 0) { 909 if (n_mismatched_checksums > 0) {
910 error_msg("WARNING: %d of %d computed checksums did NOT match", 910 bb_error_msg("WARNING: %d of %d computed checksums did NOT match",
911 n_mismatched_checksums, n_computed_checkums); 911 n_mismatched_checksums, n_computed_checkums);
912 return FALSE; 912 return FALSE;
913 } 913 }
@@ -965,31 +965,31 @@ int md5sum_main(int argc,
965 break; 965 break;
966 966
967 default: 967 default:
968 show_usage(); 968 bb_show_usage();
969 } 969 }
970 } 970 }
971 971
972 if (file_type_specified && do_check) { 972 if (file_type_specified && do_check) {
973 error_msg_and_die("the -b and -t options are meaningless when verifying checksums"); 973 bb_error_msg_and_die("the -b and -t options are meaningless when verifying checksums");
974 } 974 }
975 975
976 if (n_strings > 0 && do_check) { 976 if (n_strings > 0 && do_check) {
977 error_msg_and_die("the -g and -c options are mutually exclusive"); 977 bb_error_msg_and_die("the -g and -c options are mutually exclusive");
978 } 978 }
979 979
980 if (status_only && !do_check) { 980 if (status_only && !do_check) {
981 error_msg_and_die("the -s option is meaningful only when verifying checksums"); 981 bb_error_msg_and_die("the -s option is meaningful only when verifying checksums");
982 } 982 }
983 983
984 if (warn && !do_check) { 984 if (warn && !do_check) {
985 error_msg_and_die("the -w option is meaningful only when verifying checksums"); 985 bb_error_msg_and_die("the -w option is meaningful only when verifying checksums");
986 } 986 }
987 987
988 if (n_strings > 0) { 988 if (n_strings > 0) {
989 size_t i; 989 size_t i;
990 990
991 if (optind < argc) { 991 if (optind < argc) {
992 error_msg_and_die("no files may be specified when using -g"); 992 bb_error_msg_and_die("no files may be specified when using -g");
993 } 993 }
994 for (i = 0; i < n_strings; ++i) { 994 for (i = 0; i < n_strings; ++i) {
995 size_t cnt; 995 size_t cnt;
@@ -1002,7 +1002,7 @@ int md5sum_main(int argc,
1002 } 1002 }
1003 } else if (do_check) { 1003 } else if (do_check) {
1004 if (optind + 1 < argc) { 1004 if (optind + 1 < argc) {
1005 error_msg("only one argument may be specified when using -c"); 1005 bb_error_msg("only one argument may be specified when using -c");
1006 } 1006 }
1007 1007
1008 err = md5_check ((optind == argc) ? "-" : argv[optind]); 1008 err = md5_check ((optind == argc) ? "-" : argv[optind]);
@@ -1060,11 +1060,11 @@ int md5sum_main(int argc,
1060 } 1060 }
1061 1061
1062 if (fclose (stdout) == EOF) { 1062 if (fclose (stdout) == EOF) {
1063 error_msg_and_die("write error"); 1063 bb_error_msg_and_die("write error");
1064 } 1064 }
1065 1065
1066 if (have_read_stdin && fclose (stdin) == EOF) { 1066 if (have_read_stdin && fclose (stdin) == EOF) {
1067 error_msg_and_die("standard input"); 1067 bb_error_msg_and_die(bb_msg_standard_input);
1068 } 1068 }
1069 1069
1070 if (err == 0) 1070 if (err == 0)
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index f003db99f..b018ac181 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -20,46 +20,50 @@
20 * 20 *
21 */ 21 */
22 22
23#include <errno.h> 23/* BB_AUDIT SUSv3 compliant */
24#include <getopt.h> 24/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */
25#include <sys/stat.h> 25
26#include <sys/types.h> 26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27#include <fcntl.h> 27 *
28#include <unistd.h> 28 * Fixed broken permission setting when -p was used; especially in
29#include <stdlib.h> 29 * conjunction with -m.
30#include <string.h> 30 */
31 31
32#include <stdlib.h>
33#include <unistd.h>
32#include "busybox.h" 34#include "busybox.h"
33 35
34extern int mkdir_main (int argc, char **argv) 36extern int mkdir_main (int argc, char **argv)
35{ 37{
36 mode_t mode = -1; 38 mode_t mode = (mode_t)(-1);
39 int status = EXIT_SUCCESS;
37 int flags = 0; 40 int flags = 0;
38 int i, opt; 41 int opt;
39 42
40 while ((opt = getopt (argc, argv, "m:p")) != -1) { 43 while ((opt = getopt (argc, argv, "m:p")) > 0) {
41 switch (opt) { 44 if (opt == 'm') {
42 case 'm':
43 mode = 0777; 45 mode = 0777;
44 if (!parse_mode (optarg, &mode)) { 46 if (!bb_parse_mode (optarg, &mode)) {
45 error_msg_and_die ("invalid mode `%s'", optarg); 47 bb_error_msg_and_die ("invalid mode `%s'", optarg);
46 } 48 }
47 umask(0); 49 } else if (opt == 'p') {
48 break;
49 case 'p':
50 flags |= FILEUTILS_RECUR; 50 flags |= FILEUTILS_RECUR;
51 break; 51 } else {
52 default: 52 bb_show_usage();
53 show_usage ();
54 } 53 }
55 } 54 }
56 55
57 if (optind == argc) 56 if (optind == argc) {
58 show_usage (); 57 bb_show_usage();
59
60 for (i = optind; i < argc; i++) {
61 make_directory (argv[i], mode, flags);
62 } 58 }
63 59
64 return(EXIT_SUCCESS); 60 argv += optind;
61
62 do {
63 if (bb_make_directory(*argv, mode, flags)) {
64 status = EXIT_FAILURE;
65 }
66 } while (*++argv);
67
68 return status;
65} 69}
diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c
index ca217fa23..77e0e6dd8 100644
--- a/coreutils/mkfifo.c
+++ b/coreutils/mkfifo.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini mkfifo implementation for busybox 3 * mkfifo implementation for busybox
4 * 4 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,41 +20,32 @@
20 * 20 *
21 */ 21 */
22 22
23#include <stdio.h> 23/* BB_AUDIT SUSv3 compliant */
24#include <sys/types.h> 24/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkfifo.html */
25#include <errno.h> 25
26#include <stdlib.h> 26#include <stdlib.h>
27#include <unistd.h>
28#include <sys/types.h>
27#include "busybox.h" 29#include "busybox.h"
30#include "libcoreutils/coreutils.h"
28 31
29extern int mkfifo_main(int argc, char **argv) 32extern int mkfifo_main(int argc, char **argv)
30{ 33{
31 char *thisarg; 34 mode_t mode;
32 mode_t mode = 0666; 35 int retval = EXIT_SUCCESS;
33 36
34 argc--; 37 mode = getopt_mk_fifo_nod(argc, argv);
35 argv++;
36 38
37 /* Parse any options */ 39 if (!*(argv += optind)) {
38 while (argc > 1) { 40 bb_show_usage();
39 if (**argv != '-')
40 show_usage();
41 thisarg = *argv;
42 thisarg++;
43 switch (*thisarg) {
44 case 'm':
45 argc--;
46 argv++;
47 parse_mode(*argv, &mode);
48 break;
49 default:
50 show_usage();
51 }
52 argc--;
53 argv++;
54 } 41 }
55 if (argc < 1 || *argv[0] == '-') 42
56 show_usage(); 43 do {
57 if (mkfifo(*argv, mode) < 0) 44 if (mkfifo(*argv, mode) < 0) {
58 perror_msg_and_die("mkfifo"); 45 bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
59 return EXIT_SUCCESS; 46 retval = EXIT_FAILURE;
47 }
48 } while (*++argv);
49
50 return retval;
60} 51}
diff --git a/coreutils/mknod.c b/coreutils/mknod.c
index 432ec2b25..59294e9cb 100644
--- a/coreutils/mknod.c
+++ b/coreutils/mknod.c
@@ -1,9 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini mknod implementation for busybox 3 * mknod implementation for busybox
4 * 4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * Copyright (C) 1999-2002 by Erik Andersen <andersee@debian.org>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -21,73 +20,44 @@
21 * 20 *
22 */ 21 */
23 22
24#include <stdio.h> 23/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
25#include <errno.h> 24
26#include <fcntl.h>
27#include <unistd.h>
28#include <string.h>
29#include <stdlib.h> 25#include <stdlib.h>
30#include <sys/types.h> 26#include <string.h>
31#include <sys/stat.h> 27#include <sys/stat.h>
28#include <unistd.h>
32#include "busybox.h" 29#include "busybox.h"
30#include "libcoreutils/coreutils.h"
31
32static const char modes_chars[] = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 };
33static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK };
33 34
34int mknod_main(int argc, char **argv) 35extern int mknod_main(int argc, char **argv)
35{ 36{
36 char *thisarg; 37 mode_t mode;
37 mode_t mode = 0; 38 dev_t dev;
38 mode_t perm = 0666; 39 const char *name;
39 dev_t dev = (dev_t) 0; 40
41 mode = getopt_mk_fifo_nod(argc, argv);
42 argv += optind;
43 argc -= optind;
40 44
41 argc--; 45 if ((argc >= 2) && ((name = strchr(modes_chars, argv[1][0])) != NULL)) {
42 argv++; 46 mode |= modes_cubp[(int)(name[4])];
43 47
44 /* Parse any options */ 48 dev = 0;
45 while (argc > 1) { 49 if ((*name != 'p') && ((argc -= 2) == 0)) {
46 if (**argv != '-') 50 dev = (bb_xgetularg10_bnd(argv[2], 0, 255) << 8)
47 break; 51 + bb_xgetularg10_bnd(argv[3], 0, 255);
48 thisarg = *argv;
49 thisarg++;
50 switch (*thisarg) {
51 case 'm':
52 argc--;
53 argv++;
54 parse_mode(*argv, &perm);
55 umask(0);
56 break;
57 default:
58 show_usage();
59 } 52 }
60 argc--; 53
61 argv++; 54 if (argc == 2) {
62 } 55 name = *argv;
63 if (argc != 4 && argc != 2) { 56 if (mknod(name, mode, dev) == 0) {
64 show_usage(); 57 return EXIT_SUCCESS;
65 } 58 }
66 switch (argv[1][0]) { 59 bb_perror_msg_and_die("%s", name);
67 case 'c':
68 case 'u':
69 mode = S_IFCHR;
70 break;
71 case 'b':
72 mode = S_IFBLK;
73 break;
74 case 'p':
75 mode = S_IFIFO;
76 if (argc != 2) {
77 show_usage();
78 } 60 }
79 break;
80 default:
81 show_usage();
82 }
83
84 if (mode == S_IFCHR || mode == S_IFBLK) {
85 dev = (dev_t) ((atoi(argv[2]) << 8) | atoi(argv[3]));
86 } 61 }
87 62 bb_show_usage();
88 mode |= perm;
89
90 if (mknod(argv[0], mode, dev) != 0)
91 perror_msg_and_die("%s", argv[0]);
92 return EXIT_SUCCESS;
93} 63}
diff --git a/coreutils/mv.c b/coreutils/mv.c
index 1c4a34788..ae0ee92e4 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -2,7 +2,6 @@
2/* 2/*
3 * Mini mv implementation for busybox 3 * Mini mv implementation for busybox
4 * 4 *
5 *
6 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -21,148 +20,122 @@
21 * 20 *
22 */ 21 */
23 22
23/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
24 *
25 * Size reduction and improved error checking.
26 */
27
24#include <sys/types.h> 28#include <sys/types.h>
25#include <sys/stat.h> 29#include <sys/stat.h>
26#include <unistd.h> 30#include <unistd.h>
27#include <dirent.h> 31#include <dirent.h>
28#include <errno.h> 32#include <errno.h>
29#include <stdlib.h> 33#include <stdlib.h>
30
31#include "busybox.h" 34#include "busybox.h"
35#include "libcoreutils/coreutils.h"
32 36
33static int flags; 37static const char *fmt = "cannot overwrite %sdirectory with %sdirectory";
34 38
35static int manual_rename(const char *source, const char *dest) 39extern int mv_main(int argc, char **argv)
36{ 40{
37 struct stat source_stat; 41 struct stat source_stat;
38 struct stat dest_stat; 42 struct stat dest_stat;
39 int source_exists = 1; 43 const char *last;
40 int dest_exists = 1; 44 const char *dest;
45 int dest_exists;
46 int source_exists;
47 int opt;
48 int flags = 0;
49 int status = 0;
41 50
42 if (stat(source, &source_stat) < 0) { 51 while ((opt = getopt(argc, argv, "fi")) > 0) {
43 if (errno != ENOENT) { 52 flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE);
44 perror_msg("unable to stat `%s'", source); 53 if (opt == 'i') {
45 return -1; 54 flags |= FILEUTILS_INTERACTIVE;
55 } else if (opt == 'f') {
56 flags |= FILEUTILS_FORCE;
57 } else {
58 bb_show_usage();
46 } 59 }
47 source_exists = 0;
48 } 60 }
49 61
50 if (stat(dest, &dest_stat) < 0) { 62 if (optind + 2 > argc)
51 if (errno != ENOENT) { 63 bb_show_usage();
52 perror_msg("unable to stat `%s'", dest);
53 return -1;
54 }
55 dest_exists = 0;
56 }
57 64
58 if (dest_exists) { 65 last = argv[argc - 1];
59 if (S_ISDIR(dest_stat.st_mode) && 66 argv += optind;
60 (!source_exists || !S_ISDIR(source_stat.st_mode))) {
61 error_msg("cannot overwrite directory with non-directory");
62 return -1;
63 }
64 67
65 if (!S_ISDIR(dest_stat.st_mode) && source_exists && 68 if (optind + 2 == argc) {
66 S_ISDIR(source_stat.st_mode)) { 69 if ((dest_exists = cp_mv_stat(last, &dest_stat)) < 0) {
67 error_msg("cannot overwrite non-directory with directory"); 70 return 1;
68 return -1;
69 } 71 }
70 72
71 if (unlink(dest) < 0) { 73 if (!(dest_exists & 2)) {
72 perror_msg("cannot remove `%s'", dest); 74 dest = last;
73 return -1; 75 goto DO_MOVE;
74 } 76 }
75 } 77 }
78
79 do {
80 dest = concat_path_file(last,
81 bb_get_last_path_component(*argv));
76 82
77 if (copy_file(source, dest, 83 if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) {
78 FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) < 0) 84 goto RET_1;
79 return -1;
80
81 if (remove_file(source, FILEUTILS_RECUR | FILEUTILS_FORCE) < 0)
82 return -1;
83
84 return 0;
85}
86
87static int move_file(const char *source, const char *dest)
88{
89 struct stat dest_stat;
90 int dest_exists = 1;
91
92 if (stat(dest, &dest_stat) < 0) {
93 if (errno != ENOENT) {
94 perror_msg("unable to stat `%s'", dest);
95 return -1;
96 } 85 }
97 dest_exists = 0;
98 }
99 86
100 if (dest_exists && !(flags & FILEUTILS_FORCE) && 87 DO_MOVE:
88
89 if (dest_exists && !(flags & FILEUTILS_FORCE) &&
101 ((access(dest, W_OK) < 0 && isatty(0)) || 90 ((access(dest, W_OK) < 0 && isatty(0)) ||
102 (flags & FILEUTILS_INTERACTIVE))) { 91 (flags & FILEUTILS_INTERACTIVE))) {
103 fprintf(stderr, "mv: overwrite `%s'? ", dest); 92 if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) {
104 if (!ask_confirmation()) 93 goto RET_1; /* Ouch! fprintf failed! */
105 return 0; 94 }
106 } 95 if (!bb_ask_confirmation())
107 96 goto RET_0;
108 if (rename(source, dest) < 0) { 97 }
109 if (errno == EXDEV) 98
110 return manual_rename(source, dest); 99 if (rename(*argv, dest) < 0) {
111 100 if (errno != EXDEV) {
112 perror_msg("unable to rename `%s'", source); 101 bb_perror_msg("unable to rename `%s'", *argv);
113 return -1; 102 } else if ((source_exists = cp_mv_stat(*argv, &source_stat)) >= 0) {
114 } 103 if (dest_exists) {
115 104 if (dest_exists & 2) {
116 return 0; 105 if (!(source_exists & 2)) {
117} 106 bb_error_msg(fmt, "", "non-");
118 107 goto RET_1;
119extern int mv_main(int argc, char **argv) 108 }
120{ 109 } else {
121 int status = 0; 110 if (source_exists & 2) {
122 int opt; 111 bb_error_msg(fmt, "non-", "");
123 int i; 112 goto RET_1;
124 113 }
125 while ((opt = getopt(argc, argv, "fi")) != -1) 114 }
126 switch (opt) { 115 if (unlink(dest) < 0) {
127 case 'f': 116 bb_perror_msg("cannot remove `%s'", dest);
128 flags &= ~FILEUTILS_INTERACTIVE; 117 goto RET_1;
129 flags |= FILEUTILS_FORCE; 118 }
130 break; 119 }
131 case 'i': 120
132 flags &= ~FILEUTILS_FORCE; 121 if ((copy_file(*argv, dest,
133 flags |= FILEUTILS_INTERACTIVE; 122 FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0)
134 break; 123 && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)
135 default: 124 ) {
136 show_usage(); 125 goto RET_0;
137 } 126 }
138 127
139 if (optind + 2 > argc) 128 }
140 show_usage(); 129 RET_1:
141 130 status = 1;
142 if (optind + 2 == argc) {
143 struct stat dest_stat;
144 int dest_exists = 1;
145
146 if (stat(argv[optind + 1], &dest_stat) < 0) {
147 if (errno != ENOENT)
148 perror_msg_and_die("unable to stat `%s'", argv[optind + 1]);
149 dest_exists = 0;
150 } 131 }
151 132
152 if (!dest_exists || !S_ISDIR(dest_stat.st_mode)) { 133 RET_0:
153 if (move_file(argv[optind], argv[optind + 1]) < 0) 134 if (dest != last) {
154 status = 1; 135 free((void *) dest);
155 return status;
156 } 136 }
157 } 137
158 138 } while (*++argv != last);
159 for (i = optind; i < argc - 1; i++) { 139
160 char *dest = concat_path_file(argv[argc - 1], 140 exit(status);
161 get_last_path_component(argv[i]));
162 if (move_file(argv[i], dest) < 0)
163 status = 1;
164 free(dest);
165 }
166
167 return status;
168} 141}
diff --git a/coreutils/od.c b/coreutils/od.c
index 6187cadf2..5eaaf5024 100644
--- a/coreutils/od.c
+++ b/coreutils/od.c
@@ -23,22 +23,18 @@
23 */ 23 */
24 24
25#include <ctype.h> 25#include <ctype.h>
26#include <string.h>
26#include <getopt.h> 27#include <getopt.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include "dump.h"
29#include "busybox.h" 29#include "busybox.h"
30#include "dump.h"
30 31
31extern FS *fshead; /* head of format strings */ 32#define isdecdigit(c) (isdigit)(c)
32extern int blocksize; /* data block size */ 33#define ishexdigit(c) (isxdigit)(c)
33extern int length; /* max bytes to read */
34
35#define ishexdigit(c) \
36 ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
37 34
38static void 35static void
39odoffset(int argc, char ***argvp) 36odoffset(int argc, char ***argvp)
40{ 37{
41 extern off_t skip;
42 register char *num, *p; 38 register char *num, *p;
43 int base; 39 int base;
44 char *end; 40 char *end;
@@ -62,13 +58,15 @@ odoffset(int argc, char ***argvp)
62 return; 58 return;
63 } 59 }
64 60
65 if (*p != '+' && (argc < 2 || 61 if ((*p != '+')
66 (!isdigit(p[0]) && (p[0] != 'x' || !ishexdigit(p[1]))))) 62 && (argc < 2
63 || (!isdecdigit(p[0])
64 && ((p[0] != 'x') || !ishexdigit(p[1])))))
67 return; 65 return;
68 66
69 base = 0; 67 base = 0;
70 /* 68 /*
71 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and 69 * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
72 * set base. 70 * set base.
73 */ 71 */
74 if (p[0] == '+') 72 if (p[0] == '+')
@@ -81,11 +79,11 @@ odoffset(int argc, char ***argvp)
81 base = 16; 79 base = 16;
82 } 80 }
83 81
84 /* skip over the number */ 82 /* bb_dump_skip over the number */
85 if (base == 16) 83 if (base == 16)
86 for (num = p; ishexdigit(*p); ++p); 84 for (num = p; ishexdigit(*p); ++p);
87 else 85 else
88 for (num = p; isdigit(*p); ++p); 86 for (num = p; isdecdigit(*p); ++p);
89 87
90 /* check for no number */ 88 /* check for no number */
91 if (num == p) 89 if (num == p)
@@ -98,21 +96,23 @@ odoffset(int argc, char ***argvp)
98 base = 10; 96 base = 10;
99 } 97 }
100 98
101 skip = strtol(num, &end, base ? base : 8); 99 bb_dump_skip = strtol(num, &end, base ? base : 8);
102 100
103 /* if end isn't the same as p, we got a non-octal digit */ 101 /* if end isn't the same as p, we got a non-octal digit */
104 if (end != p) 102 if (end != p)
105 skip = 0; 103 bb_dump_skip = 0;
106 else { 104 else {
107 if (*p) { 105 if (*p) {
108 if (*p == 'b') 106 if (*p == 'b') {
109 skip *= 512; 107 bb_dump_skip *= 512;
110 else if (*p == 'B') 108 ++p;
111 skip *= 1024; 109 } else if (*p == 'B') {
112 ++p; 110 bb_dump_skip *= 1024;
111 ++p;
112 }
113 } 113 }
114 if (*p) 114 if (*p)
115 skip = 0; 115 bb_dump_skip = 0;
116 else { 116 else {
117 ++*argvp; 117 ++*argvp;
118 /* 118 /*
@@ -121,117 +121,76 @@ odoffset(int argc, char ***argvp)
121 * but it's easy. 121 * but it's easy.
122 */ 122 */
123#define TYPE_OFFSET 7 123#define TYPE_OFFSET 7
124 if (base == 16) { 124 {
125 fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; 125 char x_or_d;
126 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; 126 if (base == 16) {
127 } else if (base == 10) { 127 x_or_d = 'x';
128 fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; 128 goto DO_X_OR_D;
129 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; 129 }
130 if (base == 10) {
131 x_or_d = 'd';
132 DO_X_OR_D:
133 bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
134 = bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
135 = x_or_d;
136 }
130 } 137 }
131 } 138 }
132 } 139 }
133} 140}
134 141
135static void odprecede(void) 142static const char * const add_strings[] = {
136{ 143 "16/1 \"%3_u \" \"\\n\"", /* a */
137 static int first = 1; 144 "8/2 \" %06o \" \"\\n\"", /* B, o */
138 145 "16/1 \"%03o \" \"\\n\"", /* b */
139 if (first) { 146 "16/1 \"%3_c \" \"\\n\"", /* c */
140 first = 0; 147 "8/2 \" %05u \" \"\\n\"", /* d */
141 add("\"%07.7_Ao\n\""); 148 "4/4 \" %010u \" \"\\n\"", /* D */
142 add("\"%07.7_ao \""); 149 "2/8 \" %21.14e \" \"\\n\"", /* e (undocumented in od), F */
143 } else 150 "4/4 \" %14.7e \" \"\\n\"", /* f */
144 add("\" \""); 151 "4/4 \" %08x \" \"\\n\"", /* H, X */
145} 152 "8/2 \" %04x \" \"\\n\"", /* h, x */
153 "4/4 \" %11d \" \"\\n\"", /* I, L, l */
154 "8/2 \" %6d \" \"\\n\"", /* i */
155 "4/4 \" %011o \" \"\\n\"", /* O */
156};
157
158static const signed char od_opts[] = "aBbcDdeFfHhIiLlOovXx";
159
160static const signed char od_o2si[] = {
161 0, 1, 2, 3, 5,
162 4, 6, 6, 7, 8,
163 9, 0xa, 0xb, 0xa, 0xa,
164 0xb, 1, -1, 8, 9,
165};
146 166
147int od_main(int argc, char **argv) 167int od_main(int argc, char **argv)
148{ 168{
149 int ch; 169 int ch;
150 extern enum _vflag vflag; 170 bb_dump_vflag = FIRST;
151 vflag = FIRST; 171 bb_dump_length = -1;
152 length = -1; 172 int first = 1;
153 173 signed char *p;
154 while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF) 174
155 switch (ch) { 175 while ((ch = getopt(argc, argv, od_opts)) > 0) {
156 case 'a': 176 if (((p = strchr(od_opts, ch)) != NULL) && (*p >= 0)) {
157 odprecede(); 177 if (first) {
158 add("16/1 \"%3_u \" \"\\n\""); 178 first = 0;
159 break; 179 bb_dump_add("\"%07.7_Ao\n\"");
160 case 'B': 180 bb_dump_add("\"%07.7_ao \"");
161 case 'o': 181 } else {
162 odprecede(); 182 bb_dump_add("\" \"");
163 add("8/2 \" %06o \" \"\\n\"");
164 break;
165 case 'b':
166 odprecede();
167 add("16/1 \"%03o \" \"\\n\"");
168 break;
169 case 'c':
170 odprecede();
171 add("16/1 \"%3_c \" \"\\n\"");
172 break;
173 case 'd':
174 odprecede();
175 add("8/2 \" %05u \" \"\\n\"");
176 break;
177 case 'D':
178 odprecede();
179 add("4/4 \" %010u \" \"\\n\"");
180 break;
181 case 'e': /* undocumented in od */
182 case 'F':
183 odprecede();
184 add("2/8 \" %21.14e \" \"\\n\"");
185 break;
186
187 case 'f':
188 odprecede();
189 add("4/4 \" %14.7e \" \"\\n\"");
190 break;
191 case 'H':
192 case 'X':
193 odprecede();
194 add("4/4 \" %08x \" \"\\n\"");
195 break;
196 case 'h':
197 case 'x':
198 odprecede();
199 add("8/2 \" %04x \" \"\\n\"");
200 break;
201 case 'I':
202 case 'L':
203 case 'l':
204 odprecede();
205 add("4/4 \" %11d \" \"\\n\"");
206 break;
207 case 'i':
208 odprecede();
209 add("8/2 \" %6d \" \"\\n\"");
210 break;
211 case 'O':
212 odprecede();
213 add("4/4 \" %011o \" \"\\n\"");
214 break;
215 case 'v':
216 vflag = ALL;
217 break;
218 case 'P':
219 case 'p':
220 case 's':
221 case 'w':
222 case '?':
223 default:
224 error_msg("od: od(1) has been deprecated for hexdump(1).\n");
225 if (ch != '?') {
226 error_msg("od: hexdump(1) compatibility doesn't support the -%c option%s\n",
227 ch, ch == 's' ? "; see strings(1)." : ".");
228 } 183 }
229 show_usage(); 184 bb_dump_add(add_strings[od_o2si[(int)(p-od_opts)]]);
185 } else if (ch == 'v') {
186 bb_dump_vflag = ALL;
187 } else { /* P, p, s, w, or other unhandled */
188 bb_show_usage();
230 } 189 }
231 190 }
232 if (!fshead) { 191 if (!bb_dump_fshead) {
233 add("\"%07.7_Ao\n\""); 192 bb_dump_add("\"%07.7_Ao\n\"");
234 add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); 193 bb_dump_add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\"");
235 } 194 }
236 195
237 argc -= optind; 196 argc -= optind;
@@ -239,7 +198,7 @@ int od_main(int argc, char **argv)
239 198
240 odoffset(argc, &argv); 199 odoffset(argc, &argv);
241 200
242 return(dump(argv)); 201 return(bb_dump_dump(argv));
243} 202}
244 203
245/*- 204/*-
diff --git a/coreutils/printf.c b/coreutils/printf.c
index d579a9b4e..9602788de 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -124,7 +124,7 @@ int printf_main(int argc, char **argv)
124 124
125 exit_status = 0; 125 exit_status = 0;
126 if (argc <= 1 || **(argv + 1) == '-') { 126 if (argc <= 1 || **(argv + 1) == '-') {
127 show_usage(); 127 bb_show_usage();
128 } 128 }
129 129
130 format = argv[1]; 130 format = argv[1];
diff --git a/coreutils/pwd.c b/coreutils/pwd.c
index 9c5d70cef..7e0dc056a 100644
--- a/coreutils/pwd.c
+++ b/coreutils/pwd.c
@@ -20,24 +20,18 @@
20 * 20 *
21 */ 21 */
22 22
23/* getopt not needed */
24
25#include <stdio.h> 23#include <stdio.h>
26#include <dirent.h>
27#include <errno.h>
28#include <unistd.h>
29#include <stdlib.h> 24#include <stdlib.h>
30#include "busybox.h" 25#include "busybox.h"
31 26
32extern int pwd_main(int argc, char **argv) 27extern int pwd_main(int argc, char **argv)
33{ 28{
34 static char *buf; 29 char *buf;
35 30
36 buf = xgetcwd(buf); 31 if ((buf = xgetcwd(NULL)) != NULL) {
37
38 if (buf != NULL) {
39 puts(buf); 32 puts(buf);
40 return EXIT_SUCCESS; 33 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
41 } 34 }
35
42 return EXIT_FAILURE; 36 return EXIT_FAILURE;
43} 37}
diff --git a/coreutils/realpath.c b/coreutils/realpath.c
index f89e0a274..ec98221ad 100644
--- a/coreutils/realpath.c
+++ b/coreutils/realpath.c
@@ -14,17 +14,26 @@
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */ 15 */
16 16
17/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
18
19/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
20 *
21 * Now does proper error checking on output and returns a failure exit code
22 * if one or more paths can not be resolved.
23 */
24
17#include <limits.h> 25#include <limits.h>
18#include <stdlib.h> 26#include <stdlib.h>
19
20#include "busybox.h" 27#include "busybox.h"
21 28
22int realpath_main(int argc, char **argv) 29int realpath_main(int argc, char **argv)
23{ 30{
31 int retval = EXIT_SUCCESS;
32
24 RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX); 33 RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX);
25 34
26 if (--argc == 0) { 35 if (--argc == 0) {
27 show_usage(); 36 bb_show_usage();
28 } 37 }
29 38
30 do { 39 do {
@@ -32,11 +41,14 @@ int realpath_main(int argc, char **argv)
32 if (realpath(*argv, resolved_path) != NULL) { 41 if (realpath(*argv, resolved_path) != NULL) {
33 puts(resolved_path); 42 puts(resolved_path);
34 } else { 43 } else {
35 perror_msg("%s", *argv); 44 retval = EXIT_FAILURE;
45 bb_perror_msg("%s", *argv);
36 } 46 }
37 } while (--argc); 47 } while (--argc);
38 48
49#ifdef CONFIG_FEATURE_CLEAN_UP
39 RELEASE_CONFIG_BUFFER(resolved_path); 50 RELEASE_CONFIG_BUFFER(resolved_path);
51#endif
40 52
41 return(EXIT_SUCCESS); 53 bb_fflush_stdout_and_exit(retval);
42} 54}
diff --git a/coreutils/rm.c b/coreutils/rm.c
index 51c9f4ceb..5489350e5 100644
--- a/coreutils/rm.c
+++ b/coreutils/rm.c
@@ -2,7 +2,6 @@
2/* 2/*
3 * Mini rm implementation for busybox 3 * Mini rm implementation for busybox
4 * 4 *
5 *
6 * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
7 * 6 *
8 * 7 *
@@ -22,55 +21,51 @@
22 * 21 *
23 */ 22 */
24 23
25#include <stdio.h> 24/* BB_AUDIT SUSv3 compliant */
26#include <time.h> 25/* http://www.opengroup.org/onlinepubs/007904975/utilities/rm.html */
27#include <utime.h> 26
28#include <dirent.h> 27/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
29#include <errno.h> 28 *
29 * Size reduction.
30 */
31
30#include <unistd.h> 32#include <unistd.h>
31#include <stdlib.h>
32#include <string.h>
33#include <getopt.h>
34#include "busybox.h" 33#include "busybox.h"
35 34
36extern int rm_main(int argc, char **argv) 35extern int rm_main(int argc, char **argv)
37{ 36{
38 int status = 0; 37 int status = 0;
39 int opt;
40 int flags = 0; 38 int flags = 0;
41 int i; 39 int opt;
42 40
43 while ((opt = getopt(argc, argv, "fiRr")) != -1) { 41 while ((opt = getopt(argc, argv, "fiRr")) > 0) {
44 switch (opt) { 42 if ((opt == 'r') || (opt == 'R')) {
45 case 'f':
46 flags &= ~FILEUTILS_INTERACTIVE;
47 flags |= FILEUTILS_FORCE;
48 break;
49 case 'i':
50 flags &= ~FILEUTILS_FORCE;
51 flags |= FILEUTILS_INTERACTIVE;
52 break;
53 case 'R':
54 case 'r':
55 flags |= FILEUTILS_RECUR; 43 flags |= FILEUTILS_RECUR;
56 break; 44 } else {
45 flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE);
46 if (opt == 'i') {
47 flags |= FILEUTILS_INTERACTIVE;
48 } else if (opt == 'f') {
49 flags |= FILEUTILS_FORCE;
50 } else {
51 bb_show_usage();
52 }
57 } 53 }
58 } 54 }
59 55
60 if (!(flags & FILEUTILS_FORCE) && optind == argc) 56 if (*(argv += optind) != NULL) {
61 show_usage(); 57 do {
62 58 const char *base = bb_get_last_path_component(*argv);
63 for (i = optind; i < argc; i++) {
64 char *base = get_last_path_component(argv[i]);
65
66 if (strcmp(base, ".") == 0 || strcmp(base, "..") == 0) {
67 error_msg("cannot remove `.' or `..'");
68 status = 1;
69 continue;
70 }
71 59
72 if (remove_file(argv[i], flags) < 0) 60 if ((base[0] == '.') && (!base[1] || ((base[1] == '.') && !base[2]))) {
61 bb_error_msg("cannot remove `.' or `..'");
62 } else if (remove_file(*argv, flags) >= 0) {
63 continue;
64 }
73 status = 1; 65 status = 1;
66 } while (*++argv);
67 } else if (!(flags & FILEUTILS_FORCE)) {
68 bb_show_usage();
74 } 69 }
75 70
76 return status; 71 return status;
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c
index 83b27c9bd..3f6037170 100644
--- a/coreutils/rmdir.c
+++ b/coreutils/rmdir.c
@@ -1,9 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini rmdir implementation for busybox 3 * rmdir implementation for busybox
4 * 4 *
5 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -21,76 +20,54 @@
21 * 20 *
22 */ 21 */
23 22
24#include <getopt.h> 23/* BB_AUDIT SUSv3 compliant */
25#include <unistd.h> 24/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */
26#include <stdlib.h>
27 25
26#include <stdlib.h>
27#include <unistd.h>
28#include <libgen.h>
28#include "busybox.h" 29#include "busybox.h"
29 30
30 31extern int rmdir_main(int argc, char **argv)
31/* Return true if a path is composed of multiple components. */
32
33static int
34multiple_components_p (const char *path)
35{
36 const char *s = path;
37
38 while (s[0] != '\0' && s[0] != '/')
39 s++;
40
41 while (s[0] == '/')
42 s++;
43
44 return (s[0] != '\0');
45}
46
47
48/* Remove a directory. Returns 0 if successful, -1 on error. */
49
50static int
51remove_directory (char *path, int flags)
52{
53 if (!(flags & FILEUTILS_RECUR)) {
54 if (rmdir (path) < 0) {
55 perror_msg ("unable to remove `%s'", path);
56 return -1;
57 }
58 } else {
59 if (remove_directory (path, 0) < 0)
60 return -1;
61
62 if (multiple_components_p (path))
63 if (remove_directory (dirname (path), flags) < 0)
64 return -1;
65 }
66
67 return 0;
68}
69
70
71extern int
72rmdir_main (int argc, char **argv)
73{ 32{
74 int status = EXIT_SUCCESS; 33 int status = EXIT_SUCCESS;
75 int flags = 0; 34 int flags;
76 int i, opt; 35 int do_dot;
36 char *path;
77 37
78 while ((opt = getopt (argc, argv, "p")) != -1) 38 flags = bb_getopt_ulflags(argc, argv, "p");
79 switch (opt) {
80 case 'p':
81 flags |= FILEUTILS_RECUR;
82 break;
83 39
84 default: 40 argv += optind;
85 show_usage ();
86 }
87 41
88 if (optind == argc) 42 if (!*argv) {
89 show_usage(); 43 bb_show_usage();
44 }
90 45
91 for (i = optind; i < argc; i++) 46 do {
92 if (remove_directory (argv[i], flags) < 0) 47 path = *argv;
93 status = EXIT_FAILURE; 48
49 /* Record if the first char was a '.' so we can use dirname later. */
50 do_dot = (*path == '.');
51
52 do {
53 if (rmdir(path) < 0) {
54 bb_perror_msg("`%s'", path); /* Match gnu rmdir msg. */
55 status = EXIT_FAILURE;
56 } else if (flags) {
57 /* Note: path was not empty or null since rmdir succeeded. */
58 path = dirname(path);
59 /* Path is now just the parent component. Note that dirname
60 * returns "." if there are no parents. We must distinguish
61 * this from the case of the original path starting with '.'.
62 */
63 if (do_dot || (*path != '.') || path[1]) {
64 continue;
65 }
66 }
67 break;
68 } while (1);
69
70 } while (*++argv);
94 71
95 return status; 72 return status;
96} 73}
diff --git a/coreutils/sha1sum.c b/coreutils/sha1sum.c
index 03009f76f..d94cb4b53 100644
--- a/coreutils/sha1sum.c
+++ b/coreutils/sha1sum.c
@@ -187,7 +187,7 @@ extern int authenticate(const int argc, char **argv, void (*hash_ptr)(FILE *stre
187 break; 187 break;
188#endif 188#endif
189 default: 189 default:
190 show_usage(); 190 bb_show_usage();
191 } 191 }
192 } 192 }
193 193
@@ -204,7 +204,7 @@ extern int authenticate(const int argc, char **argv, void (*hash_ptr)(FILE *stre
204 hash_ptr(stdin, hashval); 204 hash_ptr(stdin, hashval);
205 print_hash(hash_length, hashval, NULL); 205 print_hash(hash_length, hashval, NULL);
206 } else { 206 } else {
207 FILE *stream = xfopen(argv[i], "r"); 207 FILE *stream = bb_xfopen(argv[i], "r");
208 hash_ptr(stream, hashval); 208 hash_ptr(stream, hashval);
209 fclose(stream); 209 fclose(stream);
210 print_hash(hash_length, hashval, argv[i]); 210 print_hash(hash_length, hashval, argv[i]);
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
index 7bc98d8e8..506192dd3 100644
--- a/coreutils/sleep.c
+++ b/coreutils/sleep.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini sleep implementation for busybox 3 * sleep implementation for busybox
4 * 4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,18 +20,67 @@
20 * 20 *
21 */ 21 */
22 22
23#include <stdio.h> 23/* BB_AUDIT SUSv3 compliant */
24#include <unistd.h> 24/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */
26
27/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
28 *
29 * Rewritten to do proper arg and error checking.
30 * Also, added a 'fancy' configuration to accept multiple args with
31 * time suffixes for seconds, minutes, hours, and days.
32 */
33
25#include <stdlib.h> 34#include <stdlib.h>
35#include <limits.h>
36#include <unistd.h>
26#include "busybox.h" 37#include "busybox.h"
27 38
39#ifdef CONFIG_FEATURE_FANCY_SLEEP
40static const struct suffix_mult sleep_suffixes[] = {
41 { "s", 1 },
42 { "m", 60 },
43 { "h", 60*60 },
44 { "d", 24*60*60 },
45 { NULL, 0 }
46};
47#endif
48
28extern int sleep_main(int argc, char **argv) 49extern int sleep_main(int argc, char **argv)
29{ 50{
30 if ((argc < 2) || (**(argv + 1) == '-')) { 51 unsigned int duration;
31 show_usage(); 52
53#ifdef CONFIG_FEATURE_FANCY_SLEEP
54
55 if (argc < 2) {
56 bb_show_usage();
57 }
58
59 ++argv;
60 duration = 0;
61 do {
62 duration += bb_xgetularg_bnd_sfx(*argv, 10,
63 0, UINT_MAX-duration,
64 sleep_suffixes);
65 } while (*++argv);
66
67#else /* CONFIG_FEATURE_FANCY_SLEEP */
68
69 if (argc != 2) {
70 bb_show_usage();
71 }
72
73#if UINT_MAX == ULONG_MAX
74 duration = bb_xgetularg10(argv[1]);
75#else
76 duration = bb_xgetularg10_bnd(argv[1], 0, UINT_MAX);
77#endif
78
79#endif /* CONFIG_FEATURE_FANCY_SLEEP */
80
81 if (sleep(duration)) {
82 bb_perror_nomsg_and_die();
32 } 83 }
33 84
34 if (sleep(atoi(*(++argv))) != 0)
35 perror_msg_and_die("sleep");
36 return EXIT_SUCCESS; 85 return EXIT_SUCCESS;
37} 86}
diff --git a/coreutils/sort.c b/coreutils/sort.c
index fc12dfb01..8cc4d8886 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -2,7 +2,6 @@
2/* 2/*
3 * Mini sort implementation for busybox 3 * Mini sort implementation for busybox
4 * 4 *
5 *
6 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -21,10 +20,20 @@
21 * 20 *
22 */ 21 */
23 22
24#include <getopt.h> 23/* BB_AUDIT SUSv3 _NOT_ compliant -- a number of options are not supported. */
25#include <string.h> 24/* http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */
25
26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27 *
28 * Now does proper error checking on i/o. Plus some space savings.
29 */
30
31#include <stdio.h>
26#include <stdlib.h> 32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
27#include "busybox.h" 35#include "busybox.h"
36#include "libcoreutils/coreutils.h"
28 37
29static int compare_ascii(const void *x, const void *y) 38static int compare_ascii(const void *x, const void *y)
30{ 39{
@@ -41,66 +50,51 @@ int sort_main(int argc, char **argv)
41{ 50{
42 FILE *fp; 51 FILE *fp;
43 char *line, **lines = NULL; 52 char *line, **lines = NULL;
44 int i, opt, nlines = 0; 53 int i, nlines = 0, inc;
45 int (*compare)(const void *, const void *) = compare_ascii; 54 int (*compare)(const void *, const void *) = compare_ascii;
46#ifdef CONFIG_FEATURE_SORT_REVERSE
47 int reverse = FALSE;
48#endif
49#ifdef CONFIG_FEATURE_SORT_UNIQUE
50 int unique = FALSE;
51#endif
52 55
53 while ((opt = getopt(argc, argv, "nru")) != -1) { 56 int flags;
54 switch (opt) { 57
55 case 'n': 58 bb_default_error_retval = 2;
56 compare = compare_numeric; 59
57 break; 60 flags = bb_getopt_ulflags(argc, argv, "nru");
58#ifdef CONFIG_FEATURE_SORT_REVERSE 61 if (flags & 1) {
59 case 'r': 62 compare = compare_numeric;
60 reverse = TRUE;
61 break;
62#endif
63#ifdef CONFIG_FEATURE_SORT_UNIQUE
64 case 'u':
65 unique = TRUE;
66 break;
67#endif
68 default:
69 show_usage();
70 }
71 } 63 }
72 64
73 /* read the input */ 65 argv += optind;
74 for (i = optind; i == optind || i < argc; i++) { 66 if (!*argv) {
75 if (argv[i] == NULL) 67 *--argv = "-";
76 fp = stdin; 68 }
77 else
78 fp = xfopen(argv[i], "r");
79 69
80 while ((line = get_line_from_file(fp)) != NULL) { 70 do {
71 fp = xgetoptfile_sort_uniq(argv, "r");
72 while ((line = bb_get_chomped_line_from_file(fp)) != NULL) {
81 lines = xrealloc(lines, sizeof(char *) * (nlines + 1)); 73 lines = xrealloc(lines, sizeof(char *) * (nlines + 1));
82 chomp(line);
83 lines[nlines++] = line; 74 lines[nlines++] = line;
84 } 75 }
85 } 76 bb_xferror(fp, *argv);
77 bb_fclose_nonstdin(fp);
78 } while (*++argv);
86 79
87 /* sort it */ 80 /* sort it */
88 qsort(lines, nlines, sizeof(char *), compare); 81 qsort(lines, nlines, sizeof(char *), compare);
89 82
90 /* print it */ 83 /* print it */
91#ifdef CONFIG_FEATURE_SORT_REVERSE 84 i = 0;
92 if (reverse) { 85 --nlines;
93 for (i = --nlines; 0 <= i; i--) 86 if ((inc = 1 - (flags & 2)) < 0) { /* reverse */
94#ifdef CONFIG_FEATURE_SORT_UNIQUE 87 i = nlines;
95 if((!unique) || (i == nlines) || (strcmp(lines[i + 1], lines[i]))) 88 }
96#endif 89 flags &= 4;
97 puts(lines[i]); 90
98 } else 91 while (nlines >= 0) {
99#endif 92 if (!flags || !nlines || strcmp(lines[i+inc], lines[i])) {
100 for (i = 0; i < nlines; i++) 93 puts(lines[i]);
101#ifdef CONFIG_FEATURE_SORT_UNIQUE 94 }
102 if((!unique) || (!i) || (strcmp(lines[i - 1], lines[i]))) 95 i += inc;
103#endif 96 --nlines;
104 puts(lines[i]); 97 }
105 return EXIT_SUCCESS; 98
99 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
106} 100}
diff --git a/coreutils/stty.c b/coreutils/stty.c
index a67a17c0f..a3a98d9ef 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -30,9 +30,9 @@
30 30
31//#define TEST 31//#define TEST
32 32
33#include <stddef.h>
33#include <termios.h> 34#include <termios.h>
34#include <sys/ioctl.h> 35#include <sys/ioctl.h>
35#include <getopt.h>
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <unistd.h> 38#include <unistd.h>
@@ -155,13 +155,10 @@ enum speed_setting {
155 input_speed, output_speed, both_speeds 155 input_speed, output_speed, both_speeds
156}; 156};
157 157
158/* What to output and how. */
159enum output_type {
160 changed, all, recoverable /* Default, -a, -g. */
161};
162
163/* Which member(s) of `struct termios' a mode uses. */ 158/* Which member(s) of `struct termios' a mode uses. */
164enum mode_type { 159enum mode_type {
160 /* Do NOT change the order or values, as mode_type_flag()
161 * depends on them. */
165 control, input, output, local, combination 162 control, input, output, local, combination
166}; 163};
167 164
@@ -199,156 +196,159 @@ static const char stty_dec [] = "dec";
199/* Each mode. */ 196/* Each mode. */
200struct mode_info { 197struct mode_info {
201 const char *name; /* Name given on command line. */ 198 const char *name; /* Name given on command line. */
202 enum mode_type type; /* Which structure element to change. */ 199 /* enum mode_type type; */
200 char type; /* Which structure element to change. */
203 char flags; /* Setting and display options. */ 201 char flags; /* Setting and display options. */
202 unsigned short mask; /* Other bits to turn off for this mode. */
204 unsigned long bits; /* Bits to set for this mode. */ 203 unsigned long bits; /* Bits to set for this mode. */
205 unsigned long mask; /* Other bits to turn off for this mode. */
206}; 204};
207 205
206#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
207
208static const struct mode_info mode_info[] = { 208static const struct mode_info mode_info[] = {
209 {"parenb", control, REV, PARENB, 0 }, 209 MI_ENTRY("parenb", control, REV, PARENB, 0 ),
210 {"parodd", control, REV, PARODD, 0 }, 210 MI_ENTRY("parodd", control, REV, PARODD, 0 ),
211 {"cs5", control, 0, CS5, CSIZE}, 211 MI_ENTRY("cs5", control, 0, CS5, CSIZE),
212 {"cs6", control, 0, CS6, CSIZE}, 212 MI_ENTRY("cs6", control, 0, CS6, CSIZE),
213 {"cs7", control, 0, CS7, CSIZE}, 213 MI_ENTRY("cs7", control, 0, CS7, CSIZE),
214 {"cs8", control, 0, CS8, CSIZE}, 214 MI_ENTRY("cs8", control, 0, CS8, CSIZE),
215 {"hupcl", control, REV, HUPCL, 0 }, 215 MI_ENTRY("hupcl", control, REV, HUPCL, 0 ),
216 {"hup", control, REV | OMIT, HUPCL, 0 }, 216 MI_ENTRY("hup", control, REV | OMIT, HUPCL, 0 ),
217 {"cstopb", control, REV, CSTOPB, 0 }, 217 MI_ENTRY("cstopb", control, REV, CSTOPB, 0 ),
218 {"cread", control, SANE_SET | REV, CREAD, 0 }, 218 MI_ENTRY("cread", control, SANE_SET | REV, CREAD, 0 ),
219 {"clocal", control, REV, CLOCAL, 0 }, 219 MI_ENTRY("clocal", control, REV, CLOCAL, 0 ),
220#ifdef CRTSCTS 220#ifdef CRTSCTS
221 {"crtscts", control, REV, CRTSCTS, 0 }, 221 MI_ENTRY("crtscts", control, REV, CRTSCTS, 0 ),
222#endif 222#endif
223 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0 }, 223 MI_ENTRY("ignbrk", input, SANE_UNSET | REV, IGNBRK, 0 ),
224 {"brkint", input, SANE_SET | REV, BRKINT, 0 }, 224 MI_ENTRY("brkint", input, SANE_SET | REV, BRKINT, 0 ),
225 {"ignpar", input, REV, IGNPAR, 0 }, 225 MI_ENTRY("ignpar", input, REV, IGNPAR, 0 ),
226 {"parmrk", input, REV, PARMRK, 0 }, 226 MI_ENTRY("parmrk", input, REV, PARMRK, 0 ),
227 {"inpck", input, REV, INPCK, 0 }, 227 MI_ENTRY("inpck", input, REV, INPCK, 0 ),
228 {"istrip", input, REV, ISTRIP, 0 }, 228 MI_ENTRY("istrip", input, REV, ISTRIP, 0 ),
229 {"inlcr", input, SANE_UNSET | REV, INLCR, 0 }, 229 MI_ENTRY("inlcr", input, SANE_UNSET | REV, INLCR, 0 ),
230 {"igncr", input, SANE_UNSET | REV, IGNCR, 0 }, 230 MI_ENTRY("igncr", input, SANE_UNSET | REV, IGNCR, 0 ),
231 {"icrnl", input, SANE_SET | REV, ICRNL, 0 }, 231 MI_ENTRY("icrnl", input, SANE_SET | REV, ICRNL, 0 ),
232 {"ixon", input, REV, IXON, 0 }, 232 MI_ENTRY("ixon", input, REV, IXON, 0 ),
233 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0 }, 233 MI_ENTRY("ixoff", input, SANE_UNSET | REV, IXOFF, 0 ),
234 {"tandem", input, REV | OMIT, IXOFF, 0 }, 234 MI_ENTRY("tandem", input, REV | OMIT, IXOFF, 0 ),
235#ifdef IUCLC 235#ifdef IUCLC
236 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0 }, 236 MI_ENTRY("iuclc", input, SANE_UNSET | REV, IUCLC, 0 ),
237#endif 237#endif
238#ifdef IXANY 238#ifdef IXANY
239 {"ixany", input, SANE_UNSET | REV, IXANY, 0 }, 239 MI_ENTRY("ixany", input, SANE_UNSET | REV, IXANY, 0 ),
240#endif 240#endif
241#ifdef IMAXBEL 241#ifdef IMAXBEL
242 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0 }, 242 MI_ENTRY("imaxbel", input, SANE_SET | REV, IMAXBEL, 0 ),
243#endif 243#endif
244 {"opost", output, SANE_SET | REV, OPOST, 0 }, 244 MI_ENTRY("opost", output, SANE_SET | REV, OPOST, 0 ),
245#ifdef OLCUC 245#ifdef OLCUC
246 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0 }, 246 MI_ENTRY("olcuc", output, SANE_UNSET | REV, OLCUC, 0 ),
247#endif 247#endif
248#ifdef OCRNL 248#ifdef OCRNL
249 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0 }, 249 MI_ENTRY("ocrnl", output, SANE_UNSET | REV, OCRNL, 0 ),
250#endif 250#endif
251#ifdef ONLCR 251#ifdef ONLCR
252 {"onlcr", output, SANE_SET | REV, ONLCR, 0 }, 252 MI_ENTRY("onlcr", output, SANE_SET | REV, ONLCR, 0 ),
253#endif 253#endif
254#ifdef ONOCR 254#ifdef ONOCR
255 {"onocr", output, SANE_UNSET | REV, ONOCR, 0 }, 255 MI_ENTRY("onocr", output, SANE_UNSET | REV, ONOCR, 0 ),
256#endif 256#endif
257#ifdef ONLRET 257#ifdef ONLRET
258 {"onlret", output, SANE_UNSET | REV, ONLRET, 0 }, 258 MI_ENTRY("onlret", output, SANE_UNSET | REV, ONLRET, 0 ),
259#endif 259#endif
260#ifdef OFILL 260#ifdef OFILL
261 {"ofill", output, SANE_UNSET | REV, OFILL, 0 }, 261 MI_ENTRY("ofill", output, SANE_UNSET | REV, OFILL, 0 ),
262#endif 262#endif
263#ifdef OFDEL 263#ifdef OFDEL
264 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0 }, 264 MI_ENTRY("ofdel", output, SANE_UNSET | REV, OFDEL, 0 ),
265#endif 265#endif
266#ifdef NLDLY 266#ifdef NLDLY
267 {"nl1", output, SANE_UNSET, NL1, NLDLY}, 267 MI_ENTRY("nl1", output, SANE_UNSET, NL1, NLDLY),
268 {"nl0", output, SANE_SET, NL0, NLDLY}, 268 MI_ENTRY("nl0", output, SANE_SET, NL0, NLDLY),
269#endif 269#endif
270#ifdef CRDLY 270#ifdef CRDLY
271 {"cr3", output, SANE_UNSET, CR3, CRDLY}, 271 MI_ENTRY("cr3", output, SANE_UNSET, CR3, CRDLY),
272 {"cr2", output, SANE_UNSET, CR2, CRDLY}, 272 MI_ENTRY("cr2", output, SANE_UNSET, CR2, CRDLY),
273 {"cr1", output, SANE_UNSET, CR1, CRDLY}, 273 MI_ENTRY("cr1", output, SANE_UNSET, CR1, CRDLY),
274 {"cr0", output, SANE_SET, CR0, CRDLY}, 274 MI_ENTRY("cr0", output, SANE_SET, CR0, CRDLY),
275#endif 275#endif
276 276
277#ifdef TABDLY 277#ifdef TABDLY
278 {"tab3", output, SANE_UNSET, TAB3, TABDLY}, 278 MI_ENTRY("tab3", output, SANE_UNSET, TAB3, TABDLY),
279 {"tab2", output, SANE_UNSET, TAB2, TABDLY}, 279 MI_ENTRY("tab2", output, SANE_UNSET, TAB2, TABDLY),
280 {"tab1", output, SANE_UNSET, TAB1, TABDLY}, 280 MI_ENTRY("tab1", output, SANE_UNSET, TAB1, TABDLY),
281 {"tab0", output, SANE_SET, TAB0, TABDLY}, 281 MI_ENTRY("tab0", output, SANE_SET, TAB0, TABDLY),
282#else 282#else
283# ifdef OXTABS 283# ifdef OXTABS
284 {"tab3", output, SANE_UNSET, OXTABS, 0 }, 284 MI_ENTRY("tab3", output, SANE_UNSET, OXTABS, 0 ),
285# endif 285# endif
286#endif 286#endif
287 287
288#ifdef BSDLY 288#ifdef BSDLY
289 {"bs1", output, SANE_UNSET, BS1, BSDLY}, 289 MI_ENTRY("bs1", output, SANE_UNSET, BS1, BSDLY),
290 {"bs0", output, SANE_SET, BS0, BSDLY}, 290 MI_ENTRY("bs0", output, SANE_SET, BS0, BSDLY),
291#endif 291#endif
292#ifdef VTDLY 292#ifdef VTDLY
293 {"vt1", output, SANE_UNSET, VT1, VTDLY}, 293 MI_ENTRY("vt1", output, SANE_UNSET, VT1, VTDLY),
294 {"vt0", output, SANE_SET, VT0, VTDLY}, 294 MI_ENTRY("vt0", output, SANE_SET, VT0, VTDLY),
295#endif 295#endif
296#ifdef FFDLY 296#ifdef FFDLY
297 {"ff1", output, SANE_UNSET, FF1, FFDLY}, 297 MI_ENTRY("ff1", output, SANE_UNSET, FF1, FFDLY),
298 {"ff0", output, SANE_SET, FF0, FFDLY}, 298 MI_ENTRY("ff0", output, SANE_SET, FF0, FFDLY),
299#endif 299#endif
300 {"isig", local, SANE_SET | REV, ISIG, 0 }, 300 MI_ENTRY("isig", local, SANE_SET | REV, ISIG, 0 ),
301 {"icanon", local, SANE_SET | REV, ICANON, 0 }, 301 MI_ENTRY("icanon", local, SANE_SET | REV, ICANON, 0 ),
302#ifdef IEXTEN 302#ifdef IEXTEN
303 {"iexten", local, SANE_SET | REV, IEXTEN, 0 }, 303 MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ),
304#endif 304#endif
305 {"echo", local, SANE_SET | REV, ECHO, 0 }, 305 MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ),
306 {"echoe", local, SANE_SET | REV, ECHOE, 0 }, 306 MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ),
307 {"crterase", local, REV | OMIT, ECHOE, 0 }, 307 MI_ENTRY("crterase", local, REV | OMIT, ECHOE, 0 ),
308 {"echok", local, SANE_SET | REV, ECHOK, 0 }, 308 MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ),
309 {"echonl", local, SANE_UNSET | REV, ECHONL, 0 }, 309 MI_ENTRY("echonl", local, SANE_UNSET | REV, ECHONL, 0 ),
310 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0 }, 310 MI_ENTRY("noflsh", local, SANE_UNSET | REV, NOFLSH, 0 ),
311#ifdef XCASE 311#ifdef XCASE
312 {"xcase", local, SANE_UNSET | REV, XCASE, 0 }, 312 MI_ENTRY("xcase", local, SANE_UNSET | REV, XCASE, 0 ),
313#endif 313#endif
314#ifdef TOSTOP 314#ifdef TOSTOP
315 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0 }, 315 MI_ENTRY("tostop", local, SANE_UNSET | REV, TOSTOP, 0 ),
316#endif 316#endif
317#ifdef ECHOPRT 317#ifdef ECHOPRT
318 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0 }, 318 MI_ENTRY("echoprt", local, SANE_UNSET | REV, ECHOPRT, 0 ),
319 {"prterase", local, REV | OMIT, ECHOPRT, 0 }, 319 MI_ENTRY("prterase", local, REV | OMIT, ECHOPRT, 0 ),
320#endif 320#endif
321#ifdef ECHOCTL 321#ifdef ECHOCTL
322 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0 }, 322 MI_ENTRY("echoctl", local, SANE_SET | REV, ECHOCTL, 0 ),
323 {"ctlecho", local, REV | OMIT, ECHOCTL, 0 }, 323 MI_ENTRY("ctlecho", local, REV | OMIT, ECHOCTL, 0 ),
324#endif 324#endif
325#ifdef ECHOKE 325#ifdef ECHOKE
326 {"echoke", local, SANE_SET | REV, ECHOKE, 0 }, 326 MI_ENTRY("echoke", local, SANE_SET | REV, ECHOKE, 0 ),
327 {"crtkill", local, REV | OMIT, ECHOKE, 0 }, 327 MI_ENTRY("crtkill", local, REV | OMIT, ECHOKE, 0 ),
328#endif 328#endif
329 {evenp, combination, REV | OMIT, 0, 0 }, 329 MI_ENTRY(evenp, combination, REV | OMIT, 0, 0 ),
330 {parity, combination, REV | OMIT, 0, 0 }, 330 MI_ENTRY(parity, combination, REV | OMIT, 0, 0 ),
331 {stty_oddp, combination, REV | OMIT, 0, 0 }, 331 MI_ENTRY(stty_oddp, combination, REV | OMIT, 0, 0 ),
332 {stty_nl, combination, REV | OMIT, 0, 0 }, 332 MI_ENTRY(stty_nl, combination, REV | OMIT, 0, 0 ),
333 {stty_ek, combination, OMIT, 0, 0 }, 333 MI_ENTRY(stty_ek, combination, OMIT, 0, 0 ),
334 {stty_sane, combination, OMIT, 0, 0 }, 334 MI_ENTRY(stty_sane, combination, OMIT, 0, 0 ),
335 {cooked, combination, REV | OMIT, 0, 0 }, 335 MI_ENTRY(cooked, combination, REV | OMIT, 0, 0 ),
336 {raw, combination, REV | OMIT, 0, 0 }, 336 MI_ENTRY(raw, combination, REV | OMIT, 0, 0 ),
337 {stty_pass8, combination, REV | OMIT, 0, 0 }, 337 MI_ENTRY(stty_pass8, combination, REV | OMIT, 0, 0 ),
338 {litout, combination, REV | OMIT, 0, 0 }, 338 MI_ENTRY(litout, combination, REV | OMIT, 0, 0 ),
339 {cbreak, combination, REV | OMIT, 0, 0 }, 339 MI_ENTRY(cbreak, combination, REV | OMIT, 0, 0 ),
340#ifdef IXANY 340#ifdef IXANY
341 {decctlq, combination, REV | OMIT, 0, 0 }, 341 MI_ENTRY(decctlq, combination, REV | OMIT, 0, 0 ),
342#endif 342#endif
343#if defined (TABDLY) || defined (OXTABS) 343#if defined (TABDLY) || defined (OXTABS)
344 {stty_tabs, combination, REV | OMIT, 0, 0 }, 344 MI_ENTRY(stty_tabs, combination, REV | OMIT, 0, 0 ),
345#endif 345#endif
346#if defined(XCASE) && defined(IUCLC) && defined(OLCUC) 346#if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
347 {stty_lcase, combination, REV | OMIT, 0, 0 }, 347 MI_ENTRY(stty_lcase, combination, REV | OMIT, 0, 0 ),
348 {stty_LCASE, combination, REV | OMIT, 0, 0 }, 348 MI_ENTRY(stty_LCASE, combination, REV | OMIT, 0, 0 ),
349#endif 349#endif
350 {stty_crt, combination, OMIT, 0, 0 }, 350 MI_ENTRY(stty_crt, combination, OMIT, 0, 0 ),
351 {stty_dec, combination, OMIT, 0, 0 }, 351 MI_ENTRY(stty_dec, combination, OMIT, 0, 0 ),
352}; 352};
353 353
354static const int NUM_mode_info = 354static const int NUM_mode_info =
@@ -359,7 +359,7 @@ static const int NUM_mode_info =
359struct control_info { 359struct control_info {
360 const char *name; /* Name given on command line. */ 360 const char *name; /* Name given on command line. */
361 unsigned char saneval; /* Value to set for `stty sane'. */ 361 unsigned char saneval; /* Value to set for `stty sane'. */
362 int offset; /* Offset in c_cc. */ 362 unsigned char offset; /* Offset in c_cc. */
363}; 363};
364 364
365/* Control characters. */ 365/* Control characters. */
@@ -408,7 +408,6 @@ static const int NUM_control_info =
408 408
409 409
410static const char * visible(unsigned int ch); 410static const char * visible(unsigned int ch);
411static unsigned long baud_to_value(speed_t speed);
412static int recover_mode(char *arg, struct termios *mode); 411static int recover_mode(char *arg, struct termios *mode);
413static int screen_columns(void); 412static int screen_columns(void);
414static int set_mode(const struct mode_info *info, 413static int set_mode(const struct mode_info *info,
@@ -416,12 +415,11 @@ static int set_mode(const struct mode_info *info,
416static speed_t string_to_baud(const char *arg); 415static speed_t string_to_baud(const char *arg);
417static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); 416static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode);
418static void display_all(struct termios *mode, int fd, 417static void display_all(struct termios *mode, int fd,
419 const char *device_name); 418 const char *device_name);
420static void display_changed(struct termios *mode); 419static void display_changed(struct termios *mode, int fd,
421static void display_recoverable(struct termios *mode); 420 const char *device_name);
422static void display_settings(enum output_type output_type, 421static void display_recoverable(struct termios *mode, int fd,
423 struct termios *mode, int fd, 422 const char *device_name);
424 const char *device_name);
425static void display_speed(struct termios *mode, int fancy); 423static void display_speed(struct termios *mode, int fancy);
426static void display_window_size(int fancy, int fd, 424static void display_window_size(int fancy, int fd,
427 const char *device_name); 425 const char *device_name);
@@ -479,7 +477,7 @@ extern int main(int argc, char **argv)
479#endif 477#endif
480{ 478{
481 struct termios mode; 479 struct termios mode;
482 enum output_type output_type; 480 void (*output_func)(struct termios *, int, const char *);
483 int optc; 481 int optc;
484 int require_set_attr; 482 int require_set_attr;
485 int speed_was_set; 483 int speed_was_set;
@@ -491,7 +489,7 @@ extern int main(int argc, char **argv)
491 int fd; 489 int fd;
492 const char *device_name; 490 const char *device_name;
493 491
494 output_type = changed; 492 output_func = display_changed;
495 verbose_output = 0; 493 verbose_output = 0;
496 recoverable_output = 0; 494 recoverable_output = 0;
497 495
@@ -502,17 +500,17 @@ extern int main(int argc, char **argv)
502 switch (optc) { 500 switch (optc) {
503 case 'a': 501 case 'a':
504 verbose_output = 1; 502 verbose_output = 1;
505 output_type = all; 503 output_func = display_all;
506 break; 504 break;
507 505
508 case 'g': 506 case 'g':
509 recoverable_output = 1; 507 recoverable_output = 1;
510 output_type = recoverable; 508 output_func = display_recoverable;
511 break; 509 break;
512 510
513 case 'F': 511 case 'F':
514 if (file_name) 512 if (file_name)
515 error_msg_and_die("only one device may be specified"); 513 bb_error_msg_and_die("only one device may be specified");
516 file_name = optarg; 514 file_name = optarg;
517 break; 515 break;
518 516
@@ -529,12 +527,12 @@ extern int main(int argc, char **argv)
529 noargs = 0; 527 noargs = 0;
530 528
531 /* Specifying both -a and -g gets an error. */ 529 /* Specifying both -a and -g gets an error. */
532 if (verbose_output && recoverable_output) 530 if (verbose_output & recoverable_output)
533 error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive"); 531 bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive");
534 532
535 /* Specifying any other arguments with -a or -g gets an error. */ 533 /* Specifying any other arguments with -a or -g gets an error. */
536 if (!noargs && (verbose_output || recoverable_output)) 534 if (~noargs & (verbose_output | recoverable_output))
537 error_msg_and_die ("modes may not be set when specifying an output style"); 535 bb_error_msg_and_die ("modes may not be set when specifying an output style");
538 536
539 /* FIXME: it'd be better not to open the file until we've verified 537 /* FIXME: it'd be better not to open the file until we've verified
540 that all arguments are valid. Otherwise, we could end up doing 538 that all arguments are valid. Otherwise, we could end up doing
@@ -547,26 +545,26 @@ extern int main(int argc, char **argv)
547 device_name = file_name; 545 device_name = file_name;
548 fd = open(device_name, O_RDONLY | O_NONBLOCK); 546 fd = open(device_name, O_RDONLY | O_NONBLOCK);
549 if (fd < 0) 547 if (fd < 0)
550 perror_msg_and_die("%s", device_name); 548 bb_perror_msg_and_die("%s", device_name);
551 if ((fdflags = fcntl(fd, F_GETFL)) == -1 549 if ((fdflags = fcntl(fd, F_GETFL)) == -1
552 || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) 550 || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
553 perror_msg_and_die("%s: couldn't reset non-blocking mode", 551 bb_perror_msg_and_die("%s: couldn't reset non-blocking mode",
554 device_name); 552 device_name);
555 } else { 553 } else {
556 fd = 0; 554 fd = 0;
557 device_name = "standard input"; 555 device_name = bb_msg_standard_input;
558 } 556 }
559 557
560 /* Initialize to all zeroes so there is no risk memcmp will report a 558 /* Initialize to all zeroes so there is no risk memcmp will report a
561 spurious difference in an uninitialized portion of the structure. */ 559 spurious difference in an uninitialized portion of the structure. */
562 memset(&mode, 0, sizeof(mode)); 560 memset(&mode, 0, sizeof(mode));
563 if (tcgetattr(fd, &mode)) 561 if (tcgetattr(fd, &mode))
564 perror_msg_and_die("%s", device_name); 562 bb_perror_msg_and_die("%s", device_name);
565 563
566 if (verbose_output || recoverable_output || noargs) { 564 if (verbose_output | recoverable_output | noargs) {
567 max_col = screen_columns(); 565 max_col = screen_columns();
568 current_col = 0; 566 current_col = 0;
569 display_settings(output_type, &mode, fd, device_name); 567 output_func(&mode, fd, device_name);
570 return EXIT_SUCCESS; 568 return EXIT_SUCCESS;
571 } 569 }
572 570
@@ -610,13 +608,13 @@ extern int main(int argc, char **argv)
610 } 608 }
611 609
612 if (match_found == 0 && reversed) 610 if (match_found == 0 && reversed)
613 error_msg_and_die("invalid argument `%s'", --argv[k]); 611 bb_error_msg_and_die("invalid argument `%s'", --argv[k]);
614 612
615 if (match_found == 0) 613 if (match_found == 0)
616 for (i = 0; i < NUM_control_info; ++i) 614 for (i = 0; i < NUM_control_info; ++i)
617 if (STREQ(argv[k], control_info[i].name)) { 615 if (STREQ(argv[k], control_info[i].name)) {
618 if (k == argc - 1) 616 if (k == argc - 1)
619 error_msg_and_die("missing argument to `%s'", argv[k]); 617 bb_error_msg_and_die("missing argument to `%s'", argv[k]);
620 match_found = 1; 618 match_found = 1;
621 ++k; 619 ++k;
622 set_control_char(&control_info[i], argv[k], &mode); 620 set_control_char(&control_info[i], argv[k], &mode);
@@ -627,14 +625,14 @@ extern int main(int argc, char **argv)
627 if (match_found == 0) { 625 if (match_found == 0) {
628 if (STREQ(argv[k], "ispeed")) { 626 if (STREQ(argv[k], "ispeed")) {
629 if (k == argc - 1) 627 if (k == argc - 1)
630 error_msg_and_die("missing argument to `%s'", argv[k]); 628 bb_error_msg_and_die("missing argument to `%s'", argv[k]);
631 ++k; 629 ++k;
632 set_speed(input_speed, argv[k], &mode); 630 set_speed(input_speed, argv[k], &mode);
633 speed_was_set = 1; 631 speed_was_set = 1;
634 require_set_attr = 1; 632 require_set_attr = 1;
635 } else if (STREQ(argv[k], "ospeed")) { 633 } else if (STREQ(argv[k], "ospeed")) {
636 if (k == argc - 1) 634 if (k == argc - 1)
637 error_msg_and_die("missing argument to `%s'", argv[k]); 635 bb_error_msg_and_die("missing argument to `%s'", argv[k]);
638 ++k; 636 ++k;
639 set_speed(output_speed, argv[k], &mode); 637 set_speed(output_speed, argv[k], &mode);
640 speed_was_set = 1; 638 speed_was_set = 1;
@@ -643,16 +641,16 @@ extern int main(int argc, char **argv)
643#ifdef TIOCGWINSZ 641#ifdef TIOCGWINSZ
644 else if (STREQ(argv[k], "rows")) { 642 else if (STREQ(argv[k], "rows")) {
645 if (k == argc - 1) 643 if (k == argc - 1)
646 error_msg_and_die("missing argument to `%s'", argv[k]); 644 bb_error_msg_and_die("missing argument to `%s'", argv[k]);
647 ++k; 645 ++k;
648 set_window_size((int) parse_number(argv[k], stty_suffixes), 646 set_window_size((int) bb_xparse_number(argv[k], stty_suffixes),
649 -1, fd, device_name); 647 -1, fd, device_name);
650 } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { 648 } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) {
651 if (k == argc - 1) 649 if (k == argc - 1)
652 error_msg_and_die("missing argument to `%s'", argv[k]); 650 bb_error_msg_and_die("missing argument to `%s'", argv[k]);
653 ++k; 651 ++k;
654 set_window_size(-1, 652 set_window_size(-1,
655 (int) parse_number(argv[k], stty_suffixes), 653 (int) bb_xparse_number(argv[k], stty_suffixes),
656 fd, device_name); 654 fd, device_name);
657 } else if (STREQ(argv[k], "size")) { 655 } else if (STREQ(argv[k], "size")) {
658 max_col = screen_columns(); 656 max_col = screen_columns();
@@ -663,9 +661,9 @@ extern int main(int argc, char **argv)
663#ifdef HAVE_C_LINE 661#ifdef HAVE_C_LINE
664 else if (STREQ(argv[k], "line")) { 662 else if (STREQ(argv[k], "line")) {
665 if (k == argc - 1) 663 if (k == argc - 1)
666 error_msg_and_die("missing argument to `%s'", argv[k]); 664 bb_error_msg_and_die("missing argument to `%s'", argv[k]);
667 ++k; 665 ++k;
668 mode.c_line = parse_number(argv[k], stty_suffixes); 666 mode.c_line = bb_xparse_number(argv[k], stty_suffixes);
669 require_set_attr = 1; 667 require_set_attr = 1;
670 } 668 }
671#endif 669#endif
@@ -679,7 +677,7 @@ extern int main(int argc, char **argv)
679 speed_was_set = 1; 677 speed_was_set = 1;
680 require_set_attr = 1; 678 require_set_attr = 1;
681 } else 679 } else
682 error_msg_and_die("invalid argument `%s'", argv[k]); 680 bb_error_msg_and_die("invalid argument `%s'", argv[k]);
683 } 681 }
684 } 682 }
685 683
@@ -687,7 +685,7 @@ extern int main(int argc, char **argv)
687 struct termios new_mode; 685 struct termios new_mode;
688 686
689 if (tcsetattr(fd, TCSADRAIN, &mode)) 687 if (tcsetattr(fd, TCSADRAIN, &mode))
690 perror_msg_and_die("%s", device_name); 688 bb_perror_msg_and_die("%s", device_name);
691 689
692 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if 690 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
693 it performs *any* of the requested operations. This means it 691 it performs *any* of the requested operations. This means it
@@ -700,7 +698,7 @@ extern int main(int argc, char **argv)
700 spurious difference in an uninitialized portion of the structure. */ 698 spurious difference in an uninitialized portion of the structure. */
701 memset(&new_mode, 0, sizeof(new_mode)); 699 memset(&new_mode, 0, sizeof(new_mode));
702 if (tcgetattr(fd, &new_mode)) 700 if (tcgetattr(fd, &new_mode))
703 perror_msg_and_die("%s", device_name); 701 bb_perror_msg_and_die("%s", device_name);
704 702
705 /* Normally, one shouldn't use memcmp to compare structures that 703 /* Normally, one shouldn't use memcmp to compare structures that
706 may have `holes' containing uninitialized data, but we have been 704 may have `holes' containing uninitialized data, but we have been
@@ -723,7 +721,7 @@ extern int main(int argc, char **argv)
723 new_mode.c_cflag &= (~CIBAUD); 721 new_mode.c_cflag &= (~CIBAUD);
724 if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0) 722 if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
725#endif 723#endif
726 error_msg_and_die ("%s: unable to perform all requested operations", 724 bb_error_msg_and_die ("%s: unable to perform all requested operations",
727 device_name); 725 device_name);
728 } 726 }
729 } 727 }
@@ -896,9 +894,9 @@ set_mode(const struct mode_info *info, int reversed, struct termios *mode)
896#endif 894#endif
897 } 895 }
898 } else if (reversed) 896 } else if (reversed)
899 *bitsp = *bitsp & ~info->mask & ~info->bits; 897 *bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits;
900 else 898 else
901 *bitsp = (*bitsp & ~info->mask) | info->bits; 899 *bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits;
902 900
903 return 1; 901 return 1;
904} 902}
@@ -910,7 +908,7 @@ set_control_char(const struct control_info *info, const char *arg,
910 unsigned char value; 908 unsigned char value;
911 909
912 if (info->name == stty_min || info->name == stty_time) 910 if (info->name == stty_min || info->name == stty_time)
913 value = parse_number(arg, stty_suffixes); 911 value = bb_xparse_number(arg, stty_suffixes);
914 else if (arg[0] == '\0' || arg[1] == '\0') 912 else if (arg[0] == '\0' || arg[1] == '\0')
915 value = arg[0]; 913 value = arg[0];
916 else if (STREQ(arg, "^-") || STREQ(arg, "undef")) 914 else if (STREQ(arg, "^-") || STREQ(arg, "undef"))
@@ -921,7 +919,7 @@ set_control_char(const struct control_info *info, const char *arg,
921 else 919 else
922 value = arg[1] & ~0140; /* Non-letters get weird results. */ 920 value = arg[1] & ~0140; /* Non-letters get weird results. */
923 } else 921 } else
924 value = parse_number(arg, stty_suffixes); 922 value = bb_xparse_number(arg, stty_suffixes);
925 mode->c_cc[info->offset] = value; 923 mode->c_cc[info->offset] = value;
926} 924}
927 925
@@ -931,10 +929,13 @@ set_speed(enum speed_setting type, const char *arg, struct termios *mode)
931 speed_t baud; 929 speed_t baud;
932 930
933 baud = string_to_baud(arg); 931 baud = string_to_baud(arg);
934 if (type == input_speed || type == both_speeds) 932
933 if (type != output_speed) { /* either input or both */
935 cfsetispeed(mode, baud); 934 cfsetispeed(mode, baud);
936 if (type == output_speed || type == both_speeds) 935 }
936 if (type != input_speed) { /* either output or both */
937 cfsetospeed(mode, baud); 937 cfsetospeed(mode, baud);
938 }
938} 939}
939 940
940#ifdef TIOCGWINSZ 941#ifdef TIOCGWINSZ
@@ -953,7 +954,7 @@ set_window_size(int rows, int cols, int fd, const char *device_name)
953 954
954 if (get_win_size(fd, &win)) { 955 if (get_win_size(fd, &win)) {
955 if (errno != EINVAL) 956 if (errno != EINVAL)
956 perror_msg_and_die("%s", device_name); 957 bb_perror_msg_and_die("%s", device_name);
957 memset(&win, 0, sizeof(win)); 958 memset(&win, 0, sizeof(win));
958 } 959 }
959 960
@@ -975,32 +976,28 @@ set_window_size(int rows, int cols, int fd, const char *device_name)
975 ttysz.ts_lines = win.ws_row; 976 ttysz.ts_lines = win.ws_row;
976 ttysz.ts_cols = win.ws_col; 977 ttysz.ts_cols = win.ws_col;
977 978
978 win.ws_row = 1; 979 win.ws_row = win.ws_col = 1;
979 win.ws_col = 1;
980
981 if (ioctl(fd, TIOCSWINSZ, (char *) &win))
982 perror_msg_and_die("%s", device_name);
983 980
984 if (ioctl(fd, TIOCSSIZE, (char *) &ttysz)) 981 if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0)
985 perror_msg_and_die("%s", device_name); 982 || (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) {
983 bb_perror_msg_and_die("%s", device_name);
986 return; 984 return;
987 } 985 }
988# endif 986# endif
989 987
990 if (ioctl(fd, TIOCSWINSZ, (char *) &win)) 988 if (ioctl(fd, TIOCSWINSZ, (char *) &win))
991 perror_msg_and_die("%s", device_name); 989 bb_perror_msg_and_die("%s", device_name);
992} 990}
993 991
994static void display_window_size(int fancy, int fd, const char *device_name) 992static void display_window_size(int fancy, int fd, const char *device_name)
995{ 993{
994 const char *fmt_str = "%s" "\0" "%s: no size information for this device";
996 struct winsize win; 995 struct winsize win;
997 996
998 if (get_win_size(fd, &win)) { 997 if (get_win_size(fd, &win)) {
999 if (errno != EINVAL) 998 if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
1000 perror_msg_and_die("%s", device_name); 999 bb_perror_msg_and_die(fmt_str, device_name);
1001 if (!fancy) 1000 }
1002 perror_msg_and_die("%s: no size information for this device",
1003 device_name);
1004 } else { 1001 } else {
1005 wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n", 1002 wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
1006 win.ws_row, win.ws_col); 1003 win.ws_row, win.ws_col);
@@ -1012,6 +1009,9 @@ static void display_window_size(int fancy, int fd, const char *device_name)
1012 1009
1013static int screen_columns(void) 1010static int screen_columns(void)
1014{ 1011{
1012 int columns;
1013 const char *s;
1014
1015#ifdef TIOCGWINSZ 1015#ifdef TIOCGWINSZ
1016 struct winsize win; 1016 struct winsize win;
1017 1017
@@ -1025,51 +1025,29 @@ static int screen_columns(void)
1025 return win.ws_col; 1025 return win.ws_col;
1026#endif 1026#endif
1027 1027
1028 if (getenv("COLUMNS")) 1028 columns = 80;
1029 return atoi(getenv("COLUMNS")); 1029 if ((s = getenv("COLUMNS"))) {
1030 return 80; 1030 columns = atoi(s);
1031}
1032
1033static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode)
1034{
1035 switch (type) {
1036 case control:
1037 return &mode->c_cflag;
1038
1039 case input:
1040 return &mode->c_iflag;
1041
1042 case output:
1043 return &mode->c_oflag;
1044
1045 case local:
1046 return &mode->c_lflag;
1047
1048 default: /* combination: */
1049 return NULL;
1050 } 1031 }
1032 return columns;
1051} 1033}
1052 1034
1053static void 1035static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode)
1054display_settings(enum output_type output_type, struct termios *mode,
1055 int fd, const char *device_name)
1056{ 1036{
1057 switch (output_type) { 1037 static const unsigned char tcflag_offsets[] = {
1058 case changed: 1038 offsetof(struct termios, c_cflag), /* control */
1059 display_changed(mode); 1039 offsetof(struct termios, c_iflag), /* input */
1060 break; 1040 offsetof(struct termios, c_oflag), /* output */
1061 1041 offsetof(struct termios, c_lflag) /* local */
1062 case all: 1042 };
1063 display_all(mode, fd, device_name); 1043
1064 break; 1044 if (((unsigned int) type) <= local) {
1065 1045 return (tcflag_t *)(((char *) mode) + tcflag_offsets[(int)type]);
1066 case recoverable:
1067 display_recoverable(mode);
1068 break;
1069 } 1046 }
1047 return NULL;
1070} 1048}
1071 1049
1072static void display_changed(struct termios *mode) 1050static void display_changed(struct termios *mode, int fd, const char *device_name)
1073{ 1051{
1074 int i; 1052 int i;
1075 int empty_line; 1053 int empty_line;
@@ -1206,18 +1184,25 @@ display_all(struct termios *mode, int fd, const char *device_name)
1206 1184
1207static void display_speed(struct termios *mode, int fancy) 1185static void display_speed(struct termios *mode, int fancy)
1208{ 1186{
1209 if (cfgetispeed(mode) == 0 || cfgetispeed(mode) == cfgetospeed(mode)) 1187 unsigned long ispeed, ospeed;
1210 wrapf(fancy ? "speed %lu baud;" : "%lu\n", 1188 const char *fmt_str =
1211 baud_to_value(cfgetospeed(mode))); 1189 "%lu %lu\n\0" "ispeed %lu baud; ospeed %lu baud;\0"
1212 else 1190 "%lu\n\0" "\0\0\0\0" "speed %lu baud;";
1213 wrapf(fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n", 1191
1214 baud_to_value(cfgetispeed(mode)), 1192 ospeed = ispeed = cfgetispeed(mode);
1215 baud_to_value(cfgetospeed(mode))); 1193 if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) {
1194 ispeed = ospeed; /* in case ispeed was 0 */
1195 fmt_str += 43;
1196 }
1197 if (fancy) {
1198 fmt_str += 9;
1199 }
1200 wrapf(fmt_str, bb_baud_to_value(ispeed), bb_baud_to_value(ospeed));
1216 if (!fancy) 1201 if (!fancy)
1217 current_col = 0; 1202 current_col = 0;
1218} 1203}
1219 1204
1220static void display_recoverable(struct termios *mode) 1205static void display_recoverable(struct termios *mode, int fd, const char *device_name)
1221{ 1206{
1222 int i; 1207 int i;
1223 1208
@@ -1259,62 +1244,9 @@ static int recover_mode(char *arg, struct termios *mode)
1259 return 1; 1244 return 1;
1260} 1245}
1261 1246
1262struct speed_map {
1263 speed_t speed; /* Internal form. */
1264 unsigned long value; /* Numeric value. */
1265};
1266
1267static const struct speed_map speeds[] = {
1268 {B0, 0},
1269 {B50, 50},
1270 {B75, 75},
1271 {B110, 110},
1272 {B134, 134},
1273 {B150, 150},
1274 {B200, 200},
1275 {B300, 300},
1276 {B600, 600},
1277 {B1200, 1200},
1278 {B1800, 1800},
1279 {B2400, 2400},
1280 {B4800, 4800},
1281 {B9600, 9600},
1282 {B19200, 19200},
1283 {B38400, 38400},
1284#ifdef B57600
1285 {B57600, 57600},
1286#endif
1287#ifdef B115200
1288 {B115200, 115200},
1289#endif
1290#ifdef B230400
1291 {B230400, 230400},
1292#endif
1293#ifdef B460800
1294 {B460800, 460800},
1295#endif
1296};
1297
1298static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map));
1299
1300static speed_t string_to_baud(const char *arg) 1247static speed_t string_to_baud(const char *arg)
1301{ 1248{
1302 int i; 1249 return bb_value_to_baud(bb_xparse_number(arg, 0));
1303
1304 for (i = 0; i < NUM_SPEEDS; ++i)
1305 if (parse_number(arg, 0) == speeds[i].value)
1306 return speeds[i].speed;
1307 return (speed_t) - 1;
1308}
1309
1310static unsigned long baud_to_value(speed_t speed)
1311{
1312 int i;
1313
1314 for (i = 0; i < NUM_SPEEDS; ++i)
1315 if (speed == speeds[i].speed)
1316 return speeds[i].value;
1317 return 0;
1318} 1250}
1319 1251
1320static void sane_mode(struct termios *mode) 1252static void sane_mode(struct termios *mode)
@@ -1333,10 +1265,12 @@ static void sane_mode(struct termios *mode)
1333 for (i = 0; i < NUM_mode_info; ++i) { 1265 for (i = 0; i < NUM_mode_info; ++i) {
1334 if (mode_info[i].flags & SANE_SET) { 1266 if (mode_info[i].flags & SANE_SET) {
1335 bitsp = mode_type_flag(mode_info[i].type, mode); 1267 bitsp = mode_type_flag(mode_info[i].type, mode);
1336 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits; 1268 *bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask))
1269 | mode_info[i].bits;
1337 } else if (mode_info[i].flags & SANE_UNSET) { 1270 } else if (mode_info[i].flags & SANE_UNSET) {
1338 bitsp = mode_type_flag(mode_info[i].type, mode); 1271 bitsp = mode_type_flag(mode_info[i].type, mode);
1339 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits; 1272 *bitsp = *bitsp & ~((unsigned long)mode_info[i].mask)
1273 & ~mode_info[i].bits;
1340 } 1274 }
1341 } 1275 }
1342} 1276}
@@ -1349,47 +1283,32 @@ static const char *visible(unsigned int ch)
1349 static char buf[10]; 1283 static char buf[10];
1350 char *bpout = buf; 1284 char *bpout = buf;
1351 1285
1352 if (ch == _POSIX_VDISABLE) 1286 if (ch == _POSIX_VDISABLE) {
1353 return "<undef>"; 1287 return "<undef>";
1288 }
1354 1289
1355 if (ch >= 32) { 1290 if (ch >= 128) {
1356 if (ch < 127) 1291 ch -= 128;
1357 *bpout++ = ch; 1292 *bpout++ = 'M';
1358 else if (ch == 127) { 1293 *bpout++ = '-';
1359 *bpout++ = '^'; 1294 }
1360 *bpout++ = '?'; 1295
1361 } else { 1296 if (ch < 32) {
1362 *bpout++ = 'M', *bpout++ = '-';
1363 if (ch >= 128 + 32) {
1364 if (ch < 128 + 127)
1365 *bpout++ = ch - 128;
1366 else {
1367 *bpout++ = '^';
1368 *bpout++ = '?';
1369 }
1370 } else {
1371 *bpout++ = '^';
1372 *bpout++ = ch - 128 + 64;
1373 }
1374 }
1375 } else {
1376 *bpout++ = '^'; 1297 *bpout++ = '^';
1377 *bpout++ = ch + 64; 1298 *bpout++ = ch + 64;
1299 } else if (ch < 127) {
1300 *bpout++ = ch;
1301 } else {
1302 *bpout++ = '^';
1303 *bpout++ = '?';
1378 } 1304 }
1305
1379 *bpout = '\0'; 1306 *bpout = '\0';
1380 return (const char *) buf; 1307 return (const char *) buf;
1381} 1308}
1382 1309
1383#ifdef TEST 1310#ifdef TEST
1384 1311
1385const char *applet_name = "stty"; 1312const char *bb_applet_name = "stty";
1386 1313
1387#endif 1314#endif
1388
1389/*
1390Local Variables:
1391c-file-style: "linux"
1392c-basic-offset: 4
1393tab-width: 4
1394End:
1395*/
diff --git a/coreutils/sync.c b/coreutils/sync.c
index d58168065..84746311f 100644
--- a/coreutils/sync.c
+++ b/coreutils/sync.c
@@ -20,15 +20,17 @@
20 * 20 *
21 */ 21 */
22 22
23#include <stdio.h> 23/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
24
24#include <stdlib.h> 25#include <stdlib.h>
25#include <unistd.h> 26#include <unistd.h>
26#include "busybox.h" 27#include "busybox.h"
27 28
28extern int sync_main(int argc, char **argv) 29extern int sync_main(int argc, char **argv)
29{ 30{
30 if (argc > 1 && **(argv + 1) == '-') 31 bb_warn_ignoring_args(argc - 1);
31 show_usage(); 32
32 sync(); 33 sync();
34
33 return(EXIT_SUCCESS); 35 return(EXIT_SUCCESS);
34} 36}
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 1703eefc6..8e0adf5b5 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -2,7 +2,6 @@
2/* 2/*
3 * Mini tail implementation for busybox 3 * Mini tail implementation for busybox
4 * 4 *
5 *
6 * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -21,14 +20,30 @@
21 * 20 *
22 */ 21 */
23 22
23/* BB_AUDIT SUSv3 compliant (need fancy for -c) */
24/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/tail.html */
24 26
25#include <fcntl.h> 27/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
26#include <getopt.h> 28 *
29 * Pretty much rewritten to fix numerous bugs and reduce realloc() calls.
30 * Bugs fixed (although I may have forgotten one or two... it was pretty bad)
31 * 1) mixing printf/write without fflush()ing stdout
32 * 2) no check that any open files are present
33 * 3) optstring had -q taking an arg
34 * 4) no error checking on write in some cases, and a warning even then
35 * 5) q and s interaction bug
36 * 6) no check for lseek error
37 * 7) lseek attempted when count==0 even if arg was +0 (from top)
38 */
39
40#include <stdio.h>
41#include <stdlib.h>
27#include <string.h> 42#include <string.h>
28#include <ctype.h> 43#include <ctype.h>
29#include <stdlib.h>
30#include <unistd.h> 44#include <unistd.h>
31#include <sys/types.h> 45#include <fcntl.h>
46#include <sys/stat.h>
32#include "busybox.h" 47#include "busybox.h"
33 48
34static const struct suffix_mult tail_suffixes[] = { 49static const struct suffix_mult tail_suffixes[] = {
@@ -38,234 +53,287 @@ static const struct suffix_mult tail_suffixes[] = {
38 { NULL, 0 } 53 { NULL, 0 }
39}; 54};
40 55
41static const int BYTES = 0; 56static int status
42static const int LINES = 1; 57#if EXIT_SUCCESS != 0
43 58 = EXIT_SUCCESS /* If it is 0 (paranoid check), let bss initialize it. */
44static char *tailbuf; 59#endif
45static int taillen; 60 ;
46static int newline;
47 61
48static void tailbuf_append(char *buf, int len) 62static void tail_xprint_header(const char *fmt, const char *filename)
49{ 63{
50 tailbuf = xrealloc(tailbuf, taillen + len); 64 /* If we get an output error, there is really no sense in continuing. */
51 memcpy(tailbuf + taillen, buf, len); 65 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
52 taillen += len; 66 bb_perror_nomsg_and_die();
67 }
53} 68}
54 69
55static void tailbuf_trunc(void) 70/* len should probably be size_t */
71static void tail_xbb_full_write(const char *buf, size_t len)
56{ 72{
57 char *s; 73 /* If we get a write error, there is really no sense in continuing. */
58 s = memchr(tailbuf, '\n', taillen); 74 if (bb_full_write(STDOUT_FILENO, buf, len) < 0) {
59 memmove(tailbuf, s + 1, taillen - ((s + 1) - tailbuf)); 75 bb_perror_nomsg_and_die();
60 taillen -= (s + 1) - tailbuf; 76 }
61 newline = 0;
62} 77}
63 78
64int tail_main(int argc, char **argv) 79static ssize_t tail_read(int fd, char *buf, size_t count)
65{ 80{
66 int from_top = 0, units = LINES, count = 10, sleep_period = 1; 81 ssize_t r;
67 int show_headers = 0, hide_headers = 0, follow = 0; 82
68 int *fds, nfiles = 0, status = EXIT_SUCCESS, nread, nwrite, seen = 0; 83 if ((r = safe_read(fd, buf, count)) < 0) {
69 char *s, *start, *end, buf[BUFSIZ]; 84 bb_perror_msg("read");
70 int i, opt; 85 status = EXIT_FAILURE;
71
72 if (argc >= 2) {
73 int line_num;
74 switch (argv[1][0]) {
75 case '+':
76 from_top = 1;
77 /* FALLS THROUGH */
78 case '-':
79 line_num = atoi(&argv[1][1]);
80 if (line_num != 0) {
81 optind = 2;
82 count = line_num;
83 }
84 break;
85 }
86 } 86 }
87 87
88 return r;
89}
90
91static const char tail_opts[] =
92 "fn:"
93#ifdef CONFIG_FEATURE_FANCY_TAIL
94 "c:qs:v"
95#endif
96 ;
97
98static const char header_fmt[] = "\n==> %s <==\n";
99
100int tail_main(int argc, char **argv)
101{
102 long count = 10;
103 unsigned int sleep_period = 1;
104 int from_top = 0;
105 int follow = 0;
106 int header_threshhold = 1;
88#ifdef CONFIG_FEATURE_FANCY_TAIL 107#ifdef CONFIG_FEATURE_FANCY_TAIL
89 while ((opt = getopt(argc, argv, "c:fn:q:s:v")) > 0) { 108 int count_bytes = 0;
90#else
91 while ((opt = getopt(argc, argv, "fn:")) > 0) {
92#endif 109#endif
110
111 char *tailbuf;
112 size_t tailbufsize;
113 int taillen = 0;
114 int newline = 0;
115
116 int *fds, nfiles, nread, nwrite, seen, i, opt;
117 char *s, *buf;
118 const char *fmt;
119
120 /* Allow legacy syntax of an initial numeric option without -n. */
121 if ((argv[1][0] == '+')
122 || ((argv[1][0] == '-')
123 /* && (isdigit)(argv[1][1]) */
124 && (((unsigned int)(argv[1][1] - '0')) <= 9))
125 ) {
126 optind = 2;
127 optarg = argv[1];
128 goto GET_COUNT;
129 }
130
131 while ((opt = getopt(argc, argv, tail_opts)) > 0) {
93 switch (opt) { 132 switch (opt) {
94 case 'f': 133 case 'f':
95 follow = 1; 134 follow = 1;
96 break; 135 break;
97#ifdef CONFIG_FEATURE_FANCY_TAIL 136#ifdef CONFIG_FEATURE_FANCY_TAIL
98 case 'c': 137 case 'c':
99 units = BYTES; 138 count_bytes = 1;
100 /* FALLS THROUGH */ 139 /* FALLS THROUGH */
101#endif 140#endif
102 case 'n': 141 case 'n':
103 count = parse_number(optarg, tail_suffixes); 142 GET_COUNT:
104 if (count < 0) 143 count = bb_xgetlarg10_sfx(optarg, tail_suffixes);
105 count = -count; 144 /* Note: Leading whitespace is an error trapped above. */
106 if (optarg[0] == '+') 145 if (*optarg == '+') {
107 from_top = 1; 146 from_top = 1;
147 } else {
148 from_top = 0;
149 }
150 if (count < 0) {
151 count = -count;
152 }
108 break; 153 break;
109#ifdef CONFIG_FEATURE_FANCY_TAIL 154#ifdef CONFIG_FEATURE_FANCY_TAIL
110 case 'q': 155 case 'q':
111 hide_headers = 1; 156 header_threshhold = INT_MAX;
112 break; 157 break;
113 case 's': 158 case 's':
114 sleep_period = parse_number(optarg, 0); 159 sleep_period =bb_xgetularg10_bnd(optarg, 0, UINT_MAX);
115 break; 160 break;
116 case 'v': 161 case 'v':
117 show_headers = 1; 162 header_threshhold = 0;
118 break; 163 break;
119#endif 164#endif
120 default: 165 default:
121 show_usage(); 166 bb_show_usage();
122 } 167 }
123 } 168 }
124 169
125 /* open all the files */ 170 /* open all the files */
126 fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1)); 171 fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1));
127 if (argc == optind) { 172
128 fds[nfiles++] = STDIN_FILENO; 173 argv += optind;
129 argv[optind] = "standard input"; 174 nfiles = i = 0;
130 } else { 175
131 for (i = optind; i < argc; i++) { 176 if ((argc -= optind) == 0) {
132 if (strcmp(argv[i], "-") == 0) { 177 struct stat statbuf;
133 fds[nfiles++] = STDIN_FILENO; 178
134 argv[i] = "standard input"; 179 if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
135 } else if ((fds[nfiles++] = open(argv[i], O_RDONLY)) < 0) { 180 follow = 0;
136 perror_msg("%s", argv[i]);
137 status = EXIT_FAILURE;
138 }
139 } 181 }
182 /* --argv; */
183 *argv = (char *) bb_msg_standard_input;
184 goto DO_STDIN;
185 }
186
187 do {
188 if ((argv[i][0] == '-') && !argv[i][1]) {
189 DO_STDIN:
190 fds[nfiles] = STDIN_FILENO;
191 } else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) {
192 bb_perror_msg("%s", argv[i]);
193 status = EXIT_FAILURE;
194 continue;
195 }
196 argv[nfiles] = argv[i];
197 ++nfiles;
198 } while (++i < argc);
199
200 if (!nfiles) {
201 bb_error_msg_and_die("no files");
140 } 202 }
141 203
204 tailbufsize = BUFSIZ;
142#ifdef CONFIG_FEATURE_FANCY_TAIL 205#ifdef CONFIG_FEATURE_FANCY_TAIL
143 /* tail the files */ 206 /* tail the files */
144 if (!from_top && units == BYTES) 207 if (from_top < count_bytes) { /* Each is 0 or 1, so true iff 0 < 1. */
145 tailbuf = xmalloc(count); 208 /* Hence, !from_top && count_bytes */
209 if (tailbufsize < count) {
210 tailbufsize = count + BUFSIZ;
211 }
212 }
146#endif 213#endif
214 buf = tailbuf = xmalloc(tailbufsize);
147 215
148 for (i = 0; i < nfiles; i++) { 216 fmt = header_fmt + 1; /* Skip header leading newline on first output. */
149 if (fds[i] == -1) 217 i = 0;
150 continue; 218 do {
151 if (!count) { 219 /* Be careful. It would be possible to optimize the count-bytes
152 lseek(fds[i], 0, SEEK_END); 220 * case if the file is seekable. If you do though, remember that
221 * starting file position may not be the beginning of the file.
222 * Beware of backing up too far. See example in wc.c.
223 */
224 if ((!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) {
153 continue; 225 continue;
154 } 226 }
155 seen = 0; 227
156 if (show_headers || (!hide_headers && nfiles > 1)) 228 if (nfiles > header_threshhold) {
157 printf("%s==> %s <==\n", i == 0 ? "" : "\n", argv[optind + i]); 229 tail_xprint_header(fmt, argv[i]);
158 while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { 230 fmt = header_fmt;
231 }
232
233 buf = tailbuf;
234 taillen = 0;
235 seen = 1;
236
237 while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
159 if (from_top) { 238 if (from_top) {
239 nwrite = nread;
240 if (seen < count) {
160#ifdef CONFIG_FEATURE_FANCY_TAIL 241#ifdef CONFIG_FEATURE_FANCY_TAIL
161 if (units == BYTES) { 242 if (count_bytes) {
162 if (count - 1 <= seen) 243 nwrite -= (count - seen);
163 nwrite = nread; 244 seen = count;
164 else if (count - 1 <= seen + nread) 245 } else
165 nwrite = nread + seen - (count - 1);
166 else
167 nwrite = 0;
168 seen += nread;
169 } else {
170#else
171 {
172#endif 246#endif
173 if (count - 1 <= seen) 247 {
174 nwrite = nread; 248 s = buf;
175 else { 249 do {
176 nwrite = 0; 250 --nwrite;
177 for (s = memchr(buf, '\n', nread); s != NULL; 251 if ((*s++ == '\n') && (++seen == count)) {
178 s = memchr(s+1, '\n', nread - (s + 1 - buf))) {
179 if (count - 1 <= ++seen) {
180 nwrite = nread - (s + 1 - buf);
181 break; 252 break;
182 } 253 }
183 } 254 } while (nwrite);
184 } 255 }
185 } 256 }
186 if (full_write(STDOUT_FILENO, buf + nread - nwrite, 257 tail_xbb_full_write(buf + nread - nwrite, nwrite);
187 nwrite) < 0) { 258 } else if (count) {
188 perror_msg("write");
189 status = EXIT_FAILURE;
190 break;
191 }
192 } else {
193#ifdef CONFIG_FEATURE_FANCY_TAIL 259#ifdef CONFIG_FEATURE_FANCY_TAIL
194 if (units == BYTES) { 260 if (count_bytes) {
195 if (nread < count) { 261 taillen += nread;
196 memmove(tailbuf, tailbuf + nread, count - nread); 262 if (taillen > count) {
197 memcpy(tailbuf + count - nread, buf, nread); 263 memmove(tailbuf, tailbuf + taillen - count, count);
198 } else { 264 taillen = count;
199 memcpy(tailbuf, buf + nread - count, count);
200 } 265 }
201 seen += nread; 266 } else
202 } else {
203#else
204 {
205#endif 267#endif
206 for (start = buf, end = memchr(buf, '\n', nread); 268 {
207 end != NULL; start = end+1, 269 int k = nread;
208 end = memchr(start, '\n', nread - (start - buf))) { 270 int nbuf = 0;
209 if (newline && count <= seen) 271
210 tailbuf_trunc(); 272 while (k) {
211 tailbuf_append(start, end - start + 1); 273 --k;
212 seen++; 274 if (buf[k] == '\n') {
213 newline = 1; 275 ++nbuf;
276 }
214 } 277 }
215 if (newline && count <= seen && nread - (start - buf) > 0)
216 tailbuf_trunc();
217 tailbuf_append(start, nread - (start - buf));
218 }
219 }
220 }
221 278
222 if (nread < 0) { 279 if (newline + nbuf < count) {
223 perror_msg("read"); 280 newline += nbuf;
224 status = EXIT_FAILURE; 281 taillen += nread;
225 }
226 282
227#ifdef CONFIG_FEATURE_FANCY_TAIL 283 } else {
228 if (!from_top && units == BYTES) { 284 int extra = 0;
229 if (count < seen) 285 if (buf[nread-1] != '\n') {
230 seen = count; 286 extra = 1;
231 if (full_write(STDOUT_FILENO, tailbuf + count - seen, seen) < 0) { 287 }
232 perror_msg("write"); 288
233 status = EXIT_FAILURE; 289 k = newline + nbuf + extra - count;
290 s = tailbuf;
291 while (k) {
292 if (*s == '\n') {
293 --k;
294 }
295 ++s;
296 }
297
298 taillen += nread - (s - tailbuf);
299 memmove(tailbuf, s, taillen);
300 newline = count - extra;
301 }
302 if (tailbufsize < taillen + BUFSIZ) {
303 tailbufsize = taillen + BUFSIZ;
304 tailbuf = xrealloc(tailbuf, tailbufsize);
305 }
306 }
307 buf = tailbuf + taillen;
234 } 308 }
235 } 309 }
236#endif
237 310
238 if (!from_top && units == LINES) { 311 if (!from_top) {
239 if (full_write(STDOUT_FILENO, tailbuf, taillen) < 0) { 312 tail_xbb_full_write(tailbuf, taillen);
240 perror_msg("write");
241 status = EXIT_FAILURE;
242 }
243 } 313 }
244 314
245 taillen = 0; 315 taillen = 0;
246 } 316 } while (++i < nfiles);
247
248 while (follow) {
249 sleep(sleep_period);
250 317
251 for (i = 0; i < nfiles; i++) { 318 buf = xrealloc(tailbuf, BUFSIZ);
252 if (fds[i] == -1)
253 continue;
254 319
255 if ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { 320 fmt = NULL;
256 if (show_headers || (!hide_headers && nfiles > 1))
257 printf("\n==> %s <==\n", argv[optind + i]);
258 321
259 do { 322 while (follow) {
260 full_write(STDOUT_FILENO, buf, nread); 323 sleep(sleep_period);
261 } while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0); 324 i = 0;
325 do {
326 if (nfiles > header_threshhold) {
327 fmt = header_fmt;
262 } 328 }
263 329 while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
264 if (nread < 0) { 330 if (fmt) {
265 perror_msg("read"); 331 tail_xprint_header(fmt, argv[i]);
266 status = EXIT_FAILURE; 332 fmt = NULL;
333 }
334 tail_xbb_full_write(buf, nread);
267 } 335 }
268 } 336 } while (++i < nfiles);
269 } 337 }
270 338
271 return status; 339 return status;
diff --git a/coreutils/tee.c b/coreutils/tee.c
index 1c145426a..7e86f2e29 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini tee implementation for busybox 3 * tee implementation for busybox
4 * 4 *
5 * Copyright (C) 2000,2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,47 +20,96 @@
20 * 20 *
21 */ 21 */
22 22
23#include "busybox.h" 23/* BB_AUDIT SUSv3 compliant */
24#include <getopt.h> 24/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
25
25#include <stdio.h> 26#include <stdio.h>
27#include <stdlib.h>
28#include <signal.h>
29#include <unistd.h>
30#include "busybox.h"
26 31
27int 32int tee_main(int argc, char **argv)
28tee_main(int argc, char **argv)
29{ 33{
30 char *mode = "w"; 34 const char *mode = "w\0a";
31 int c, i, status = 0, nfiles = 0;
32 FILE **files; 35 FILE **files;
36 FILE **p;
37 char **filenames;
38 int flags;
39 int retval = EXIT_SUCCESS;
40#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
41 size_t c;
42 RESERVE_CONFIG_BUFFER(buf, BUFSIZ);
43#else
44 int c;
45#endif
46
47 flags = bb_getopt_ulflags(argc, argv, "ia"); /* 'a' must be 2nd */
48
49 mode += (flags & 2); /* Since 'a' is the 2nd option... */
50
51 if (flags & 1) {
52 signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction.*/
53 }
54
55 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
56 * that doesn't consume all its input. Good idea... */
57 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/
33 58
34 while ((c = getopt(argc, argv, "a")) != EOF) { 59 /* Allocate an array of FILE *'s, with one extra for a sentinal. */
35 switch (c) { 60 p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));
36 case 'a': 61 *p = stdout;
37 mode = "a"; 62 argv += optind - 1;
38 break; 63 filenames = argv - 1;
39 default: 64 *filenames = (char *) bb_msg_standard_input; /* for later */
40 show_usage(); 65 goto GOT_NEW_FILE;
66
67 do {
68 if ((*p = bb_wfopen(*argv, mode)) == NULL) {
69 retval = EXIT_FAILURE;
70 continue;
71 }
72 filenames[(int)(p - files)] = *argv;
73 GOT_NEW_FILE:
74 setbuf(*p, NULL); /* tee must not buffer output. */
75 ++p;
76 } while (*++argv);
77
78 *p = NULL; /* Store the sentinal value. */
79
80#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
81 while ((c = fread(buf, 1, BUFSIZ, stdin)) != 0) {
82 for (p=files ; *p ; p++) {
83 fwrite(buf, 1, c, *p);
41 } 84 }
42 } 85 }
43 86
44 files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 1)); 87#ifdef CONFIG_FEATURE_CLEAN_UP
45 files[nfiles++] = stdout; 88 RELEASE_CONFIG_BUFFER(buf);
46 while (optind < argc) { 89#endif
47 if ((files[nfiles++] = wfopen(argv[optind++], mode)) == NULL) { 90
48 nfiles--; 91#else
49 status = 1; 92 while ((c = getchar()) != EOF) {
93 for (p=files ; *p ; p++) {
94 putc(c, *p);
50 } 95 }
51 } 96 }
97#endif
52 98
53 while ((c = getchar()) != EOF) 99 /* Now we need to check for i/o errors on stdin and the various
54 for (i = 0; i < nfiles; i++) 100 * output files. Since we know that the first entry in the output
55 putc(c, files[i]); 101 * file table is stdout, we can save one "if ferror" test by
102 * setting the first entry to stdin and checking stdout error
103 * status with bb_fflush_stdout_and_exit()... although fflush()ing
104 * is unnecessary here. */
56 105
57 return status; 106 p = files;
58} 107 *p = stdin;
108 do { /* Now check for (input and) output errors. */
109 /* Checking ferror should be sufficient, but we may want to fclose.
110 * If we do, remember not to close stdin! */
111 bb_xferror(*p, filenames[(int)(p - files)]);
112 } while (*++p);
59 113
60/* 114 bb_fflush_stdout_and_exit(retval);
61Local Variables: 115}
62c-file-style: "linux"
63c-basic-offset: 4
64tab-width: 4
65End:
66*/
diff --git a/coreutils/test.c b/coreutils/test.c
index 83e31ea5c..0bce66e6f 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -180,9 +180,9 @@ extern int test_main(int argc, char **argv)
180{ 180{
181 int res; 181 int res;
182 182
183 if (strcmp(applet_name, "[") == 0) { 183 if (strcmp(bb_applet_name, "[") == 0) {
184 if (strcmp(argv[--argc], "]")) 184 if (strcmp(argv[--argc], "]"))
185 error_msg_and_die("missing ]"); 185 bb_error_msg_and_die("missing ]");
186 argv[argc] = NULL; 186 argv[argc] = NULL;
187 } 187 }
188 /* Implement special cases from POSIX.2, section 4.62.4 */ 188 /* Implement special cases from POSIX.2, section 4.62.4 */
@@ -226,9 +226,9 @@ extern int test_main(int argc, char **argv)
226static void syntax(const char *op, const char *msg) 226static void syntax(const char *op, const char *msg)
227{ 227{
228 if (op && *op) { 228 if (op && *op) {
229 error_msg_and_die("%s: %s", op, msg); 229 bb_error_msg_and_die("%s: %s", op, msg);
230 } else { 230 } else {
231 error_msg_and_die("%s", msg); 231 bb_error_msg_and_die("%s", msg);
232 } 232 }
233} 233}
234 234
@@ -450,13 +450,13 @@ static int getn(const char *s)
450 r = strtol(s, &p, 10); 450 r = strtol(s, &p, 10);
451 451
452 if (errno != 0) 452 if (errno != 0)
453 error_msg_and_die("%s: out of range", s); 453 bb_error_msg_and_die("%s: out of range", s);
454 454
455 while (isspace(*p)) 455 while (isspace(*p))
456 p++; 456 p++;
457 457
458 if (*p) 458 if (*p)
459 error_msg_and_die("%s: bad number", s); 459 bb_error_msg_and_die("%s: bad number", s);
460 460
461 return (int) r; 461 return (int) r;
462} 462}
diff --git a/coreutils/touch.c b/coreutils/touch.c
index f1c6dc484..c66f26e0d 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -21,6 +21,16 @@
21 * 21 *
22 */ 22 */
23 23
24/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m, -r, -t not supported. */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */
26
27/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
28 *
29 * Previous version called open() and then utime(). While this will be
30 * be necessary to implement -r and -t, it currently only makes things bigger.
31 * Also, exiting on a failure was a bug. All args should be processed.
32 */
33
24#include <stdio.h> 34#include <stdio.h>
25#include <sys/types.h> 35#include <sys/types.h>
26#include <fcntl.h> 36#include <fcntl.h>
@@ -33,44 +43,35 @@
33extern int touch_main(int argc, char **argv) 43extern int touch_main(int argc, char **argv)
34{ 44{
35 int fd; 45 int fd;
36 int create = TRUE; 46 int flags;
47 int status = EXIT_SUCCESS;
37 48
38 /* Parse options */ 49 flags = bb_getopt_ulflags(argc, argv, "c");
39 while (--argc > 0 && **(++argv) == '-') { 50
40 while (*(++(*argv))) { 51 argv += optind;
41 switch (**argv) {
42 case 'c':
43 create = FALSE;
44 break;
45 default:
46 show_usage();
47 }
48 }
49 }
50 52
51 if (argc < 1) { 53 if (!*argv) {
52 show_usage(); 54 bb_show_usage();
53 } 55 }
54 56
55 while (argc > 0) { 57 do {
56 fd = open(*argv, create ? O_RDWR | O_CREAT : O_RDWR,
57 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
58 if (fd < 0) {
59 if (! create && errno == ENOENT) {
60 argc--;
61 argv++;
62 continue;
63 } else {
64 perror_msg_and_die("%s", *argv);
65 }
66 }
67 close(fd);
68 if (utime(*argv, NULL)) { 58 if (utime(*argv, NULL)) {
69 perror_msg_and_die("%s", *argv); 59 if (errno == ENOENT) { /* no such file*/
60 if (flags & 1) { /* Creation is disabled, so ignore. */
61 continue;
62 }
63 /* Try to create the file. */
64 fd = open(*argv, O_RDWR | O_CREAT,
65 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
66 );
67 if ((fd >= 0) && !close(fd)) {
68 continue;
69 }
70 }
71 status = EXIT_FAILURE;
72 bb_perror_msg("%s", *argv);
70 } 73 }
71 argc--; 74 } while (*++argv);
72 argv++;
73 }
74 75
75 return EXIT_SUCCESS; 76 return status;
76} 77}
diff --git a/coreutils/tr.c b/coreutils/tr.c
index e2a4ef6c5..a00e36134 100644
--- a/coreutils/tr.c
+++ b/coreutils/tr.c
@@ -54,7 +54,7 @@ static void convert(void)
54 if (in_index == read_chars) { 54 if (in_index == read_chars) {
55 if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) { 55 if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) {
56 if (write(1, (char *) poutput, out_index) != out_index) 56 if (write(1, (char *) poutput, out_index) != out_index)
57 error_msg("%s", write_error); 57 bb_error_msg(bb_msg_write_error);
58 exit(0); 58 exit(0);
59 } 59 }
60 in_index = 0; 60 in_index = 0;
@@ -68,7 +68,7 @@ static void convert(void)
68 poutput[out_index++] = last = coded; 68 poutput[out_index++] = last = coded;
69 if (out_index == BUFSIZ) { 69 if (out_index == BUFSIZ) {
70 if (write(1, (char *) poutput, out_index) != out_index) 70 if (write(1, (char *) poutput, out_index) != out_index)
71 error_msg_and_die("%s", write_error); 71 bb_error_msg_and_die(bb_msg_write_error);
72 out_index = 0; 72 out_index = 0;
73 } 73 }
74 } 74 }
@@ -102,7 +102,7 @@ static unsigned int expand(const char *arg, register unsigned char *buffer)
102 while (*arg) { 102 while (*arg) {
103 if (*arg == '\\') { 103 if (*arg == '\\') {
104 arg++; 104 arg++;
105 *buffer++ = process_escape_sequence(&arg); 105 *buffer++ = bb_process_escape_sequence(&arg);
106 } else if (*(arg+1) == '-') { 106 } else if (*(arg+1) == '-') {
107 ac = *(arg+2); 107 ac = *(arg+2);
108 if(ac == 0) { 108 if(ac == 0) {
@@ -181,7 +181,7 @@ extern int tr_main(int argc, char **argv)
181 sq_fl = TRUE; 181 sq_fl = TRUE;
182 break; 182 break;
183 default: 183 default:
184 show_usage(); 184 bb_show_usage();
185 } 185 }
186 } 186 }
187 idx++; 187 idx++;
@@ -197,7 +197,7 @@ extern int tr_main(int argc, char **argv)
197 input_length = complement(input, input_length); 197 input_length = complement(input, input_length);
198 if (argv[idx] != NULL) { 198 if (argv[idx] != NULL) {
199 if (*argv[idx] == '\0') 199 if (*argv[idx] == '\0')
200 error_msg_and_die("STRING2 cannot be empty"); 200 bb_error_msg_and_die("STRING2 cannot be empty");
201 output_length = expand(argv[idx], output); 201 output_length = expand(argv[idx], output);
202 map(input, input_length, output, output_length); 202 map(input, input_length, output, output_length);
203 } 203 }
diff --git a/coreutils/true.c b/coreutils/true.c
index 9644aad4a..0fbe1023d 100644
--- a/coreutils/true.c
+++ b/coreutils/true.c
@@ -21,7 +21,8 @@
21 * 21 *
22 */ 22 */
23 23
24/* getopt not needed */ 24/* BB_AUDIT SUSv3 compliant */
25/* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */
25 26
26#include <stdlib.h> 27#include <stdlib.h>
27#include "busybox.h" 28#include "busybox.h"
diff --git a/coreutils/tty.c b/coreutils/tty.c
index 4510c2996..cd2c784fd 100644
--- a/coreutils/tty.c
+++ b/coreutils/tty.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini tty implementation for busybox 3 * tty implementation for busybox
4 * 4 *
5 * Copyright (C) 2000 Edward Betts <edward@debian.org>. 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,25 +20,39 @@
20 * 20 *
21 */ 21 */
22 22
23/* BB_AUDIT SUSv3 compliant */
24/* http://www.opengroup.org/onlinepubs/007904975/utilities/tty.html */
25
23#include <stdio.h> 26#include <stdio.h>
24#include <stdlib.h> 27#include <stdlib.h>
25#include <unistd.h> 28#include <unistd.h>
26#include <sys/types.h>
27#include "busybox.h" 29#include "busybox.h"
28 30
29extern int tty_main(int argc, char **argv) 31extern int tty_main(int argc, char **argv)
30{ 32{
31 char *tty; 33 const char *s;
32 34 int silent; /* Note: No longer relevant in SUSv3. */
33 if (argc > 1) { 35 int retval;
34 if (argv[1][0] != '-' || argv[1][1] != 's') 36
35 show_usage(); 37 bb_default_error_retval = 2; /* SUSv3 requires > 1 for error. */
36 } else { 38
37 tty = ttyname(0); 39 silent = bb_getopt_ulflags(argc, argv, "s");
38 if (tty) 40
39 puts(tty); 41 /* gnu tty outputs a warning that it is ignoring all args. */
40 else 42 bb_warn_ignoring_args(argc - optind);
41 puts("not a tty"); 43
44 retval = 0;
45
46 if ((s = ttyname(0)) == NULL) {
47 /* According to SUSv3, ttyname can on fail with EBADF or ENOTTY.
48 * We know the file descriptor is good, so failure means not a tty. */
49 s = "not a tty";
50 retval = 1;
51 }
52
53 if (!silent) {
54 puts(s);
42 } 55 }
43 return(isatty(0) ? EXIT_SUCCESS : EXIT_FAILURE); 56
57 bb_fflush_stdout_and_exit(retval);
44} 58}
diff --git a/coreutils/uname.c b/coreutils/uname.c
index df4f14ea0..a3e52e39f 100644
--- a/coreutils/uname.c
+++ b/coreutils/uname.c
@@ -16,6 +16,9 @@
16 along with this program; if not, write to the Free Software Foundation, 16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 18
19/* BB_AUDIT SUSv3 compliant */
20/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */
21
19/* Option Example 22/* Option Example
20 23
21 -s, --sysname SunOS 24 -s, --sysname SunOS
@@ -33,13 +36,18 @@
33 36
34/* Further size reductions by Glenn McGrath and Manuel Novoa III. */ 37/* Further size reductions by Glenn McGrath and Manuel Novoa III. */
35 38
39/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
40 *
41 * Now does proper error checking on i/o. Plus some further space savings.
42 */
43
36#include <stdio.h> 44#include <stdio.h>
37#include <stdlib.h> 45#include <stdlib.h>
38#include <stddef.h> 46#include <stddef.h>
39#include <string.h> 47#include <string.h>
48#include <unistd.h>
40#include <sys/types.h> 49#include <sys/types.h>
41#include <sys/utsname.h> 50#include <sys/utsname.h>
42#include <getopt.h>
43#include "busybox.h" 51#include "busybox.h"
44 52
45typedef struct { 53typedef struct {
@@ -48,7 +56,6 @@ typedef struct {
48} uname_info_t; 56} uname_info_t;
49 57
50static const char options[] = "snrvmpa"; 58static const char options[] = "snrvmpa";
51static const char flags[] = "\x01\x02\x04\x08\x10\x20\x3f";
52static const unsigned short int utsname_offset[] = { 59static const unsigned short int utsname_offset[] = {
53 offsetof(uname_info_t,name.sysname), 60 offsetof(uname_info_t,name.sysname),
54 offsetof(uname_info_t,name.nodename), 61 offsetof(uname_info_t,name.nodename),
@@ -61,29 +68,28 @@ static const unsigned short int utsname_offset[] = {
61int uname_main(int argc, char **argv) 68int uname_main(int argc, char **argv)
62{ 69{
63 uname_info_t uname_info; 70 uname_info_t uname_info;
64
65#if defined(__sparc__) && defined(__linux__) 71#if defined(__sparc__) && defined(__linux__)
66 char *fake_sparc = getenv("FAKE_SPARC"); 72 char *fake_sparc = getenv("FAKE_SPARC");
67#endif 73#endif
68
69 const unsigned short int *delta; 74 const unsigned short int *delta;
70 int opt; 75 char toprint;
71 char toprint = 0;
72 76
73 while ((opt = getopt(argc, argv, options)) != -1) { 77 toprint = bb_getopt_ulflags(argc, argv, options);
74 const char *p = strchr(options,opt); 78
75 if (p == NULL) { 79 if (argc != optind) {
76 show_usage(); 80 bb_show_usage();
77 } 81 }
78 toprint |= flags[(int)(p-options)]; 82
83 if (toprint & (1 << 6)) {
84 toprint = 0x3f;
79 } 85 }
80 86
81 if (toprint == 0) { 87 if (toprint == 0) {
82 toprint = flags[0]; /* sysname */ 88 toprint = 1; /* sysname */
83 } 89 }
84 90
85 if (uname(&uname_info.name) == -1) { 91 if (uname(&uname_info.name) == -1) {
86 error_msg_and_die("cannot get system name"); 92 bb_error_msg_and_die("cannot get system name");
87 } 93 }
88 94
89#if defined(__sparc__) && defined(__linux__) 95#if defined(__sparc__) && defined(__linux__)
@@ -99,7 +105,7 @@ int uname_main(int argc, char **argv)
99 delta=utsname_offset; 105 delta=utsname_offset;
100 do { 106 do {
101 if (toprint & 1) { 107 if (toprint & 1) {
102 printf(((char *)(&uname_info)) + *delta); 108 bb_printf(((char *)(&uname_info)) + *delta);
103 if (toprint > 1) { 109 if (toprint > 1) {
104 putchar(' '); 110 putchar(' ');
105 } 111 }
@@ -108,5 +114,5 @@ int uname_main(int argc, char **argv)
108 } while (toprint >>= 1); 114 } while (toprint >>= 1);
109 putchar('\n'); 115 putchar('\n');
110 116
111 return EXIT_SUCCESS; 117 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
112} 118}
diff --git a/coreutils/uniq.c b/coreutils/uniq.c
index cb63c4277..90686c9af 100644
--- a/coreutils/uniq.c
+++ b/coreutils/uniq.c
@@ -1,10 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini uniq implementation for busybox 3 * uniq implementation for busybox
4 * 4 *
5 * Copyright (C) 1999 by Lineo, inc. and John Beppu 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7 * Rewritten by Matt Kraai <kraai@alumni.carnegiemellon.edu>
8 * 6 *
9 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -22,67 +20,93 @@
22 * 20 *
23 */ 21 */
24 22
23/* BB_AUDIT SUSv3 compliant */
24/* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */
25
25#include <stdio.h> 26#include <stdio.h>
26#include <string.h>
27#include <getopt.h>
28#include <errno.h>
29#include <stdlib.h> 27#include <stdlib.h>
28#include <string.h>
29#include <ctype.h>
30#include <unistd.h>
30#include "busybox.h" 31#include "busybox.h"
32#include "libcoreutils/coreutils.h"
31 33
32static int print_count; 34static const char uniq_opts[] = "f:s:cdu\0\7\3\5\1\2\4";
33static int print_uniq = 1;
34static int print_duplicates = 1;
35
36static void print_line(char *line, int count, FILE *fp)
37{
38 if ((print_duplicates && count > 1) || (print_uniq && count == 1)) {
39 if (print_count)
40 fprintf(fp, "%7d\t%s", count, line);
41 else
42 fputs(line, fp);
43 }
44}
45 35
46int uniq_main(int argc, char **argv) 36int uniq_main(int argc, char **argv)
47{ 37{
48 FILE *in = stdin, *out = stdout; 38 FILE *in, *out;
49 char *lastline = NULL, *input; 39 /* Note: Ignore the warning about dups and e0 possibly being uninitialized.
50 int opt, count = 0; 40 * They will be initialized on the fist pass of the loop (since s0 is NULL). */
41 unsigned long dups, skip_fields, skip_chars, i;
42 const char *s0, *e0, *s1, *e1, *input_filename;
43 int opt;
44 int uniq_flags = 6; /* -u */
51 45
52 /* parse argv[] */ 46 skip_fields = skip_chars = 0;
53 while ((opt = getopt(argc, argv, "cdu")) > 0) { 47
54 switch (opt) { 48 while ((opt = getopt(argc, argv, uniq_opts)) > 0) {
55 case 'c': 49 if (opt == 'f') {
56 print_count = 1; 50 skip_fields = bb_xgetularg10(optarg);
57 break; 51 } else if (opt == 's') {
58 case 'd': 52 skip_chars = bb_xgetularg10(optarg);
59 print_duplicates = 1; 53 } else if ((s0 = strchr(uniq_opts, opt)) != NULL) {
60 print_uniq = 0; 54 uniq_flags &= s0[4];
61 break; 55 uniq_flags |= s0[7];
62 case 'u': 56 } else {
63 print_duplicates = 0; 57 bb_show_usage();
64 print_uniq = 1;
65 break;
66 } 58 }
67 } 59 }
68 60
69 if (argv[optind] != NULL) { 61 input_filename = *(argv += optind);
70 in = xfopen(argv[optind], "r"); 62
71 if (argv[optind+1] != NULL) 63 in = xgetoptfile_sort_uniq(argv, "r");
72 out = xfopen(argv[optind+1], "w"); 64 if (*argv) {
65 ++argv;
73 } 66 }
67 out = xgetoptfile_sort_uniq(argv, "w");
68 if (*argv && argv[1]) {
69 bb_show_usage();
70 }
71
72 s0 = NULL;
74 73
75 while ((input = get_line_from_file(in)) != NULL) { 74 /* gnu uniq ignores newlines */
76 if (lastline == NULL || strcmp(input, lastline) != 0) { 75 while ((s1 = bb_get_chomped_line_from_file(in)) != NULL) {
77 print_line(lastline, count, out); 76 e1 = s1;
78 free(lastline); 77 for (i=skip_fields ; i ; i--) {
79 lastline = input; 78 e1 = bb_skip_whitespace(e1);
80 count = 0; 79 while (*e1 && !isspace(*e1)) {
80 ++e1;
81 }
82 }
83 for (i = skip_chars ; *e1 && i ; i--) {
84 ++e1;
85 }
86 if (s0) {
87 if (strcmp(e0, e1) == 0) {
88 ++dups; /* Note: Testing for overflow seems excessive. */
89 continue;
90 }
91 DO_LAST:
92 if ((dups && (uniq_flags & 2)) || (!dups && (uniq_flags & 4))) {
93 bb_fprintf(out, "\0%7d\t" + (uniq_flags & 1), dups + 1);
94 bb_fprintf(out, "%s\n", s0);
95 }
96 free((void *)s0);
81 } 97 }
82 count++; 98
99 s0 = s1;
100 e0 = e1;
101 dups = 0;
102 }
103
104 if (s0) {
105 e1 = NULL;
106 goto DO_LAST;
83 } 107 }
84 print_line(lastline, count, out);
85 free(lastline);
86 108
87 return EXIT_SUCCESS; 109 bb_xferror(in, input_filename);
110
111 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
88} 112}
diff --git a/coreutils/usleep.c b/coreutils/usleep.c
index ac268b485..f570f2734 100644
--- a/coreutils/usleep.c
+++ b/coreutils/usleep.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini usleep implementation for busybox 3 * usleep implementation for busybox
4 * 4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,18 +20,22 @@
20 * 20 *
21 */ 21 */
22 22
23/* getopt not needed */ 23/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
24 24
25#include <stdlib.h> 25#include <stdlib.h>
26#include <limits.h>
26#include <unistd.h> 27#include <unistd.h>
27#include "busybox.h" 28#include "busybox.h"
28 29
29extern int usleep_main(int argc, char **argv) 30extern int usleep_main(int argc, char **argv)
30{ 31{
31 if ((argc < 2) || (**(argv + 1) == '-')) { 32 if (argc != 2) {
32 show_usage(); 33 bb_show_usage();
34 }
35
36 if (usleep(bb_xgetularg10_bnd(argv[1], 0, UINT_MAX))) {
37 bb_perror_nomsg_and_die();
33 } 38 }
34 39
35 usleep(atoi(*(++argv))); /* return void */
36 return EXIT_SUCCESS; 40 return EXIT_SUCCESS;
37} 41}
diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c
index a5ac002e9..4f9270c18 100644
--- a/coreutils/uudecode.c
+++ b/coreutils/uudecode.c
@@ -46,7 +46,7 @@ static int read_stduu (const char *inname)
46 char *p; 46 char *p;
47 47
48 if (fgets (buf, sizeof(buf), stdin) == NULL) { 48 if (fgets (buf, sizeof(buf), stdin) == NULL) {
49 error_msg("%s: Short file", inname); 49 bb_error_msg("%s: Short file", inname);
50 return FALSE; 50 return FALSE;
51 } 51 }
52 p = buf; 52 p = buf;
@@ -81,7 +81,7 @@ static int read_stduu (const char *inname)
81 81
82 if (fgets (buf, sizeof(buf), stdin) == NULL 82 if (fgets (buf, sizeof(buf), stdin) == NULL
83 || strcmp (buf, "end\n")) { 83 || strcmp (buf, "end\n")) {
84 error_msg("%s: No `end' line", inname); 84 bb_error_msg("%s: No `end' line", inname);
85 return FALSE; 85 return FALSE;
86 } 86 }
87 87
@@ -131,7 +131,7 @@ static int read_base64 (const char *inname)
131 unsigned char *p; 131 unsigned char *p;
132 132
133 if (fgets (buf, sizeof(buf), stdin) == NULL) { 133 if (fgets (buf, sizeof(buf), stdin) == NULL) {
134 error_msg("%s: Short file", inname); 134 bb_error_msg("%s: Short file", inname);
135 return FALSE; 135 return FALSE;
136 } 136 }
137 p = buf; 137 p = buf;
@@ -139,7 +139,7 @@ static int read_base64 (const char *inname)
139 if (memcmp (buf, "====", 4) == 0) 139 if (memcmp (buf, "====", 4) == 0)
140 break; 140 break;
141 if (last_data != 0) { 141 if (last_data != 0) {
142 error_msg("%s: data following `=' padding character", inname); 142 bb_error_msg("%s: data following `=' padding character", inname);
143 return FALSE; 143 return FALSE;
144 } 144 }
145 145
@@ -161,14 +161,14 @@ static int read_base64 (const char *inname)
161 161
162 while ((b64_tab[*p] & '\100') != 0) 162 while ((b64_tab[*p] & '\100') != 0)
163 if (*p == '\n' || *p++ == '=') { 163 if (*p == '\n' || *p++ == '=') {
164 error_msg("%s: illegal line", inname); 164 bb_error_msg("%s: illegal line", inname);
165 return FALSE; 165 return FALSE;
166 } 166 }
167 c2 = b64_tab[*p++]; 167 c2 = b64_tab[*p++];
168 168
169 while (b64_tab[*p] == '\177') 169 while (b64_tab[*p] == '\177')
170 if (*p++ == '\n') { 170 if (*p++ == '\n') {
171 error_msg("%s: illegal line", inname); 171 bb_error_msg("%s: illegal line", inname);
172 return FALSE; 172 return FALSE;
173 } 173 }
174 if (*p == '=') { 174 if (*p == '=') {
@@ -180,7 +180,7 @@ static int read_base64 (const char *inname)
180 180
181 while (b64_tab[*p] == '\177') 181 while (b64_tab[*p] == '\177')
182 if (*p++ == '\n') { 182 if (*p++ == '\n') {
183 error_msg("%s: illegal line", inname); 183 bb_error_msg("%s: illegal line", inname);
184 return FALSE; 184 return FALSE;
185 } 185 }
186 putchar (c1 << 2 | c2 >> 4); 186 putchar (c1 << 2 | c2 >> 4);
@@ -213,7 +213,7 @@ static int decode (const char *inname,
213 213
214 while (1) { 214 while (1) {
215 if (fgets (buf, sizeof (buf), stdin) == NULL) { 215 if (fgets (buf, sizeof (buf), stdin) == NULL) {
216 error_msg("%s: No `begin' line", inname); 216 bb_error_msg("%s: No `begin' line", inname);
217 return FALSE; 217 return FALSE;
218 } 218 }
219 219
@@ -239,13 +239,13 @@ static int decode (const char *inname,
239 while (*p != '/') 239 while (*p != '/')
240 ++p; 240 ++p;
241 if (*p == '\0') { 241 if (*p == '\0') {
242 error_msg("%s: Illegal ~user", inname); 242 bb_error_msg("%s: Illegal ~user", inname);
243 return FALSE; 243 return FALSE;
244 } 244 }
245 *p++ = '\0'; 245 *p++ = '\0';
246 pw = getpwnam (buf + 1); 246 pw = getpwnam (buf + 1);
247 if (pw == NULL) { 247 if (pw == NULL) {
248 error_msg("%s: No user `%s'", inname, buf + 1); 248 bb_error_msg("%s: No user `%s'", inname, buf + 1);
249 return FALSE; 249 return FALSE;
250 } 250 }
251 outname = concat_path_file(pw->pw_dir, p); 251 outname = concat_path_file(pw->pw_dir, p);
@@ -258,7 +258,7 @@ static int decode (const char *inname,
258 && (freopen (outname, "w", stdout) == NULL 258 && (freopen (outname, "w", stdout) == NULL
259 || chmod (outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) 259 || chmod (outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO))
260 )) { 260 )) {
261 perror_msg("%s", outname); /* */ 261 bb_perror_msg("%s", outname); /* */
262 if (dofre) 262 if (dofre)
263 free(outname); 263 free(outname);
264 return FALSE; 264 return FALSE;
@@ -295,7 +295,7 @@ int uudecode_main (int argc,
295 break; 295 break;
296 296
297 default: 297 default:
298 show_usage(); 298 bb_show_usage();
299 } 299 }
300 } 300 }
301 301
@@ -308,7 +308,7 @@ int uudecode_main (int argc,
308 if (decode (argv[optind], outname) != 0) 308 if (decode (argv[optind], outname) != 0)
309 exit_status = FALSE; 309 exit_status = FALSE;
310 } else { 310 } else {
311 perror_msg("%s", argv[optind]); 311 bb_perror_msg("%s", argv[optind]);
312 exit_status = EXIT_FAILURE; 312 exit_status = EXIT_FAILURE;
313 } 313 }
314 optind++; 314 optind++;
diff --git a/coreutils/uuencode.c b/coreutils/uuencode.c
index 49b2d9189..fd3326d80 100644
--- a/coreutils/uuencode.c
+++ b/coreutils/uuencode.c
@@ -29,7 +29,7 @@
29#include "busybox.h" 29#include "busybox.h"
30 30
31/* Conversion table. for base 64 */ 31/* Conversion table. for base 64 */
32static char tbl_base64[65] = { 32static const char tbl_base64[65] = {
33 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 33 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
34 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 34 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
35 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 35 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
@@ -41,7 +41,7 @@ static char tbl_base64[65] = {
41 '=' /* termination character */ 41 '=' /* termination character */
42}; 42};
43 43
44static char tbl_std[65] = { 44static const char tbl_std[65] = {
45 '`', '!', '"', '#', '$', '%', '&', '\'', 45 '`', '!', '"', '#', '$', '%', '&', '\'',
46 '(', ')', '*', '+', ',', '-', '.', '/', 46 '(', ')', '*', '+', ',', '-', '.', '/',
47 '0', '1', '2', '3', '4', '5', '6', '7', 47 '0', '1', '2', '3', '4', '5', '6', '7',
@@ -92,40 +92,36 @@ int uuencode_main(int argc, char **argv)
92 int write_size = dst_buf_size; 92 int write_size = dst_buf_size;
93 struct stat stat_buf; 93 struct stat stat_buf;
94 FILE *src_stream = stdin; 94 FILE *src_stream = stdin;
95 char *tbl = tbl_std; 95 const char *tbl;
96 size_t size; 96 size_t size;
97 mode_t mode; 97 mode_t mode;
98 int opt;
99 RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1); 98 RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
100 RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1); 99 RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
101 100
102 while ((opt = getopt(argc, argv, "m")) != -1) { 101 tbl = tbl_std;
103 switch (opt) { 102 if (bb_getopt_ulflags(argc, argv, "m") & 1) {
104 case 'm': 103 tbl = tbl_base64;
105 tbl = tbl_base64;
106 break;
107 default:
108 show_usage();
109 }
110 } 104 }
111 105
112 switch (argc - optind) { 106 switch (argc - optind) {
113 case 2: 107 case 2:
114 src_stream = xfopen(argv[optind], "r"); 108 src_stream = bb_xfopen(argv[optind], "r");
115 stat(argv[optind], &stat_buf); 109 if (stat(argv[optind], &stat_buf) < 0) {
110 bb_perror_msg_and_die("stat");
111 }
116 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 112 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
117 if (src_stream == stdout) { 113 if (src_stream == stdout) {
118 printf("NULL\n"); 114 puts("NULL");
119 } 115 }
120 break; 116 break;
121 case 1: 117 case 1:
122 mode = 0666 & ~umask(0666); 118 mode = 0666 & ~umask(0666);
123 break; 119 break;
124 default: 120 default:
125 show_usage(); 121 bb_show_usage();
126 } 122 }
127 123
128 printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]); 124 bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
129 125
130 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) { 126 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
131 if (size != src_buf_size) { 127 if (size != src_buf_size) {
@@ -142,10 +138,12 @@ int uuencode_main(int argc, char **argv)
142 putchar(tbl[size]); 138 putchar(tbl[size]);
143 } 139 }
144 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) { 140 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
145 perror("Couldnt finish writing"); 141 bb_perror_msg_and_die(bb_msg_write_error);
146 } 142 }
147 } 143 }
148 printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n"); 144 bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
145
146 bb_xferror(src_stream, "source"); /* TODO - Fix this! */
149 147
150 return(EXIT_SUCCESS); 148 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
151} 149}
diff --git a/coreutils/watch.c b/coreutils/watch.c
index c275f3bb3..f9f40189e 100644
--- a/coreutils/watch.c
+++ b/coreutils/watch.c
@@ -20,67 +20,76 @@
20 * 20 *
21 */ 21 */
22 22
23/* getopt not needed */ 23/* BB_AUDIT SUSv3 N/A */
24/* BB_AUDIT GNU defects -- only option -n is supported. */
25
26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27 *
28 * Removed dependency on date_main(), added proper error checking, and
29 * reduced size.
30 */
24 31
25#include <stdio.h> 32#include <stdio.h>
26#include <errno.h>
27#include <unistd.h>
28#include <stdlib.h> 33#include <stdlib.h>
29#include <string.h> 34#include <string.h>
35#include <limits.h>
36#include <time.h>
37#include <assert.h>
38#include <unistd.h>
30#include <sys/wait.h> 39#include <sys/wait.h>
31#include "busybox.h" 40#include "busybox.h"
32 41
33extern int watch_main(int argc, char **argv) 42extern int watch_main(int argc, char **argv)
34{ 43{
35 const char date_argv[2][10] = { "date", "" };
36 const int header_len = 40; 44 const int header_len = 40;
37 char header[header_len + 1]; 45 time_t t;
38 int period = 2;
39 char **cargv;
40 int cargc;
41 pid_t pid; 46 pid_t pid;
47 unsigned period = 2;
42 int old_stdout; 48 int old_stdout;
43 int i; 49 int len, len2;
50 char **watched_argv;
51 char header[header_len + 1];
44 52
45 if (argc < 2) { 53 if (argc < 2) {
46 show_usage(); 54 bb_show_usage();
47 } else {
48 cargv = argv + 1;
49 cargc = argc - 1;
50
51 /* don't use getopt, because it permutes the arguments */
52 if (argc >= 3 && !strcmp(argv[1], "-n")) {
53 period = strtol(argv[2], NULL, 10);
54 if (period < 1)
55 show_usage();
56 cargv += 2;
57 cargc -= 2;
58 }
59 } 55 }
60 56
61 57 /* don't use getopt, because it permutes the arguments */
62 /* create header */ 58 ++argv;
63 snprintf(header, header_len, "Every %ds: ", period); 59 if ((argc > 3) && !strcmp(*argv, "-n")
64 for (i = 0; i < cargc && (strlen(header) + strlen(cargv[i]) < header_len); 60 ) {
65 i++) { 61 period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
66 strcat(header, cargv[i]); 62 argv += 2;
67 strcat(header, " ");
68 } 63 }
64 watched_argv = argv;
69 65
70 /* fill with blanks */ 66 /* create header */
71 for (i = strlen(header); i < header_len; i++)
72 header[i] = ' ';
73 67
74 header[header_len - 1] = '\0'; 68 len = snprintf(header, header_len, "Every %ds:", period);
69 /* Don't bother checking for len < 0, as it should never happen.
70 * But, just to be prepared... */
71 assert(len >= 0);
72 do {
73 len2 = strlen(*argv);
74 if (len + len2 >= header_len-1) {
75 break;
76 }
77 header[len] = ' ';
78 memcpy(header+len+1, *argv, len2);
79 len += len2+1;
80 } while (*++argv);
75 81
82 header[len] = 0;
76 83
77 /* thanks to lye, who showed me how to redirect stdin/stdout */ 84 /* thanks to lye, who showed me how to redirect stdin/stdout */
78 old_stdout = dup(1); 85 old_stdout = dup(1);
79 86
80 while (1) { 87 while (1) {
81 printf("\033[H\033[J%s", header); 88 time(&t);
82 date_main(1, (char **) date_argv); 89 /* Use dprintf to avoid fflush()ing stdout. */
83 printf("\n"); 90 if (dprintf(1, "\033[H\033[J%-*s%s\n", header_len, header, ctime(&t)) < 0) {
91 bb_perror_msg_and_die("printf");
92 }
84 93
85 pid = vfork(); /* vfork, because of ucLinux */ 94 pid = vfork(); /* vfork, because of ucLinux */
86 if (pid > 0) { 95 if (pid > 0) {
@@ -91,13 +100,11 @@ extern int watch_main(int argc, char **argv)
91 //child 100 //child
92 close(1); 101 close(1);
93 dup(old_stdout); 102 dup(old_stdout);
94 if (execvp(*cargv, cargv)) 103 if (execvp(*watched_argv, watched_argv)) {
95 error_msg_and_die("Couldn't run command\n"); 104 bb_error_msg_and_die("Couldn't run command\n");
105 }
96 } else { 106 } else {
97 error_msg_and_die("Couldn't vfork\n"); 107 bb_error_msg_and_die("Couldn't vfork\n");
98 } 108 }
99 } 109 }
100
101
102 return EXIT_SUCCESS;
103} 110}
diff --git a/coreutils/wc.c b/coreutils/wc.c
index 8e3b5bbf4..779901524 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini wc implementation for busybox 3 * wc implementation for busybox
4 * 4 *
5 * Copyright (C) 2000 Edward Betts <edward@debian.org> 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,159 +20,208 @@
20 * 20 *
21 */ 21 */
22 22
23/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */
24/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */
25
26/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
27 *
28 * Rewritten to fix a number of problems and do some size optimizations.
29 * Problems in the previous busybox implementation (besides bloat) included:
30 * 1) broken 'wc -c' optimization (read note below)
31 * 2) broken handling of '-' args
32 * 3) no checking of ferror on EOF returns
33 * 4) isprint() wasn't considered when word counting.
34 *
35 * TODO:
36 *
37 * When locale support is enabled, count multibyte chars in the '-m' case.
38 *
39 * NOTES:
40 *
41 * The previous busybox wc attempted an optimization using stat for the
42 * case of counting chars only. I omitted that because it was broken.
43 * It didn't take into account the possibility of input coming from a
44 * pipe, or input from a file with file pointer not at the beginning.
45 *
46 * To implement such a speed optimization correctly, not only do you
47 * need the size, but also the file position. Note also that the
48 * file position may be past the end of file. Consider the example
49 * (adapted from example in gnu wc.c)
50 *
51 * echo hello > /tmp/testfile &&
52 * (dd ibs=1k skip=1 count=0 &> /dev/null ; wc -c) < /tmp/testfile
53 *
54 * for which 'wc -c' should output '0'.
55 */
56
23#include <stdio.h> 57#include <stdio.h>
24#include <getopt.h>
25#include <string.h>
26#include <stdlib.h> 58#include <stdlib.h>
59#include <string.h>
60#include <unistd.h>
27#include "busybox.h" 61#include "busybox.h"
28 62
29enum print_e { 63#ifdef CONFIG_LOCALE_SUPPORT
30 print_lines = 1, 64#include <locale.h>
31 print_words = 2, 65#include <ctype.h>
32 print_chars = 4, 66#define isspace_given_isprint(c) isspace(c)
33 print_length = 8 67#else
68#undef isspace
69#undef isprint
70#define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))
71#define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))
72#define isspace_given_isprint(c) ((c) == ' ')
73#endif
74
75enum {
76 WC_LINES = 0,
77 WC_WORDS = 1,
78 WC_CHARS = 2,
79 WC_LENGTH = 3
34}; 80};
35 81
36static unsigned int total_lines = 0; 82/* Note: If this changes, remember to change the initialization of
37static unsigned int total_words = 0; 83 * 'name' in wc_main. It needs to point to the terminating nul. */
38static unsigned int total_chars = 0; 84static const char wc_opts[] = "lwcL"; /* READ THE WARNING ABOVE! */
39static unsigned int max_length = 0;
40static char print_type = 0;
41 85
42static void print_counts(const unsigned int lines, const unsigned int words, 86enum {
43 const unsigned int chars, const unsigned int length, const char *name) 87 OP_INC_LINE = 1, /* OP_INC_LINE must be 1. */
44{ 88 OP_SPACE = 2,
45 int output = 0; 89 OP_NEWLINE = 4,
90 OP_TAB = 8,
91 OP_NUL = 16,
92};
46 93
47 if (print_type & print_lines) { 94/* Note: If fmt_str changes, the offsets to 's' in the OUTPUT section
48 printf("%7d", lines); 95 * will need to be updated. */
49 output++; 96static const char fmt_str[] = " %7u\0 %s\n";
50 } 97static const char total_str[] = "total";
51 if (print_type & print_words) {
52 if (output++)
53 putchar(' ');
54 printf("%7d", words);
55 }
56 if (print_type & print_chars) {
57 if (output++)
58 putchar(' ');
59 printf("%7d", chars);
60 }
61 if (print_type & print_length) {
62 if (output++)
63 putchar(' ');
64 printf("%7d", length);
65 }
66 if (*name) {
67 printf(" %s", name);
68 }
69 putchar('\n');
70}
71 98
72static void wc_file(FILE * file, const char *name) 99int wc_main(int argc, char **argv)
73{ 100{
74 unsigned int lines = 0; 101 FILE *fp;
75 unsigned int words = 0; 102 const char *s;
76 unsigned int chars = 0; 103 unsigned int *pcounts;
77 unsigned int length = 0; 104 unsigned int counts[4];
78 unsigned int linepos = 0; 105 unsigned int totals[4];
79 char in_word = 0; 106 unsigned int linepos;
107 unsigned int u;
108 int num_files = 0;
80 int c; 109 int c;
81 110 char status = EXIT_SUCCESS;
82 while ((c = getc(file)) != EOF) { 111 char in_word;
83 chars++; 112 char print_type;
84 switch (c) { 113
85 case '\n': 114 print_type = bb_getopt_ulflags(argc, argv, wc_opts);
86 lines++; 115
87 case '\r': 116 if (print_type == 0) {
88 case '\f': 117 print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
89 if (linepos > length)
90 length = linepos;
91 linepos = 0;
92 goto word_separator;
93 case '\t':
94 linepos += 8 - (linepos % 8);
95 goto word_separator;
96 case ' ':
97 linepos++;
98 case '\v':
99word_separator:
100 if (in_word) {
101 in_word = 0;
102 words++;
103 }
104 break;
105 default:
106 linepos++;
107 in_word = 1;
108 break;
109 }
110 }
111 if (linepos > length) {
112 length = linepos;
113 }
114 if (in_word) {
115 words++;
116 } 118 }
117 print_counts(lines, words, chars, length, name); 119
118 total_lines += lines; 120 argv += optind;
119 total_words += words; 121 if (!*argv) {
120 total_chars += chars; 122 *--argv = (char *) bb_msg_standard_input;
121 if (length > max_length) {
122 max_length = length;
123 } 123 }
124} 124
125 125 memset(totals, 0, sizeof(totals));
126int wc_main(int argc, char **argv) 126
127{ 127 pcounts = counts;
128 int opt; 128
129 129 do {
130 while ((opt = getopt(argc, argv, "clLw")) > 0) { 130 ++num_files;
131 switch (opt) { 131 if (!(fp = bb_wfopen_input(*argv))) {
132 case 'c': 132 status = EXIT_FAILURE;
133 print_type |= print_chars; 133 continue;
134 break;
135 case 'l':
136 print_type |= print_lines;
137 break;
138 case 'L':
139 print_type |= print_length;
140 break;
141 case 'w':
142 print_type |= print_words;
143 break;
144 default:
145 show_usage();
146 } 134 }
147 } 135
148 136 memset(counts, 0, sizeof(counts));
149 if (print_type == 0) { 137 linepos = 0;
150 print_type = print_lines | print_words | print_chars; 138 in_word = 0;
151 } 139
152 140 do {
153 if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) { 141 ++counts[WC_CHARS];
154 wc_file(stdin, ""); 142 c = getc(fp);
155 } else { 143 if (isprint(c)) {
156 unsigned short num_files_counted = 0; 144 ++linepos;
157 while (optind < argc) { 145 if (!isspace_given_isprint(c)) {
158 if (print_type == print_chars) { 146 in_word = 1;
159 struct stat statbuf; 147 continue;
160 stat(argv[optind], &statbuf); 148 }
161 print_counts(0, 0, statbuf.st_size, 0, argv[optind]); 149 } else if (((unsigned int)(c - 9)) <= 4) {
162 total_chars += statbuf.st_size; 150 /* \t 9
151 * \n 10
152 * \v 11
153 * \f 12
154 * \r 13
155 */
156 if (c == '\t') {
157 linepos = (linepos | 7) + 1;
158 } else { /* '\n', '\r', '\f', or '\v' */
159 DO_EOF:
160 if (linepos > counts[WC_LENGTH]) {
161 counts[WC_LENGTH] = linepos;
162 }
163 if (c == '\n') {
164 ++counts[WC_LINES];
165 }
166 if (c != '\v') {
167 linepos = 0;
168 }
169 }
170 } else if (c == EOF) {
171 if (ferror(fp)) {
172 bb_perror_msg("%s", *argv);
173 status = EXIT_FAILURE;
174 }
175 --counts[WC_CHARS];
176 goto DO_EOF; /* Treat an EOF as '\r'. */
163 } else { 177 } else {
164 FILE *file; 178 continue;
165 file = xfopen(argv[optind], "r"); 179 }
166 wc_file(file, argv[optind]); 180
167 fclose(file); 181 counts[WC_WORDS] += in_word;
182 in_word = 0;
183 if (c == EOF) {
184 break;
168 } 185 }
169 optind++; 186 } while (1);
170 num_files_counted++; 187
188 if (totals[WC_LENGTH] < counts[WC_LENGTH]) {
189 totals[WC_LENGTH] = counts[WC_LENGTH];
171 } 190 }
172 if (num_files_counted > 1) { 191 totals[WC_LENGTH] -= counts[WC_LENGTH];
173 print_counts(total_lines, total_words, total_chars, max_length, "total"); 192
193 bb_fclose_nonstdin(fp);
194
195 OUTPUT:
196 s = fmt_str + 1; /* Skip the leading space on 1st pass. */
197 u = 0;
198 do {
199 if (print_type & (1 << u)) {
200 bb_printf(s, pcounts[u]);
201 s = fmt_str; /* Ok... restore the leading space. */
202 }
203 totals[u] += pcounts[u];
204 } while (++u < 4);
205
206 s += 8; /* Set the format to the empty string. */
207
208 if (*argv != bb_msg_standard_input) {
209 s -= 3; /* We have a name, so do %s conversion. */
174 } 210 }
211 bb_printf(s, *argv);
212
213 } while (*++argv);
214
215 /* If more than one file was processed, we want the totals. To save some
216 * space, we set the pcounts ptr to the totals array. This has the side
217 * effect of trashing the totals array after outputting it, but that's
218 * irrelavent since we no longer need it. */
219 if (num_files > 1) {
220 num_files = 0; /* Make sure we don't get here again. */
221 *--argv = (char *) total_str;
222 pcounts = totals;
223 goto OUTPUT;
175 } 224 }
176 225
177 return(EXIT_SUCCESS); 226 bb_fflush_stdout_and_exit(status);
178} 227}
diff --git a/coreutils/who.c b/coreutils/who.c
index 3da7ed1c7..1bf552056 100644
--- a/coreutils/who.c
+++ b/coreutils/who.c
@@ -23,7 +23,7 @@
23#include <errno.h> 23#include <errno.h>
24#include <string.h> 24#include <string.h>
25#include <time.h> 25#include <time.h>
26#include <busybox.h> 26#include "busybox.h"
27 27
28extern int who_main(int argc, char **argv) 28extern int who_main(int argc, char **argv)
29{ 29{
@@ -33,7 +33,7 @@ extern int who_main(int argc, char **argv)
33 time_t now, idle; 33 time_t now, idle;
34 34
35 if (argc > 1) 35 if (argc > 1)
36 show_usage(); 36 bb_show_usage();
37 37
38 setutent(); 38 setutent();
39 devlen = sizeof("/dev/") - 1; 39 devlen = sizeof("/dev/") - 1;
@@ -81,5 +81,3 @@ extern int who_main(int argc, char **argv)
81 81
82 return 0; 82 return 0;
83} 83}
84
85
diff --git a/coreutils/whoami.c b/coreutils/whoami.c
index a9d6ecf26..f93034d3a 100644
--- a/coreutils/whoami.c
+++ b/coreutils/whoami.c
@@ -20,7 +20,7 @@
20 * 20 *
21 */ 21 */
22 22
23/* getopt not needed */ 23/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
24 24
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
@@ -30,14 +30,15 @@
30extern int whoami_main(int argc, char **argv) 30extern int whoami_main(int argc, char **argv)
31{ 31{
32 char user[9]; 32 char user[9];
33 uid_t uid = geteuid(); 33 uid_t uid;
34 34
35 if (argc > 1) 35 if (argc > 1)
36 show_usage(); 36 bb_show_usage();
37 37
38 uid = geteuid();
38 if (my_getpwuid(user, uid)) { 39 if (my_getpwuid(user, uid)) {
39 puts(user); 40 puts(user);
40 return EXIT_SUCCESS; 41 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
41 } 42 }
42 error_msg_and_die("cannot find username for UID %u", (unsigned) uid); 43 bb_error_msg_and_die("cannot find username for UID %u", (unsigned) uid);
43} 44}
diff --git a/coreutils/yes.c b/coreutils/yes.c
index 7d9596d0b..74f7571cf 100644
--- a/coreutils/yes.c
+++ b/coreutils/yes.c
@@ -1,8 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini yes implementation for busybox 3 * yes implementation for busybox
4 * 4 *
5 * Copyright (C) 2000 Edward Betts <edward@debian.org>. 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -20,7 +20,12 @@
20 * 20 *
21 */ 21 */
22 22
23/* getopt not needed */ 23/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
24
25/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
26 *
27 * Size reductions and removed redundant applet name prefix from error messages.
28 */
24 29
25#include <stdio.h> 30#include <stdio.h>
26#include <stdlib.h> 31#include <stdlib.h>
@@ -28,26 +33,24 @@
28 33
29extern int yes_main(int argc, char **argv) 34extern int yes_main(int argc, char **argv)
30{ 35{
31 int i; 36 static const char fmt_str[] = " %s";
32 37 const char *fmt;
33 if (argc >= 2 && *argv[1] == '-') 38 char **first_arg;
34 show_usage();
35 39
36 if (argc == 1) { 40 *argv = "y";
37 while (1) 41 if (argc != 1) {
38 if (puts("y") == EOF) { 42 ++argv;
39 perror("yes");
40 return EXIT_FAILURE;
41 }
42 } 43 }
43 44
44 while (1) 45 first_arg = argv;
45 for (i = 1; i < argc; i++) 46 do {
46 if (fputs(argv[i], stdout) == EOF 47 fmt = fmt_str + 1;
47 || putchar(i == argc - 1 ? '\n' : ' ') == EOF) { 48 do {
48 perror("yes"); 49 bb_printf(fmt, *argv);
49 return EXIT_FAILURE; 50 fmt = fmt_str;
50 } 51 } while (*++argv);
52 argv = first_arg;
53 } while (putchar('\n') != EOF);
51 54
52 return EXIT_SUCCESS; 55 bb_perror_nomsg_and_die();
53} 56}