Wrap a table (bg set to black, width=80%) around the screenshot
[oweals/busybox.git] / busybox.c
1 /* vi: set sw=4 ts=4: */
2 #include "busybox.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <errno.h>
7 #include <stdlib.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         struct BB_applet search_applet, *applet;
91         const char                              *s;
92
93         for (s = applet_name = argv[0]; *s != '\0';) {
94                 if (*s++ == '/')
95                         applet_name = s;
96         }
97
98 #ifdef BB_SH
99         /* Add in a special case hack -- whenever **argv == '-'
100          * (i.e. '-su' or '-sh') always invoke the shell */
101         if (**argv == '-' && *(*argv+1)!= '-') {
102                 exit(((*(shell_main)) (argc, argv)));
103         }
104 #endif
105
106         /* Do a binary search to find the applet entry given the name. */
107         search_applet.name = applet_name;
108         applet = bsearch(&search_applet, applets, NUM_APPLETS,
109                         sizeof(struct BB_applet), applet_name_compare);
110         if (applet != NULL) {
111                 if (applet->usage && argv[1] && strcmp(argv[1], "--help") == 0)
112                         usage(applet->usage); 
113                 exit((*(applet->main)) (argc, argv));
114         }
115
116         error_msg_and_die("applet not found\n");
117 }
118
119
120 int busybox_main(int argc, char **argv)
121 {
122         int col = 0, len, i;
123
124 #ifdef BB_FEATURE_INSTALLER     
125         /* 
126          * This style of argument parsing doesn't scale well 
127          * in the event that busybox starts wanting more --options.
128          * If someone has a cleaner approach, by all means implement it.
129          */
130         if (argc > 1 && (strcmp(argv[1], "--install") == 0)) {
131                 int use_symbolic_links = 0;
132                 int rc = 0;
133                 char *busybox;
134
135                 /* to use symlinks, or not to use symlinks... */
136                 if (argc > 2) {
137                         if ((strcmp(argv[2], "-s") == 0)) { 
138                                 use_symbolic_links = 1; 
139                         }
140                 }
141
142                 /* link */
143                 busybox = busybox_fullpath();
144                 if (busybox) {
145                         install_links(busybox, use_symbolic_links);
146                         free(busybox);
147                 } else {
148                         rc = 1;
149                 }
150                 return rc;
151         }
152 #endif /* BB_FEATURE_INSTALLER */
153
154         argc--;
155
156         /* If we've already been here once, exit now */
157         if (been_there_done_that == 1 || argc < 1) {
158                 const struct BB_applet *a = applets;
159
160                 fprintf(stderr, "%s\n\n"
161                                 "Usage: busybox [function] [arguments]...\n"
162                                 "   or: [function] [arguments]...\n\n"
163                                 "\tBusyBox is a multi-call binary that combines many common Unix\n"
164                                 "\tutilities into a single executable.  Most people will create a\n"
165                                 "\tlink to busybox for each function they wish to use, and BusyBox\n"
166                                 "\twill act like whatever it was invoked as.\n" 
167                                 "\nCurrently defined functions:\n", full_version);
168
169                 while (a->name != 0) {
170                         col +=
171                                 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
172                                                 (a++)->name);
173                         if (col > 60 && a->name != 0) {
174                                 fprintf(stderr, ",\n");
175                                 col = 0;
176                         }
177                 }
178                 fprintf(stderr, "\n\n");
179                 exit(-1);
180         }
181
182         /* Flag that we've been here already */
183         been_there_done_that = 1;
184         
185         /* Move the command line down a notch */
186         len = argv[argc] + strlen(argv[argc]) - argv[1];
187         memmove(argv[0], argv[1], len);
188         memset(argv[0] + len, 0, argv[1] - argv[0]);
189
190         /* Fix up the argv pointers */
191         len = argv[1] - argv[0];
192         memmove(argv, argv + 1, sizeof(char *) * (argc + 1));
193         for (i = 0; i < argc; i++)
194                 argv[i] -= len;
195
196         return (main(argc, argv));
197 }
198
199 /*
200 Local Variables:
201 c-file-style: "linux"
202 c-basic-offset: 4
203 tab-width: 4
204 End:
205 */