PArtial Changelog update. I'm still on vacation (I'm at a campground
[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         /* Add in a special case hack for a leading hyphen */
78         if (**argv == '-' && *(*argv+1)!= '-') {
79                 applet_name = (*argv+1);
80         }
81
82 #ifdef BB_LOCALE_SUPPORT 
83 #ifdef BB_INIT
84         if(getpid()!=1) /* Do not set locale for `init' */
85 #endif
86         {
87                 setlocale(LC_ALL, "");
88         }
89 #endif
90
91         run_applet_by_name(applet_name, argc, argv);
92         error_msg_and_die("applet not found");
93 }
94
95
96 int busybox_main(int argc, char **argv)
97 {
98         int col = 0, len, i;
99
100 #ifdef BB_FEATURE_INSTALLER     
101         /* 
102          * This style of argument parsing doesn't scale well 
103          * in the event that busybox starts wanting more --options.
104          * If someone has a cleaner approach, by all means implement it.
105          */
106         if (argc > 1 && (strcmp(argv[1], "--install") == 0)) {
107                 int use_symbolic_links = 0;
108                 int rc = 0;
109                 char *busybox;
110
111                 /* to use symlinks, or not to use symlinks... */
112                 if (argc > 2) {
113                         if ((strcmp(argv[2], "-s") == 0)) { 
114                                 use_symbolic_links = 1; 
115                         }
116                 }
117
118                 /* link */
119                 busybox = busybox_fullpath();
120                 if (busybox) {
121                         install_links(busybox, use_symbolic_links);
122                         free(busybox);
123                 } else {
124                         rc = 1;
125                 }
126                 return rc;
127         }
128 #endif /* BB_FEATURE_INSTALLER */
129
130         argc--;
131
132         /* If we've already been here once, exit now */
133         if (been_there_done_that == 1 || argc < 1) {
134                 const struct BB_applet *a = applets;
135
136                 fprintf(stderr, "%s\n\n"
137                                 "Usage: busybox [function] [arguments]...\n"
138                                 "   or: [function] [arguments]...\n\n"
139                                 "\tBusyBox is a multi-call binary that combines many common Unix\n"
140                                 "\tutilities into a single executable.  Most people will create a\n"
141                                 "\tlink to busybox for each function they wish to use, and BusyBox\n"
142                                 "\twill act like whatever it was invoked as.\n" 
143                                 "\nCurrently defined functions:\n", full_version);
144
145                 while (a->name != 0) {
146                         col +=
147                                 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
148                                                 (a++)->name);
149                         if (col > 60 && a->name != 0) {
150                                 fprintf(stderr, ",\n");
151                                 col = 0;
152                         }
153                 }
154                 fprintf(stderr, "\n\n");
155                 exit(0);
156         }
157
158         /* Flag that we've been here already */
159         been_there_done_that = 1;
160         
161         /* Move the command line down a notch */
162         len = argv[argc] + strlen(argv[argc]) - argv[1];
163         memmove(argv[0], argv[1], len);
164         memset(argv[0] + len, 0, argv[1] - argv[0]);
165
166         /* Fix up the argv pointers */
167         len = argv[1] - argv[0];
168         memmove(argv, argv + 1, sizeof(char *) * (argc + 1));
169         for (i = 0; i < argc; i++)
170                 argv[i] -= len;
171
172         return (main(argc, argv));
173 }
174
175 /*
176 Local Variables:
177 c-file-style: "linux"
178 c-basic-offset: 4
179 tab-width: 4
180 End:
181 */