It turns out that DODMALLOC was broken when I reorganized busybox.h
[oweals/busybox.git] / applets / busybox.c
1 /* vi: set sw=4 ts=4: */
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include "busybox.h"
8
9 #undef APPLET
10 #undef APPLET_NOUSAGE
11 #undef PROTOTYPES
12 #include "applets.h"
13
14 #define bb_need_full_version
15 #define BB_DECLARE_EXTERN
16 #include "messages.c"
17
18 static int been_there_done_that = 0;
19 const char *applet_name;
20
21 #ifdef BB_FEATURE_INSTALLER
22 /* 
23  * directory table
24  *              this should be consistent w/ the enum, busybox.h::Location,
25  *              or else...
26  */
27 static char* install_dir[] = {
28         "/",
29         "/bin",
30         "/sbin",
31         "/usr/bin",
32         "/usr/sbin",
33 };
34
35 /* abstract link() */
36 typedef int (*__link_f)(const char *, const char *);
37
38 /* 
39  * Where in the filesystem is this busybox?
40  * [return]
41  *              malloc'd string w/ full pathname of busybox's location
42  *              NULL on failure
43  */
44 static char *busybox_fullpath()
45 {
46         pid_t pid;
47         char path[256];
48         char proc[256];
49         int len;
50
51         pid = getpid();
52         sprintf(proc, "/proc/%d/exe", pid);
53         len = readlink(proc, path, 256);
54         if (len != -1) {
55                 path[len] = 0;
56         } else {
57                 perror_msg("%s", proc);
58                 return NULL;
59         }
60         return strdup(path);
61 }
62
63 /* create (sym)links for each applet */
64 static void install_links(const char *busybox, int use_symbolic_links)
65 {
66         __link_f Link = link;
67
68         char command[256];
69         int i;
70         int rc;
71
72         if (use_symbolic_links) 
73                 Link = symlink;
74
75         for (i = 0; applets[i].name != NULL; i++) {
76                 sprintf ( command, "%s/%s", 
77                                 install_dir[applets[i].location], applets[i].name);
78                 rc = Link(busybox, command);
79
80                 if (rc) {
81                         perror_msg("%s", command);
82                 }
83         }
84 }
85
86 #endif /* BB_FEATURE_INSTALLER */
87
88 int main(int argc, char **argv)
89 {
90         const char *s;
91
92         for (s = applet_name = argv[0]; *s != '\0';) {
93                 if (*s++ == '/')
94                         applet_name = s;
95         }
96
97 #ifdef BB_SH
98         /* Add in a special case hack -- whenever **argv == '-'
99          * (i.e. '-su' or '-sh') always invoke the shell */
100         if (**argv == '-' && *(*argv+1)!= '-') {
101                 exit(((*(shell_main)) (argc, argv)));
102         }
103 #endif
104
105         run_applet_by_name(applet_name, argc, argv);
106         error_msg_and_die("applet not found");
107 }
108
109
110 int busybox_main(int argc, char **argv)
111 {
112         int col = 0, len, i;
113
114 #ifdef BB_FEATURE_INSTALLER     
115         /* 
116          * This style of argument parsing doesn't scale well 
117          * in the event that busybox starts wanting more --options.
118          * If someone has a cleaner approach, by all means implement it.
119          */
120         if (argc > 1 && (strcmp(argv[1], "--install") == 0)) {
121                 int use_symbolic_links = 0;
122                 int rc = 0;
123                 char *busybox;
124
125                 /* to use symlinks, or not to use symlinks... */
126                 if (argc > 2) {
127                         if ((strcmp(argv[2], "-s") == 0)) { 
128                                 use_symbolic_links = 1; 
129                         }
130                 }
131
132                 /* link */
133                 busybox = busybox_fullpath();
134                 if (busybox) {
135                         install_links(busybox, use_symbolic_links);
136                         free(busybox);
137                 } else {
138                         rc = 1;
139                 }
140                 return rc;
141         }
142 #endif /* BB_FEATURE_INSTALLER */
143
144         argc--;
145
146         /* If we've already been here once, exit now */
147         if (been_there_done_that == 1 || argc < 1) {
148                 const struct BB_applet *a = applets;
149
150                 fprintf(stderr, "%s\n\n"
151                                 "Usage: busybox [function] [arguments]...\n"
152                                 "   or: [function] [arguments]...\n\n"
153                                 "\tBusyBox is a multi-call binary that combines many common Unix\n"
154                                 "\tutilities into a single executable.  Most people will create a\n"
155                                 "\tlink to busybox for each function they wish to use, and BusyBox\n"
156                                 "\twill act like whatever it was invoked as.\n" 
157                                 "\nCurrently defined functions:\n", full_version);
158
159                 while (a->name != 0) {
160                         col +=
161                                 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
162                                                 (a++)->name);
163                         if (col > 60 && a->name != 0) {
164                                 fprintf(stderr, ",\n");
165                                 col = 0;
166                         }
167                 }
168                 fprintf(stderr, "\n\n");
169                 exit(-1);
170         }
171
172         /* Flag that we've been here already */
173         been_there_done_that = 1;
174         
175         /* Move the command line down a notch */
176         len = argv[argc] + strlen(argv[argc]) - argv[1];
177         memmove(argv[0], argv[1], len);
178         memset(argv[0] + len, 0, argv[1] - argv[0]);
179
180         /* Fix up the argv pointers */
181         len = argv[1] - argv[0];
182         memmove(argv, argv + 1, sizeof(char *) * (argc + 1));
183         for (i = 0; i < argc; i++)
184                 argv[i] -= len;
185
186         return (main(argc, argv));
187 }
188
189 /*
190 Local Variables:
191 c-file-style: "linux"
192 c-basic-offset: 4
193 tab-width: 4
194 End:
195 */