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