Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/libbb/appletlib.c


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/libbb/appletlib.c

    r3232 r3621  
    3030
    3131#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
    32         || defined(__APPLE__) \
     32    || defined(__APPLE__) \
    3333    )
    3434# include <malloc.h> /* for mallopt */
     
    5353#include "usage_compressed.h"
    5454
     55static void run_applet_and_exit(const char *name, char **argv) NORETURN;
    5556
    5657#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
     
    131132            full_write2_str(" ");
    132133            full_write2_str(p);
    133             full_write2_str("\n\n");
     134            full_write2_str("\n");
    134135        }
    135136        if (ENABLE_FEATURE_CLEAN_UP)
     
    140141}
    141142
    142 #if NUM_APPLETS > 8
    143 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 #endif
    149143int FAST_FUNC find_applet_by_name(const char *name)
    150144{
    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;
    153147    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;
    160172#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);
    166224            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++;
    168264        i++;
    169265    }
     
    185281    applet_name = applet;
    186282
    187     /* Set locale for everybody except 'init' */
    188     if (ENABLE_LOCALE_SUPPORT && getpid() != 1)
     283    if (ENABLE_LOCALE_SUPPORT)
    189284        setlocale(LC_ALL, "");
    190285
     
    195290     && !argv[2]
    196291     && strcmp(argv[1], "--help") == 0
    197      && strncmp(applet, "busybox", 7) != 0
     292     && !is_prefixed_with(applet, "busybox")
    198293    ) {
    199294        /* Special case. POSIX says "test --help"
     
    439534                    }
    440535                    *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) {
    442537                        errmsg = "unknown user/group";
    443538                        goto pe_label;
     
    459554            goto pe_label;
    460555        }
    461 
    462556    } /* while (1) */
    463557
     
    586680    int (*lf)(const char *, const char *);
    587681    char *fpc;
     682        const char *appname = applet_names;
    588683    unsigned i;
    589684    int rc;
     
    596691        fpc = concat_path_file(
    597692                custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)],
    598                 APPLET_NAME(i));
     693                appname);
    599694        // debug: bb_error_msg("%slinking %s to busybox",
    600695        //      use_symbolic_links ? "sym" : "", fpc);
     
    604699        }
    605700        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
     706static void install_links(const char *busybox UNUSED_PARAM,
     707        int use_symbolic_links UNUSED_PARAM,
     708        char *custom_install_dir UNUSED_PARAM)
     709{
     710}
    610711# endif
    611712
     713# if ENABLE_BUSYBOX
    612714/* If we were called as "busybox..." */
    613715static int busybox_main(char **argv)
     
    622724        if (ENABLE_FEATURE_AUTOWIDTH) {
    623725            /* Obtain the terminal width */
    624             get_terminal_width_height(0, &output_width, NULL);
     726            output_width = get_terminal_width(2);
    625727        }
    626728
     
    629731        full_write2_str(" multi-call binary.\n"); /* reuse */
    630732        full_write2_str(
    631             "BusyBox is copyrighted by many authors between 1998-2012.\n"
     733            "BusyBox is copyrighted by many authors between 1998-2015.\n"
    632734            "Licensed under GPLv2. See source distribution for detailed\n"
    633735            "copyright notices.\n"
     
    640742            "   or: function [arguments]...\n"
    641743            "\n"
     744            IF_NOT_FEATURE_SH_STANDALONE(
    642745            "\tBusyBox is a multi-call binary that combines many common Unix\n"
    643746            "\tutilities into a single executable.  Most people will create a\n"
    644747            "\tlink to busybox for each function they wish to use and BusyBox\n"
    645748            "\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            )
    646757            "\n"
    647758            "Currently defined functions:\n"
     
    671782    }
    672783
    673     if (strncmp(argv[1], "--list", 6) == 0) {
     784    if (is_prefixed_with(argv[1], "--list")) {
    674785        unsigned i = 0;
    675786        const char *a = applet_names;
    676787        dup2(1, 2);
    677788        while (*a) {
    678 # if ENABLE_FEATURE_INSTALLER
     789#  if ENABLE_FEATURE_INSTALLER
    679790            if (argv[1][6]) /* --list-full? */
    680791                full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
    681 # endif
     792#  endif
    682793            full_write2_str(a);
    683794            full_write2_str("\n");
    684795            i++;
    685             a += strlen(a) + 1;
     796            while (*a++ != '\0')
     797                continue;
    686798        }
    687799        return 0;
     
    727839    applet_name = bb_get_last_path_component_nostrip(argv[0]);
    728840    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
    735843
    736844void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
     
    743851    /* Reinit some shared global data */
    744852    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;
    754874            bb_show_usage();
    755875        }
     
    760880}
    761881
    762 void FAST_FUNC run_applet_and_exit(const char *name, char **argv)
    763 {
    764     int applet = find_applet_by_name(name);
     882static 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);
    765892    if (applet >= 0)
    766893        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);
    769900}
    770901
     
    779910#endif
    780911{
     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
    781925    /* Tweak malloc for reduced memory consumption */
    782926#ifdef M_TRIM_THRESHOLD
     
    804948#if defined(SINGLE_APPLET_MAIN)
    805949    /* 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")) {
    807951        /* "busybox <applet> <params>" should still work as expected */
    808952        argv++;
     
    814958    lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
    815959
     960#if !ENABLE_BUSYBOX
     961    if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox"))
     962        argv++;
     963#endif
    816964    applet_name = argv[0];
    817965    if (applet_name[0] == '-')
     
    822970
    823971    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.