Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/libbb/vfork_daemon_rexec.c

    r1765 r2725  
    1313 * Modified for uClibc by Erik Andersen <andersee@debian.org>
    1414 *
    15  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     15 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1616 */
    1717
    18 #include <paths.h>
    19 #include "busybox.h" /* for struct bb_applet */
     18#include "busybox.h" /* uses applet tables */
    2019
    2120/* This does a fork/exec in one call, using vfork().  Returns PID of new child,
    2221 * -1 for failure.  Runs argv[0], searching path if that has no / in it. */
    23 pid_t spawn(char **argv)
     22pid_t FAST_FUNC spawn(char **argv)
    2423{
    2524    /* Compiler should not optimize stores here */
     
    2726    pid_t pid;
    2827
    29 // Ain't it a good place to fflush(NULL)?
     28    fflush_all();
    3029
    3130    /* Be nice to nommu machines. */
     
    4342         */
    4443        failed = errno;
     44        /* mount, for example, does not want the message */
     45        /*bb_perror_msg("can't execute '%s'", argv[0]);*/
    4546        _exit(111);
    4647    }
     
    5253     * If 111 - then it (most probably) failed to exec */
    5354    if (failed) {
     55        safe_waitpid(pid, NULL, 0); /* prevent zombie */
    5456        errno = failed;
    5557        return -1;
     
    5961
    6062/* Die with an error message if we can't spawn a child process. */
    61 pid_t xspawn(char **argv)
     63pid_t FAST_FUNC xspawn(char **argv)
    6264{
    6365    pid_t pid = spawn(argv);
    6466    if (pid < 0)
    65         bb_perror_msg_and_die("%s", *argv);
     67        bb_simple_perror_msg_and_die(*argv);
    6668    return pid;
    6769}
    6870
    69 // Wait for the specified child PID to exit, returning child's error return.
    70 int wait4pid(int pid)
    71 {
    72     int status;
    73 
    74     if (pid <= 0) {
    75         /*errno = ECHILD; -- wrong. */
    76         /* we expect errno to be already set from failed [v]fork/exec */
    77         return -1;
    78     }
    79     if (waitpid(pid, &status, 0) == -1)
    80         return -1;
    81     if (WIFEXITED(status))
    82         return WEXITSTATUS(status);
    83     if (WIFSIGNALED(status))
    84         return WTERMSIG(status) + 1000;
    85     return 0;
    86 }
    87 
    88 int wait_nohang(int *wstat)
    89 {
    90     return waitpid(-1, wstat, WNOHANG);
    91 }
    92 
    93 int wait_pid(int *wstat, int pid)
    94 {
    95     int r;
    96 
    97     do
    98         r = waitpid(pid, wstat, 0);
    99     while ((r == -1) && (errno == EINTR));
    100     return r;
    101 }
    102 
    10371#if ENABLE_FEATURE_PREFER_APPLETS
    104 void save_nofork_data(struct nofork_save_area *save)
     72void FAST_FUNC save_nofork_data(struct nofork_save_area *save)
    10573{
    10674    memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp));
    107     save->current_applet = current_applet;
     75    save->applet_name = applet_name;
    10876    save->xfunc_error_retval = xfunc_error_retval;
    10977    save->option_mask32 = option_mask32;
     
    11280}
    11381
    114 void restore_nofork_data(struct nofork_save_area *save)
     82void FAST_FUNC restore_nofork_data(struct nofork_save_area *save)
    11583{
    11684    memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp));
    117     current_applet = save->current_applet;
     85    applet_name = save->applet_name;
    11886    xfunc_error_retval = save->xfunc_error_retval;
    11987    option_mask32 = save->option_mask32;
    12088    die_sleep = save->die_sleep;
    121 
    122     applet_name = current_applet->name;
    123 }
    124 
    125 int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv)
     89}
     90
     91int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv)
    12692{
    12793    int rc, argc;
    12894
    129     current_applet = a;
    130     applet_name = a->name;
     95    applet_name = APPLET_NAME(applet_no);
     96
    13197    xfunc_error_retval = EXIT_FAILURE;
    132     /*option_mask32 = 0; - not needed */
    133     /* special flag for xfunc_die(). If xfunc will "die"
     98
     99    /* Special flag for xfunc_die(). If xfunc will "die"
    134100     * in NOFORK applet, xfunc_die() sees negative
    135101     * die_sleep and longjmp here instead. */
    136102    die_sleep = -1;
     103
     104    /* In case getopt() or getopt32() was already called:
     105     * reset the libc getopt() function, which keeps internal state.
     106     *
     107     * BSD-derived getopt() functions require that optind be set to 1 in
     108     * order to reset getopt() state.  This used to be generally accepted
     109     * way of resetting getopt().  However, glibc's getopt()
     110     * has additional getopt() state beyond optind, and requires that
     111     * optind be set to zero to reset its state.  So the unfortunate state of
     112     * affairs is that BSD-derived versions of getopt() misbehave if
     113     * optind is set to 0 in order to reset getopt(), and glibc's getopt()
     114     * will core dump if optind is set 1 in order to reset getopt().
     115     *
     116     * More modern versions of BSD require that optreset be set to 1 in
     117     * order to reset getopt().  Sigh.  Standards, anyone?
     118     */
     119#ifdef __GLIBC__
     120    optind = 0;
     121#else /* BSD style */
     122    optind = 1;
     123    /* optreset = 1; */
     124#endif
     125    /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */
     126    /* (values above are what they initialized to in glibc and uclibc) */
     127    /* option_mask32 = 0; - not needed, no applet depends on it being 0 */
    137128
    138129    argc = 1;
     
    147138        memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
    148139        /* Finally we can call NOFORK applet's main() */
    149         rc = a->main(argc, tmp_argv);
     140        rc = applet_main[applet_no](argc, tmp_argv);
     141
     142    /* The whole reason behind nofork_save_area is that <applet>_main
     143     * may exit non-locally! For example, in hush Ctrl-Z tries
     144     * (modulo bugs) to dynamically create a child (backgrounded task)
     145     * if it detects that Ctrl-Z was pressed when a NOFORK was running.
     146     * Testcase: interactive "rm -i".
     147     * Don't fool yourself into thinking "and <applet>_main() returns
     148     * quickly here" and removing "useless" nofork_save_area code. */
     149
    150150    } else { /* xfunc died in NOFORK applet */
    151151        /* in case they meant to return 0... */
     
    154154    }
    155155
    156     /* Restoring globals */
     156    /* Restoring some globals */
    157157    restore_nofork_data(old);
    158     return rc;
    159 }
    160 
    161 int run_nofork_applet(const struct bb_applet *a, char **argv)
     158
     159    /* Other globals can be simply reset to defaults */
     160#ifdef __GLIBC__
     161    optind = 0;
     162#else /* BSD style */
     163    optind = 1;
     164#endif
     165
     166    return rc & 0xff; /* don't confuse people with "exitcodes" >255 */
     167}
     168
     169int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
    162170{
    163171    struct nofork_save_area old;
     
    165173    /* Saving globals */
    166174    save_nofork_data(&old);
    167     return run_nofork_applet_prime(&old, a, argv);
     175    return run_nofork_applet_prime(&old, applet_no, argv);
    168176}
    169177#endif /* FEATURE_PREFER_APPLETS */
    170178
    171 int spawn_and_wait(char **argv)
     179int FAST_FUNC spawn_and_wait(char **argv)
    172180{
    173181    int rc;
    174182#if ENABLE_FEATURE_PREFER_APPLETS
    175     const struct bb_applet *a = find_applet_by_name(argv[0]);
    176 
    177     if (a && (a->nofork
     183    int a = find_applet_by_name(argv[0]);
     184
     185    if (a >= 0 && (APPLET_IS_NOFORK(a)
    178186#if BB_MMU
    179          || a->noexec /* NOEXEC trick needs fork() */
     187            || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */
    180188#endif
    181189    )) {
    182190#if BB_MMU
    183         if (a->nofork)
     191        if (APPLET_IS_NOFORK(a))
    184192#endif
    185193        {
     
    194202        /* child */
    195203        xfunc_error_retval = EXIT_FAILURE;
    196         current_applet = a;
    197         run_current_applet_and_exit(argv);
     204        run_applet_no_and_exit(a, argv);
    198205#endif
    199206    }
     
    204211
    205212#if !BB_MMU
    206 void re_exec(char **argv)
     213void FAST_FUNC re_exec(char **argv)
    207214{
    208215    /* high-order bit of first char in argv[0] is a hidden
     
    210217    argv[0][0] |= 0x80;
    211218    execv(bb_busybox_exec_path, argv);
    212     bb_perror_msg_and_die("exec %s", bb_busybox_exec_path);
    213 }
    214 
    215 void forkexit_or_rexec(char **argv)
     219    bb_perror_msg_and_die("can't execute '%s'", bb_busybox_exec_path);
     220}
     221
     222pid_t FAST_FUNC fork_or_rexec(char **argv)
    216223{
    217224    pid_t pid;
    218225    /* Maybe we are already re-execed and come here again? */
    219226    if (re_execed)
    220         return;
    221 
    222     pid = vfork();
    223     if (pid < 0) /* wtf? */
    224         bb_perror_msg_and_die("vfork");
     227        return 0;
     228    pid = xvfork();
    225229    if (pid) /* parent */
    226         exit(0);
     230        return pid;
    227231    /* child - re-exec ourself */
    228232    re_exec(argv);
    229233}
    230 #else
    231 /* Dance around (void)...*/
    232 #undef forkexit_or_rexec
    233 void forkexit_or_rexec(void)
    234 {
    235     pid_t pid;
    236     pid = fork();
    237     if (pid < 0) /* wtf? */
    238         bb_perror_msg_and_die("fork");
    239     if (pid) /* parent */
    240         exit(0);
    241     /* child */
    242 }
    243 #define forkexit_or_rexec(argv) forkexit_or_rexec()
    244234#endif
    245235
    246236/* Due to a #define in libbb.h on MMU systems we actually have 1 argument -
    247237 * char **argv "vanishes" */
    248 void bb_daemonize_or_rexec(int flags, char **argv)
     238void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
    249239{
    250240    int fd;
     
    259249    }
    260250
    261     fd = xopen(bb_dev_null, O_RDWR);
     251    fd = open(bb_dev_null, O_RDWR);
     252    if (fd < 0) {
     253        /* NB: we can be called as bb_sanitize_stdio() from init
     254         * or mdev, and there /dev/null may legitimately not (yet) exist!
     255         * Do not use xopen above, but obtain _ANY_ open descriptor,
     256         * even bogus one as below. */
     257        fd = xopen("/", O_RDONLY); /* don't believe this can fail */
     258    }
    262259
    263260    while ((unsigned)fd < 2)
     
    265262
    266263    if (!(flags & DAEMON_ONLY_SANITIZE)) {
    267         forkexit_or_rexec(argv);
     264        if (fork_or_rexec(argv))
     265            exit(EXIT_SUCCESS); /* parent */
    268266        /* if daemonizing, make sure we detach from stdio & ctty */
    269267        setsid();
     
    280278}
    281279
    282 void bb_sanitize_stdio(void)
     280void FAST_FUNC bb_sanitize_stdio(void)
    283281{
    284282    bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL);
Note: See TracChangeset for help on using the changeset viewer.