From 8876fb2f59a0b515b3121d5894933eef88ce566a Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Fri, 20 Jun 2003 09:01:58 +0000 Subject: [PATCH] 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 --- coreutils/cut.c | 68 ++++---- coreutils/date.c | 65 ++++---- coreutils/dd.c | 4 +- coreutils/df.c | 32 ++-- coreutils/du.c | 93 +++++------ coreutils/env.c | 17 +- coreutils/mkdir.c | 26 +-- coreutils/mv.c | 36 +++-- coreutils/rm.c | 22 +-- coreutils/stty.c | 71 ++++----- coreutils/test.c | 6 +- findutils/grep.c | 355 +++++++++++++++++++++-------------------- findutils/xargs.c | 25 +-- include/libbb.h | 3 + libbb/getopt_ulflags.c | 145 ++++++++++++++++- libbb/inode_hash.c | 2 + loginutils/addgroup.c | 31 ++-- loginutils/adduser.c | 40 ++--- 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 @@ #include #include -#include /* getopt */ +#include +#include #include #include #include "busybox.h" -/* globals from other files */ -extern int optind; -extern char *optarg; - - /* option vars */ -static char part = 0; /* (b)yte, (c)har, (f)ields */ -static unsigned int supress_non_delimited_lines = 0; +static const char optstring[] = "b:c:f:d:sn"; +#define OPT_BYTE_FLGS 1 +#define OPT_CHAR_FLGS 2 +#define OPT_FIELDS_FLGS 4 +#define OPT_DELIM_FLGS 8 +#define OPT_SUPRESS_FLGS 16 +static char part; /* (b)yte, (c)har, (f)ields */ +static unsigned int supress_non_delimited_lines; static char delim = '\t'; /* delimiter, default is tab */ struct cut_list { @@ -270,11 +272,11 @@ static void cut_file(FILE *file) while ((line = bb_get_chomped_line_from_file(file)) != NULL) { /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ - if (part == 'c' || part == 'b') + if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS))) cut_line_by_chars(line); /* cut based on fields */ - else if (part == 'f') { + else { if (delim == '\n') cut_file_by_lines(line, linenum); else @@ -289,46 +291,32 @@ static void cut_file(FILE *file) extern int cut_main(int argc, char **argv) { - int opt; - - while ((opt = getopt(argc, argv, "b:c:d:f:ns")) > 0) { - switch (opt) { - case 'b': - case 'c': - case 'f': - /* make sure they didn't ask for two types of lists */ - if (part != 0) { + unsigned long opt; + char *sopt, *sdopt; + + bb_opt_complementaly = "b~bcf:c~bcf:f~bcf"; + opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt); + part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); + if(part == 0) + bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); + if(opt & 0x80000000UL) bb_error_msg_and_die("only one type of list may be specified"); - } - part = (char)opt; - parse_lists(optarg); - break; - case 'd': - if (strlen(optarg) > 1) { + parse_lists(sopt); + if((opt & (OPT_DELIM_FLGS))) { + if (strlen(sdopt) > 1) { bb_error_msg_and_die("the delimiter must be a single character"); } - delim = optarg[0]; - break; - case 'n': - /* no-op */ - break; - case 's': - supress_non_delimited_lines++; - break; - } - } - - if (part == 0) { - bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); + delim = sdopt[0]; } + supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS; /* non-field (char or byte) cutting has some special handling */ - if (part != 'f') { + if (part != OPT_FIELDS_FLGS) { if (supress_non_delimited_lines) { bb_error_msg_and_die("suppressing non-delimited lines makes sense" " only when operating on fields"); } - if (delim != '\t' && part != 'f') { + if (delim != '\t') { bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); } } 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) char *date_str = NULL; char *date_fmt = NULL; char *t_buff; - int c; - int set_time = 0; - int rfc822 = 0; - int utc = 0; + int set_time; + int rfc822; + int utc; int use_arg = 0; time_t tm; + unsigned long opt; struct tm tm_time; #ifdef CONFIG_FEATURE_DATE_ISOFMT int ifmt = 0; + char *isofmt_arg; # define GETOPT_ISOFMT "I::" #else # define GETOPT_ISOFMT #endif - - /* Interpret command line args */ - while ((c = getopt(argc, argv, "Rs:ud:" GETOPT_ISOFMT)) != EOF) { - switch (c) { - case 'R': - rfc822 = 1; - break; - case 's': - set_time = 1; - if ((date_str != NULL) || ((date_str = optarg) == NULL)) { - bb_show_usage(); - } - break; - case 'u': - utc = 1; + bb_opt_complementaly = "d~ds:s~ds"; + opt = bb_getopt_ulflags(argc, argv, "Rs:ud:" GETOPT_ISOFMT, + &date_str, &date_str +#ifdef CONFIG_FEATURE_DATE_ISOFMT + , &isofmt_arg +#endif + ); + rfc822 = opt & 1; + set_time = opt & 2; + utc = opt & 4; + if(utc) { if (putenv("TZ=UTC0") != 0) bb_error_msg_and_die(bb_msg_memory_exhausted); - break; - case 'd': - use_arg = 1; - if ((date_str != NULL) || ((date_str = optarg) == NULL)) + } + use_arg = opt & 8; + if(opt & 0x80000000UL) bb_show_usage(); - break; #ifdef CONFIG_FEATURE_DATE_ISOFMT - case 'I': - if (!optarg) + if(opt & 16) { + if (!isofmt_arg) ifmt = 1; else { - int ifmt_len = bb_strlen(optarg); + int ifmt_len = bb_strlen(isofmt_arg); if ((ifmt_len <= 4) - && (strncmp(optarg, "date", ifmt_len) == 0)) { + && (strncmp(isofmt_arg, "date", ifmt_len) == 0)) { ifmt = 1; } else if ((ifmt_len <= 5) - && (strncmp(optarg, "hours", ifmt_len) == 0)) { + && (strncmp(isofmt_arg, "hours", ifmt_len) == 0)) { ifmt = 2; } else if ((ifmt_len <= 7) - && (strncmp(optarg, "minutes", ifmt_len) == 0)) { + && (strncmp(isofmt_arg, "minutes", ifmt_len) == 0)) { ifmt = 3; } else if ((ifmt_len <= 7) - && (strncmp(optarg, "seconds", ifmt_len) == 0)) { + && (strncmp(isofmt_arg, "seconds", ifmt_len) == 0)) { ifmt = 4; } } - if (ifmt) { - break; /* else bb_show_usage(); */ - } -#endif - default: + if (!ifmt) { bb_show_usage(); } } - +#endif if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { 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) buf = xmalloc(bs); if (infile != NULL) { - if ((ifd = open(infile, O_RDONLY)) < 0) { - bb_perror_msg_and_die("%s", infile); - } + ifd = bb_xopen(infile, O_RDONLY); } else { ifd = STDIN_FILENO; 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) unsigned long df_disp_hr = KILOBYTE; #endif int status = EXIT_SUCCESS; - int opt; + unsigned long opt; FILE *mount_table; struct mntent *mount_entry; struct statfs s; static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */ const char *disp_units_hdr = hdr_1k; - while ((opt = getopt(argc, argv, "k" #ifdef CONFIG_FEATURE_HUMAN_READABLE - "hm" -#endif -)) > 0) - { - switch (opt) { -#ifdef CONFIG_FEATURE_HUMAN_READABLE - case 'h': + bb_opt_complementaly = "h-km:k-hm:m-hk"; + opt = bb_getopt_ulflags(argc, argv, "hmk"); + if(opt & 1) { df_disp_hr = 0; disp_units_hdr = " Size"; - break; - case 'm': + } + if(opt & 2) { df_disp_hr = MEGABYTE; disp_units_hdr = "1M-blocks"; - break; -#endif - case 'k': - /* default display is kilobytes */ -#ifdef CONFIG_FEATURE_HUMAN_READABLE - df_disp_hr = KILOBYTE; - disp_units_hdr = hdr_1k; -#endif - break; - default: - bb_show_usage(); - } } +#else + opt = bb_getopt_ulflags(argc, argv, "k"); +#endif bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n", "", 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) { long total; int slink_depth_save; - int print_final_total = 0; - int c; + int print_final_total; + char *smax_print_depth; + unsigned long opt; #ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */ @@ -185,57 +186,57 @@ int du_main(int argc, char **argv) * gnu du exits with an error code in this case. We choose to simply * ignore -a. This is consistent with -s being equivalent to -d 0. */ - - while ((c = getopt(argc, argv, "aHkLsx" "d:" "lc" -#ifdef CONFIG_FEATURE_HUMAN_READABLE - "hm" -#endif - )) > 0) { - switch (c) { - case 'a': - print_files = INT_MAX; - break; - case 'H': - slink_depth = 1; - break; - case 'k': #ifdef CONFIG_FEATURE_HUMAN_READABLE + bb_opt_complementaly = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s"; + opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth); + if((opt & (1 << 9))) { + /* -h opt */ + disp_hr = 0; + } + if((opt & (1 << 10))) { + /* -m opt */ + disp_hr = MEGABYTE; + } + if((opt & (1 << 2))) { + /* -k opt */ disp_hr = KILOBYTE; -#elif !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K + } +#else + bb_opt_complementaly = "H-L:L-H:s-d:d-s"; + opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth); +#if !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K + if((opt & (1 << 2))) { + /* -k opt */ disp_k = 1; + } +#endif #endif - break; - case 'L': + if((opt & (1 << 0))) { + /* -a opt */ + print_files = INT_MAX; + } + if((opt & (1 << 1))) { + /* -H opt */ + slink_depth = 1; + } + if((opt & (1 << 3))) { + /* -L opt */ slink_depth = INT_MAX; - break; - case 's': + } + if((opt & (1 << 4))) { + /* -s opt */ max_print_depth = 0; - break; - case 'x': - one_file_system = 1; - break; - - case 'd': - max_print_depth = bb_xgetularg10_bnd(optarg, 0, INT_MAX); - break; - case 'l': - count_hardlinks = 1; - break; - case 'c': - print_final_total = 1; - break; -#ifdef CONFIG_FEATURE_HUMAN_READABLE - case 'h': - disp_hr = 0; - break; - case 'm': - disp_hr = MEGABYTE; - break; -#endif - default: - bb_show_usage(); } + one_file_system = opt & (1 << 5); /* -x opt */ + if((opt & (1 << 6))) { + /* -d opt */ + max_print_depth = bb_xgetularg10_bnd(smax_print_depth, 0, INT_MAX); } + if((opt & (1 << 7))) { + /* -l opt */ + count_hardlinks = 1; + } + print_final_total = opt & (1 << 8); /* -c opt */ /* go through remaining args (if any) */ argv += optind; @@ -252,7 +253,9 @@ int du_main(int argc, char **argv) total += du(*argv); slink_depth = slink_depth_save; } while (*++argv); +#ifdef CONFIG_FEATURE_CLEAN_UP reset_ino_dev_hashtable(); +#endif if (print_final_total) { 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) { char **ep, *p; char *cleanenv[1] = { NULL }; - int ch; + unsigned long opt; - while ((ch = getopt(argc, argv, "iu:")) > 0) { - switch(ch) { - case 'i': + opt = bb_getopt_ulflags(argc, argv, "iu:", &p); + if(opt & 1) environ = cleanenv; - break; - case 'u': - unsetenv(optarg); - break; - default: - bb_show_usage(); - } - } + if(opt & 2) + unsetenv(p); argv += optind; 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 @@ #include #include +#include #include "busybox.h" +static const struct option mkdir_long_options[] = { + { "mode", 1, NULL, 'm' }, + { "parents", 0, NULL, 'p' }, + { 0, 0, 0, 0 } +}; + extern int mkdir_main (int argc, char **argv) { mode_t mode = (mode_t)(-1); int status = EXIT_SUCCESS; int flags = 0; - int opt; + unsigned long opt; + char *smode; - while ((opt = getopt (argc, argv, "m:p")) > 0) { - if (opt == 'm') { + bb_applet_long_options = mkdir_long_options; + opt = bb_getopt_ulflags(argc, argv, "m:p", &smode); + if(opt & 1) { mode = 0777; - if (!bb_parse_mode (optarg, &mode)) { - bb_error_msg_and_die ("invalid mode `%s'", optarg); - } - } else if (opt == 'p') { - flags |= FILEUTILS_RECUR; - } else { - bb_show_usage(); + if (!bb_parse_mode (smode, &mode)) { + bb_error_msg_and_die ("invalid mode `%s'", smode); } } + if(opt & 2) + flags |= FILEUTILS_RECUR; if (optind == argc) { 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 @@ #include #include #include +#include #include "busybox.h" #include "libcoreutils/coreutils.h" -static const char *fmt = "cannot overwrite %sdirectory with %sdirectory"; +static const struct option mv_long_options[] = { + { "interactive", 0, NULL, 'i' }, + { "force", 0, NULL, 'f' }, + { 0, 0, 0, 0 } +}; + +static const char mv_getopt_short_option[] = "fi"; +#define OPT_FILEUTILS_FORCE 1 +#define OPT_FILEUTILS_INTERACTIVE 2 + +static const char fmt[] = "cannot overwrite %sdirectory with %sdirectory"; extern int mv_main(int argc, char **argv) { @@ -44,20 +55,12 @@ extern int mv_main(int argc, char **argv) const char *dest; int dest_exists; int source_exists; - int opt; - int flags = 0; + unsigned long flags; int status = 0; - while ((opt = getopt(argc, argv, "fi")) > 0) { - flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE); - if (opt == 'i') { - flags |= FILEUTILS_INTERACTIVE; - } else if (opt == 'f') { - flags |= FILEUTILS_FORCE; - } else { - bb_show_usage(); - } - } + bb_applet_long_options = mv_long_options; + bb_opt_complementaly = "f-i:i-f"; + flags = bb_getopt_ulflags(argc, argv, mv_getopt_short_option); if (optind + 2 > argc) bb_show_usage(); @@ -77,8 +80,7 @@ extern int mv_main(int argc, char **argv) } do { - dest = concat_path_file(last, - bb_get_last_path_component(*argv)); + dest = concat_path_file(last, bb_get_last_path_component(*argv)); if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) { goto RET_1; @@ -86,9 +88,9 @@ extern int mv_main(int argc, char **argv) DO_MOVE: - if (dest_exists && !(flags & FILEUTILS_FORCE) && + if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) && ((access(dest, W_OK) < 0 && isatty(0)) || - (flags & FILEUTILS_INTERACTIVE))) { + (flags & OPT_FILEUTILS_INTERACTIVE))) { if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) { goto RET_1; /* Ouch! fprintf failed! */ } 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) { int status = 0; int flags = 0; - int opt; + unsigned long opt; - while ((opt = getopt(argc, argv, "fiRr")) > 0) { - if ((opt == 'r') || (opt == 'R')) { - flags |= FILEUTILS_RECUR; - } else { - flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE); - if (opt == 'i') { - flags |= FILEUTILS_INTERACTIVE; - } else if (opt == 'f') { + bb_opt_complementaly = "f-i:i-f"; + opt = bb_getopt_ulflags(argc, argv, "fiRr"); + if(opt & 1) flags |= FILEUTILS_FORCE; - } else { - bb_show_usage(); - } - } - } + if(opt & 2) + flags |= FILEUTILS_INTERACTIVE; + if(opt & 12) + flags |= FILEUTILS_RECUR; if (*(argv += optind) != NULL) { 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, int reversed, struct termios *mode); static speed_t string_to_baud(const char *arg); static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); -static void display_all(struct termios *mode, int fd, - const char *device_name); -static void display_changed(struct termios *mode, int fd, - const char *device_name); -static void display_recoverable(struct termios *mode, int fd, - const char *device_name); +static void display_all(struct termios *mode, int fd); +static void display_changed(struct termios *mode, int fd); +static void display_recoverable(struct termios *mode, int fd); static void display_speed(struct termios *mode, int fancy); -static void display_window_size(int fancy, int fd, - const char *device_name); +static void display_window_size(int fancy, int fd); static void sane_mode(struct termios *mode); static void set_control_char(const struct control_info *info, const char *arg, struct termios *mode); static void set_speed(enum speed_setting type, const char *arg, struct termios *mode); -static void set_window_size(int rows, int cols, int fd, - const char *device_name); +static void set_window_size(int rows, int cols, int fd); + +static const char *device_name; + +static __attribute__ ((noreturn)) void perror_on_device(const char *fmt) +{ + bb_perror_msg_and_die(fmt, device_name); +} + /* The width of the screen, for output wrapping. */ static int max_col; @@ -477,7 +480,7 @@ extern int main(int argc, char **argv) #endif { struct termios mode; - void (*output_func)(struct termios *, int, const char *); + void (*output_func)(struct termios *, int); int optc; int require_set_attr; int speed_was_set; @@ -487,7 +490,7 @@ extern int main(int argc, char **argv) int noargs = 1; char * file_name = NULL; int fd; - const char *device_name; + output_func = display_changed; verbose_output = 0; @@ -543,13 +546,10 @@ extern int main(int argc, char **argv) int fdflags; device_name = file_name; - fd = open(device_name, O_RDONLY | O_NONBLOCK); - if (fd < 0) - bb_perror_msg_and_die("%s", device_name); + fd = bb_xopen(device_name, O_RDONLY | O_NONBLOCK); if ((fdflags = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) - bb_perror_msg_and_die("%s: couldn't reset non-blocking mode", - device_name); + perror_on_device("%s: couldn't reset non-blocking mode"); } else { fd = 0; device_name = bb_msg_standard_input; @@ -559,12 +559,12 @@ extern int main(int argc, char **argv) spurious difference in an uninitialized portion of the structure. */ memset(&mode, 0, sizeof(mode)); if (tcgetattr(fd, &mode)) - bb_perror_msg_and_die("%s", device_name); + perror_on_device("%s"); if (verbose_output | recoverable_output | noargs) { max_col = screen_columns(); current_col = 0; - output_func(&mode, fd, device_name); + output_func(&mode, fd); return EXIT_SUCCESS; } @@ -644,18 +644,18 @@ extern int main(int argc, char **argv) bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; set_window_size((int) bb_xparse_number(argv[k], stty_suffixes), - -1, fd, device_name); + -1, fd); } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { if (k == argc - 1) bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; set_window_size(-1, (int) bb_xparse_number(argv[k], stty_suffixes), - fd, device_name); + fd); } else if (STREQ(argv[k], "size")) { max_col = screen_columns(); current_col = 0; - display_window_size(0, fd, device_name); + display_window_size(0, fd); } #endif #ifdef HAVE_C_LINE @@ -685,7 +685,7 @@ extern int main(int argc, char **argv) struct termios new_mode; if (tcsetattr(fd, TCSADRAIN, &mode)) - bb_perror_msg_and_die("%s", device_name); + perror_on_device("%s"); /* POSIX (according to Zlotnick's book) tcsetattr returns zero if it performs *any* of the requested operations. This means it @@ -698,7 +698,7 @@ extern int main(int argc, char **argv) spurious difference in an uninitialized portion of the structure. */ memset(&new_mode, 0, sizeof(new_mode)); if (tcgetattr(fd, &new_mode)) - bb_perror_msg_and_die("%s", device_name); + perror_on_device("%s"); /* Normally, one shouldn't use memcmp to compare structures that may have `holes' containing uninitialized data, but we have been @@ -721,8 +721,7 @@ extern int main(int argc, char **argv) new_mode.c_cflag &= (~CIBAUD); if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0) #endif - bb_error_msg_and_die ("%s: unable to perform all requested operations", - device_name); + perror_on_device ("%s: unable to perform all requested operations"); } } @@ -948,13 +947,13 @@ static int get_win_size(int fd, struct winsize *win) } static void -set_window_size(int rows, int cols, int fd, const char *device_name) +set_window_size(int rows, int cols, int fd) { struct winsize win; if (get_win_size(fd, &win)) { if (errno != EINVAL) - bb_perror_msg_and_die("%s", device_name); + perror_on_device("%s"); memset(&win, 0, sizeof(win)); } @@ -980,23 +979,23 @@ set_window_size(int rows, int cols, int fd, const char *device_name) if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0) || (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) { - bb_perror_msg_and_die("%s", device_name); + perror_on_device("%s"); return; } # endif if (ioctl(fd, TIOCSWINSZ, (char *) &win)) - bb_perror_msg_and_die("%s", device_name); + perror_on_device("%s"); } -static void display_window_size(int fancy, int fd, const char *device_name) +static void display_window_size(int fancy, int fd) { const char *fmt_str = "%s" "\0" "%s: no size information for this device"; struct winsize win; if (get_win_size(fd, &win)) { if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) { - bb_perror_msg_and_die(fmt_str, device_name); + perror_on_device(fmt_str); } } else { 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) return NULL; } -static void display_changed(struct termios *mode, int fd, const char *device_name) +static void display_changed(struct termios *mode, int fd) { int i; int empty_line; @@ -1122,7 +1121,7 @@ static void display_changed(struct termios *mode, int fd, const char *device_nam } static void -display_all(struct termios *mode, int fd, const char *device_name) +display_all(struct termios *mode, int fd) { int i; tcflag_t *bitsp; @@ -1131,7 +1130,7 @@ display_all(struct termios *mode, int fd, const char *device_name) display_speed(mode, 1); #ifdef TIOCGWINSZ - display_window_size(1, fd, device_name); + display_window_size(1, fd); #endif #ifdef HAVE_C_LINE wrapf("line = %d;", mode->c_line); @@ -1202,7 +1201,7 @@ static void display_speed(struct termios *mode, int fancy) current_col = 0; } -static void display_recoverable(struct termios *mode, int fd, const char *device_name) +static void display_recoverable(struct termios *mode, int fd) { int i; 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) if (errno != 0) bb_error_msg_and_die("%s: out of range", s); - while (isspace(*p)) - p++; - - if (*p) + /* p = bb_skip_whitespace(p); avoid const warning */ + if (*(bb_skip_whitespace(p))) bb_error_msg_and_die("%s: bad number", s); 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 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* + * Jun 2003 by Vladimir Oleynik - + * correction "-e pattern1 -e -e pattern2" logic and more optimizations. +*/ #include #include #include #include -#include /* for strerror() */ +#include #include #include "busybox.h" -extern int optind; /* in unistd.h */ -extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */ - /* options */ -static int reflags = REG_NOSUB; -static int print_filename = 0; -static int print_line_num = 0; -static int print_match_counts = 0; -static int be_quiet = 0; -static int invert_search = 0; -static int suppress_err_msgs = 0; -static int print_files_with_matches = 0; -static int fgrep_flag = 0; +#define GREP_OPTS "lnqvscFiHhe:f:" +#define GREP_OPT_l 1 +static char print_files_with_matches; +#define GREP_OPT_n 2 +static char print_line_num; +#define GREP_OPT_q 4 +static char be_quiet; +#define GREP_OPT_v 8 +typedef char invert_search_t; +static invert_search_t invert_search; +#define GREP_OPT_s 16 +static char suppress_err_msgs; +#define GREP_OPT_c 32 +static char print_match_counts; +#define GREP_OPT_F 64 +static char fgrep_flag; +#define GREP_OPT_i 128 +#define GREP_OPT_H 256 +#define GREP_OPT_h 512 +#define GREP_OPT_e 1024 +#define GREP_OPT_f 2048 +#ifdef CONFIG_FEATURE_GREP_CONTEXT +#define GREP_OPT_CONTEXT "A:B:C" +#define GREP_OPT_A 4096 +#define GREP_OPT_B 8192 +#define GREP_OPT_C 16384 +#define GREP_OPT_E 32768U +#else +#define GREP_OPT_CONTEXT "" +#define GREP_OPT_E 4096 +#endif +#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS +# define OPT_EGREP "E" +#else +# define OPT_EGREP "" +#endif + +static int reflags; +static int print_filename; #ifdef CONFIG_FEATURE_GREP_CONTEXT -extern char *optarg; /* in getopt.h */ -static int lines_before = 0; -static int lines_after = 0; -static char **before_buf = NULL; -static int last_line_printed = 0; +static int lines_before; +static int lines_after; +static char **before_buf; +static int last_line_printed; #endif /* CONFIG_FEATURE_GREP_CONTEXT */ /* globals used internally */ -static llist_t *pattern_head = NULL; /* growable list of patterns to match */ -static int matched; /* keeps track of whether we ever matched */ -static char *cur_file = NULL; /* the current file we are reading */ +static llist_t *pattern_head; /* growable list of patterns to match */ +static char *cur_file; /* the current file we are reading */ 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) puts(line); } +extern void xregcomp(regex_t *preg, const char *regex, int cflags); + -static void grep_file(FILE *file) +static int grep_file(FILE *file) { - char *line = NULL; - int ret; + char *line; + invert_search_t ret; int linenum = 0; int nmatches = 0; #ifdef CONFIG_FEATURE_GREP_CONTEXT @@ -91,15 +122,10 @@ static void grep_file(FILE *file) llist_t *pattern_ptr = pattern_head; linenum++; - + ret = 0; while (pattern_ptr) { if (fgrep_flag) { - if (strstr(line, pattern_ptr->data)) { - /* Match found */ - ret = 0; - } else { - ret = 1; - } + ret = strstr(line, pattern_ptr->data) != NULL; } else { /* * test for a postitive-assertion match (regexec returns success (0) @@ -109,15 +135,22 @@ static void grep_file(FILE *file) */ regex_t regex; xregcomp(®ex, pattern_ptr->data, reflags); - ret = regexec(®ex, line, 0, NULL, 0); + ret = regexec(®ex, line, 0, NULL, 0) == 0; regfree(®ex); } - if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) { + if (!ret) + break; + pattern_ptr = pattern_ptr->link; + } /* while (pattern_ptr) */ + + if ((ret ^ invert_search)) { + + if (print_files_with_matches || be_quiet) + free(line); - /* if we found a match but were told to be quiet, stop here and - * return success */ + /* if we found a match but were told to be quiet, stop here */ if (be_quiet) - exit(0); + return -1; /* keep track of matches */ nmatches++; @@ -177,8 +210,6 @@ static void grep_file(FILE *file) print_n_lines_after--; } #endif /* CONFIG_FEATURE_GREP_CONTEXT */ - pattern_ptr = pattern_ptr->link; - } /* for */ free(line); } @@ -190,9 +221,6 @@ static void grep_file(FILE *file) if (print_match_counts) { if (print_filename) printf("%s:", cur_file); - if (print_files_with_matches && nmatches > 0) - printf("1\n"); - else printf("%d\n", nmatches); } @@ -201,188 +229,163 @@ static void grep_file(FILE *file) puts(cur_file); } - - /* remember if we matched */ - if (nmatches != 0) - matched = 1; -} - -#if 0 -static void add_pattern(char *restr) -{ -// regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes)); -// xregcomp(®exes[nregexes-1], restr, reflags); - pattern_head = llist_add_to(pattern_head, restr); + return nmatches; } -#endif -static void load_regexes_from_file(const char *filename) +static void load_regexes_from_file(llist_t *fopt) { char *line; - FILE *f = bb_xfopen(filename, "r"); + FILE *f; + + while(fopt) { + llist_t *cur = fopt; + char *ffile = cur->data; + + fopt = cur->link; + free(cur); + f = bb_xfopen(ffile, "r"); while ((line = bb_get_chomped_line_from_file(f)) != NULL) { pattern_head = llist_add_to(pattern_head, line); } -} - - -#ifdef CONFIG_FEATURE_CLEAN_UP -static void destroy_regexes(void) -{ - llist_t *pattern_head_ptr; - - if (pattern_head == NULL) - return; - - /* destroy all the elments in the pattern list */ - while (pattern_head) { - pattern_head_ptr = pattern_head; - pattern_head = pattern_head->link; - free(pattern_head_ptr->data); - free(pattern_head_ptr); } } -#endif extern int grep_main(int argc, char **argv) { - int opt; -#if defined (CONFIG_FEATURE_GREP_CONTEXT) - char *junk; -#endif - -#ifdef CONFIG_FEATURE_CLEAN_UP - /* destroy command strings on exit */ - atexit(destroy_regexes); -#endif - -#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS - if (strcmp(bb_get_last_path_component(argv[0]), "egrep") == 0) - reflags |= REG_EXTENDED; -#endif + FILE *file; + int matched; + unsigned long opt; + llist_t *fopt; /* do normal option parsing */ - while ((opt = getopt(argc, argv, "iHhlnqvsce:f:F" #ifdef CONFIG_FEATURE_GREP_CONTEXT -"A:B:C:" -#endif -#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS -"E" -#endif -)) > 0) { - switch (opt) { - case 'i': - reflags |= REG_ICASE; - break; - case 'l': - print_files_with_matches++; - break; - case 'H': - print_filename++; - break; - case 'h': - print_filename--; - break; - case 'n': - print_line_num++; - break; - case 'q': - be_quiet++; - break; - case 'v': - invert_search++; - break; - case 's': - suppress_err_msgs++; - break; - case 'c': - print_match_counts++; - break; - case 'e': - pattern_head = llist_add_to(pattern_head, strdup(optarg)); - break; -#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS - case 'E': - reflags |= REG_EXTENDED; - break; -#endif - case 'F': - fgrep_flag = 1; - break; - case 'f': - load_regexes_from_file(optarg); - break; -#ifdef CONFIG_FEATURE_GREP_CONTEXT - case 'A': - lines_after = strtoul(optarg, &junk, 10); - if(*junk != '\0') - bb_error_msg_and_die("invalid context length argument"); - break; - case 'B': - lines_before = strtoul(optarg, &junk, 10); + { + char *junk; + char *slines_after; + char *slines_before; + char *Copt; + + bb_opt_complementaly = "H-h:e*:f*:C-AB"; + opt = bb_getopt_ulflags(argc, argv, + GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP, + &pattern_head, &fopt, + &slines_after, &slines_before, &Copt); + + if(opt & GREP_OPT_C) { + /* C option unseted A and B options, but next -A or -B + may be ovewrite own option */ + if(!(opt & GREP_OPT_A)) /* not overwtited */ + slines_after = Copt; + if(!(opt & GREP_OPT_B)) /* not overwtited */ + slines_before = Copt; + opt |= GREP_OPT_A|GREP_OPT_B; /* set for parse now */ + } + if(opt & GREP_OPT_A) { + lines_after = strtoul(slines_after, &junk, 10); if(*junk != '\0') bb_error_msg_and_die("invalid context length argument"); - before_buf = (char **)xcalloc(lines_before, sizeof(char *)); - break; - case 'C': - lines_after = lines_before = strtoul(optarg, &junk, 10); + } + if(opt & GREP_OPT_B) { + lines_before = strtoul(slines_before, &junk, 10); if(*junk != '\0') bb_error_msg_and_die("invalid context length argument"); - before_buf = (char **)xcalloc(lines_before, sizeof(char *)); - break; -#endif /* CONFIG_FEATURE_GREP_CONTEXT */ - default: - bb_show_usage(); } + /* sanity checks after parse may be invalid numbers ;-) */ + if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l))) { + opt &= ~GREP_OPT_n; + lines_before = 0; + lines_after = 0; + } else if(lines_before > 0) + before_buf = (char **)xcalloc(lines_before, sizeof(char *)); } +#else + /* with auto sanity checks */ + bb_opt_complementaly = "H-h:e*:f*:c-n:q-n:l-n"; + opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP, + &pattern_head, &fopt); + +#endif + print_files_with_matches = opt & GREP_OPT_l; + print_line_num = opt & GREP_OPT_n; + be_quiet = opt & GREP_OPT_q; + invert_search = (opt & GREP_OPT_v) != 0; /* 0 | 1 */ + suppress_err_msgs = opt & GREP_OPT_s; + print_match_counts = opt & GREP_OPT_c; + fgrep_flag = opt & GREP_OPT_F; + if(opt & GREP_OPT_H) + print_filename++; + if(opt & GREP_OPT_h) + print_filename--; + if(opt & GREP_OPT_f) + load_regexes_from_file(fopt); + +#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS + if(bb_applet_name[0] == 'e' || (opt & GREP_OPT_E)) + reflags = REG_EXTENDED | REG_NOSUB; + else +#endif + reflags = REG_NOSUB; + + if(opt & GREP_OPT_i) + reflags |= REG_ICASE; + + argv += optind; + argc -= optind; /* if we didn't get a pattern from a -e and no command file was specified, * argv[optind] should be the pattern. no pattern, no worky */ if (pattern_head == NULL) { - if (argv[optind] == NULL) + if (*argv == NULL) bb_show_usage(); else { - pattern_head = llist_add_to(pattern_head, strdup(argv[optind])); - optind++; + pattern_head = llist_add_to(pattern_head, *argv++); + argc--; } } - /* sanity checks */ - if (print_match_counts || be_quiet || print_files_with_matches) { - print_line_num = 0; -#ifdef CONFIG_FEATURE_GREP_CONTEXT - lines_before = 0; - lines_after = 0; -#endif - } - /* argv[(optind)..(argc-1)] should be names of file to grep through. If * there is more than one file to grep, we will print the filenames */ - if ((argc-1) - (optind) > 0) + if (argc > 1) { print_filename++; /* If no files were specified, or '-' was specified, take input from * stdin. Otherwise, we grep through all the files specified. */ - if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { - grep_file(stdin); + } else if (argc == 0) { + argc++; } - else { - int i; - FILE *file; - for (i = optind; i < argc; i++) { - cur_file = argv[i]; + matched = 0; + while (argc--) { + cur_file = *argv++; + if(!cur_file || (*cur_file == '-' && !cur_file[1])) { + cur_file = "-"; + file = stdin; + } else { file = fopen(cur_file, "r"); + } if (file == NULL) { if (!suppress_err_msgs) bb_perror_msg("%s", cur_file); + } else { + matched += grep_file(file); + if(matched < 0) { + /* we found a match but were told to be quiet, stop here and + * return success */ + break; } - else { - grep_file(file); fclose(file); } } + +#ifdef CONFIG_FEATURE_CLEAN_UP + /* destroy all the elments in the pattern list */ + while (pattern_head) { + llist_t *pattern_head_ptr = pattern_head; + + pattern_head = pattern_head->link; + free(pattern_head_ptr); } +#endif return !matched; /* invert return value 0 = success, 1 = failed */ } 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) char *file_to_act_on; char **args; int i, a; - char flg_vi = 0; /* verbose |& interactive */ - char flg_no_empty = 0; + char flg_vi; /* verbose |& interactive */ + char flg_no_empty; - while ((a = getopt(argc, argv, "prt")) > 0) { - switch(a) { - case 'p': - flg_vi |= 3; - break; - case 't': - flg_vi |= 1; - break; - case 'r': - flg_no_empty = 1; - break; - default: - bb_show_usage(); - } - } + bb_opt_complementaly = "pt"; + a = bb_getopt_ulflags(argc, argv, "tpr"); + flg_vi = a & 3; + flg_no_empty = a & 4; a = argc - optind; argv += optind; @@ -110,7 +99,7 @@ int xargs_main(int argc, char **argv) fputc(' ', stderr); fputs(args[i], stderr); } - fprintf(stderr, "%s", ((flg_vi & 2) ? " ?..." : "\n")); + fputs(((flg_vi & 2) ? " ?..." : "\n"), stderr); } if((flg_vi & 2) == 0 || bb_ask_confirmation() != 0 ) { 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); //#warning rename? extern int bb_fclose_nonstdin(FILE *f); extern void bb_fflush_stdout_and_exit(int retval) __attribute__ ((noreturn)); + +extern const char *bb_opt_complementaly; +extern const struct option *bb_applet_long_options; extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts); //#warning rename? 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 @@ /* vi: set sw=4 ts=4: */ /* - * getopt_ulflags implementation for busybox + * universal getopt_ulflags implementation for busybox * - * Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2003 Vladimir Oleynik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,20 +22,149 @@ #include #include +#include +#include #include "libbb.h" -unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts) +/* +You can set bb_opt_complementaly as string with one or more +complementaly or incongruously options. +If sequential founded option haved from this string +then your incongruously pairs unsets and complementaly make add sets. +Format: +one char - option for check, +chars - complementaly option for add sets. +- chars - option triggered for unsets. +~ chars - option incongruously. +* - option list, called add_to_list(*ptr_from_usaged, optarg) +: - separator. +Example: du applet can have options "-s" and "-d size" +If getopt found -s then -d option flag unset or if found -d then -s unset. +For this result you must set bb_opt_complementaly = "s-d:d-s". +Result have last option flag only from called arguments. +Warning! You can check returned flag, pointer to "d:" argument seted +to own optarg always. +Example two: cut applet must only one type of list may be specified, +and -b, -c and -f incongruously option, overwited option is error also. +You must set bb_opt_complementaly = "b~bcf:c~bcf:f~bcf". +If called have more one specified, return value have error flag - +high bite set (0x80000000UL). +Example three: grep applet can have one or more "-e pattern" arguments. +You should use bb_getopt_ulflags() as +llist_t *paterns; +bb_opt_complementaly = "e*"; +bb_getopt_ulflags (argc, argv, "e:", &paterns); +*/ + +const char *bb_opt_complementaly; + +typedef struct +{ + char opt; + char list_flg; + unsigned long switch_on; + unsigned long switch_off; + unsigned long incongruously; + void **optarg; /* char **optarg or llist_t **optarg */ +} t_complementaly; + +/* You can set bb_applet_long_options for parse called long options */ + +static const struct option bb_default_long_options[] = { + /* { "help", 0, NULL, '?' }, */ + { 0, 0, 0, 0 } +}; + +const struct option *bb_applet_long_options = bb_default_long_options; + + +unsigned long +bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) { unsigned long flags = 0; + int c = 0; const char *s; - int c; + t_complementaly *complementaly; + t_complementaly *on_off; + va_list p; + + va_start (p, applet_opts); - while ((c = getopt(argc, argv, applet_opts)) > 0) { - if (!(s = strchr(applet_opts, c))) { - bb_show_usage(); + for (s = applet_opts; *s; s++) { + c++; + while (s[1] == ':') { + /* check GNU extension "o::" - optional arg */ + s++; + } + } + complementaly = xcalloc (c + 1, sizeof (t_complementaly)); + c = 0; + for (s = applet_opts; *s; s++) { + complementaly->opt = *s; + complementaly->switch_on |= (1 << c); + c++; + if (s[1] == ':') { + complementaly->optarg = va_arg (p, void **); + do + s++; + while (s[1] == ':'); } - flags |= (1 << (s-applet_opts)); + complementaly++; } + complementaly->opt = 0; + complementaly -= c; + c = 0; + for (s = bb_opt_complementaly; s && *s; s++) { + t_complementaly *pair; + + if (*s == ':') { + c = 0; + continue; + } + if (c) + continue; + for (on_off = complementaly; on_off->opt; on_off++) + if (on_off->opt == *s) + break; + pair = on_off; + for(s++; *s && *s != ':'; s++) { + if (*s == '-' || *s == '~') { + c = *s; + } else if(*s == '*') { + pair->list_flg++; + } else { + unsigned long *pair_switch = &(pair->switch_on); + if(c) + pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); + for (on_off = complementaly; on_off->opt; on_off++) + if (on_off->opt == *s) { + *pair_switch |= on_off->switch_on; + break; + } + } + } + s--; + } + + while ((c = getopt_long (argc, argv, applet_opts, + bb_applet_long_options, NULL)) > 0) { + + for (on_off = complementaly; on_off->opt != c; on_off++) { + if(!on_off->opt) + bb_show_usage (); + } + if(flags & on_off->incongruously) + flags |= 0x80000000UL; + flags &= ~on_off->switch_off; + flags |= on_off->switch_on; + if(on_off->list_flg) { + *(llist_t **)(on_off->optarg) = + llist_add_to(*(llist_t **)(on_off->optarg), optarg); + } else if (on_off->optarg) { + *(char **)(on_off->optarg) = optarg; + } + } + free(complementaly); return flags; } 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) ino_dev_hashtable[i] = bucket; } +#ifdef CONFIG_FEATURE_CLEAN_UP /* Clear statbuf hash table */ void reset_ino_dev_hashtable(void) { @@ -97,6 +98,7 @@ void reset_ino_dev_hashtable(void) } } } +#endif /* 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 return 0; } +#ifndef CONFIG_ADDUSER +static inline void if_i_am_not_root(void) +{ + if (geteuid()) { + bb_error_msg_and_die( "Only root may add a user or group to the system."); + } +} +#else +extern void if_i_am_not_root(void); +#endif + /* * addgroup will take a login_name as its first parameter. * @@ -131,21 +142,13 @@ static int addgroup(const char *filename, char *group, gid_t gid, const char *us * ________________________________________________________________________ */ int addgroup_main(int argc, char **argv) { - int opt; char *group; char *user; gid_t gid = 0; /* get remaining args */ - while ((opt = getopt (argc, argv, "g:")) != -1) { - switch (opt) { - case 'g': - gid = strtol(optarg, NULL, 10); - break; - default: - bb_show_usage(); - break; - } + if(bb_getopt_ulflags(argc, argv, "g:", &group)) { + gid = strtol(group, NULL, 10); } if (optind < argc) { @@ -161,14 +164,8 @@ int addgroup_main(int argc, char **argv) } else { user = ""; } - - if (geteuid() != 0) { - bb_error_msg_and_die - ("Only root may add a group to the system."); - } + if_i_am_not_root(); /* werk */ return addgroup(bb_path_group_file, group, gid, user); } - -/* $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) /* return current uid (root is always uid == 0, right?) */ -static inline uid_t i_am_not_root(void) +#ifndef CONFIG_ADDGROUP +static inline void if_i_am_not_root(void) +#else +void if_i_am_not_root(void) +#endif { - return geteuid(); + if (geteuid()) { + bb_error_msg_and_die( "Only root may add a user or group to the system."); + } } /* @@ -224,11 +230,10 @@ static inline uid_t i_am_not_root(void) * ________________________________________________________________________ */ int adduser_main(int argc, char **argv) { - int opt; const char *login; - const char *gecos; + const char *gecos = default_gecos; const char *home = NULL; - const char *shell; + const char *shell = default_shell; struct passwd pw; @@ -236,30 +241,11 @@ int adduser_main(int argc, char **argv) if (argc < 2) { bb_show_usage(); } - gecos = default_gecos; - shell = default_shell; - /* get args */ - while ((opt = getopt (argc, argv, "h:g:s:")) != -1) - switch (opt) { - case 'h': - home = optarg; - break; - case 'g': - gecos = optarg; - break; - case 's': - shell = optarg; - break; - default: - bb_show_usage(); - break; - } + bb_getopt_ulflags(argc, argv, "h:g:s:", &home, &gecos, &shell); /* got root? */ - if (i_am_not_root()) { - bb_error_msg_and_die( "Only root may add a user or group to the system."); - } + if_i_am_not_root(); /* get login */ if (optind >= argc) { @@ -288,5 +274,3 @@ int adduser_main(int argc, char **argv) /* grand finale */ return adduser(bb_path_passwd_file, &pw); } - -/* $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; int crond_main(int ac, char **av) { - int i; + unsigned long opt; + char *lopt, *Lopt, *copt; +#ifdef FEATURE_DEBUG_OPT + char *dopt; + bb_opt_complementaly = "f-b:b-f:S-L:L-S:d-l"; +#else + bb_opt_complementaly = "f-b:b-f:S-L:L-S"; +#endif opterr = 0; /* disable getopt 'errors' message.*/ - - while ((i = getopt(ac,av, + opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:" #ifdef FEATURE_DEBUG_OPT "d:" #endif - "l:L:fbSc:")) != EOF){ - - switch (i){ - case 'l': - LogLevel = atoi(optarg); - break; + , &lopt, &Lopt, &copt #ifdef FEATURE_DEBUG_OPT - case 'd': - DebugOpt = atoi(optarg); - LogLevel = 0; - break; + , &dopt #endif - case 'f': - ForegroundOpt = 1; - break; - case 'b': - ForegroundOpt = 0; - break; - case 'S': /* select logging to syslog */ - LoggerOpt = 0; - break; - case 'L': /* select internal file logger */ - LoggerOpt = 1; - if (*optarg != 0) LogFile = optarg; - break; - case 'c': - if (*optarg != 0) CDir = optarg; - break; - default: /* parse error */ - bb_show_usage(); + ); + if(opt & 1) + LogLevel = atoi(lopt); + LoggerOpt = opt & 2; + if(LoggerOpt) + if (*Lopt != 0) LogFile = Lopt; + ForegroundOpt = opt & 4; + if(opt & 32) { + if (*copt != 0) CDir = copt; } +#ifdef FEATURE_DEBUG_OPT + if(opt & 64) { + DebugOpt = atoi(dopt); + LogLevel = 0; } +#endif /* * change directory @@ -165,6 +159,9 @@ crond_main(int ac, char **av) if (chdir(CDir) != 0) bb_perror_msg_and_die("chdir"); + signal(SIGHUP,SIG_IGN); /* hmm.. but, if kill -HUP original + * version - his died. ;( + */ /* * close stdin and stdout, stderr. * close unused descriptors - don't need. @@ -177,9 +174,6 @@ crond_main(int ac, char **av) } (void)startlogger(); /* need if syslog mode selected */ - signal(SIGHUP,SIG_IGN); /* hmm.. but, if kill -HUP original - * version - his died. ;( - */ /* * main loop - synchronize to 1 second after the minute, minimum sleep -- 2.25.1