source: branches/2.2.2/mindi-busybox/libbb/run_parts.c @ 1247

Last change on this file since 1247 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 2.6 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * run command from specified directory
4 *
5 *
6 * Copyright (C) 2001 by Emanuele Aina <emanuele.aina@tiscali.it>
7 * rewrite to vfork usage by
8 * Copyright (C) 2002 by Vladimir Oleynik <dzo@simtreas.ru>
9 *
10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11 */
12
13
14#include <sys/types.h>
15#include <sys/wait.h>
16#include <stdlib.h>
17#include <dirent.h>
18#include <unistd.h>
19#include <ctype.h>
20#include <errno.h>
21
22#include "libbb.h"
23
24/* valid_name */
25/* True or false? Is this a valid filename (upper/lower alpha, digits,
26 * underscores, and hyphens only?)
27 */
28static int valid_name(const struct dirent *d)
29{
30    char *c = d->d_name;
31
32    while (*c) {
33        if (!isalnum(*c) && (*c != '_') && (*c != '-')) {
34            return 0;
35        }
36        ++c;
37    }
38    return 1;
39}
40
41/* test mode = 1 is the same as official run_parts
42 * test_mode = 2 means to fail silently on missing directories
43 */
44
45int run_parts(char **args, const unsigned char test_mode, char **env)
46{
47    struct dirent **namelist = 0;
48    struct stat st;
49    char *filename;
50    char *arg0 = args[0];
51    int entries;
52    int i;
53    int exitstatus = 0;
54
55#if __GNUC__
56    /* Avoid longjmp clobbering */
57    (void) &i;
58    (void) &exitstatus;
59#endif
60    /* scandir() isn't POSIX, but it makes things easy. */
61    entries = scandir(arg0, &namelist, valid_name, alphasort);
62
63    if (entries == -1) {
64        if (test_mode & 2) {
65            return(2);
66        }
67        bb_perror_msg_and_die("unable to open `%s'", arg0);
68    }
69
70    for (i = 0; i < entries; i++) {
71
72        filename = concat_path_file(arg0, namelist[i]->d_name);
73
74        xstat(filename, &st);
75        if (S_ISREG(st.st_mode) && !access(filename, X_OK)) {
76            if (test_mode) {
77                puts(filename);
78            } else {
79                /* exec_errno is common vfork variable */
80                volatile int exec_errno = 0;
81                int result;
82                int pid;
83
84                if ((pid = vfork()) < 0) {
85                    bb_perror_msg_and_die("failed to fork");
86                } else if (!pid) {
87                    args[0] = filename;
88                    execve(filename, args, env);
89                    exec_errno = errno;
90                    _exit(1);
91                }
92
93                waitpid(pid, &result, 0);
94                if(exec_errno) {
95                    errno = exec_errno;
96                    bb_perror_msg("failed to exec %s", filename);
97                    exitstatus = 1;
98                }
99                if (WIFEXITED(result) && WEXITSTATUS(result)) {
100                    bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result));
101                    exitstatus = 1;
102                } else if (WIFSIGNALED(result)) {
103                    bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result));
104                    exitstatus = 1;
105                }
106            }
107        }
108        else if (!S_ISDIR(st.st_mode)) {
109            bb_error_msg("component %s is not an executable plain file", filename);
110            exitstatus = 1;
111        }
112
113        free(namelist[i]);
114        free(filename);
115    }
116    free(namelist);
117
118    return(exitstatus);
119}
Note: See TracBrowser for help on using the repository browser.