source: MondoRescue/branches/stable/mindi-busybox/libbb/run_parts.c@ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 18 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.