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