implemented a builtin echo command in ash. moved the guts of the
[people/mcb30/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 *bb_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                         bb_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         bb_applet_name = argv[0];
76
77         if (bb_applet_name[0] == '-')
78                 bb_applet_name++;
79
80         for (s = bb_applet_name; *s != '\0';) {
81                 if (*s++ == '/')
82                         bb_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(bb_applet_name, argc, argv);
95         bb_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                 int output_width = 60;
139
140 #ifdef CONFIG_FEATURE_AUTOWIDTH
141                 /* Obtain the terminal width.  */
142                 get_terminal_width_height(0, &output_width, NULL);
143                 /* leading tab and room to wrap */
144                 output_width -= 20;
145 #endif
146
147                 printf("%s\n\n"
148                        "Usage: busybox [function] [arguments]...\n"
149                        "   or: [function] [arguments]...\n\n"
150                        "\tBusyBox is a multi-call binary that combines many common Unix\n"
151                        "\tutilities into a single executable.  Most people will create a\n"
152                        "\tlink to busybox for each function they wish to use and BusyBox\n"
153                        "\twill act like whatever it was invoked as!\n"
154                        "\nCurrently defined functions:\n", bb_msg_full_version);
155
156                 while (a->name != 0) {
157                         col +=
158                                 printf("%s%s", ((col == 0) ? "\t" : ", "),
159                                        (a++)->name);
160                         if (col > output_width && a->name != 0) {
161                                 printf(",\n");
162                                 col = 0;
163                         }
164                 }
165                 printf("\n\n");
166                 exit(0);
167         }
168
169         /* Flag that we've been here already */
170         been_there_done_that = 1;
171
172         /* Move the command line down a notch */
173         /* Preserve pointers so setproctitle() works consistently */
174         len = argv[argc] + strlen(argv[argc]) - argv[1];
175         memmove(argv[0], argv[1], len);
176         memset(argv[0] + len, 0, argv[1] - argv[0]);
177
178         /* Fix up the argv pointers */
179         len = argv[1] - argv[0];
180         memmove(argv, argv + 1, sizeof(char *) * (argc + 1));
181         for (i = 0; i < argc; i++)
182                 argv[i] -= len;
183
184         return (main(argc, argv));
185 }
186
187 /*
188 Local Variables:
189 c-file-style: "linux"
190 c-basic-offset: 4
191 tab-width: 4
192 End:
193 */