Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/libbb/appletlib.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/libbb/appletlib.c
r3232 r3621 30 30 31 31 #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ 32 32 || defined(__APPLE__) \ 33 33 ) 34 34 # include <malloc.h> /* for mallopt */ … … 53 53 #include "usage_compressed.h" 54 54 55 static void run_applet_and_exit(const char *name, char **argv) NORETURN; 55 56 56 57 #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE … … 131 132 full_write2_str(" "); 132 133 full_write2_str(p); 133 full_write2_str("\n \n");134 full_write2_str("\n"); 134 135 } 135 136 if (ENABLE_FEATURE_CLEAN_UP) … … 140 141 } 141 142 142 #if NUM_APPLETS > 8143 static int applet_name_compare(const void *name, const void *idx)144 {145 int i = (int)(ptrdiff_t)idx - 1;146 return strcmp(name, APPLET_NAME(i));147 }148 #endif149 143 int FAST_FUNC find_applet_by_name(const char *name) 150 144 { 151 #if NUM_APPLETS > 8 152 /* Do a binary search to find the applet entry given the name. */145 unsigned i, max; 146 int j; 153 147 const char *p; 154 p = bsearch(name, (void*)(ptrdiff_t)1, ARRAY_SIZE(applet_main), 1, applet_name_compare); 155 /* 156 * if (!p) return -1; 157 * ^^^^^^^^^^^^^^^^^^ the code below will do this if p == NULL :) 158 */ 159 return (int)(ptrdiff_t)p - 1; 148 149 /* The commented-out word-at-a-time code is ~40% faster, but +160 bytes. 150 * "Faster" here saves ~0.5 microsecond of real time - not worth it. 151 */ 152 #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ 153 uint32_t n32; 154 155 /* Handle all names < 2 chars long early */ 156 if (name[0] == '\0') 157 return -1; /* "" is not a valid applet name */ 158 if (name[1] == '\0') { 159 if (!ENABLE_TEST) 160 return -1; /* 1-char name is not valid */ 161 if (name[0] != ']') 162 return -1; /* 1-char name which isn't "[" is not valid */ 163 /* applet "[" is always applet #0: */ 164 return 0; 165 } 166 #endif 167 168 p = applet_names; 169 i = 0; 170 #if KNOWN_APPNAME_OFFSETS <= 0 171 max = NUM_APPLETS; 160 172 #else 161 /* A version which does not pull in bsearch */ 162 int i = 0; 163 const char *p = applet_names; 164 while (i < NUM_APPLETS) { 165 if (strcmp(name, p) == 0) 173 max = NUM_APPLETS * KNOWN_APPNAME_OFFSETS; 174 for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) { 175 const char *pp = applet_names + applet_nameofs[j]; 176 if (strcmp(name, pp) >= 0) { 177 //bb_error_msg("name:'%s' >= pp:'%s'", name, pp); 178 p = pp; 179 i = max - NUM_APPLETS; 180 break; 181 } 182 max -= NUM_APPLETS; 183 } 184 max /= (unsigned)KNOWN_APPNAME_OFFSETS; 185 i /= (unsigned)KNOWN_APPNAME_OFFSETS; 186 //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max); 187 #endif 188 189 /* Open-coded linear search without strcmp/strlen calls for speed */ 190 191 #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ 192 /* skip "[\0" name, it's surely not it */ 193 if (ENABLE_TEST && LONE_CHAR(p, '[')) 194 i++, p += 2; 195 /* All remaining applet names in p[] are at least 2 chars long */ 196 /* name[] is also at least 2 chars long */ 197 198 n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16); 199 while (i < max) { 200 uint32_t p32; 201 char ch; 202 203 /* Quickly check match of the first 3 bytes */ 204 move_from_unaligned32(p32, p); 205 p += 3; 206 if ((p32 & 0x00ffffff) != n32) { 207 /* Most likely case: 3 first bytes do not match */ 208 i++; 209 if ((p32 & 0x00ff0000) == '\0') 210 continue; // p[2] was NUL 211 p++; 212 if ((p32 & 0xff000000) == '\0') 213 continue; // p[3] was NUL 214 /* p[0..3] aren't matching and none is NUL, check the rest */ 215 while (*p++ != '\0') 216 continue; 217 continue; 218 } 219 220 /* Unlikely branch: first 3 bytes ([0..2]) match */ 221 if ((p32 & 0x00ff0000) == '\0') { 222 /* name is 2-byte long, it is full match */ 223 //bb_error_msg("found:'%s' i:%u", name, i); 166 224 return i; 167 p += strlen(p) + 1; 225 } 226 /* Check remaining bytes [3..NUL] */ 227 ch = (p32 >> 24); 228 j = 3; 229 while (ch == name[j]) { 230 if (ch == '\0') { 231 //bb_error_msg("found:'%s' i:%u", name, i); 232 return i; 233 } 234 ch = *++p; 235 j++; 236 } 237 /* Not a match. Skip it, including NUL */ 238 while (ch != '\0') 239 ch = *++p; 240 p++; 241 i++; 242 } 243 return -1; 244 #else 245 while (i < max) { 246 char ch; 247 j = 0; 248 /* Do we see "name\0" in applet_names[p] position? */ 249 while ((ch = *p) == name[j]) { 250 if (ch == '\0') { 251 //bb_error_msg("found:'%s' i:%u", name, i); 252 return i; /* yes */ 253 } 254 p++; 255 j++; 256 } 257 /* No. 258 * p => 1st non-matching char in applet_names[], 259 * skip to and including NUL. 260 */ 261 while (ch != '\0') 262 ch = *++p; 263 p++; 168 264 i++; 169 265 } … … 185 281 applet_name = applet; 186 282 187 /* Set locale for everybody except 'init' */ 188 if (ENABLE_LOCALE_SUPPORT && getpid() != 1) 283 if (ENABLE_LOCALE_SUPPORT) 189 284 setlocale(LC_ALL, ""); 190 285 … … 195 290 && !argv[2] 196 291 && strcmp(argv[1], "--help") == 0 197 && strncmp(applet, "busybox", 7) != 0292 && !is_prefixed_with(applet, "busybox") 198 293 ) { 199 294 /* Special case. POSIX says "test --help" … … 439 534 } 440 535 *e = ':'; /* get_uidgid needs USER:GROUP syntax */ 441 if (get_uidgid(&sct->m_ugid, s , /*allow_numeric:*/ 1) == 0) {536 if (get_uidgid(&sct->m_ugid, s) == 0) { 442 537 errmsg = "unknown user/group"; 443 538 goto pe_label; … … 459 554 goto pe_label; 460 555 } 461 462 556 } /* while (1) */ 463 557 … … 586 680 int (*lf)(const char *, const char *); 587 681 char *fpc; 682 const char *appname = applet_names; 588 683 unsigned i; 589 684 int rc; … … 596 691 fpc = concat_path_file( 597 692 custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], 598 APPLET_NAME(i));693 appname); 599 694 // debug: bb_error_msg("%slinking %s to busybox", 600 695 // use_symbolic_links ? "sym" : "", fpc); … … 604 699 } 605 700 free(fpc); 606 } 607 } 608 # else 609 # define install_links(x,y,z) ((void)0) 701 while (*appname++ != '\0') 702 continue; 703 } 704 } 705 # elif ENABLE_BUSYBOX 706 static void install_links(const char *busybox UNUSED_PARAM, 707 int use_symbolic_links UNUSED_PARAM, 708 char *custom_install_dir UNUSED_PARAM) 709 { 710 } 610 711 # endif 611 712 713 # if ENABLE_BUSYBOX 612 714 /* If we were called as "busybox..." */ 613 715 static int busybox_main(char **argv) … … 622 724 if (ENABLE_FEATURE_AUTOWIDTH) { 623 725 /* Obtain the terminal width */ 624 get_terminal_width_height(0, &output_width, NULL);726 output_width = get_terminal_width(2); 625 727 } 626 728 … … 629 731 full_write2_str(" multi-call binary.\n"); /* reuse */ 630 732 full_write2_str( 631 "BusyBox is copyrighted by many authors between 1998-201 2.\n"733 "BusyBox is copyrighted by many authors between 1998-2015.\n" 632 734 "Licensed under GPLv2. See source distribution for detailed\n" 633 735 "copyright notices.\n" … … 640 742 " or: function [arguments]...\n" 641 743 "\n" 744 IF_NOT_FEATURE_SH_STANDALONE( 642 745 "\tBusyBox is a multi-call binary that combines many common Unix\n" 643 746 "\tutilities into a single executable. Most people will create a\n" 644 747 "\tlink to busybox for each function they wish to use and BusyBox\n" 645 748 "\twill act like whatever it was invoked as.\n" 749 ) 750 IF_FEATURE_SH_STANDALONE( 751 "\tBusyBox is a multi-call binary that combines many common Unix\n" 752 "\tutilities into a single executable. The shell in this build\n" 753 "\tis configured to run built-in utilities without $PATH search.\n" 754 "\tYou don't need to install a link to busybox for each utility.\n" 755 "\tTo run external program, use full path (/sbin/ip instead of ip).\n" 756 ) 646 757 "\n" 647 758 "Currently defined functions:\n" … … 671 782 } 672 783 673 if ( strncmp(argv[1], "--list", 6) == 0) {784 if (is_prefixed_with(argv[1], "--list")) { 674 785 unsigned i = 0; 675 786 const char *a = applet_names; 676 787 dup2(1, 2); 677 788 while (*a) { 678 # if ENABLE_FEATURE_INSTALLER789 # if ENABLE_FEATURE_INSTALLER 679 790 if (argv[1][6]) /* --list-full? */ 680 791 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); 681 # endif792 # endif 682 793 full_write2_str(a); 683 794 full_write2_str("\n"); 684 795 i++; 685 a += strlen(a) + 1; 796 while (*a++ != '\0') 797 continue; 686 798 } 687 799 return 0; … … 727 839 applet_name = bb_get_last_path_component_nostrip(argv[0]); 728 840 run_applet_and_exit(applet_name, argv); 729 730 /*bb_error_msg_and_die("applet not found"); - sucks in printf */ 731 full_write2_str(applet_name); 732 full_write2_str(": applet not found\n"); 733 xfunc_die(); 734 } 841 } 842 # endif 735 843 736 844 void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) … … 743 851 /* Reinit some shared global data */ 744 852 xfunc_error_retval = EXIT_FAILURE; 745 746 applet_name = APPLET_NAME(applet_no); 747 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 748 /* Special case. POSIX says "test --help" 749 * should be no different from e.g. "test --foo". */ 750 //TODO: just compare applet_no with APPLET_NO_test 751 if (!ENABLE_TEST || strcmp(applet_name, "test") != 0) { 752 /* If you want "foo --help" to return 0: */ 753 /*xfunc_error_retval = 0;*/ 853 applet_name = bb_get_last_path_component_nostrip(argv[0]); 854 855 /* Special case. POSIX says "test --help" 856 * should be no different from e.g. "test --foo". 857 * Thus for "test", we skip --help check. 858 * "true" and "false" are also special. 859 */ 860 if (1 861 #if defined APPLET_NO_test 862 && applet_no != APPLET_NO_test 863 #endif 864 #if defined APPLET_NO_true 865 && applet_no != APPLET_NO_true 866 #endif 867 #if defined APPLET_NO_false 868 && applet_no != APPLET_NO_false 869 #endif 870 ) { 871 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 872 /* Make "foo --help" exit with 0: */ 873 xfunc_error_retval = 0; 754 874 bb_show_usage(); 755 875 } … … 760 880 } 761 881 762 void FAST_FUNC run_applet_and_exit(const char *name, char **argv) 763 { 764 int applet = find_applet_by_name(name); 882 static NORETURN void run_applet_and_exit(const char *name, char **argv) 883 { 884 int applet; 885 886 # if ENABLE_BUSYBOX 887 if (is_prefixed_with(name, "busybox")) 888 exit(busybox_main(argv)); 889 # endif 890 /* find_applet_by_name() search is more expensive, so goes second */ 891 applet = find_applet_by_name(name); 765 892 if (applet >= 0) 766 893 run_applet_no_and_exit(applet, argv); 767 if (strncmp(name, "busybox", 7) == 0) 768 exit(busybox_main(argv)); 894 895 /*bb_error_msg_and_die("applet not found"); - links in printf */ 896 full_write2_str(applet_name); 897 full_write2_str(": applet not found\n"); 898 /* POSIX: "If a command is not found, the exit status shall be 127" */ 899 exit(127); 769 900 } 770 901 … … 779 910 #endif 780 911 { 912 #if 0 913 /* TODO: find a use for a block of memory between end of .bss 914 * and end of page. For example, I'm getting "_end:0x812e698 2408 bytes" 915 * - more than 2k of wasted memory (in this particular build) 916 * *per each running process*! 917 * (If your linker does not generate "_end" name, weak attribute 918 * makes &_end == NULL, end_len == 0 here.) 919 */ 920 extern char _end[] __attribute__((weak)); 921 unsigned end_len = (-(int)_end) & 0xfff; 922 printf("_end:%p %u bytes\n", &_end, end_len); 923 #endif 924 781 925 /* Tweak malloc for reduced memory consumption */ 782 926 #ifdef M_TRIM_THRESHOLD … … 804 948 #if defined(SINGLE_APPLET_MAIN) 805 949 /* Only one applet is selected in .config */ 806 if (argv[1] && strncmp(argv[0], "busybox", 7) == 0) {950 if (argv[1] && is_prefixed_with(argv[0], "busybox")) { 807 951 /* "busybox <applet> <params>" should still work as expected */ 808 952 argv++; … … 814 958 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); 815 959 960 #if !ENABLE_BUSYBOX 961 if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) 962 argv++; 963 #endif 816 964 applet_name = argv[0]; 817 965 if (applet_name[0] == '-') … … 822 970 823 971 run_applet_and_exit(applet_name, argv); 824 825 /*bb_error_msg_and_die("applet not found"); - sucks in printf */ 826 full_write2_str(applet_name); 827 full_write2_str(": applet not found\n"); 828 xfunc_die(); 829 #endif 830 } 972 #endif 973 }
Note:
See TracChangeset
for help on using the changeset viewer.