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