last_patch89 from vodz:
No binary (build failed)
—
(log yok)
| @@ -22,20 +22,22 @@ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| - | #include <unistd.h> /* getopt */ |
| + | #include <getopt.h> |
| + | #include <unistd.h> |
| #include <string.h> | |
| #include <limits.h> | |
| #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"); | |
| } | |
| } | |
| @@ -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 '+' */ | |
| @@ -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; | |
| @@ -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); | |
| @@ -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"); | |
| @@ -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; | |
| @@ -31,27 +31,33 @@ | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| + | #include <getopt.h> |
| #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(); | |
| @@ -31,10 +31,21 @@ | |
| #include <dirent.h> | |
| #include <errno.h> | |
| #include <stdlib.h> | |
| + | #include <getopt.h> |
| #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! */ | |
| } | |
| @@ -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 { | |
| @@ -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; | |
| @@ -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; | |
| @@ -19,42 +19,71 @@ | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| * | |
| */ | |
| + | /* |
| + | * Jun 2003 by Vladimir Oleynik <[email protected]> - |
| + | * correction "-e pattern1 -e -e pattern2" logic and more optimizations. |
| + | */ |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <getopt.h> | |
| #include <regex.h> | |
| - | #include <string.h> /* for strerror() */ |
| + | #include <string.h> |
| #include <errno.h> | |
| #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 */ | |
| } | |
| @@ -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); | |
| @@ -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); | |
| @@ -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 <[email protected]> |
| + | * Copyright (C) 2003 Vladimir Oleynik <[email protected]> |
| * | |
| * 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 <getopt.h> | |
| #include <string.h> | |
| + | #include <assert.h> |
| + | #include <stdlib.h> |
| #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; | |
| } | |
| @@ -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 */ | |
| @@ -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 $ */ |
| @@ -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 $ */ |
| @@ -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 | |