diff options
author | Eric Andersen <andersen@codepoet.org> | 2003-06-20 09:01:58 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2003-06-20 09:01:58 +0000 |
commit | 8876fb2f59a0b515b3121d5894933eef88ce566a (patch) | |
tree | f67de9320202043aca8ded20fb80d668c3b0c2d8 | |
parent | dfce3536ace2bcd38bdd3731841998ce344d786e (diff) | |
download | busybox-w32-8876fb2f59a0b515b3121d5894933eef88ce566a.tar.gz busybox-w32-8876fb2f59a0b515b3121d5894933eef88ce566a.tar.bz2 busybox-w32-8876fb2f59a0b515b3121d5894933eef88ce566a.zip |
last_patch89 from vodz:
Manuel,
I rewrite bb_getopt_ulflags() function for more universal usage.
My version support now:
- options with arguments (optional arg as GNU extension also)
- complementaly and/or incomplementaly and/or incongruously and/or list
options
- long_opt (all applets may have long option, add supporting is trivial)
This realisation full compatibile from your version.
Code size grow 480 bytes, but only coreutils/* over compensate this size
after using new function. Last patch reduced over 800 bytes and not full
applied to all. "mkdir" and "mv" applets have long_opt now for demonstrate
trivial addition support long_opt with usage new bb_getopt_ulflags().
Complementaly and/or incomplementaly and/or incongruously and/or list options
logic is not trivial, but new "cut" and "grep" applets using this logic
for examples with full demostrating. New "grep" applet reduced over 300
bytes.
Mark,
Also. I removed bug from "grep" applet.
$ echo a b | busybox grep -e a b
a b
a b
But right is printing one only.
--w
vodz
-rw-r--r-- | coreutils/cut.c | 68 | ||||
-rw-r--r-- | coreutils/date.c | 65 | ||||
-rw-r--r-- | coreutils/dd.c | 4 | ||||
-rw-r--r-- | coreutils/df.c | 32 | ||||
-rw-r--r-- | coreutils/du.c | 93 | ||||
-rw-r--r-- | coreutils/env.c | 17 | ||||
-rw-r--r-- | coreutils/mkdir.c | 26 | ||||
-rw-r--r-- | coreutils/mv.c | 36 | ||||
-rw-r--r-- | coreutils/rm.c | 22 | ||||
-rw-r--r-- | coreutils/stty.c | 71 | ||||
-rw-r--r-- | coreutils/test.c | 6 | ||||
-rw-r--r-- | findutils/grep.c | 355 | ||||
-rw-r--r-- | findutils/xargs.c | 25 | ||||
-rw-r--r-- | include/libbb.h | 3 | ||||
-rw-r--r-- | libbb/getopt_ulflags.c | 145 | ||||
-rw-r--r-- | libbb/inode_hash.c | 2 | ||||
-rw-r--r-- | loginutils/addgroup.c | 31 | ||||
-rw-r--r-- | loginutils/adduser.c | 40 | ||||
-rw-r--r-- | miscutils/crond.c | 62 |
19 files changed, 581 insertions, 522 deletions
diff --git a/coreutils/cut.c b/coreutils/cut.c index c24cf6611..8ae762fb3 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c | |||
@@ -22,20 +22,22 @@ | |||
22 | 22 | ||
23 | #include <stdio.h> | 23 | #include <stdio.h> |
24 | #include <stdlib.h> | 24 | #include <stdlib.h> |
25 | #include <unistd.h> /* getopt */ | 25 | #include <getopt.h> |
26 | #include <unistd.h> | ||
26 | #include <string.h> | 27 | #include <string.h> |
27 | #include <limits.h> | 28 | #include <limits.h> |
28 | #include "busybox.h" | 29 | #include "busybox.h" |
29 | 30 | ||
30 | 31 | ||
31 | /* globals from other files */ | ||
32 | extern int optind; | ||
33 | extern char *optarg; | ||
34 | |||
35 | |||
36 | /* option vars */ | 32 | /* option vars */ |
37 | static char part = 0; /* (b)yte, (c)har, (f)ields */ | 33 | static const char optstring[] = "b:c:f:d:sn"; |
38 | static unsigned int supress_non_delimited_lines = 0; | 34 | #define OPT_BYTE_FLGS 1 |
35 | #define OPT_CHAR_FLGS 2 | ||
36 | #define OPT_FIELDS_FLGS 4 | ||
37 | #define OPT_DELIM_FLGS 8 | ||
38 | #define OPT_SUPRESS_FLGS 16 | ||
39 | static char part; /* (b)yte, (c)har, (f)ields */ | ||
40 | static unsigned int supress_non_delimited_lines; | ||
39 | static char delim = '\t'; /* delimiter, default is tab */ | 41 | static char delim = '\t'; /* delimiter, default is tab */ |
40 | 42 | ||
41 | struct cut_list { | 43 | struct cut_list { |
@@ -270,11 +272,11 @@ static void cut_file(FILE *file) | |||
270 | while ((line = bb_get_chomped_line_from_file(file)) != NULL) { | 272 | while ((line = bb_get_chomped_line_from_file(file)) != NULL) { |
271 | 273 | ||
272 | /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ | 274 | /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ |
273 | if (part == 'c' || part == 'b') | 275 | if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS))) |
274 | cut_line_by_chars(line); | 276 | cut_line_by_chars(line); |
275 | 277 | ||
276 | /* cut based on fields */ | 278 | /* cut based on fields */ |
277 | else if (part == 'f') { | 279 | else { |
278 | if (delim == '\n') | 280 | if (delim == '\n') |
279 | cut_file_by_lines(line, linenum); | 281 | cut_file_by_lines(line, linenum); |
280 | else | 282 | else |
@@ -289,46 +291,32 @@ static void cut_file(FILE *file) | |||
289 | 291 | ||
290 | extern int cut_main(int argc, char **argv) | 292 | extern int cut_main(int argc, char **argv) |
291 | { | 293 | { |
292 | int opt; | 294 | unsigned long opt; |
293 | 295 | char *sopt, *sdopt; | |
294 | while ((opt = getopt(argc, argv, "b:c:d:f:ns")) > 0) { | 296 | |
295 | switch (opt) { | 297 | bb_opt_complementaly = "b~bcf:c~bcf:f~bcf"; |
296 | case 'b': | 298 | opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt); |
297 | case 'c': | 299 | part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); |
298 | case 'f': | 300 | if(part == 0) |
299 | /* make sure they didn't ask for two types of lists */ | 301 | bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); |
300 | if (part != 0) { | 302 | if(opt & 0x80000000UL) |
301 | bb_error_msg_and_die("only one type of list may be specified"); | 303 | bb_error_msg_and_die("only one type of list may be specified"); |
302 | } | 304 | parse_lists(sopt); |
303 | part = (char)opt; | 305 | if((opt & (OPT_DELIM_FLGS))) { |
304 | parse_lists(optarg); | 306 | if (strlen(sdopt) > 1) { |
305 | break; | ||
306 | case 'd': | ||
307 | if (strlen(optarg) > 1) { | ||
308 | bb_error_msg_and_die("the delimiter must be a single character"); | 307 | bb_error_msg_and_die("the delimiter must be a single character"); |
309 | } | 308 | } |
310 | delim = optarg[0]; | 309 | delim = sdopt[0]; |
311 | break; | ||
312 | case 'n': | ||
313 | /* no-op */ | ||
314 | break; | ||
315 | case 's': | ||
316 | supress_non_delimited_lines++; | ||
317 | break; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | if (part == 0) { | ||
322 | bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); | ||
323 | } | 310 | } |
311 | supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS; | ||
324 | 312 | ||
325 | /* non-field (char or byte) cutting has some special handling */ | 313 | /* non-field (char or byte) cutting has some special handling */ |
326 | if (part != 'f') { | 314 | if (part != OPT_FIELDS_FLGS) { |
327 | if (supress_non_delimited_lines) { | 315 | if (supress_non_delimited_lines) { |
328 | bb_error_msg_and_die("suppressing non-delimited lines makes sense" | 316 | bb_error_msg_and_die("suppressing non-delimited lines makes sense" |
329 | " only when operating on fields"); | 317 | " only when operating on fields"); |
330 | } | 318 | } |
331 | if (delim != '\t' && part != 'f') { | 319 | if (delim != '\t') { |
332 | bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); | 320 | bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); |
333 | } | 321 | } |
334 | } | 322 | } |
diff --git a/coreutils/date.c b/coreutils/date.c index afbedb90d..6e7aa1f0c 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -120,74 +120,65 @@ int date_main(int argc, char **argv) | |||
120 | char *date_str = NULL; | 120 | char *date_str = NULL; |
121 | char *date_fmt = NULL; | 121 | char *date_fmt = NULL; |
122 | char *t_buff; | 122 | char *t_buff; |
123 | int c; | 123 | int set_time; |
124 | int set_time = 0; | 124 | int rfc822; |
125 | int rfc822 = 0; | 125 | int utc; |
126 | int utc = 0; | ||
127 | int use_arg = 0; | 126 | int use_arg = 0; |
128 | time_t tm; | 127 | time_t tm; |
128 | unsigned long opt; | ||
129 | struct tm tm_time; | 129 | struct tm tm_time; |
130 | 130 | ||
131 | #ifdef CONFIG_FEATURE_DATE_ISOFMT | 131 | #ifdef CONFIG_FEATURE_DATE_ISOFMT |
132 | int ifmt = 0; | 132 | int ifmt = 0; |
133 | char *isofmt_arg; | ||
133 | 134 | ||
134 | # define GETOPT_ISOFMT "I::" | 135 | # define GETOPT_ISOFMT "I::" |
135 | #else | 136 | #else |
136 | # define GETOPT_ISOFMT | 137 | # define GETOPT_ISOFMT |
137 | #endif | 138 | #endif |
138 | 139 | bb_opt_complementaly = "d~ds:s~ds"; | |
139 | /* Interpret command line args */ | 140 | opt = bb_getopt_ulflags(argc, argv, "Rs:ud:" GETOPT_ISOFMT, |
140 | while ((c = getopt(argc, argv, "Rs:ud:" GETOPT_ISOFMT)) != EOF) { | 141 | &date_str, &date_str |
141 | switch (c) { | 142 | #ifdef CONFIG_FEATURE_DATE_ISOFMT |
142 | case 'R': | 143 | , &isofmt_arg |
143 | rfc822 = 1; | 144 | #endif |
144 | break; | 145 | ); |
145 | case 's': | 146 | rfc822 = opt & 1; |
146 | set_time = 1; | 147 | set_time = opt & 2; |
147 | if ((date_str != NULL) || ((date_str = optarg) == NULL)) { | 148 | utc = opt & 4; |
148 | bb_show_usage(); | 149 | if(utc) { |
149 | } | ||
150 | break; | ||
151 | case 'u': | ||
152 | utc = 1; | ||
153 | if (putenv("TZ=UTC0") != 0) | 150 | if (putenv("TZ=UTC0") != 0) |
154 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 151 | bb_error_msg_and_die(bb_msg_memory_exhausted); |
155 | break; | 152 | } |
156 | case 'd': | 153 | use_arg = opt & 8; |
157 | use_arg = 1; | 154 | if(opt & 0x80000000UL) |
158 | if ((date_str != NULL) || ((date_str = optarg) == NULL)) | ||
159 | bb_show_usage(); | 155 | bb_show_usage(); |
160 | break; | ||
161 | #ifdef CONFIG_FEATURE_DATE_ISOFMT | 156 | #ifdef CONFIG_FEATURE_DATE_ISOFMT |
162 | case 'I': | 157 | if(opt & 16) { |
163 | if (!optarg) | 158 | if (!isofmt_arg) |
164 | ifmt = 1; | 159 | ifmt = 1; |
165 | else { | 160 | else { |
166 | int ifmt_len = bb_strlen(optarg); | 161 | int ifmt_len = bb_strlen(isofmt_arg); |
167 | 162 | ||
168 | if ((ifmt_len <= 4) | 163 | if ((ifmt_len <= 4) |
169 | && (strncmp(optarg, "date", ifmt_len) == 0)) { | 164 | && (strncmp(isofmt_arg, "date", ifmt_len) == 0)) { |
170 | ifmt = 1; | 165 | ifmt = 1; |
171 | } else if ((ifmt_len <= 5) | 166 | } else if ((ifmt_len <= 5) |
172 | && (strncmp(optarg, "hours", ifmt_len) == 0)) { | 167 | && (strncmp(isofmt_arg, "hours", ifmt_len) == 0)) { |
173 | ifmt = 2; | 168 | ifmt = 2; |
174 | } else if ((ifmt_len <= 7) | 169 | } else if ((ifmt_len <= 7) |
175 | && (strncmp(optarg, "minutes", ifmt_len) == 0)) { | 170 | && (strncmp(isofmt_arg, "minutes", ifmt_len) == 0)) { |
176 | ifmt = 3; | 171 | ifmt = 3; |
177 | } else if ((ifmt_len <= 7) | 172 | } else if ((ifmt_len <= 7) |
178 | && (strncmp(optarg, "seconds", ifmt_len) == 0)) { | 173 | && (strncmp(isofmt_arg, "seconds", ifmt_len) == 0)) { |
179 | ifmt = 4; | 174 | ifmt = 4; |
180 | } | 175 | } |
181 | } | 176 | } |
182 | if (ifmt) { | 177 | if (!ifmt) { |
183 | break; /* else bb_show_usage(); */ | ||
184 | } | ||
185 | #endif | ||
186 | default: | ||
187 | bb_show_usage(); | 178 | bb_show_usage(); |
188 | } | 179 | } |
189 | } | 180 | } |
190 | 181 | #endif | |
191 | 182 | ||
192 | if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { | 183 | if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { |
193 | date_fmt = &argv[optind][1]; /* Skip over the '+' */ | 184 | date_fmt = &argv[optind][1]; /* Skip over the '+' */ |
diff --git a/coreutils/dd.c b/coreutils/dd.c index 11508614f..cd97b24ee 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -106,9 +106,7 @@ int dd_main(int argc, char **argv) | |||
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 | ifd = bb_xopen(infile, O_RDONLY); |
110 | bb_perror_msg_and_die("%s", infile); | ||
111 | } | ||
112 | } else { | 110 | } else { |
113 | ifd = STDIN_FILENO; | 111 | ifd = STDIN_FILENO; |
114 | infile = bb_msg_standard_input; | 112 | infile = bb_msg_standard_input; |
diff --git a/coreutils/df.c b/coreutils/df.c index 708e12cc0..9673633cc 100644 --- a/coreutils/df.c +++ b/coreutils/df.c | |||
@@ -55,41 +55,27 @@ extern int df_main(int argc, char **argv) | |||
55 | unsigned long df_disp_hr = KILOBYTE; | 55 | unsigned long df_disp_hr = KILOBYTE; |
56 | #endif | 56 | #endif |
57 | int status = EXIT_SUCCESS; | 57 | int status = EXIT_SUCCESS; |
58 | int opt; | 58 | unsigned long opt; |
59 | FILE *mount_table; | 59 | FILE *mount_table; |
60 | struct mntent *mount_entry; | 60 | struct mntent *mount_entry; |
61 | struct statfs s; | 61 | struct statfs s; |
62 | static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */ | 62 | static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */ |
63 | const char *disp_units_hdr = hdr_1k; | 63 | const char *disp_units_hdr = hdr_1k; |
64 | 64 | ||
65 | while ((opt = getopt(argc, argv, "k" | ||
66 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | 65 | #ifdef CONFIG_FEATURE_HUMAN_READABLE |
67 | "hm" | 66 | bb_opt_complementaly = "h-km:k-hm:m-hk"; |
68 | #endif | 67 | opt = bb_getopt_ulflags(argc, argv, "hmk"); |
69 | )) > 0) | 68 | if(opt & 1) { |
70 | { | ||
71 | switch (opt) { | ||
72 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | ||
73 | case 'h': | ||
74 | df_disp_hr = 0; | 69 | df_disp_hr = 0; |
75 | disp_units_hdr = " Size"; | 70 | disp_units_hdr = " Size"; |
76 | break; | 71 | } |
77 | case 'm': | 72 | if(opt & 2) { |
78 | df_disp_hr = MEGABYTE; | 73 | df_disp_hr = MEGABYTE; |
79 | disp_units_hdr = "1M-blocks"; | 74 | disp_units_hdr = "1M-blocks"; |
80 | break; | ||
81 | #endif | ||
82 | case 'k': | ||
83 | /* default display is kilobytes */ | ||
84 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | ||
85 | df_disp_hr = KILOBYTE; | ||
86 | disp_units_hdr = hdr_1k; | ||
87 | #endif | ||
88 | break; | ||
89 | default: | ||
90 | bb_show_usage(); | ||
91 | } | ||
92 | } | 75 | } |
76 | #else | ||
77 | opt = bb_getopt_ulflags(argc, argv, "k"); | ||
78 | #endif | ||
93 | 79 | ||
94 | bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n", | 80 | bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n", |
95 | "", disp_units_hdr); | 81 | "", disp_units_hdr); |
diff --git a/coreutils/du.c b/coreutils/du.c index 1c16cfbd4..a9f6c28ba 100644 --- a/coreutils/du.c +++ b/coreutils/du.c | |||
@@ -166,8 +166,9 @@ int du_main(int argc, char **argv) | |||
166 | { | 166 | { |
167 | long total; | 167 | long total; |
168 | int slink_depth_save; | 168 | int slink_depth_save; |
169 | int print_final_total = 0; | 169 | int print_final_total; |
170 | int c; | 170 | char *smax_print_depth; |
171 | unsigned long opt; | ||
171 | 172 | ||
172 | #ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K | 173 | #ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K |
173 | if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */ | 174 | if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */ |
@@ -185,57 +186,57 @@ int du_main(int argc, char **argv) | |||
185 | * gnu du exits with an error code in this case. We choose to simply | 186 | * gnu du exits with an error code in this case. We choose to simply |
186 | * ignore -a. This is consistent with -s being equivalent to -d 0. | 187 | * ignore -a. This is consistent with -s being equivalent to -d 0. |
187 | */ | 188 | */ |
188 | |||
189 | while ((c = getopt(argc, argv, "aHkLsx" "d:" "lc" | ||
190 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | ||
191 | "hm" | ||
192 | #endif | ||
193 | )) > 0) { | ||
194 | switch (c) { | ||
195 | case 'a': | ||
196 | print_files = INT_MAX; | ||
197 | break; | ||
198 | case 'H': | ||
199 | slink_depth = 1; | ||
200 | break; | ||
201 | case 'k': | ||
202 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | 189 | #ifdef CONFIG_FEATURE_HUMAN_READABLE |
190 | bb_opt_complementaly = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s"; | ||
191 | opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth); | ||
192 | if((opt & (1 << 9))) { | ||
193 | /* -h opt */ | ||
194 | disp_hr = 0; | ||
195 | } | ||
196 | if((opt & (1 << 10))) { | ||
197 | /* -m opt */ | ||
198 | disp_hr = MEGABYTE; | ||
199 | } | ||
200 | if((opt & (1 << 2))) { | ||
201 | /* -k opt */ | ||
203 | disp_hr = KILOBYTE; | 202 | disp_hr = KILOBYTE; |
204 | #elif !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K | 203 | } |
204 | #else | ||
205 | bb_opt_complementaly = "H-L:L-H:s-d:d-s"; | ||
206 | opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth); | ||
207 | #if !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K | ||
208 | if((opt & (1 << 2))) { | ||
209 | /* -k opt */ | ||
205 | disp_k = 1; | 210 | disp_k = 1; |
211 | } | ||
212 | #endif | ||
206 | #endif | 213 | #endif |
207 | break; | 214 | if((opt & (1 << 0))) { |
208 | case 'L': | 215 | /* -a opt */ |
216 | print_files = INT_MAX; | ||
217 | } | ||
218 | if((opt & (1 << 1))) { | ||
219 | /* -H opt */ | ||
220 | slink_depth = 1; | ||
221 | } | ||
222 | if((opt & (1 << 3))) { | ||
223 | /* -L opt */ | ||
209 | slink_depth = INT_MAX; | 224 | slink_depth = INT_MAX; |
210 | break; | 225 | } |
211 | case 's': | 226 | if((opt & (1 << 4))) { |
227 | /* -s opt */ | ||
212 | max_print_depth = 0; | 228 | max_print_depth = 0; |
213 | break; | ||
214 | case 'x': | ||
215 | one_file_system = 1; | ||
216 | break; | ||
217 | |||
218 | case 'd': | ||
219 | max_print_depth = bb_xgetularg10_bnd(optarg, 0, INT_MAX); | ||
220 | break; | ||
221 | case 'l': | ||
222 | count_hardlinks = 1; | ||
223 | break; | ||
224 | case 'c': | ||
225 | print_final_total = 1; | ||
226 | break; | ||
227 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | ||
228 | case 'h': | ||
229 | disp_hr = 0; | ||
230 | break; | ||
231 | case 'm': | ||
232 | disp_hr = MEGABYTE; | ||
233 | break; | ||
234 | #endif | ||
235 | default: | ||
236 | bb_show_usage(); | ||
237 | } | 229 | } |
230 | one_file_system = opt & (1 << 5); /* -x opt */ | ||
231 | if((opt & (1 << 6))) { | ||
232 | /* -d opt */ | ||
233 | max_print_depth = bb_xgetularg10_bnd(smax_print_depth, 0, INT_MAX); | ||
238 | } | 234 | } |
235 | if((opt & (1 << 7))) { | ||
236 | /* -l opt */ | ||
237 | count_hardlinks = 1; | ||
238 | } | ||
239 | print_final_total = opt & (1 << 8); /* -c opt */ | ||
239 | 240 | ||
240 | /* go through remaining args (if any) */ | 241 | /* go through remaining args (if any) */ |
241 | argv += optind; | 242 | argv += optind; |
@@ -252,7 +253,9 @@ int du_main(int argc, char **argv) | |||
252 | total += du(*argv); | 253 | total += du(*argv); |
253 | slink_depth = slink_depth_save; | 254 | slink_depth = slink_depth_save; |
254 | } while (*++argv); | 255 | } while (*++argv); |
256 | #ifdef CONFIG_FEATURE_CLEAN_UP | ||
255 | reset_ino_dev_hashtable(); | 257 | reset_ino_dev_hashtable(); |
258 | #endif | ||
256 | 259 | ||
257 | if (print_final_total) { | 260 | if (print_final_total) { |
258 | print(total, "total"); | 261 | print(total, "total"); |
diff --git a/coreutils/env.c b/coreutils/env.c index db13b3aed..eb761e9e9 100644 --- a/coreutils/env.c +++ b/coreutils/env.c | |||
@@ -44,20 +44,13 @@ extern int env_main(int argc, char** argv) | |||
44 | { | 44 | { |
45 | char **ep, *p; | 45 | char **ep, *p; |
46 | char *cleanenv[1] = { NULL }; | 46 | char *cleanenv[1] = { NULL }; |
47 | int ch; | 47 | unsigned long opt; |
48 | 48 | ||
49 | while ((ch = getopt(argc, argv, "iu:")) > 0) { | 49 | opt = bb_getopt_ulflags(argc, argv, "iu:", &p); |
50 | switch(ch) { | 50 | if(opt & 1) |
51 | case 'i': | ||
52 | environ = cleanenv; | 51 | environ = cleanenv; |
53 | break; | 52 | if(opt & 2) |
54 | case 'u': | 53 | unsetenv(p); |
55 | unsetenv(optarg); | ||
56 | break; | ||
57 | default: | ||
58 | bb_show_usage(); | ||
59 | } | ||
60 | } | ||
61 | 54 | ||
62 | argv += optind; | 55 | argv += optind; |
63 | 56 | ||
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index b018ac181..50364f17f 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c | |||
@@ -31,27 +31,33 @@ | |||
31 | 31 | ||
32 | #include <stdlib.h> | 32 | #include <stdlib.h> |
33 | #include <unistd.h> | 33 | #include <unistd.h> |
34 | #include <getopt.h> | ||
34 | #include "busybox.h" | 35 | #include "busybox.h" |
35 | 36 | ||
37 | static const struct option mkdir_long_options[] = { | ||
38 | { "mode", 1, NULL, 'm' }, | ||
39 | { "parents", 0, NULL, 'p' }, | ||
40 | { 0, 0, 0, 0 } | ||
41 | }; | ||
42 | |||
36 | extern int mkdir_main (int argc, char **argv) | 43 | extern int mkdir_main (int argc, char **argv) |
37 | { | 44 | { |
38 | mode_t mode = (mode_t)(-1); | 45 | mode_t mode = (mode_t)(-1); |
39 | int status = EXIT_SUCCESS; | 46 | int status = EXIT_SUCCESS; |
40 | int flags = 0; | 47 | int flags = 0; |
41 | int opt; | 48 | unsigned long opt; |
49 | char *smode; | ||
42 | 50 | ||
43 | while ((opt = getopt (argc, argv, "m:p")) > 0) { | 51 | bb_applet_long_options = mkdir_long_options; |
44 | if (opt == 'm') { | 52 | opt = bb_getopt_ulflags(argc, argv, "m:p", &smode); |
53 | if(opt & 1) { | ||
45 | mode = 0777; | 54 | mode = 0777; |
46 | if (!bb_parse_mode (optarg, &mode)) { | 55 | if (!bb_parse_mode (smode, &mode)) { |
47 | bb_error_msg_and_die ("invalid mode `%s'", optarg); | 56 | bb_error_msg_and_die ("invalid mode `%s'", smode); |
48 | } | ||
49 | } else if (opt == 'p') { | ||
50 | flags |= FILEUTILS_RECUR; | ||
51 | } else { | ||
52 | bb_show_usage(); | ||
53 | } | 57 | } |
54 | } | 58 | } |
59 | if(opt & 2) | ||
60 | flags |= FILEUTILS_RECUR; | ||
55 | 61 | ||
56 | if (optind == argc) { | 62 | if (optind == argc) { |
57 | bb_show_usage(); | 63 | bb_show_usage(); |
diff --git a/coreutils/mv.c b/coreutils/mv.c index ae0ee92e4..55da2cc68 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c | |||
@@ -31,10 +31,21 @@ | |||
31 | #include <dirent.h> | 31 | #include <dirent.h> |
32 | #include <errno.h> | 32 | #include <errno.h> |
33 | #include <stdlib.h> | 33 | #include <stdlib.h> |
34 | #include <getopt.h> | ||
34 | #include "busybox.h" | 35 | #include "busybox.h" |
35 | #include "libcoreutils/coreutils.h" | 36 | #include "libcoreutils/coreutils.h" |
36 | 37 | ||
37 | static const char *fmt = "cannot overwrite %sdirectory with %sdirectory"; | 38 | static const struct option mv_long_options[] = { |
39 | { "interactive", 0, NULL, 'i' }, | ||
40 | { "force", 0, NULL, 'f' }, | ||
41 | { 0, 0, 0, 0 } | ||
42 | }; | ||
43 | |||
44 | static const char mv_getopt_short_option[] = "fi"; | ||
45 | #define OPT_FILEUTILS_FORCE 1 | ||
46 | #define OPT_FILEUTILS_INTERACTIVE 2 | ||
47 | |||
48 | static const char fmt[] = "cannot overwrite %sdirectory with %sdirectory"; | ||
38 | 49 | ||
39 | extern int mv_main(int argc, char **argv) | 50 | extern int mv_main(int argc, char **argv) |
40 | { | 51 | { |
@@ -44,20 +55,12 @@ extern int mv_main(int argc, char **argv) | |||
44 | const char *dest; | 55 | const char *dest; |
45 | int dest_exists; | 56 | int dest_exists; |
46 | int source_exists; | 57 | int source_exists; |
47 | int opt; | 58 | unsigned long flags; |
48 | int flags = 0; | ||
49 | int status = 0; | 59 | int status = 0; |
50 | 60 | ||
51 | while ((opt = getopt(argc, argv, "fi")) > 0) { | 61 | bb_applet_long_options = mv_long_options; |
52 | flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE); | 62 | bb_opt_complementaly = "f-i:i-f"; |
53 | if (opt == 'i') { | 63 | flags = bb_getopt_ulflags(argc, argv, mv_getopt_short_option); |
54 | flags |= FILEUTILS_INTERACTIVE; | ||
55 | } else if (opt == 'f') { | ||
56 | flags |= FILEUTILS_FORCE; | ||
57 | } else { | ||
58 | bb_show_usage(); | ||
59 | } | ||
60 | } | ||
61 | 64 | ||
62 | if (optind + 2 > argc) | 65 | if (optind + 2 > argc) |
63 | bb_show_usage(); | 66 | bb_show_usage(); |
@@ -77,8 +80,7 @@ extern int mv_main(int argc, char **argv) | |||
77 | } | 80 | } |
78 | 81 | ||
79 | do { | 82 | do { |
80 | dest = concat_path_file(last, | 83 | dest = concat_path_file(last, bb_get_last_path_component(*argv)); |
81 | bb_get_last_path_component(*argv)); | ||
82 | 84 | ||
83 | if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) { | 85 | if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) { |
84 | goto RET_1; | 86 | goto RET_1; |
@@ -86,9 +88,9 @@ extern int mv_main(int argc, char **argv) | |||
86 | 88 | ||
87 | DO_MOVE: | 89 | DO_MOVE: |
88 | 90 | ||
89 | if (dest_exists && !(flags & FILEUTILS_FORCE) && | 91 | if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) && |
90 | ((access(dest, W_OK) < 0 && isatty(0)) || | 92 | ((access(dest, W_OK) < 0 && isatty(0)) || |
91 | (flags & FILEUTILS_INTERACTIVE))) { | 93 | (flags & OPT_FILEUTILS_INTERACTIVE))) { |
92 | if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) { | 94 | if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) { |
93 | goto RET_1; /* Ouch! fprintf failed! */ | 95 | goto RET_1; /* Ouch! fprintf failed! */ |
94 | } | 96 | } |
diff --git a/coreutils/rm.c b/coreutils/rm.c index 5489350e5..39609e7b8 100644 --- a/coreutils/rm.c +++ b/coreutils/rm.c | |||
@@ -36,22 +36,16 @@ extern int rm_main(int argc, char **argv) | |||
36 | { | 36 | { |
37 | int status = 0; | 37 | int status = 0; |
38 | int flags = 0; | 38 | int flags = 0; |
39 | int opt; | 39 | unsigned long opt; |
40 | 40 | ||
41 | while ((opt = getopt(argc, argv, "fiRr")) > 0) { | 41 | bb_opt_complementaly = "f-i:i-f"; |
42 | if ((opt == 'r') || (opt == 'R')) { | 42 | opt = bb_getopt_ulflags(argc, argv, "fiRr"); |
43 | flags |= FILEUTILS_RECUR; | 43 | if(opt & 1) |
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; | 44 | flags |= FILEUTILS_FORCE; |
50 | } else { | 45 | if(opt & 2) |
51 | bb_show_usage(); | 46 | flags |= FILEUTILS_INTERACTIVE; |
52 | } | 47 | if(opt & 12) |
53 | } | 48 | flags |= FILEUTILS_RECUR; |
54 | } | ||
55 | 49 | ||
56 | if (*(argv += optind) != NULL) { | 50 | if (*(argv += optind) != NULL) { |
57 | do { | 51 | do { |
diff --git a/coreutils/stty.c b/coreutils/stty.c index a3a98d9ef..bd3a36911 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
@@ -414,22 +414,25 @@ static int set_mode(const struct mode_info *info, | |||
414 | int reversed, struct termios *mode); | 414 | int reversed, struct termios *mode); |
415 | static speed_t string_to_baud(const char *arg); | 415 | static speed_t string_to_baud(const char *arg); |
416 | static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); | 416 | static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); |
417 | static void display_all(struct termios *mode, int fd, | 417 | static void display_all(struct termios *mode, int fd); |
418 | const char *device_name); | 418 | static void display_changed(struct termios *mode, int fd); |
419 | static void display_changed(struct termios *mode, int fd, | 419 | static void display_recoverable(struct termios *mode, int fd); |
420 | const char *device_name); | ||
421 | static void display_recoverable(struct termios *mode, int fd, | ||
422 | const char *device_name); | ||
423 | static void display_speed(struct termios *mode, int fancy); | 420 | static void display_speed(struct termios *mode, int fancy); |
424 | static void display_window_size(int fancy, int fd, | 421 | static void display_window_size(int fancy, int fd); |
425 | const char *device_name); | ||
426 | static void sane_mode(struct termios *mode); | 422 | static void sane_mode(struct termios *mode); |
427 | static void set_control_char(const struct control_info *info, | 423 | static void set_control_char(const struct control_info *info, |
428 | const char *arg, struct termios *mode); | 424 | const char *arg, struct termios *mode); |
429 | static void set_speed(enum speed_setting type, | 425 | static void set_speed(enum speed_setting type, |
430 | const char *arg, struct termios *mode); | 426 | const char *arg, struct termios *mode); |
431 | static void set_window_size(int rows, int cols, int fd, | 427 | static void set_window_size(int rows, int cols, int fd); |
432 | const char *device_name); | 428 | |
429 | static const char *device_name; | ||
430 | |||
431 | static __attribute__ ((noreturn)) void perror_on_device(const char *fmt) | ||
432 | { | ||
433 | bb_perror_msg_and_die(fmt, device_name); | ||
434 | } | ||
435 | |||
433 | 436 | ||
434 | /* The width of the screen, for output wrapping. */ | 437 | /* The width of the screen, for output wrapping. */ |
435 | static int max_col; | 438 | static int max_col; |
@@ -477,7 +480,7 @@ extern int main(int argc, char **argv) | |||
477 | #endif | 480 | #endif |
478 | { | 481 | { |
479 | struct termios mode; | 482 | struct termios mode; |
480 | void (*output_func)(struct termios *, int, const char *); | 483 | void (*output_func)(struct termios *, int); |
481 | int optc; | 484 | int optc; |
482 | int require_set_attr; | 485 | int require_set_attr; |
483 | int speed_was_set; | 486 | int speed_was_set; |
@@ -487,7 +490,7 @@ extern int main(int argc, char **argv) | |||
487 | int noargs = 1; | 490 | int noargs = 1; |
488 | char * file_name = NULL; | 491 | char * file_name = NULL; |
489 | int fd; | 492 | int fd; |
490 | const char *device_name; | 493 | |
491 | 494 | ||
492 | output_func = display_changed; | 495 | output_func = display_changed; |
493 | verbose_output = 0; | 496 | verbose_output = 0; |
@@ -543,13 +546,10 @@ extern int main(int argc, char **argv) | |||
543 | int fdflags; | 546 | int fdflags; |
544 | 547 | ||
545 | device_name = file_name; | 548 | device_name = file_name; |
546 | fd = open(device_name, O_RDONLY | O_NONBLOCK); | 549 | fd = bb_xopen(device_name, O_RDONLY | O_NONBLOCK); |
547 | if (fd < 0) | ||
548 | bb_perror_msg_and_die("%s", device_name); | ||
549 | if ((fdflags = fcntl(fd, F_GETFL)) == -1 | 550 | if ((fdflags = fcntl(fd, F_GETFL)) == -1 |
550 | || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) | 551 | || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) |
551 | bb_perror_msg_and_die("%s: couldn't reset non-blocking mode", | 552 | perror_on_device("%s: couldn't reset non-blocking mode"); |
552 | device_name); | ||
553 | } else { | 553 | } else { |
554 | fd = 0; | 554 | fd = 0; |
555 | device_name = bb_msg_standard_input; | 555 | device_name = bb_msg_standard_input; |
@@ -559,12 +559,12 @@ extern int main(int argc, char **argv) | |||
559 | spurious difference in an uninitialized portion of the structure. */ | 559 | spurious difference in an uninitialized portion of the structure. */ |
560 | memset(&mode, 0, sizeof(mode)); | 560 | memset(&mode, 0, sizeof(mode)); |
561 | if (tcgetattr(fd, &mode)) | 561 | if (tcgetattr(fd, &mode)) |
562 | bb_perror_msg_and_die("%s", device_name); | 562 | perror_on_device("%s"); |
563 | 563 | ||
564 | if (verbose_output | recoverable_output | noargs) { | 564 | if (verbose_output | recoverable_output | noargs) { |
565 | max_col = screen_columns(); | 565 | max_col = screen_columns(); |
566 | current_col = 0; | 566 | current_col = 0; |
567 | output_func(&mode, fd, device_name); | 567 | output_func(&mode, fd); |
568 | return EXIT_SUCCESS; | 568 | return EXIT_SUCCESS; |
569 | } | 569 | } |
570 | 570 | ||
@@ -644,18 +644,18 @@ extern int main(int argc, char **argv) | |||
644 | bb_error_msg_and_die("missing argument to `%s'", argv[k]); | 644 | bb_error_msg_and_die("missing argument to `%s'", argv[k]); |
645 | ++k; | 645 | ++k; |
646 | set_window_size((int) bb_xparse_number(argv[k], stty_suffixes), | 646 | set_window_size((int) bb_xparse_number(argv[k], stty_suffixes), |
647 | -1, fd, device_name); | 647 | -1, fd); |
648 | } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { | 648 | } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { |
649 | if (k == argc - 1) | 649 | if (k == argc - 1) |
650 | bb_error_msg_and_die("missing argument to `%s'", argv[k]); | 650 | bb_error_msg_and_die("missing argument to `%s'", argv[k]); |
651 | ++k; | 651 | ++k; |
652 | set_window_size(-1, | 652 | set_window_size(-1, |
653 | (int) bb_xparse_number(argv[k], stty_suffixes), | 653 | (int) bb_xparse_number(argv[k], stty_suffixes), |
654 | fd, device_name); | 654 | fd); |
655 | } else if (STREQ(argv[k], "size")) { | 655 | } else if (STREQ(argv[k], "size")) { |
656 | max_col = screen_columns(); | 656 | max_col = screen_columns(); |
657 | current_col = 0; | 657 | current_col = 0; |
658 | display_window_size(0, fd, device_name); | 658 | display_window_size(0, fd); |
659 | } | 659 | } |
660 | #endif | 660 | #endif |
661 | #ifdef HAVE_C_LINE | 661 | #ifdef HAVE_C_LINE |
@@ -685,7 +685,7 @@ extern int main(int argc, char **argv) | |||
685 | struct termios new_mode; | 685 | struct termios new_mode; |
686 | 686 | ||
687 | if (tcsetattr(fd, TCSADRAIN, &mode)) | 687 | if (tcsetattr(fd, TCSADRAIN, &mode)) |
688 | bb_perror_msg_and_die("%s", device_name); | 688 | perror_on_device("%s"); |
689 | 689 | ||
690 | /* POSIX (according to Zlotnick's book) tcsetattr returns zero if | 690 | /* POSIX (according to Zlotnick's book) tcsetattr returns zero if |
691 | it performs *any* of the requested operations. This means it | 691 | it performs *any* of the requested operations. This means it |
@@ -698,7 +698,7 @@ extern int main(int argc, char **argv) | |||
698 | spurious difference in an uninitialized portion of the structure. */ | 698 | spurious difference in an uninitialized portion of the structure. */ |
699 | memset(&new_mode, 0, sizeof(new_mode)); | 699 | memset(&new_mode, 0, sizeof(new_mode)); |
700 | if (tcgetattr(fd, &new_mode)) | 700 | if (tcgetattr(fd, &new_mode)) |
701 | bb_perror_msg_and_die("%s", device_name); | 701 | perror_on_device("%s"); |
702 | 702 | ||
703 | /* Normally, one shouldn't use memcmp to compare structures that | 703 | /* Normally, one shouldn't use memcmp to compare structures that |
704 | may have `holes' containing uninitialized data, but we have been | 704 | may have `holes' containing uninitialized data, but we have been |
@@ -721,8 +721,7 @@ extern int main(int argc, char **argv) | |||
721 | new_mode.c_cflag &= (~CIBAUD); | 721 | new_mode.c_cflag &= (~CIBAUD); |
722 | if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0) | 722 | if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0) |
723 | #endif | 723 | #endif |
724 | bb_error_msg_and_die ("%s: unable to perform all requested operations", | 724 | perror_on_device ("%s: unable to perform all requested operations"); |
725 | device_name); | ||
726 | } | 725 | } |
727 | } | 726 | } |
728 | 727 | ||
@@ -948,13 +947,13 @@ static int get_win_size(int fd, struct winsize *win) | |||
948 | } | 947 | } |
949 | 948 | ||
950 | static void | 949 | static void |
951 | set_window_size(int rows, int cols, int fd, const char *device_name) | 950 | set_window_size(int rows, int cols, int fd) |
952 | { | 951 | { |
953 | struct winsize win; | 952 | struct winsize win; |
954 | 953 | ||
955 | if (get_win_size(fd, &win)) { | 954 | if (get_win_size(fd, &win)) { |
956 | if (errno != EINVAL) | 955 | if (errno != EINVAL) |
957 | bb_perror_msg_and_die("%s", device_name); | 956 | perror_on_device("%s"); |
958 | memset(&win, 0, sizeof(win)); | 957 | memset(&win, 0, sizeof(win)); |
959 | } | 958 | } |
960 | 959 | ||
@@ -980,23 +979,23 @@ set_window_size(int rows, int cols, int fd, const char *device_name) | |||
980 | 979 | ||
981 | if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0) | 980 | if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0) |
982 | || (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) { | 981 | || (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) { |
983 | bb_perror_msg_and_die("%s", device_name); | 982 | perror_on_device("%s"); |
984 | return; | 983 | return; |
985 | } | 984 | } |
986 | # endif | 985 | # endif |
987 | 986 | ||
988 | if (ioctl(fd, TIOCSWINSZ, (char *) &win)) | 987 | if (ioctl(fd, TIOCSWINSZ, (char *) &win)) |
989 | bb_perror_msg_and_die("%s", device_name); | 988 | perror_on_device("%s"); |
990 | } | 989 | } |
991 | 990 | ||
992 | static void display_window_size(int fancy, int fd, const char *device_name) | 991 | static void display_window_size(int fancy, int fd) |
993 | { | 992 | { |
994 | const char *fmt_str = "%s" "\0" "%s: no size information for this device"; | 993 | const char *fmt_str = "%s" "\0" "%s: no size information for this device"; |
995 | struct winsize win; | 994 | struct winsize win; |
996 | 995 | ||
997 | if (get_win_size(fd, &win)) { | 996 | if (get_win_size(fd, &win)) { |
998 | if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) { | 997 | if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) { |
999 | bb_perror_msg_and_die(fmt_str, device_name); | 998 | perror_on_device(fmt_str); |
1000 | } | 999 | } |
1001 | } else { | 1000 | } else { |
1002 | wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n", | 1001 | wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n", |
@@ -1047,7 +1046,7 @@ static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode) | |||
1047 | return NULL; | 1046 | return NULL; |
1048 | } | 1047 | } |
1049 | 1048 | ||
1050 | static void display_changed(struct termios *mode, int fd, const char *device_name) | 1049 | static void display_changed(struct termios *mode, int fd) |
1051 | { | 1050 | { |
1052 | int i; | 1051 | int i; |
1053 | int empty_line; | 1052 | int empty_line; |
@@ -1122,7 +1121,7 @@ static void display_changed(struct termios *mode, int fd, const char *device_nam | |||
1122 | } | 1121 | } |
1123 | 1122 | ||
1124 | static void | 1123 | static void |
1125 | display_all(struct termios *mode, int fd, const char *device_name) | 1124 | display_all(struct termios *mode, int fd) |
1126 | { | 1125 | { |
1127 | int i; | 1126 | int i; |
1128 | tcflag_t *bitsp; | 1127 | tcflag_t *bitsp; |
@@ -1131,7 +1130,7 @@ display_all(struct termios *mode, int fd, const char *device_name) | |||
1131 | 1130 | ||
1132 | display_speed(mode, 1); | 1131 | display_speed(mode, 1); |
1133 | #ifdef TIOCGWINSZ | 1132 | #ifdef TIOCGWINSZ |
1134 | display_window_size(1, fd, device_name); | 1133 | display_window_size(1, fd); |
1135 | #endif | 1134 | #endif |
1136 | #ifdef HAVE_C_LINE | 1135 | #ifdef HAVE_C_LINE |
1137 | wrapf("line = %d;", mode->c_line); | 1136 | wrapf("line = %d;", mode->c_line); |
@@ -1202,7 +1201,7 @@ static void display_speed(struct termios *mode, int fancy) | |||
1202 | current_col = 0; | 1201 | current_col = 0; |
1203 | } | 1202 | } |
1204 | 1203 | ||
1205 | static void display_recoverable(struct termios *mode, int fd, const char *device_name) | 1204 | static void display_recoverable(struct termios *mode, int fd) |
1206 | { | 1205 | { |
1207 | int i; | 1206 | int i; |
1208 | 1207 | ||
diff --git a/coreutils/test.c b/coreutils/test.c index 0bce66e6f..31ac87f34 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -452,10 +452,8 @@ static int getn(const char *s) | |||
452 | if (errno != 0) | 452 | if (errno != 0) |
453 | bb_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 | /* p = bb_skip_whitespace(p); avoid const warning */ |
456 | p++; | 456 | if (*(bb_skip_whitespace(p))) |
457 | |||
458 | if (*p) | ||
459 | bb_error_msg_and_die("%s: bad number", s); | 457 | bb_error_msg_and_die("%s: bad number", s); |
460 | 458 | ||
461 | return (int) r; | 459 | return (int) r; |
diff --git a/findutils/grep.c b/findutils/grep.c index e26a8d5ad..241099c79 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -19,42 +19,71 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | /* | ||
23 | * Jun 2003 by Vladimir Oleynik <dzo@simtreas.ru> - | ||
24 | * correction "-e pattern1 -e -e pattern2" logic and more optimizations. | ||
25 | */ | ||
22 | 26 | ||
23 | #include <stdio.h> | 27 | #include <stdio.h> |
24 | #include <stdlib.h> | 28 | #include <stdlib.h> |
25 | #include <getopt.h> | 29 | #include <getopt.h> |
26 | #include <regex.h> | 30 | #include <regex.h> |
27 | #include <string.h> /* for strerror() */ | 31 | #include <string.h> |
28 | #include <errno.h> | 32 | #include <errno.h> |
29 | #include "busybox.h" | 33 | #include "busybox.h" |
30 | 34 | ||
31 | 35 | ||
32 | extern int optind; /* in unistd.h */ | ||
33 | extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */ | ||
34 | |||
35 | /* options */ | 36 | /* options */ |
36 | static int reflags = REG_NOSUB; | 37 | #define GREP_OPTS "lnqvscFiHhe:f:" |
37 | static int print_filename = 0; | 38 | #define GREP_OPT_l 1 |
38 | static int print_line_num = 0; | 39 | static char print_files_with_matches; |
39 | static int print_match_counts = 0; | 40 | #define GREP_OPT_n 2 |
40 | static int be_quiet = 0; | 41 | static char print_line_num; |
41 | static int invert_search = 0; | 42 | #define GREP_OPT_q 4 |
42 | static int suppress_err_msgs = 0; | 43 | static char be_quiet; |
43 | static int print_files_with_matches = 0; | 44 | #define GREP_OPT_v 8 |
44 | static int fgrep_flag = 0; | 45 | typedef char invert_search_t; |
46 | static invert_search_t invert_search; | ||
47 | #define GREP_OPT_s 16 | ||
48 | static char suppress_err_msgs; | ||
49 | #define GREP_OPT_c 32 | ||
50 | static char print_match_counts; | ||
51 | #define GREP_OPT_F 64 | ||
52 | static char fgrep_flag; | ||
53 | #define GREP_OPT_i 128 | ||
54 | #define GREP_OPT_H 256 | ||
55 | #define GREP_OPT_h 512 | ||
56 | #define GREP_OPT_e 1024 | ||
57 | #define GREP_OPT_f 2048 | ||
58 | #ifdef CONFIG_FEATURE_GREP_CONTEXT | ||
59 | #define GREP_OPT_CONTEXT "A:B:C" | ||
60 | #define GREP_OPT_A 4096 | ||
61 | #define GREP_OPT_B 8192 | ||
62 | #define GREP_OPT_C 16384 | ||
63 | #define GREP_OPT_E 32768U | ||
64 | #else | ||
65 | #define GREP_OPT_CONTEXT "" | ||
66 | #define GREP_OPT_E 4096 | ||
67 | #endif | ||
68 | #ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS | ||
69 | # define OPT_EGREP "E" | ||
70 | #else | ||
71 | # define OPT_EGREP "" | ||
72 | #endif | ||
73 | |||
74 | static int reflags; | ||
75 | static int print_filename; | ||
45 | 76 | ||
46 | #ifdef CONFIG_FEATURE_GREP_CONTEXT | 77 | #ifdef CONFIG_FEATURE_GREP_CONTEXT |
47 | extern char *optarg; /* in getopt.h */ | 78 | static int lines_before; |
48 | static int lines_before = 0; | 79 | static int lines_after; |
49 | static int lines_after = 0; | 80 | static char **before_buf; |
50 | static char **before_buf = NULL; | 81 | static int last_line_printed; |
51 | static int last_line_printed = 0; | ||
52 | #endif /* CONFIG_FEATURE_GREP_CONTEXT */ | 82 | #endif /* CONFIG_FEATURE_GREP_CONTEXT */ |
53 | 83 | ||
54 | /* globals used internally */ | 84 | /* globals used internally */ |
55 | static llist_t *pattern_head = NULL; /* growable list of patterns to match */ | 85 | static llist_t *pattern_head; /* growable list of patterns to match */ |
56 | static int matched; /* keeps track of whether we ever matched */ | 86 | static char *cur_file; /* the current file we are reading */ |
57 | static char *cur_file = NULL; /* the current file we are reading */ | ||
58 | 87 | ||
59 | 88 | ||
60 | static void print_line(const char *line, int linenum, char decoration) | 89 | static void print_line(const char *line, int linenum, char decoration) |
@@ -74,11 +103,13 @@ static void print_line(const char *line, int linenum, char decoration) | |||
74 | puts(line); | 103 | puts(line); |
75 | } | 104 | } |
76 | 105 | ||
106 | extern void xregcomp(regex_t *preg, const char *regex, int cflags); | ||
107 | |||
77 | 108 | ||
78 | static void grep_file(FILE *file) | 109 | static int grep_file(FILE *file) |
79 | { | 110 | { |
80 | char *line = NULL; | 111 | char *line; |
81 | int ret; | 112 | invert_search_t ret; |
82 | int linenum = 0; | 113 | int linenum = 0; |
83 | int nmatches = 0; | 114 | int nmatches = 0; |
84 | #ifdef CONFIG_FEATURE_GREP_CONTEXT | 115 | #ifdef CONFIG_FEATURE_GREP_CONTEXT |
@@ -91,15 +122,10 @@ static void grep_file(FILE *file) | |||
91 | llist_t *pattern_ptr = pattern_head; | 122 | llist_t *pattern_ptr = pattern_head; |
92 | 123 | ||
93 | linenum++; | 124 | linenum++; |
94 | 125 | ret = 0; | |
95 | while (pattern_ptr) { | 126 | while (pattern_ptr) { |
96 | if (fgrep_flag) { | 127 | if (fgrep_flag) { |
97 | if (strstr(line, pattern_ptr->data)) { | 128 | ret = strstr(line, pattern_ptr->data) != NULL; |
98 | /* Match found */ | ||
99 | ret = 0; | ||
100 | } else { | ||
101 | ret = 1; | ||
102 | } | ||
103 | } else { | 129 | } else { |
104 | /* | 130 | /* |
105 | * test for a postitive-assertion match (regexec returns success (0) | 131 | * test for a postitive-assertion match (regexec returns success (0) |
@@ -109,15 +135,22 @@ static void grep_file(FILE *file) | |||
109 | */ | 135 | */ |
110 | regex_t regex; | 136 | regex_t regex; |
111 | xregcomp(®ex, pattern_ptr->data, reflags); | 137 | xregcomp(®ex, pattern_ptr->data, reflags); |
112 | ret = regexec(®ex, line, 0, NULL, 0); | 138 | ret = regexec(®ex, line, 0, NULL, 0) == 0; |
113 | regfree(®ex); | 139 | regfree(®ex); |
114 | } | 140 | } |
115 | if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) { | 141 | if (!ret) |
142 | break; | ||
143 | pattern_ptr = pattern_ptr->link; | ||
144 | } /* while (pattern_ptr) */ | ||
145 | |||
146 | if ((ret ^ invert_search)) { | ||
147 | |||
148 | if (print_files_with_matches || be_quiet) | ||
149 | free(line); | ||
116 | 150 | ||
117 | /* if we found a match but were told to be quiet, stop here and | 151 | /* if we found a match but were told to be quiet, stop here */ |
118 | * return success */ | ||
119 | if (be_quiet) | 152 | if (be_quiet) |
120 | exit(0); | 153 | return -1; |
121 | 154 | ||
122 | /* keep track of matches */ | 155 | /* keep track of matches */ |
123 | nmatches++; | 156 | nmatches++; |
@@ -177,8 +210,6 @@ static void grep_file(FILE *file) | |||
177 | print_n_lines_after--; | 210 | print_n_lines_after--; |
178 | } | 211 | } |
179 | #endif /* CONFIG_FEATURE_GREP_CONTEXT */ | 212 | #endif /* CONFIG_FEATURE_GREP_CONTEXT */ |
180 | pattern_ptr = pattern_ptr->link; | ||
181 | } /* for */ | ||
182 | free(line); | 213 | free(line); |
183 | } | 214 | } |
184 | 215 | ||
@@ -190,9 +221,6 @@ static void grep_file(FILE *file) | |||
190 | if (print_match_counts) { | 221 | if (print_match_counts) { |
191 | if (print_filename) | 222 | if (print_filename) |
192 | printf("%s:", cur_file); | 223 | printf("%s:", cur_file); |
193 | if (print_files_with_matches && nmatches > 0) | ||
194 | printf("1\n"); | ||
195 | else | ||
196 | printf("%d\n", nmatches); | 224 | printf("%d\n", nmatches); |
197 | } | 225 | } |
198 | 226 | ||
@@ -201,188 +229,163 @@ static void grep_file(FILE *file) | |||
201 | puts(cur_file); | 229 | puts(cur_file); |
202 | } | 230 | } |
203 | 231 | ||
204 | 232 | return nmatches; | |
205 | /* remember if we matched */ | ||
206 | if (nmatches != 0) | ||
207 | matched = 1; | ||
208 | } | ||
209 | |||
210 | #if 0 | ||
211 | static void add_pattern(char *restr) | ||
212 | { | ||
213 | // regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes)); | ||
214 | // xregcomp(®exes[nregexes-1], restr, reflags); | ||
215 | pattern_head = llist_add_to(pattern_head, restr); | ||
216 | } | 233 | } |
217 | #endif | ||
218 | 234 | ||
219 | static void load_regexes_from_file(const char *filename) | 235 | static void load_regexes_from_file(llist_t *fopt) |
220 | { | 236 | { |
221 | char *line; | 237 | char *line; |
222 | FILE *f = bb_xfopen(filename, "r"); | 238 | FILE *f; |
239 | |||
240 | while(fopt) { | ||
241 | llist_t *cur = fopt; | ||
242 | char *ffile = cur->data; | ||
243 | |||
244 | fopt = cur->link; | ||
245 | free(cur); | ||
246 | f = bb_xfopen(ffile, "r"); | ||
223 | while ((line = bb_get_chomped_line_from_file(f)) != NULL) { | 247 | while ((line = bb_get_chomped_line_from_file(f)) != NULL) { |
224 | pattern_head = llist_add_to(pattern_head, line); | 248 | pattern_head = llist_add_to(pattern_head, line); |
225 | } | 249 | } |
226 | } | ||
227 | |||
228 | |||
229 | #ifdef CONFIG_FEATURE_CLEAN_UP | ||
230 | static void destroy_regexes(void) | ||
231 | { | ||
232 | llist_t *pattern_head_ptr; | ||
233 | |||
234 | if (pattern_head == NULL) | ||
235 | return; | ||
236 | |||
237 | /* destroy all the elments in the pattern list */ | ||
238 | while (pattern_head) { | ||
239 | pattern_head_ptr = pattern_head; | ||
240 | pattern_head = pattern_head->link; | ||
241 | free(pattern_head_ptr->data); | ||
242 | free(pattern_head_ptr); | ||
243 | } | 250 | } |
244 | } | 251 | } |
245 | #endif | ||
246 | 252 | ||
247 | 253 | ||
248 | extern int grep_main(int argc, char **argv) | 254 | extern int grep_main(int argc, char **argv) |
249 | { | 255 | { |
250 | int opt; | 256 | FILE *file; |
251 | #if defined (CONFIG_FEATURE_GREP_CONTEXT) | 257 | int matched; |
252 | char *junk; | 258 | unsigned long opt; |
253 | #endif | 259 | llist_t *fopt; |
254 | |||
255 | #ifdef CONFIG_FEATURE_CLEAN_UP | ||
256 | /* destroy command strings on exit */ | ||
257 | atexit(destroy_regexes); | ||
258 | #endif | ||
259 | |||
260 | #ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS | ||
261 | if (strcmp(bb_get_last_path_component(argv[0]), "egrep") == 0) | ||
262 | reflags |= REG_EXTENDED; | ||
263 | #endif | ||
264 | 260 | ||
265 | /* do normal option parsing */ | 261 | /* do normal option parsing */ |
266 | while ((opt = getopt(argc, argv, "iHhlnqvsce:f:F" | ||
267 | #ifdef CONFIG_FEATURE_GREP_CONTEXT | 262 | #ifdef CONFIG_FEATURE_GREP_CONTEXT |
268 | "A:B:C:" | 263 | { |
269 | #endif | 264 | char *junk; |
270 | #ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS | 265 | char *slines_after; |
271 | "E" | 266 | char *slines_before; |
272 | #endif | 267 | char *Copt; |
273 | )) > 0) { | 268 | |
274 | switch (opt) { | 269 | bb_opt_complementaly = "H-h:e*:f*:C-AB"; |
275 | case 'i': | 270 | opt = bb_getopt_ulflags(argc, argv, |
276 | reflags |= REG_ICASE; | 271 | GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP, |
277 | break; | 272 | &pattern_head, &fopt, |
278 | case 'l': | 273 | &slines_after, &slines_before, &Copt); |
279 | print_files_with_matches++; | 274 | |
280 | break; | 275 | if(opt & GREP_OPT_C) { |
281 | case 'H': | 276 | /* C option unseted A and B options, but next -A or -B |
282 | print_filename++; | 277 | may be ovewrite own option */ |
283 | break; | 278 | if(!(opt & GREP_OPT_A)) /* not overwtited */ |
284 | case 'h': | 279 | slines_after = Copt; |
285 | print_filename--; | 280 | if(!(opt & GREP_OPT_B)) /* not overwtited */ |
286 | break; | 281 | slines_before = Copt; |
287 | case 'n': | 282 | opt |= GREP_OPT_A|GREP_OPT_B; /* set for parse now */ |
288 | print_line_num++; | 283 | } |
289 | break; | 284 | if(opt & GREP_OPT_A) { |
290 | case 'q': | 285 | lines_after = strtoul(slines_after, &junk, 10); |
291 | be_quiet++; | ||
292 | break; | ||
293 | case 'v': | ||
294 | invert_search++; | ||
295 | break; | ||
296 | case 's': | ||
297 | suppress_err_msgs++; | ||
298 | break; | ||
299 | case 'c': | ||
300 | print_match_counts++; | ||
301 | break; | ||
302 | case 'e': | ||
303 | pattern_head = llist_add_to(pattern_head, strdup(optarg)); | ||
304 | break; | ||
305 | #ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS | ||
306 | case 'E': | ||
307 | reflags |= REG_EXTENDED; | ||
308 | break; | ||
309 | #endif | ||
310 | case 'F': | ||
311 | fgrep_flag = 1; | ||
312 | break; | ||
313 | case 'f': | ||
314 | load_regexes_from_file(optarg); | ||
315 | break; | ||
316 | #ifdef CONFIG_FEATURE_GREP_CONTEXT | ||
317 | case 'A': | ||
318 | lines_after = strtoul(optarg, &junk, 10); | ||
319 | if(*junk != '\0') | ||
320 | bb_error_msg_and_die("invalid context length argument"); | ||
321 | break; | ||
322 | case 'B': | ||
323 | lines_before = strtoul(optarg, &junk, 10); | ||
324 | if(*junk != '\0') | 286 | if(*junk != '\0') |
325 | bb_error_msg_and_die("invalid context length argument"); | 287 | bb_error_msg_and_die("invalid context length argument"); |
326 | before_buf = (char **)xcalloc(lines_before, sizeof(char *)); | 288 | } |
327 | break; | 289 | if(opt & GREP_OPT_B) { |
328 | case 'C': | 290 | lines_before = strtoul(slines_before, &junk, 10); |
329 | lines_after = lines_before = strtoul(optarg, &junk, 10); | ||
330 | if(*junk != '\0') | 291 | if(*junk != '\0') |
331 | bb_error_msg_and_die("invalid context length argument"); | 292 | bb_error_msg_and_die("invalid context length argument"); |
332 | before_buf = (char **)xcalloc(lines_before, sizeof(char *)); | ||
333 | break; | ||
334 | #endif /* CONFIG_FEATURE_GREP_CONTEXT */ | ||
335 | default: | ||
336 | bb_show_usage(); | ||
337 | } | 293 | } |
294 | /* sanity checks after parse may be invalid numbers ;-) */ | ||
295 | if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l))) { | ||
296 | opt &= ~GREP_OPT_n; | ||
297 | lines_before = 0; | ||
298 | lines_after = 0; | ||
299 | } else if(lines_before > 0) | ||
300 | before_buf = (char **)xcalloc(lines_before, sizeof(char *)); | ||
338 | } | 301 | } |
302 | #else | ||
303 | /* with auto sanity checks */ | ||
304 | bb_opt_complementaly = "H-h:e*:f*:c-n:q-n:l-n"; | ||
305 | opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP, | ||
306 | &pattern_head, &fopt); | ||
307 | |||
308 | #endif | ||
309 | print_files_with_matches = opt & GREP_OPT_l; | ||
310 | print_line_num = opt & GREP_OPT_n; | ||
311 | be_quiet = opt & GREP_OPT_q; | ||
312 | invert_search = (opt & GREP_OPT_v) != 0; /* 0 | 1 */ | ||
313 | suppress_err_msgs = opt & GREP_OPT_s; | ||
314 | print_match_counts = opt & GREP_OPT_c; | ||
315 | fgrep_flag = opt & GREP_OPT_F; | ||
316 | if(opt & GREP_OPT_H) | ||
317 | print_filename++; | ||
318 | if(opt & GREP_OPT_h) | ||
319 | print_filename--; | ||
320 | if(opt & GREP_OPT_f) | ||
321 | load_regexes_from_file(fopt); | ||
322 | |||
323 | #ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS | ||
324 | if(bb_applet_name[0] == 'e' || (opt & GREP_OPT_E)) | ||
325 | reflags = REG_EXTENDED | REG_NOSUB; | ||
326 | else | ||
327 | #endif | ||
328 | reflags = REG_NOSUB; | ||
329 | |||
330 | if(opt & GREP_OPT_i) | ||
331 | reflags |= REG_ICASE; | ||
332 | |||
333 | argv += optind; | ||
334 | argc -= optind; | ||
339 | 335 | ||
340 | /* if we didn't get a pattern from a -e and no command file was specified, | 336 | /* if we didn't get a pattern from a -e and no command file was specified, |
341 | * argv[optind] should be the pattern. no pattern, no worky */ | 337 | * argv[optind] should be the pattern. no pattern, no worky */ |
342 | if (pattern_head == NULL) { | 338 | if (pattern_head == NULL) { |
343 | if (argv[optind] == NULL) | 339 | if (*argv == NULL) |
344 | bb_show_usage(); | 340 | bb_show_usage(); |
345 | else { | 341 | else { |
346 | pattern_head = llist_add_to(pattern_head, strdup(argv[optind])); | 342 | pattern_head = llist_add_to(pattern_head, *argv++); |
347 | optind++; | 343 | argc--; |
348 | } | 344 | } |
349 | } | 345 | } |
350 | 346 | ||
351 | /* sanity checks */ | ||
352 | if (print_match_counts || be_quiet || print_files_with_matches) { | ||
353 | print_line_num = 0; | ||
354 | #ifdef CONFIG_FEATURE_GREP_CONTEXT | ||
355 | lines_before = 0; | ||
356 | lines_after = 0; | ||
357 | #endif | ||
358 | } | ||
359 | |||
360 | /* argv[(optind)..(argc-1)] should be names of file to grep through. If | 347 | /* argv[(optind)..(argc-1)] should be names of file to grep through. If |
361 | * there is more than one file to grep, we will print the filenames */ | 348 | * there is more than one file to grep, we will print the filenames */ |
362 | if ((argc-1) - (optind) > 0) | 349 | if (argc > 1) { |
363 | print_filename++; | 350 | print_filename++; |
364 | 351 | ||
365 | /* If no files were specified, or '-' was specified, take input from | 352 | /* If no files were specified, or '-' was specified, take input from |
366 | * stdin. Otherwise, we grep through all the files specified. */ | 353 | * stdin. Otherwise, we grep through all the files specified. */ |
367 | if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { | 354 | } else if (argc == 0) { |
368 | grep_file(stdin); | 355 | argc++; |
369 | } | 356 | } |
370 | else { | 357 | matched = 0; |
371 | int i; | 358 | while (argc--) { |
372 | FILE *file; | 359 | cur_file = *argv++; |
373 | for (i = optind; i < argc; i++) { | 360 | if(!cur_file || (*cur_file == '-' && !cur_file[1])) { |
374 | cur_file = argv[i]; | 361 | cur_file = "-"; |
362 | file = stdin; | ||
363 | } else { | ||
375 | file = fopen(cur_file, "r"); | 364 | file = fopen(cur_file, "r"); |
365 | } | ||
376 | if (file == NULL) { | 366 | if (file == NULL) { |
377 | if (!suppress_err_msgs) | 367 | if (!suppress_err_msgs) |
378 | bb_perror_msg("%s", cur_file); | 368 | bb_perror_msg("%s", cur_file); |
369 | } else { | ||
370 | matched += grep_file(file); | ||
371 | if(matched < 0) { | ||
372 | /* we found a match but were told to be quiet, stop here and | ||
373 | * return success */ | ||
374 | break; | ||
379 | } | 375 | } |
380 | else { | ||
381 | grep_file(file); | ||
382 | fclose(file); | 376 | fclose(file); |
383 | } | 377 | } |
384 | } | 378 | } |
379 | |||
380 | #ifdef CONFIG_FEATURE_CLEAN_UP | ||
381 | /* destroy all the elments in the pattern list */ | ||
382 | while (pattern_head) { | ||
383 | llist_t *pattern_head_ptr = pattern_head; | ||
384 | |||
385 | pattern_head = pattern_head->link; | ||
386 | free(pattern_head_ptr); | ||
385 | } | 387 | } |
388 | #endif | ||
386 | 389 | ||
387 | return !matched; /* invert return value 0 = success, 1 = failed */ | 390 | return !matched; /* invert return value 0 = success, 1 = failed */ |
388 | } | 391 | } |
diff --git a/findutils/xargs.c b/findutils/xargs.c index d4bed57f0..2b18f8f28 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
@@ -66,24 +66,13 @@ int xargs_main(int argc, char **argv) | |||
66 | char *file_to_act_on; | 66 | char *file_to_act_on; |
67 | char **args; | 67 | char **args; |
68 | int i, a; | 68 | int i, a; |
69 | char flg_vi = 0; /* verbose |& interactive */ | 69 | char flg_vi; /* verbose |& interactive */ |
70 | char flg_no_empty = 0; | 70 | char flg_no_empty; |
71 | 71 | ||
72 | while ((a = getopt(argc, argv, "prt")) > 0) { | 72 | bb_opt_complementaly = "pt"; |
73 | switch(a) { | 73 | a = bb_getopt_ulflags(argc, argv, "tpr"); |
74 | case 'p': | 74 | flg_vi = a & 3; |
75 | flg_vi |= 3; | 75 | flg_no_empty = a & 4; |
76 | break; | ||
77 | case 't': | ||
78 | flg_vi |= 1; | ||
79 | break; | ||
80 | case 'r': | ||
81 | flg_no_empty = 1; | ||
82 | break; | ||
83 | default: | ||
84 | bb_show_usage(); | ||
85 | } | ||
86 | } | ||
87 | 76 | ||
88 | a = argc - optind; | 77 | a = argc - optind; |
89 | argv += optind; | 78 | argv += optind; |
@@ -110,7 +99,7 @@ int xargs_main(int argc, char **argv) | |||
110 | fputc(' ', stderr); | 99 | fputc(' ', stderr); |
111 | fputs(args[i], stderr); | 100 | fputs(args[i], stderr); |
112 | } | 101 | } |
113 | fprintf(stderr, "%s", ((flg_vi & 2) ? " ?..." : "\n")); | 102 | fputs(((flg_vi & 2) ? " ?..." : "\n"), stderr); |
114 | } | 103 | } |
115 | if((flg_vi & 2) == 0 || bb_ask_confirmation() != 0 ) { | 104 | if((flg_vi & 2) == 0 || bb_ask_confirmation() != 0 ) { |
116 | xargs_exec(args); | 105 | xargs_exec(args); |
diff --git a/include/libbb.h b/include/libbb.h index 2828456bc..0a9f2a271 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -158,6 +158,9 @@ extern FILE *bb_xfopen(const char *path, const char *mode); | |||
158 | //#warning rename? | 158 | //#warning rename? |
159 | extern int bb_fclose_nonstdin(FILE *f); | 159 | extern int bb_fclose_nonstdin(FILE *f); |
160 | extern void bb_fflush_stdout_and_exit(int retval) __attribute__ ((noreturn)); | 160 | extern void bb_fflush_stdout_and_exit(int retval) __attribute__ ((noreturn)); |
161 | |||
162 | extern const char *bb_opt_complementaly; | ||
163 | extern const struct option *bb_applet_long_options; | ||
161 | extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts); | 164 | extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts); |
162 | //#warning rename? | 165 | //#warning rename? |
163 | extern FILE *bb_wfopen_input(const char *filename); | 166 | extern FILE *bb_wfopen_input(const char *filename); |
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c index 91de392b6..9bf8c0559 100644 --- a/libbb/getopt_ulflags.c +++ b/libbb/getopt_ulflags.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * getopt_ulflags implementation for busybox | 3 | * universal getopt_ulflags implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> | 5 | * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru> |
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 |
@@ -22,20 +22,149 @@ | |||
22 | 22 | ||
23 | #include <getopt.h> | 23 | #include <getopt.h> |
24 | #include <string.h> | 24 | #include <string.h> |
25 | #include <assert.h> | ||
26 | #include <stdlib.h> | ||
25 | #include "libbb.h" | 27 | #include "libbb.h" |
26 | 28 | ||
27 | unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts) | 29 | /* |
30 | You can set bb_opt_complementaly as string with one or more | ||
31 | complementaly or incongruously options. | ||
32 | If sequential founded option haved from this string | ||
33 | then your incongruously pairs unsets and complementaly make add sets. | ||
34 | Format: | ||
35 | one char - option for check, | ||
36 | chars - complementaly option for add sets. | ||
37 | - chars - option triggered for unsets. | ||
38 | ~ chars - option incongruously. | ||
39 | * - option list, called add_to_list(*ptr_from_usaged, optarg) | ||
40 | : - separator. | ||
41 | Example: du applet can have options "-s" and "-d size" | ||
42 | If getopt found -s then -d option flag unset or if found -d then -s unset. | ||
43 | For this result you must set bb_opt_complementaly = "s-d:d-s". | ||
44 | Result have last option flag only from called arguments. | ||
45 | Warning! You can check returned flag, pointer to "d:" argument seted | ||
46 | to own optarg always. | ||
47 | Example two: cut applet must only one type of list may be specified, | ||
48 | and -b, -c and -f incongruously option, overwited option is error also. | ||
49 | You must set bb_opt_complementaly = "b~bcf:c~bcf:f~bcf". | ||
50 | If called have more one specified, return value have error flag - | ||
51 | high bite set (0x80000000UL). | ||
52 | Example three: grep applet can have one or more "-e pattern" arguments. | ||
53 | You should use bb_getopt_ulflags() as | ||
54 | llist_t *paterns; | ||
55 | bb_opt_complementaly = "e*"; | ||
56 | bb_getopt_ulflags (argc, argv, "e:", &paterns); | ||
57 | */ | ||
58 | |||
59 | const char *bb_opt_complementaly; | ||
60 | |||
61 | typedef struct | ||
62 | { | ||
63 | char opt; | ||
64 | char list_flg; | ||
65 | unsigned long switch_on; | ||
66 | unsigned long switch_off; | ||
67 | unsigned long incongruously; | ||
68 | void **optarg; /* char **optarg or llist_t **optarg */ | ||
69 | } t_complementaly; | ||
70 | |||
71 | /* You can set bb_applet_long_options for parse called long options */ | ||
72 | |||
73 | static const struct option bb_default_long_options[] = { | ||
74 | /* { "help", 0, NULL, '?' }, */ | ||
75 | { 0, 0, 0, 0 } | ||
76 | }; | ||
77 | |||
78 | const struct option *bb_applet_long_options = bb_default_long_options; | ||
79 | |||
80 | |||
81 | unsigned long | ||
82 | bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | ||
28 | { | 83 | { |
29 | unsigned long flags = 0; | 84 | unsigned long flags = 0; |
85 | int c = 0; | ||
30 | const char *s; | 86 | const char *s; |
31 | int c; | 87 | t_complementaly *complementaly; |
88 | t_complementaly *on_off; | ||
89 | va_list p; | ||
90 | |||
91 | va_start (p, applet_opts); | ||
32 | 92 | ||
33 | while ((c = getopt(argc, argv, applet_opts)) > 0) { | 93 | for (s = applet_opts; *s; s++) { |
34 | if (!(s = strchr(applet_opts, c))) { | 94 | c++; |
35 | bb_show_usage(); | 95 | while (s[1] == ':') { |
96 | /* check GNU extension "o::" - optional arg */ | ||
97 | s++; | ||
98 | } | ||
99 | } | ||
100 | complementaly = xcalloc (c + 1, sizeof (t_complementaly)); | ||
101 | c = 0; | ||
102 | for (s = applet_opts; *s; s++) { | ||
103 | complementaly->opt = *s; | ||
104 | complementaly->switch_on |= (1 << c); | ||
105 | c++; | ||
106 | if (s[1] == ':') { | ||
107 | complementaly->optarg = va_arg (p, void **); | ||
108 | do | ||
109 | s++; | ||
110 | while (s[1] == ':'); | ||
36 | } | 111 | } |
37 | flags |= (1 << (s-applet_opts)); | 112 | complementaly++; |
38 | } | 113 | } |
114 | complementaly->opt = 0; | ||
115 | complementaly -= c; | ||
116 | c = 0; | ||
117 | for (s = bb_opt_complementaly; s && *s; s++) { | ||
118 | t_complementaly *pair; | ||
119 | |||
120 | if (*s == ':') { | ||
121 | c = 0; | ||
122 | continue; | ||
123 | } | ||
124 | if (c) | ||
125 | continue; | ||
126 | for (on_off = complementaly; on_off->opt; on_off++) | ||
127 | if (on_off->opt == *s) | ||
128 | break; | ||
129 | pair = on_off; | ||
130 | for(s++; *s && *s != ':'; s++) { | ||
131 | if (*s == '-' || *s == '~') { | ||
132 | c = *s; | ||
133 | } else if(*s == '*') { | ||
134 | pair->list_flg++; | ||
135 | } else { | ||
136 | unsigned long *pair_switch = &(pair->switch_on); | ||
39 | 137 | ||
138 | if(c) | ||
139 | pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); | ||
140 | for (on_off = complementaly; on_off->opt; on_off++) | ||
141 | if (on_off->opt == *s) { | ||
142 | *pair_switch |= on_off->switch_on; | ||
143 | break; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | s--; | ||
148 | } | ||
149 | |||
150 | while ((c = getopt_long (argc, argv, applet_opts, | ||
151 | bb_applet_long_options, NULL)) > 0) { | ||
152 | |||
153 | for (on_off = complementaly; on_off->opt != c; on_off++) { | ||
154 | if(!on_off->opt) | ||
155 | bb_show_usage (); | ||
156 | } | ||
157 | if(flags & on_off->incongruously) | ||
158 | flags |= 0x80000000UL; | ||
159 | flags &= ~on_off->switch_off; | ||
160 | flags |= on_off->switch_on; | ||
161 | if(on_off->list_flg) { | ||
162 | *(llist_t **)(on_off->optarg) = | ||
163 | llist_add_to(*(llist_t **)(on_off->optarg), optarg); | ||
164 | } else if (on_off->optarg) { | ||
165 | *(char **)(on_off->optarg) = optarg; | ||
166 | } | ||
167 | } | ||
168 | free(complementaly); | ||
40 | return flags; | 169 | return flags; |
41 | } | 170 | } |
diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c index 36484e6ae..4393a5188 100644 --- a/libbb/inode_hash.c +++ b/libbb/inode_hash.c | |||
@@ -83,6 +83,7 @@ void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) | |||
83 | ino_dev_hashtable[i] = bucket; | 83 | ino_dev_hashtable[i] = bucket; |
84 | } | 84 | } |
85 | 85 | ||
86 | #ifdef CONFIG_FEATURE_CLEAN_UP | ||
86 | /* Clear statbuf hash table */ | 87 | /* Clear statbuf hash table */ |
87 | void reset_ino_dev_hashtable(void) | 88 | void reset_ino_dev_hashtable(void) |
88 | { | 89 | { |
@@ -97,6 +98,7 @@ void reset_ino_dev_hashtable(void) | |||
97 | } | 98 | } |
98 | } | 99 | } |
99 | } | 100 | } |
101 | #endif | ||
100 | 102 | ||
101 | 103 | ||
102 | /* END CODE */ | 104 | /* END CODE */ |
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 2e8188dec..af1cd7a83 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c | |||
@@ -122,6 +122,17 @@ static int addgroup(const char *filename, char *group, gid_t gid, const char *us | |||
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
124 | 124 | ||
125 | #ifndef CONFIG_ADDUSER | ||
126 | static inline void if_i_am_not_root(void) | ||
127 | { | ||
128 | if (geteuid()) { | ||
129 | bb_error_msg_and_die( "Only root may add a user or group to the system."); | ||
130 | } | ||
131 | } | ||
132 | #else | ||
133 | extern void if_i_am_not_root(void); | ||
134 | #endif | ||
135 | |||
125 | /* | 136 | /* |
126 | * addgroup will take a login_name as its first parameter. | 137 | * addgroup will take a login_name as its first parameter. |
127 | * | 138 | * |
@@ -131,21 +142,13 @@ static int addgroup(const char *filename, char *group, gid_t gid, const char *us | |||
131 | * ________________________________________________________________________ */ | 142 | * ________________________________________________________________________ */ |
132 | int addgroup_main(int argc, char **argv) | 143 | int addgroup_main(int argc, char **argv) |
133 | { | 144 | { |
134 | int opt; | ||
135 | char *group; | 145 | char *group; |
136 | char *user; | 146 | char *user; |
137 | gid_t gid = 0; | 147 | gid_t gid = 0; |
138 | 148 | ||
139 | /* get remaining args */ | 149 | /* get remaining args */ |
140 | while ((opt = getopt (argc, argv, "g:")) != -1) { | 150 | if(bb_getopt_ulflags(argc, argv, "g:", &group)) { |
141 | switch (opt) { | 151 | gid = strtol(group, NULL, 10); |
142 | case 'g': | ||
143 | gid = strtol(optarg, NULL, 10); | ||
144 | break; | ||
145 | default: | ||
146 | bb_show_usage(); | ||
147 | break; | ||
148 | } | ||
149 | } | 152 | } |
150 | 153 | ||
151 | if (optind < argc) { | 154 | if (optind < argc) { |
@@ -161,14 +164,8 @@ int addgroup_main(int argc, char **argv) | |||
161 | } else { | 164 | } else { |
162 | user = ""; | 165 | user = ""; |
163 | } | 166 | } |
164 | 167 | if_i_am_not_root(); | |
165 | if (geteuid() != 0) { | ||
166 | bb_error_msg_and_die | ||
167 | ("Only root may add a group to the system."); | ||
168 | } | ||
169 | 168 | ||
170 | /* werk */ | 169 | /* werk */ |
171 | return addgroup(bb_path_group_file, group, gid, user); | 170 | return addgroup(bb_path_group_file, group, gid, user); |
172 | } | 171 | } |
173 | |||
174 | /* $Id: addgroup.c,v 1.10 2003/03/19 09:12:20 mjn3 Exp $ */ | ||
diff --git a/loginutils/adduser.c b/loginutils/adduser.c index cfaf860e0..6784d32cc 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c | |||
@@ -208,9 +208,15 @@ static int adduser(const char *filename, struct passwd *p) | |||
208 | 208 | ||
209 | 209 | ||
210 | /* return current uid (root is always uid == 0, right?) */ | 210 | /* return current uid (root is always uid == 0, right?) */ |
211 | static inline uid_t i_am_not_root(void) | 211 | #ifndef CONFIG_ADDGROUP |
212 | static inline void if_i_am_not_root(void) | ||
213 | #else | ||
214 | void if_i_am_not_root(void) | ||
215 | #endif | ||
212 | { | 216 | { |
213 | return geteuid(); | 217 | if (geteuid()) { |
218 | bb_error_msg_and_die( "Only root may add a user or group to the system."); | ||
219 | } | ||
214 | } | 220 | } |
215 | 221 | ||
216 | /* | 222 | /* |
@@ -224,11 +230,10 @@ static inline uid_t i_am_not_root(void) | |||
224 | * ________________________________________________________________________ */ | 230 | * ________________________________________________________________________ */ |
225 | int adduser_main(int argc, char **argv) | 231 | int adduser_main(int argc, char **argv) |
226 | { | 232 | { |
227 | int opt; | ||
228 | const char *login; | 233 | const char *login; |
229 | const char *gecos; | 234 | const char *gecos = default_gecos; |
230 | const char *home = NULL; | 235 | const char *home = NULL; |
231 | const char *shell; | 236 | const char *shell = default_shell; |
232 | 237 | ||
233 | struct passwd pw; | 238 | struct passwd pw; |
234 | 239 | ||
@@ -236,30 +241,11 @@ int adduser_main(int argc, char **argv) | |||
236 | if (argc < 2) { | 241 | if (argc < 2) { |
237 | bb_show_usage(); | 242 | bb_show_usage(); |
238 | } | 243 | } |
239 | gecos = default_gecos; | ||
240 | shell = default_shell; | ||
241 | |||
242 | /* get args */ | 244 | /* get args */ |
243 | while ((opt = getopt (argc, argv, "h:g:s:")) != -1) | 245 | bb_getopt_ulflags(argc, argv, "h:g:s:", &home, &gecos, &shell); |
244 | switch (opt) { | ||
245 | case 'h': | ||
246 | home = optarg; | ||
247 | break; | ||
248 | case 'g': | ||
249 | gecos = optarg; | ||
250 | break; | ||
251 | case 's': | ||
252 | shell = optarg; | ||
253 | break; | ||
254 | default: | ||
255 | bb_show_usage(); | ||
256 | break; | ||
257 | } | ||
258 | 246 | ||
259 | /* got root? */ | 247 | /* got root? */ |
260 | if (i_am_not_root()) { | 248 | if_i_am_not_root(); |
261 | bb_error_msg_and_die( "Only root may add a user or group to the system."); | ||
262 | } | ||
263 | 249 | ||
264 | /* get login */ | 250 | /* get login */ |
265 | if (optind >= argc) { | 251 | if (optind >= argc) { |
@@ -288,5 +274,3 @@ int adduser_main(int argc, char **argv) | |||
288 | /* grand finale */ | 274 | /* grand finale */ |
289 | return adduser(bb_path_passwd_file, &pw); | 275 | return adduser(bb_path_passwd_file, &pw); |
290 | } | 276 | } |
291 | |||
292 | /* $Id: adduser.c,v 1.5 2003/03/19 09:12:20 mjn3 Exp $ */ | ||
diff --git a/miscutils/crond.c b/miscutils/crond.c index cbb4ffc58..9d9ecc290 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -117,46 +117,40 @@ static CronFile *FileBase; | |||
117 | int | 117 | int |
118 | crond_main(int ac, char **av) | 118 | crond_main(int ac, char **av) |
119 | { | 119 | { |
120 | int i; | 120 | unsigned long opt; |
121 | char *lopt, *Lopt, *copt; | ||
122 | #ifdef FEATURE_DEBUG_OPT | ||
123 | char *dopt; | ||
124 | bb_opt_complementaly = "f-b:b-f:S-L:L-S:d-l"; | ||
125 | #else | ||
126 | bb_opt_complementaly = "f-b:b-f:S-L:L-S"; | ||
127 | #endif | ||
121 | 128 | ||
122 | opterr = 0; /* disable getopt 'errors' message.*/ | 129 | opterr = 0; /* disable getopt 'errors' message.*/ |
123 | 130 | opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:" | |
124 | while ((i = getopt(ac,av, | ||
125 | #ifdef FEATURE_DEBUG_OPT | 131 | #ifdef FEATURE_DEBUG_OPT |
126 | "d:" | 132 | "d:" |
127 | #endif | 133 | #endif |
128 | "l:L:fbSc:")) != EOF){ | 134 | , &lopt, &Lopt, &copt |
129 | |||
130 | switch (i){ | ||
131 | case 'l': | ||
132 | LogLevel = atoi(optarg); | ||
133 | break; | ||
134 | #ifdef FEATURE_DEBUG_OPT | 135 | #ifdef FEATURE_DEBUG_OPT |
135 | case 'd': | 136 | , &dopt |
136 | DebugOpt = atoi(optarg); | ||
137 | LogLevel = 0; | ||
138 | break; | ||
139 | #endif | 137 | #endif |
140 | case 'f': | 138 | ); |
141 | ForegroundOpt = 1; | 139 | if(opt & 1) |
142 | break; | 140 | LogLevel = atoi(lopt); |
143 | case 'b': | 141 | LoggerOpt = opt & 2; |
144 | ForegroundOpt = 0; | 142 | if(LoggerOpt) |
145 | break; | 143 | if (*Lopt != 0) LogFile = Lopt; |
146 | case 'S': /* select logging to syslog */ | 144 | ForegroundOpt = opt & 4; |
147 | LoggerOpt = 0; | 145 | if(opt & 32) { |
148 | break; | 146 | if (*copt != 0) CDir = copt; |
149 | case 'L': /* select internal file logger */ | ||
150 | LoggerOpt = 1; | ||
151 | if (*optarg != 0) LogFile = optarg; | ||
152 | break; | ||
153 | case 'c': | ||
154 | if (*optarg != 0) CDir = optarg; | ||
155 | break; | ||
156 | default: /* parse error */ | ||
157 | bb_show_usage(); | ||
158 | } | 147 | } |
148 | #ifdef FEATURE_DEBUG_OPT | ||
149 | if(opt & 64) { | ||
150 | DebugOpt = atoi(dopt); | ||
151 | LogLevel = 0; | ||
159 | } | 152 | } |
153 | #endif | ||
160 | 154 | ||
161 | /* | 155 | /* |
162 | * change directory | 156 | * change directory |
@@ -165,6 +159,9 @@ crond_main(int ac, char **av) | |||
165 | if (chdir(CDir) != 0) | 159 | if (chdir(CDir) != 0) |
166 | bb_perror_msg_and_die("chdir"); | 160 | bb_perror_msg_and_die("chdir"); |
167 | 161 | ||
162 | signal(SIGHUP,SIG_IGN); /* hmm.. but, if kill -HUP original | ||
163 | * version - his died. ;( | ||
164 | */ | ||
168 | /* | 165 | /* |
169 | * close stdin and stdout, stderr. | 166 | * close stdin and stdout, stderr. |
170 | * close unused descriptors - don't need. | 167 | * close unused descriptors - don't need. |
@@ -177,9 +174,6 @@ crond_main(int ac, char **av) | |||
177 | } | 174 | } |
178 | 175 | ||
179 | (void)startlogger(); /* need if syslog mode selected */ | 176 | (void)startlogger(); /* need if syslog mode selected */ |
180 | signal(SIGHUP,SIG_IGN); /* hmm.. but, if kill -HUP original | ||
181 | * version - his died. ;( | ||
182 | */ | ||
183 | 177 | ||
184 | /* | 178 | /* |
185 | * main loop - synchronize to 1 second after the minute, minimum sleep | 179 | * main loop - synchronize to 1 second after the minute, minimum sleep |