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