diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-09 03:05:48 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-09 03:05:48 +0000 |
commit | 32b633aa3f7e96bc1a31feb9d3937c0c340a7430 (patch) | |
tree | 041e4a83f8d523c2d9b3b8b4abb410616e2694a1 | |
parent | 786834bcee178ea6c05aa57869337f03678d02dc (diff) | |
download | busybox-w32-32b633aa3f7e96bc1a31feb9d3937c0c340a7430.tar.gz busybox-w32-32b633aa3f7e96bc1a31feb9d3937c0c340a7430.tar.bz2 busybox-w32-32b633aa3f7e96bc1a31feb9d3937c0c340a7430.zip |
merge busybox.c into applets.c
-rw-r--r-- | applets/Kbuild | 1 | ||||
-rw-r--r-- | applets/applets.c | 237 | ||||
-rw-r--r-- | applets/busybox.c | 158 | ||||
-rw-r--r-- | include/applets.h | 8 | ||||
-rw-r--r-- | include/busybox.h | 3 | ||||
-rw-r--r-- | include/libbb.h | 1 |
6 files changed, 199 insertions, 209 deletions
diff --git a/applets/Kbuild b/applets/Kbuild index 4323e85f2..1d4a96cdc 100644 --- a/applets/Kbuild +++ b/applets/Kbuild | |||
@@ -6,7 +6,6 @@ | |||
6 | 6 | ||
7 | obj-y:= | 7 | obj-y:= |
8 | obj-y += applets.o | 8 | obj-y += applets.o |
9 | obj-y += busybox.o | ||
10 | 9 | ||
11 | # Generated file needs additional love | 10 | # Generated file needs additional love |
12 | 11 | ||
diff --git a/applets/applets.c b/applets/applets.c index b4580a5b4..8acfd95a9 100644 --- a/applets/applets.c +++ b/applets/applets.c | |||
@@ -15,11 +15,6 @@ | |||
15 | #include <assert.h> | 15 | #include <assert.h> |
16 | #include "busybox.h" | 16 | #include "busybox.h" |
17 | 17 | ||
18 | #define PROTOTYPES | ||
19 | #include "applets.h" | ||
20 | #undef PROTOTYPES | ||
21 | |||
22 | |||
23 | /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ | 18 | /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ |
24 | #if ENABLE_STATIC && defined(__GLIBC__) && !defined(__UCLIBC__) | 19 | #if ENABLE_STATIC && defined(__GLIBC__) && !defined(__UCLIBC__) |
25 | #warning Static linking against glibc produces buggy executables | 20 | #warning Static linking against glibc produces buggy executables |
@@ -30,7 +25,14 @@ | |||
30 | #warning from top-level Makefile and remove this warning. | 25 | #warning from top-level Makefile and remove this warning. |
31 | #endif | 26 | #endif |
32 | 27 | ||
28 | |||
29 | /* Declare <applet>_main() */ | ||
30 | #define PROTOTYPES | ||
31 | #include "applets.h" | ||
32 | #undef PROTOTYPES | ||
33 | |||
33 | #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE | 34 | #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE |
35 | /* Define usage_messages[] */ | ||
34 | static const char usage_messages[] = | 36 | static const char usage_messages[] = |
35 | #define MAKE_USAGE | 37 | #define MAKE_USAGE |
36 | #include "usage.h" | 38 | #include "usage.h" |
@@ -39,24 +41,25 @@ static const char usage_messages[] = | |||
39 | #undef MAKE_USAGE | 41 | #undef MAKE_USAGE |
40 | #else | 42 | #else |
41 | #define usage_messages 0 | 43 | #define usage_messages 0 |
42 | #endif /* ENABLE_SHOW_USAGE */ | 44 | #endif /* SHOW_USAGE */ |
43 | 45 | ||
44 | #undef APPLET | 46 | /* Define struct BB_applet applets[] */ |
45 | #undef APPLET_NOUSAGE | ||
46 | #undef PROTOTYPES | ||
47 | #include "applets.h" | 47 | #include "applets.h" |
48 | /* The -1 arises because of the {0,NULL,0,-1} entry. */ | ||
49 | const unsigned short NUM_APPLETS = sizeof(applets) / sizeof(struct BB_applet) - 1; | ||
48 | 50 | ||
49 | static struct BB_applet *applet_using; | ||
50 | 51 | ||
51 | /* The -1 arises because of the {0,NULL,0,-1} entry. */ | 52 | static struct BB_applet *current_applet; |
52 | const unsigned short NUM_APPLETS = (sizeof(applets) / sizeof(struct BB_applet) - 1); | 53 | const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE; |
54 | #ifdef BB_NOMMU | ||
55 | smallint re_execed; | ||
56 | #endif | ||
53 | 57 | ||
54 | 58 | ||
55 | #if ENABLE_FEATURE_SUID_CONFIG | ||
56 | 59 | ||
57 | #include <ctype.h> | 60 | #if ENABLE_FEATURE_SUID_CONFIG |
58 | 61 | ||
59 | /* applets [] is const, so we have to define this "override" structure */ | 62 | /* applets[] is const, so we have to define this "override" structure */ |
60 | static struct BB_suid_config | 63 | static struct BB_suid_config |
61 | { | 64 | { |
62 | struct BB_applet *m_applet; | 65 | struct BB_applet *m_applet; |
@@ -68,7 +71,7 @@ static struct BB_suid_config | |||
68 | struct BB_suid_config *m_next; | 71 | struct BB_suid_config *m_next; |
69 | } *suid_config; | 72 | } *suid_config; |
70 | 73 | ||
71 | static int suid_cfg_readable; | 74 | static smallint suid_cfg_readable; |
72 | 75 | ||
73 | /* check if u is member of group g */ | 76 | /* check if u is member of group g */ |
74 | static int ingroup(uid_t u, gid_t g) | 77 | static int ingroup(uid_t u, gid_t g) |
@@ -101,16 +104,13 @@ static char *get_trimmed_slice(char *s, char *e) | |||
101 | break; | 104 | break; |
102 | } | 105 | } |
103 | } | 106 | } |
104 | e[1] = 0; | 107 | e[1] = '\0'; |
105 | 108 | ||
106 | /* Next, advance past all leading space and return a ptr to the | 109 | /* Next, advance past all leading space and return a ptr to the |
107 | * first non-space char; possibly the terminating nul. */ | 110 | * first non-space char; possibly the terminating nul. */ |
108 | return skip_whitespace(s); | 111 | return skip_whitespace(s); |
109 | } | 112 | } |
110 | 113 | ||
111 | |||
112 | #define parse_error(x) do { errmsg = x; goto pe_label; } while(0) | ||
113 | |||
114 | /* Don't depend on the tools to combine strings. */ | 114 | /* Don't depend on the tools to combine strings. */ |
115 | static const char config_file[] = "/etc/busybox.conf"; | 115 | static const char config_file[] = "/etc/busybox.conf"; |
116 | 116 | ||
@@ -121,12 +121,14 @@ static const char mode_chars[] = "Ssx-\0Ssx-\0Ttx-"; | |||
121 | * necessary below. Also, we use unsigned short here to save some | 121 | * necessary below. Also, we use unsigned short here to save some |
122 | * space even though these are really mode_t values. */ | 122 | * space even though these are really mode_t values. */ |
123 | static const unsigned short mode_mask[] = { | 123 | static const unsigned short mode_mask[] = { |
124 | /* SST sst xxx --- */ | 124 | /* SST sst xxx --- */ |
125 | S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* user */ | 125 | S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* user */ |
126 | S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* group */ | 126 | S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* group */ |
127 | 0, S_IXOTH, S_IXOTH, 0 /* other */ | 127 | 0, S_IXOTH, S_IXOTH, 0 /* other */ |
128 | }; | 128 | }; |
129 | 129 | ||
130 | #define parse_error(x) do { errmsg = x; goto pe_label; } while(0) | ||
131 | |||
130 | static void parse_config_file(void) | 132 | static void parse_config_file(void) |
131 | { | 133 | { |
132 | struct BB_suid_config *sct_head; | 134 | struct BB_suid_config *sct_head; |
@@ -155,7 +157,7 @@ static void parse_config_file(void) | |||
155 | sct_head = NULL; | 157 | sct_head = NULL; |
156 | section = lc = 0; | 158 | section = lc = 0; |
157 | 159 | ||
158 | do { | 160 | while (1) { |
159 | s = buffer; | 161 | s = buffer; |
160 | 162 | ||
161 | if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */ | 163 | if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */ |
@@ -234,7 +236,7 @@ static void parse_config_file(void) | |||
234 | 236 | ||
235 | /* Ok, we have an applet name. Process the rhs if this | 237 | /* Ok, we have an applet name. Process the rhs if this |
236 | * applet is currently built in and ignore it otherwise. | 238 | * applet is currently built in and ignore it otherwise. |
237 | * Note: This can hide config file bugs which only pop | 239 | * Note: this can hide config file bugs which only pop |
238 | * up when the busybox configuration is changed. */ | 240 | * up when the busybox configuration is changed. */ |
239 | applet = find_applet_by_name(s); | 241 | applet = find_applet_by_name(s); |
240 | if (applet) { | 242 | if (applet) { |
@@ -266,7 +268,7 @@ static void parse_config_file(void) | |||
266 | 268 | ||
267 | s = skip_whitespace(e); | 269 | s = skip_whitespace(e); |
268 | 270 | ||
269 | /* Note: We require whitespace between the mode and the | 271 | /* Note: we require whitespace between the mode and the |
270 | * user/group info. */ | 272 | * user/group info. */ |
271 | if ((s == e) || !(e = strchr(s, '.'))) { | 273 | if ((s == e) || !(e = strchr(s, '.'))) { |
272 | parse_error("<uid>.<gid>"); | 274 | parse_error("<uid>.<gid>"); |
@@ -308,7 +310,7 @@ static void parse_config_file(void) | |||
308 | parse_error("keyword outside section"); | 310 | parse_error("keyword outside section"); |
309 | } | 311 | } |
310 | 312 | ||
311 | } while (1); | 313 | } /* while (1) */ |
312 | 314 | ||
313 | pe_label: | 315 | pe_label: |
314 | fprintf(stderr, "Parse error in %s, line %d: %s\n", | 316 | fprintf(stderr, "Parse error in %s, line %d: %s\n", |
@@ -322,10 +324,10 @@ static void parse_config_file(void) | |||
322 | sct_head = sct; | 324 | sct_head = sct; |
323 | } | 325 | } |
324 | } | 326 | } |
325 | |||
326 | #else | 327 | #else |
327 | #define parse_config_file() ((void)0) | 328 | #define parse_config_file() ((void)0) |
328 | #endif /* CONFIG_FEATURE_SUID_CONFIG */ | 329 | #endif /* FEATURE_SUID_CONFIG */ |
330 | |||
329 | 331 | ||
330 | #if ENABLE_FEATURE_SUID | 332 | #if ENABLE_FEATURE_SUID |
331 | static void check_suid(struct BB_applet *applet) | 333 | static void check_suid(struct BB_applet *applet) |
@@ -391,9 +393,8 @@ static void check_suid(struct BB_applet *applet) | |||
391 | } | 393 | } |
392 | } | 394 | } |
393 | #else | 395 | #else |
394 | #define check_suid(x) | 396 | #define check_suid(x) ((void)0) |
395 | #endif /* CONFIG_FEATURE_SUID */ | 397 | #endif /* FEATURE_SUID */ |
396 | |||
397 | 398 | ||
398 | 399 | ||
399 | #if ENABLE_FEATURE_COMPRESS_USAGE | 400 | #if ENABLE_FEATURE_COMPRESS_USAGE |
@@ -409,6 +410,7 @@ static const char *unpack_usage_messages(void) | |||
409 | if (pipe(input) < 0 || pipe(output) < 0) | 410 | if (pipe(input) < 0 || pipe(output) < 0) |
410 | exit(1); | 411 | exit(1); |
411 | 412 | ||
413 | //TODO: not NOMMU friendly! | ||
412 | pid = fork(); | 414 | pid = fork(); |
413 | switch (pid) { | 415 | switch (pid) { |
414 | case -1: /* error */ | 416 | case -1: /* error */ |
@@ -438,10 +440,10 @@ static const char *unpack_usage_messages(void) | |||
438 | full_read(output[0], buf, SIZEOF_usage_messages); | 440 | full_read(output[0], buf, SIZEOF_usage_messages); |
439 | return buf; | 441 | return buf; |
440 | } | 442 | } |
441 | |||
442 | #else | 443 | #else |
443 | #define unpack_usage_messages() usage_messages | 444 | #define unpack_usage_messages() usage_messages |
444 | #endif /* ENABLE_FEATURE_COMPRESS_USAGE */ | 445 | #endif /* FEATURE_COMPRESS_USAGE */ |
446 | |||
445 | 447 | ||
446 | void bb_show_usage(void) | 448 | void bb_show_usage(void) |
447 | { | 449 | { |
@@ -450,19 +452,23 @@ void bb_show_usage(void) | |||
450 | const char *usage_string = unpack_usage_messages(); | 452 | const char *usage_string = unpack_usage_messages(); |
451 | int i; | 453 | int i; |
452 | 454 | ||
453 | for (i = applet_using - applets; i > 0;) | 455 | i = current_applet - applets; |
454 | if (!*usage_string++) --i; | 456 | while (i) { |
457 | while (*usage_string++) continue; | ||
458 | i--; | ||
459 | } | ||
455 | 460 | ||
456 | format_string = "%s\n\nUsage: %s %s\n\n"; | 461 | format_string = "%s\n\nUsage: %s %s\n\n"; |
457 | if (*usage_string == '\b') | 462 | if (*usage_string == '\b') |
458 | format_string = "%s\n\nNo help available.\n\n"; | 463 | format_string = "%s\n\nNo help available.\n\n"; |
459 | fprintf(stderr, format_string, bb_msg_full_version, | 464 | fprintf(stderr, format_string, bb_msg_full_version, |
460 | applet_using->name, usage_string); | 465 | applet_name, usage_string); |
461 | } | 466 | } |
462 | 467 | ||
463 | exit(xfunc_error_retval); | 468 | exit(xfunc_error_retval); |
464 | } | 469 | } |
465 | 470 | ||
471 | |||
466 | static int applet_name_compare(const void *name, const void *vapplet) | 472 | static int applet_name_compare(const void *name, const void *vapplet) |
467 | { | 473 | { |
468 | const struct BB_applet *applet = vapplet; | 474 | const struct BB_applet *applet = vapplet; |
@@ -472,25 +478,168 @@ static int applet_name_compare(const void *name, const void *vapplet) | |||
472 | 478 | ||
473 | struct BB_applet *find_applet_by_name(const char *name) | 479 | struct BB_applet *find_applet_by_name(const char *name) |
474 | { | 480 | { |
481 | /* Do a binary search to find the applet entry given the name. */ | ||
475 | return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet), | 482 | return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet), |
476 | applet_name_compare); | 483 | applet_name_compare); |
477 | } | 484 | } |
478 | 485 | ||
479 | void run_applet_by_name(const char *name, int argc, char **argv) | 486 | |
487 | #if ENABLE_FEATURE_INSTALLER | ||
488 | /* | ||
489 | * directory table | ||
490 | * this should be consistent w/ the enum, busybox.h::Location, | ||
491 | * or else... | ||
492 | */ | ||
493 | static const char usr_bin [] = "/usr/bin"; | ||
494 | static const char usr_sbin[] = "/usr/sbin"; | ||
495 | |||
496 | static const char *const install_dir[] = { | ||
497 | &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */ | ||
498 | &usr_bin [4], /* "/bin" */ | ||
499 | &usr_sbin[4], /* "/sbin" */ | ||
500 | usr_bin, | ||
501 | usr_sbin | ||
502 | }; | ||
503 | |||
504 | /* create (sym)links for each applet */ | ||
505 | static void install_links(const char *busybox, int use_symbolic_links) | ||
480 | { | 506 | { |
481 | if (ENABLE_FEATURE_SUID_CONFIG) | 507 | int (*lf)(const char *, const char *) = link; |
482 | parse_config_file(); | 508 | char *fpc; |
509 | int i; | ||
510 | int rc; | ||
511 | |||
512 | if (use_symbolic_links) | ||
513 | lf = symlink; | ||
514 | |||
515 | for (i = 0; applets[i].name != NULL; i++) { | ||
516 | fpc = concat_path_file( | ||
517 | install_dir[applets[i].location], | ||
518 | applets[i].name); | ||
519 | rc = lf(busybox, fpc); | ||
520 | if (rc != 0 && errno != EEXIST) { | ||
521 | bb_perror_msg("%s", fpc); | ||
522 | } | ||
523 | free(fpc); | ||
524 | } | ||
525 | } | ||
526 | #else | ||
527 | #define install_links(x,y) ((void)0) | ||
528 | #endif /* FEATURE_INSTALLER */ | ||
483 | 529 | ||
484 | /* Do a binary search to find the applet entry given the name. */ | 530 | |
485 | applet_using = find_applet_by_name(name); | 531 | /* If we were called as "busybox..." */ |
486 | if (applet_using) { | 532 | static int busybox_main(int argc, char **argv) |
487 | applet_name = applet_using->name; | 533 | { |
534 | if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) { | ||
535 | int use_symbolic_links = 0; | ||
536 | char *busybox; | ||
537 | |||
538 | /* to use symlinks, or not to use symlinks... */ | ||
539 | if (argc > 2) | ||
540 | if (strcmp(argv[2], "-s") == 0) | ||
541 | use_symbolic_links = 1; | ||
542 | |||
543 | /* link */ | ||
544 | busybox = xmalloc_readlink_or_warn("/proc/self/exe"); | ||
545 | if (!busybox) | ||
546 | return 1; | ||
547 | install_links(busybox, use_symbolic_links); | ||
548 | if (ENABLE_FEATURE_CLEAN_UP) | ||
549 | free(busybox); | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | /* Deal with --help. Also print help when called with no arguments */ | ||
554 | |||
555 | if (argc == 1 || !strcmp(argv[1], "--help") ) { | ||
556 | if (argc > 2) { | ||
557 | /* set name for proper "<name>: applet not found" */ | ||
558 | applet_name = argv[2]; | ||
559 | run_applet_by_name(applet_name, 2, argv); | ||
560 | } else { | ||
561 | const struct BB_applet *a; | ||
562 | int col, output_width; | ||
563 | |||
564 | output_width = 80 - sizeof("start-stop-daemon, ") - 8; | ||
565 | if (ENABLE_FEATURE_AUTOWIDTH) { | ||
566 | /* Obtain the terminal width. */ | ||
567 | get_terminal_width_height(0, &output_width, NULL); | ||
568 | /* leading tab and room to wrap */ | ||
569 | output_width -= sizeof("start-stop-daemon, ") + 8; | ||
570 | } | ||
571 | |||
572 | printf("%s\n" | ||
573 | "Copyright (C) 1998-2006 Erik Andersen, Rob Landley, and others.\n" | ||
574 | "Licensed under GPLv2. See source distribution for full notice.\n" | ||
575 | "\n" | ||
576 | "Usage: busybox [function] [arguments]...\n" | ||
577 | " or: [function] [arguments]...\n" | ||
578 | "\n" | ||
579 | "\tBusyBox is a multi-call binary that combines many common Unix\n" | ||
580 | "\tutilities into a single executable. Most people will create a\n" | ||
581 | "\tlink to busybox for each function they wish to use and BusyBox\n" | ||
582 | "\twill act like whatever it was invoked as!\n" | ||
583 | "\nCurrently defined functions:\n", bb_msg_full_version); | ||
584 | col = 0; | ||
585 | a = applets; | ||
586 | while (a->name) { | ||
587 | col += printf("%s%s", (col ? ", " : "\t"), a->name); | ||
588 | a++; | ||
589 | if (col > output_width && a->name) { | ||
590 | puts(","); | ||
591 | col = 0; | ||
592 | } | ||
593 | } | ||
594 | puts("\n"); | ||
595 | return 0; | ||
596 | } | ||
597 | } else run_applet_by_name(argv[1], argc - 1, argv + 1); | ||
598 | |||
599 | bb_error_msg_and_die("applet not found"); | ||
600 | } | ||
601 | |||
602 | void run_applet_by_name(const char *name, int argc, char **argv) | ||
603 | { | ||
604 | current_applet = find_applet_by_name(name); | ||
605 | if (current_applet) { | ||
606 | applet_name = current_applet->name; | ||
488 | if (argc == 2 && !strcmp(argv[1], "--help")) | 607 | if (argc == 2 && !strcmp(argv[1], "--help")) |
489 | bb_show_usage(); | 608 | bb_show_usage(); |
490 | if (ENABLE_FEATURE_SUID) | 609 | if (ENABLE_FEATURE_SUID) |
491 | check_suid(applet_using); | 610 | check_suid(current_applet); |
492 | exit(applet_using->main(argc, argv)); | 611 | exit(current_applet->main(argc, argv)); |
493 | } | 612 | } |
494 | if (!strncmp(name, "busybox", 7)) | 613 | if (!strncmp(name, "busybox", 7)) |
495 | exit(busybox_main(argc, argv)); | 614 | exit(busybox_main(argc, argv)); |
496 | } | 615 | } |
616 | |||
617 | |||
618 | int main(int argc, char **argv) | ||
619 | { | ||
620 | const char *s; | ||
621 | |||
622 | applet_name = argv[0]; | ||
623 | #ifdef BB_NOMMU | ||
624 | /* NOMMU re-exec trick sets high-order bit in first byte of name */ | ||
625 | if (applet_name[0] & 0x80) { | ||
626 | re_execed = 1; | ||
627 | applet_name[0] &= 0x7f; | ||
628 | } | ||
629 | #endif | ||
630 | if (applet_name[0] == '-') | ||
631 | applet_name++; | ||
632 | s = strrchr(applet_name, '/'); | ||
633 | if (s) | ||
634 | applet_name = s + 1; | ||
635 | |||
636 | if (ENABLE_FEATURE_SUID_CONFIG) | ||
637 | parse_config_file(); | ||
638 | |||
639 | /* Set locale for everybody except 'init' */ | ||
640 | if (ENABLE_LOCALE_SUPPORT && getpid() != 1) | ||
641 | setlocale(LC_ALL, ""); | ||
642 | |||
643 | run_applet_by_name(applet_name, argc, argv); | ||
644 | bb_error_msg_and_die("applet not found"); | ||
645 | } | ||
diff --git a/applets/busybox.c b/applets/busybox.c deleted file mode 100644 index 47a8b4097..000000000 --- a/applets/busybox.c +++ /dev/null | |||
@@ -1,158 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * BusyBox' main applet dispatcher. | ||
4 | * | ||
5 | * Licensed under GPLv2, see file LICENSE in this tarball for details. | ||
6 | */ | ||
7 | #include "busybox.h" | ||
8 | |||
9 | const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE; | ||
10 | #ifdef BB_NOMMU | ||
11 | smallint re_execed; | ||
12 | #endif | ||
13 | |||
14 | #ifdef CONFIG_FEATURE_INSTALLER | ||
15 | /* | ||
16 | * directory table | ||
17 | * this should be consistent w/ the enum, busybox.h::Location, | ||
18 | * or else... | ||
19 | */ | ||
20 | static const char usr_bin [] = "/usr/bin"; | ||
21 | static const char usr_sbin[] = "/usr/sbin"; | ||
22 | |||
23 | static const char* const install_dir[] = { | ||
24 | &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */ | ||
25 | &usr_bin [4], /* "/bin" */ | ||
26 | &usr_sbin[4], /* "/sbin" */ | ||
27 | usr_bin, | ||
28 | usr_sbin | ||
29 | }; | ||
30 | |||
31 | /* abstract link() */ | ||
32 | typedef int (*link_func)(const char *, const char *); | ||
33 | |||
34 | /* create (sym)links for each applet */ | ||
35 | static void install_links(const char *busybox, int use_symbolic_links) | ||
36 | { | ||
37 | link_func lf = link; | ||
38 | char *fpc; | ||
39 | int i; | ||
40 | int rc; | ||
41 | |||
42 | if (use_symbolic_links) | ||
43 | lf = symlink; | ||
44 | |||
45 | for (i = 0; applets[i].name != NULL; i++) { | ||
46 | fpc = concat_path_file( | ||
47 | install_dir[applets[i].location], | ||
48 | applets[i].name); | ||
49 | rc = lf(busybox, fpc); | ||
50 | if (rc != 0 && errno != EEXIST) { | ||
51 | bb_perror_msg("%s", fpc); | ||
52 | } | ||
53 | free(fpc); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | #else | ||
58 | #define install_links(x,y) | ||
59 | #endif /* CONFIG_FEATURE_INSTALLER */ | ||
60 | |||
61 | int main(int argc, char **argv) | ||
62 | { | ||
63 | const char *s; | ||
64 | |||
65 | #ifdef BB_NOMMU | ||
66 | /* NOMMU re-exec trick sets high-order bit in first byte of name */ | ||
67 | if (argv[0][0] & 0x80) { | ||
68 | re_execed = 1; | ||
69 | argv[0][0] &= 0x7f; | ||
70 | } | ||
71 | #endif | ||
72 | |||
73 | applet_name = argv[0]; | ||
74 | if (*applet_name == '-') | ||
75 | applet_name++; | ||
76 | while ((s = strchr(applet_name, '/'))) | ||
77 | applet_name = s + 1; | ||
78 | |||
79 | /* Set locale for everybody except 'init' */ | ||
80 | if (ENABLE_LOCALE_SUPPORT && getpid() != 1) | ||
81 | setlocale(LC_ALL, ""); | ||
82 | |||
83 | run_applet_by_name(applet_name, argc, argv); | ||
84 | bb_error_msg_and_die("applet not found"); | ||
85 | } | ||
86 | |||
87 | int busybox_main(int argc, char **argv); | ||
88 | int busybox_main(int argc, char **argv) | ||
89 | { | ||
90 | /* | ||
91 | * This style of argument parsing doesn't scale well | ||
92 | * in the event that busybox starts wanting more --options. | ||
93 | * If someone has a cleaner approach, by all means implement it. | ||
94 | */ | ||
95 | if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) { | ||
96 | int use_symbolic_links = 0; | ||
97 | char *busybox; | ||
98 | |||
99 | /* to use symlinks, or not to use symlinks... */ | ||
100 | if (argc > 2) | ||
101 | if (strcmp(argv[2], "-s") == 0) | ||
102 | use_symbolic_links = 1; | ||
103 | |||
104 | /* link */ | ||
105 | // XXX: FIXME: this is broken. Why not just use argv[0] ? | ||
106 | busybox = xmalloc_readlink_or_warn("/proc/self/exe"); | ||
107 | if (!busybox) | ||
108 | return 1; | ||
109 | install_links(busybox, use_symbolic_links); | ||
110 | if (ENABLE_FEATURE_CLEAN_UP) | ||
111 | free(busybox); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /* Deal with --help. (Also print help when called with no arguments) */ | ||
116 | |||
117 | if (argc == 1 || !strcmp(argv[1], "--help") ) { | ||
118 | if (argc > 2) { | ||
119 | applet_name = argv[2]; | ||
120 | run_applet_by_name(applet_name, 2, argv); | ||
121 | } else { | ||
122 | const struct BB_applet *a; | ||
123 | int col, output_width; | ||
124 | |||
125 | output_width = 80 - sizeof("start-stop-daemon, ") - 8; | ||
126 | if (ENABLE_FEATURE_AUTOWIDTH) { | ||
127 | /* Obtain the terminal width. */ | ||
128 | get_terminal_width_height(0, &output_width, NULL); | ||
129 | /* leading tab and room to wrap */ | ||
130 | output_width -= sizeof("start-stop-daemon, ") + 8; | ||
131 | } | ||
132 | |||
133 | printf("%s\n" | ||
134 | "Copyright (C) 1998-2006 Erik Andersen, Rob Landley, and others.\n" | ||
135 | "Licensed under GPLv2. See source distribution for full notice.\n\n" | ||
136 | "Usage: busybox [function] [arguments]...\n" | ||
137 | " or: [function] [arguments]...\n\n" | ||
138 | "\tBusyBox is a multi-call binary that combines many common Unix\n" | ||
139 | "\tutilities into a single executable. Most people will create a\n" | ||
140 | "\tlink to busybox for each function they wish to use and BusyBox\n" | ||
141 | "\twill act like whatever it was invoked as!\n" | ||
142 | "\nCurrently defined functions:\n", bb_msg_full_version); | ||
143 | col = 0; | ||
144 | for (a = applets; a->name;) { | ||
145 | col += printf("%s%s", (col ? ", " : "\t"), a->name); | ||
146 | a++; | ||
147 | if (col > output_width && a->name) { | ||
148 | puts(","); | ||
149 | col = 0; | ||
150 | } | ||
151 | } | ||
152 | puts("\n"); | ||
153 | return 0; | ||
154 | } | ||
155 | } else run_applet_by_name(argv[1], argc - 1, argv + 1); | ||
156 | |||
157 | bb_error_msg_and_die("applet not found"); | ||
158 | } | ||
diff --git a/include/applets.h b/include/applets.h index 0ead89db8..e8d75b7d7 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -11,10 +11,6 @@ | |||
11 | * file result in the listing remaining in ascii order. You have been warned. | 11 | * file result in the listing remaining in ascii order. You have been warned. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #undef APPLET | ||
15 | #undef APPLET_ODDNAME | ||
16 | #undef APPLET_NOUSAGE | ||
17 | |||
18 | /* | 14 | /* |
19 | name - applet name as it is typed on command line | 15 | name - applet name as it is typed on command line |
20 | name2 - applet name, converted to C (ether-wake: name2 = ether_wake) | 16 | name2 - applet name, converted to C (ether-wake: name2 = ether_wake) |
@@ -352,3 +348,7 @@ USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER)) | |||
352 | }; | 348 | }; |
353 | 349 | ||
354 | #endif | 350 | #endif |
351 | |||
352 | #undef APPLET | ||
353 | #undef APPLET_NOUSAGE | ||
354 | #undef APPLET_ODDNAME | ||
diff --git a/include/busybox.h b/include/busybox.h index 76ff7b76a..988137497 100644 --- a/include/busybox.h +++ b/include/busybox.h | |||
@@ -31,8 +31,7 @@ struct BB_applet { | |||
31 | __extension__ enum SUIDRoot need_suid:4; | 31 | __extension__ enum SUIDRoot need_suid:4; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | /* Defined in busybox.c and applet.c */ | 34 | /* Defined in applet.c */ |
35 | extern int busybox_main(int argc, char **argv); | ||
36 | extern const struct BB_applet applets[]; | 35 | extern const struct BB_applet applets[]; |
37 | extern const unsigned short NUM_APPLETS; | 36 | extern const unsigned short NUM_APPLETS; |
38 | 37 | ||
diff --git a/include/libbb.h b/include/libbb.h index 6731adfe3..8f43aeafc 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -663,6 +663,7 @@ const struct hwtype *get_hwntype(int type); | |||
663 | 663 | ||
664 | #ifndef BUILD_INDIVIDUAL | 664 | #ifndef BUILD_INDIVIDUAL |
665 | extern struct BB_applet *find_applet_by_name(const char *name); | 665 | extern struct BB_applet *find_applet_by_name(const char *name); |
666 | /* Returns only if applet is not found. */ | ||
666 | extern void run_applet_by_name(const char *name, int argc, char **argv); | 667 | extern void run_applet_by_name(const char *name, int argc, char **argv); |
667 | #endif | 668 | #endif |
668 | 669 | ||