aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2003-06-20 09:01:58 +0000
committerandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2003-06-20 09:01:58 +0000
commit3b4406c151cabd47b24d309dbbd9c5b19e9d6b33 (patch)
treef67de9320202043aca8ded20fb80d668c3b0c2d8
parent90e9e2c71f1e3ed8031334106594ef7fa9e0173b (diff)
downloadbusybox-w32-3b4406c151cabd47b24d309dbbd9c5b19e9d6b33.tar.gz
busybox-w32-3b4406c151cabd47b24d309dbbd9c5b19e9d6b33.tar.bz2
busybox-w32-3b4406c151cabd47b24d309dbbd9c5b19e9d6b33.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 git-svn-id: svn://busybox.net/trunk/busybox@6939 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--coreutils/cut.c68
-rw-r--r--coreutils/date.c65
-rw-r--r--coreutils/dd.c4
-rw-r--r--coreutils/df.c32
-rw-r--r--coreutils/du.c93
-rw-r--r--coreutils/env.c17
-rw-r--r--coreutils/mkdir.c26
-rw-r--r--coreutils/mv.c36
-rw-r--r--coreutils/rm.c22
-rw-r--r--coreutils/stty.c71
-rw-r--r--coreutils/test.c6
-rw-r--r--findutils/grep.c355
-rw-r--r--findutils/xargs.c25
-rw-r--r--include/libbb.h3
-rw-r--r--libbb/getopt_ulflags.c145
-rw-r--r--libbb/inode_hash.c2
-rw-r--r--loginutils/addgroup.c31
-rw-r--r--loginutils/adduser.c40
-rw-r--r--miscutils/crond.c62
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 */
32extern int optind;
33extern char *optarg;
34
35
36/* option vars */ 32/* option vars */
37static char part = 0; /* (b)yte, (c)har, (f)ields */ 33static const char optstring[] = "b:c:f:d:sn";
38static 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
39static char part; /* (b)yte, (c)har, (f)ields */
40static unsigned int supress_non_delimited_lines;
39static char delim = '\t'; /* delimiter, default is tab */ 41static char delim = '\t'; /* delimiter, default is tab */
40 42
41struct cut_list { 43struct 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
290extern int cut_main(int argc, char **argv) 292extern 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
37static const struct option mkdir_long_options[] = {
38 { "mode", 1, NULL, 'm' },
39 { "parents", 0, NULL, 'p' },
40 { 0, 0, 0, 0 }
41};
42
36extern int mkdir_main (int argc, char **argv) 43extern 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
37static const char *fmt = "cannot overwrite %sdirectory with %sdirectory"; 38static const struct option mv_long_options[] = {
39 { "interactive", 0, NULL, 'i' },
40 { "force", 0, NULL, 'f' },
41 { 0, 0, 0, 0 }
42};
43
44static const char mv_getopt_short_option[] = "fi";
45#define OPT_FILEUTILS_FORCE 1
46#define OPT_FILEUTILS_INTERACTIVE 2
47
48static const char fmt[] = "cannot overwrite %sdirectory with %sdirectory";
38 49
39extern int mv_main(int argc, char **argv) 50extern 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);
415static speed_t string_to_baud(const char *arg); 415static speed_t string_to_baud(const char *arg);
416static 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);
417static void display_all(struct termios *mode, int fd, 417static void display_all(struct termios *mode, int fd);
418 const char *device_name); 418static void display_changed(struct termios *mode, int fd);
419static void display_changed(struct termios *mode, int fd, 419static void display_recoverable(struct termios *mode, int fd);
420 const char *device_name);
421static void display_recoverable(struct termios *mode, int fd,
422 const char *device_name);
423static void display_speed(struct termios *mode, int fancy); 420static void display_speed(struct termios *mode, int fancy);
424static void display_window_size(int fancy, int fd, 421static void display_window_size(int fancy, int fd);
425 const char *device_name);
426static void sane_mode(struct termios *mode); 422static void sane_mode(struct termios *mode);
427static void set_control_char(const struct control_info *info, 423static void set_control_char(const struct control_info *info,
428 const char *arg, struct termios *mode); 424 const char *arg, struct termios *mode);
429static void set_speed(enum speed_setting type, 425static void set_speed(enum speed_setting type,
430 const char *arg, struct termios *mode); 426 const char *arg, struct termios *mode);
431static void set_window_size(int rows, int cols, int fd, 427static void set_window_size(int rows, int cols, int fd);
432 const char *device_name); 428
429static const char *device_name;
430
431static __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. */
435static int max_col; 438static 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
950static void 949static void
951set_window_size(int rows, int cols, int fd, const char *device_name) 950set_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
992static void display_window_size(int fancy, int fd, const char *device_name) 991static 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
1050static void display_changed(struct termios *mode, int fd, const char *device_name) 1049static 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
1124static void 1123static void
1125display_all(struct termios *mode, int fd, const char *device_name) 1124display_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
1205static void display_recoverable(struct termios *mode, int fd, const char *device_name) 1204static 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
32extern int optind; /* in unistd.h */
33extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */
34
35/* options */ 36/* options */
36static int reflags = REG_NOSUB; 37#define GREP_OPTS "lnqvscFiHhe:f:"
37static int print_filename = 0; 38#define GREP_OPT_l 1
38static int print_line_num = 0; 39static char print_files_with_matches;
39static int print_match_counts = 0; 40#define GREP_OPT_n 2
40static int be_quiet = 0; 41static char print_line_num;
41static int invert_search = 0; 42#define GREP_OPT_q 4
42static int suppress_err_msgs = 0; 43static char be_quiet;
43static int print_files_with_matches = 0; 44#define GREP_OPT_v 8
44static int fgrep_flag = 0; 45typedef char invert_search_t;
46static invert_search_t invert_search;
47#define GREP_OPT_s 16
48static char suppress_err_msgs;
49#define GREP_OPT_c 32
50static char print_match_counts;
51#define GREP_OPT_F 64
52static 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
74static int reflags;
75static int print_filename;
45 76
46#ifdef CONFIG_FEATURE_GREP_CONTEXT 77#ifdef CONFIG_FEATURE_GREP_CONTEXT
47extern char *optarg; /* in getopt.h */ 78static int lines_before;
48static int lines_before = 0; 79static int lines_after;
49static int lines_after = 0; 80static char **before_buf;
50static char **before_buf = NULL; 81static int last_line_printed;
51static 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 */
55static llist_t *pattern_head = NULL; /* growable list of patterns to match */ 85static llist_t *pattern_head; /* growable list of patterns to match */
56static int matched; /* keeps track of whether we ever matched */ 86static char *cur_file; /* the current file we are reading */
57static char *cur_file = NULL; /* the current file we are reading */
58 87
59 88
60static void print_line(const char *line, int linenum, char decoration) 89static 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
106extern void xregcomp(regex_t *preg, const char *regex, int cflags);
107
77 108
78static void grep_file(FILE *file) 109static 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(&regex, pattern_ptr->data, reflags); 137 xregcomp(&regex, pattern_ptr->data, reflags);
112 ret = regexec(&regex, line, 0, NULL, 0); 138 ret = regexec(&regex, line, 0, NULL, 0) == 0;
113 regfree(&regex); 139 regfree(&regex);
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
211static void add_pattern(char *restr)
212{
213// regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes));
214// xregcomp(&regexes[nregexes-1], restr, reflags);
215 pattern_head = llist_add_to(pattern_head, restr);
216} 233}
217#endif
218 234
219static void load_regexes_from_file(const char *filename) 235static 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
230static 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
248extern int grep_main(int argc, char **argv) 254extern 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?
159extern int bb_fclose_nonstdin(FILE *f); 159extern int bb_fclose_nonstdin(FILE *f);
160extern void bb_fflush_stdout_and_exit(int retval) __attribute__ ((noreturn)); 160extern void bb_fflush_stdout_and_exit(int retval) __attribute__ ((noreturn));
161
162extern const char *bb_opt_complementaly;
163extern const struct option *bb_applet_long_options;
161extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts); 164extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts);
162//#warning rename? 165//#warning rename?
163extern FILE *bb_wfopen_input(const char *filename); 166extern 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
27unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts) 29/*
30You can set bb_opt_complementaly as string with one or more
31complementaly or incongruously options.
32If sequential founded option haved from this string
33then your incongruously pairs unsets and complementaly make add sets.
34Format:
35one char - option for check,
36chars - 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.
41Example: du applet can have options "-s" and "-d size"
42If getopt found -s then -d option flag unset or if found -d then -s unset.
43For this result you must set bb_opt_complementaly = "s-d:d-s".
44Result have last option flag only from called arguments.
45Warning! You can check returned flag, pointer to "d:" argument seted
46to own optarg always.
47Example two: cut applet must only one type of list may be specified,
48and -b, -c and -f incongruously option, overwited option is error also.
49You must set bb_opt_complementaly = "b~bcf:c~bcf:f~bcf".
50If called have more one specified, return value have error flag -
51high bite set (0x80000000UL).
52Example three: grep applet can have one or more "-e pattern" arguments.
53You should use bb_getopt_ulflags() as
54llist_t *paterns;
55bb_opt_complementaly = "e*";
56bb_getopt_ulflags (argc, argv, "e:", &paterns);
57*/
58
59const char *bb_opt_complementaly;
60
61typedef 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
73static const struct option bb_default_long_options[] = {
74 /* { "help", 0, NULL, '?' }, */
75 { 0, 0, 0, 0 }
76};
77
78const struct option *bb_applet_long_options = bb_default_long_options;
79
80
81unsigned long
82bb_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 */
87void reset_ino_dev_hashtable(void) 88void 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
126static 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
133extern 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 * ________________________________________________________________________ */
132int addgroup_main(int argc, char **argv) 143int 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?) */
211static inline uid_t i_am_not_root(void) 211#ifndef CONFIG_ADDGROUP
212static inline void if_i_am_not_root(void)
213#else
214void 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 * ________________________________________________________________________ */
225int adduser_main(int argc, char **argv) 231int 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;
117int 117int
118crond_main(int ac, char **av) 118crond_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