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