+ busybox --install [-s]
[oweals/busybox.git] / busybox.c
1 /* vi: set sw=4 ts=4: */
2 #include "internal.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include <errno.h>
6
7 static int been_there_done_that = 0;
8
9 /* It has been alledged that doing such things can
10  * help reduce binary size when staticly linking,
11  * of course with glibc, this is unlikely as long
12  * as we use things like printf -- perhaps a printf
13  * replacement may be in order 
14  */
15 #if 0
16 void exit(int status) __attribute__ ((noreturn));
17 void exit(int status)
18 {
19         _exit(status);
20 };
21 void abort(void) __attribute__ ((__noreturn__));
22 void abort(void)
23 {
24         _exit(0);
25 };
26 int atexit(void (*__func) (void))
27 {
28         _exit(0);
29 };
30 void *__libc_stack_end;
31 #endif
32
33 const struct BB_applet applets[] = {
34
35 #ifdef BB_AR
36         {"ar", ar_main, _BB_DIR_USR_BIN},
37 #endif
38 #ifdef BB_BASENAME
39         {"basename", basename_main, _BB_DIR_USR_BIN},
40 #endif
41         {"busybox", busybox_main, _BB_DIR_BIN},
42 #ifdef BB_BLOCK_DEVICE
43         {"block_device", block_device_main, _BB_DIR_SBIN},
44 #endif
45 #ifdef BB_CAT
46         {"cat", cat_main, _BB_DIR_BIN},
47 #endif
48 #ifdef BB_CHMOD_CHOWN_CHGRP
49         {"chgrp", chmod_chown_chgrp_main, _BB_DIR_BIN},
50 #endif
51 #ifdef BB_CHMOD_CHOWN_CHGRP
52         {"chmod", chmod_chown_chgrp_main, _BB_DIR_BIN},
53 #endif
54 #ifdef BB_CHMOD_CHOWN_CHGRP
55         {"chown", chmod_chown_chgrp_main, _BB_DIR_BIN},
56 #endif
57 #ifdef BB_CHROOT
58         {"chroot", chroot_main, _BB_DIR_SBIN},
59 #endif
60 #ifdef BB_CLEAR
61         {"clear", clear_main, _BB_DIR_USR_BIN},
62 #endif
63 #ifdef BB_CHVT
64         {"chvt", chvt_main, _BB_DIR_USR_BIN},
65 #endif
66 #ifdef BB_CP_MV
67         {"cp", cp_mv_main, _BB_DIR_BIN},
68 #endif
69 #ifdef BB_CUT
70         {"cut", cut_main, _BB_DIR_USR_BIN},
71 #endif
72 #ifdef BB_DATE
73         {"date", date_main, _BB_DIR_BIN},
74 #endif
75 #ifdef BB_DC
76         {"dc", dc_main, _BB_DIR_USR_BIN},
77 #endif
78 #ifdef BB_DD
79         {"dd", dd_main, _BB_DIR_BIN},
80 #endif
81 #ifdef BB_DF
82         {"df", df_main, _BB_DIR_BIN},
83 #endif
84 #ifdef BB_DIRNAME
85         {"dirname", dirname_main, _BB_DIR_USR_BIN},
86 #endif
87 #ifdef BB_DMESG
88         {"dmesg", dmesg_main, _BB_DIR_BIN},
89 #endif
90 #ifdef BB_DU
91         {"du", du_main, _BB_DIR_BIN},
92 #endif
93 #ifdef BB_DUTMP
94         {"dutmp", dutmp_main, _BB_DIR_USR_SBIN},
95 #endif
96 #ifdef BB_ECHO
97         {"echo", echo_main, _BB_DIR_BIN},
98 #endif
99 #ifdef BB_TRUE_FALSE
100         {"false", false_main, _BB_DIR_BIN},
101 #endif
102 #ifdef BB_FBSET
103         {"fbset", fbset_main, _BB_DIR_USR_SBIN},
104 #endif
105 #ifdef BB_FDFLUSH
106         {"fdflush", fdflush_main, _BB_DIR_BIN},
107 #endif
108 #ifdef BB_FIND
109         {"find", find_main, _BB_DIR_USR_BIN},
110 #endif
111 #ifdef BB_FREE
112         {"free", free_main, _BB_DIR_USR_BIN},
113 #endif
114 #ifdef BB_FREERAMDISK
115         {"freeramdisk", freeramdisk_main, _BB_DIR_SBIN},
116 #endif
117 #ifdef BB_DEALLOCVT
118         {"deallocvt", deallocvt_main, _BB_DIR_USR_BIN},
119 #endif
120 #ifdef BB_FSCK_MINIX
121         {"fsck.minix", fsck_minix_main, _BB_DIR_SBIN},
122 #endif
123 #ifdef BB_GREP
124         {"grep", grep_main, _BB_DIR_BIN},
125 #endif
126 #ifdef BB_GUNZIP
127         {"gunzip", gunzip_main, _BB_DIR_BIN},
128 #endif
129 #ifdef BB_GZIP
130         {"gzip", gzip_main, _BB_DIR_BIN},
131 #endif
132 #ifdef BB_HALT
133         {"halt", halt_main, _BB_DIR_SBIN},
134 #endif
135 #ifdef BB_HEAD
136         {"head", head_main, _BB_DIR_BIN},
137 #endif
138 #ifdef BB_HOSTID
139         {"hostid", hostid_main, _BB_DIR_USR_BIN},
140 #endif
141 #ifdef BB_HOSTNAME
142         {"hostname", hostname_main, _BB_DIR_BIN},
143 #endif
144 #ifdef BB_ID
145         {"id", id_main, _BB_DIR_USR_BIN},
146 #endif
147 #ifdef BB_INIT
148         {"init", init_main, _BB_DIR_SBIN},
149 #endif
150 #ifdef BB_INSMOD
151         {"insmod", insmod_main, _BB_DIR_SBIN},
152 #endif
153 #ifdef BB_KILL
154         {"kill", kill_main, _BB_DIR_BIN},
155 #endif
156 #ifdef BB_KILLALL
157         {"killall", kill_main, _BB_DIR_USR_BIN},
158 #endif
159 #ifdef BB_LENGTH
160         {"length", length_main, _BB_DIR_USR_BIN},
161 #endif
162 #ifdef BB_LINUXRC
163         {"linuxrc", init_main, _BB_DIR_ROOT},
164 #endif
165 #ifdef BB_LN
166         {"ln", ln_main, _BB_DIR_BIN},
167 #endif
168 #ifdef BB_LOADACM
169         {"loadacm", loadacm_main, _BB_DIR_USR_BIN},
170 #endif
171 #ifdef BB_LOADFONT
172         {"loadfont", loadfont_main, _BB_DIR_USR_BIN},
173 #endif
174 #ifdef BB_LOADKMAP
175         {"loadkmap", loadkmap_main, _BB_DIR_SBIN},
176 #endif
177 #ifdef BB_LOGGER
178         {"logger", logger_main, _BB_DIR_USR_BIN},
179 #endif
180 #ifdef BB_LOGNAME
181         {"logname", logname_main, _BB_DIR_USR_BIN},
182 #endif
183 #ifdef BB_LS
184         {"ls", ls_main, _BB_DIR_BIN},
185 #endif
186 #ifdef BB_LSMOD
187         {"lsmod", lsmod_main, _BB_DIR_SBIN},
188 #endif
189 #ifdef BB_MAKEDEVS
190         {"makedevs", makedevs_main, _BB_DIR_SBIN},
191 #endif
192 #ifdef BB_MD5SUM
193         {"md5sum", md5sum_main, _BB_DIR_USR_BIN},
194 #endif
195 #ifdef BB_MKDIR
196         {"mkdir", mkdir_main, _BB_DIR_BIN},
197 #endif
198 #ifdef BB_MKFIFO
199         {"mkfifo", mkfifo_main, _BB_DIR_USR_BIN},
200 #endif
201 #ifdef BB_MKFS_MINIX
202         {"mkfs.minix", mkfs_minix_main, _BB_DIR_SBIN},
203 #endif
204 #ifdef BB_MKNOD
205         {"mknod", mknod_main, _BB_DIR_BIN},
206 #endif
207 #ifdef BB_MKSWAP
208         {"mkswap", mkswap_main, _BB_DIR_SBIN},
209 #endif
210 #ifdef BB_MKTEMP
211         {"mktemp", mktemp_main, _BB_DIR_BIN},
212 #endif
213 #ifdef BB_NC
214         {"nc", nc_main, _BB_DIR_USR_BIN},
215 #endif
216 #ifdef BB_MORE
217         {"more", more_main, _BB_DIR_BIN},
218 #endif
219 #ifdef BB_MOUNT
220         {"mount", mount_main, _BB_DIR_BIN},
221 #endif
222 #ifdef BB_MT
223         {"mt", mt_main, _BB_DIR_BIN},
224 #endif
225 #ifdef BB_CP_MV
226         {"mv", cp_mv_main, _BB_DIR_BIN},
227 #endif
228 #ifdef BB_NSLOOKUP
229         {"nslookup", nslookup_main, _BB_DIR_USR_BIN},
230 #endif
231 #ifdef BB_PING
232         {"ping", ping_main, _BB_DIR_BIN},
233 #endif
234 #ifdef BB_POWEROFF
235         {"poweroff", poweroff_main, _BB_DIR_SBIN},
236 #endif
237 #ifdef BB_PRINTF
238         {"printf", printf_main, _BB_DIR_USR_BIN},
239 #endif
240 #ifdef BB_PS
241         {"ps", ps_main, _BB_DIR_BIN},
242 #endif
243 #ifdef BB_PWD
244         {"pwd", pwd_main, _BB_DIR_BIN},
245 #endif
246 #ifdef BB_REBOOT
247         {"reboot", reboot_main, _BB_DIR_SBIN},
248 #endif
249 #ifdef BB_RM
250         {"rm", rm_main, _BB_DIR_BIN},
251 #endif
252 #ifdef BB_RMDIR
253         {"rmdir", rmdir_main, _BB_DIR_BIN},
254 #endif
255 #ifdef BB_RMMOD
256         {"rmmod", rmmod_main, _BB_DIR_SBIN},
257 #endif
258 #ifdef BB_SED
259         {"sed", sed_main, _BB_DIR_BIN},
260 #endif
261 #ifdef BB_SETKEYCODES
262         {"setkeycodes", setkeycodes_main, _BB_DIR_USR_BIN},
263 #endif
264 #ifdef BB_SFDISK
265         {"sfdisk", sfdisk_main, _BB_DIR_SBIN},
266 #endif
267 #ifdef BB_SH
268         {"sh", shell_main, _BB_DIR_BIN},
269 #endif
270 #ifdef BB_SLEEP
271         {"sleep", sleep_main, _BB_DIR_BIN},
272 #endif
273 #ifdef BB_SORT
274         {"sort", sort_main, _BB_DIR_BIN},
275 #endif
276 #ifdef BB_SYNC
277         {"sync", sync_main, _BB_DIR_BIN},
278 #endif
279 #ifdef BB_SYSLOGD
280         {"syslogd", syslogd_main, _BB_DIR_SBIN},
281 #endif
282 #ifdef BB_SWAPONOFF
283         {"swapon", swap_on_off_main, _BB_DIR_SBIN},
284 #endif
285 #ifdef BB_SWAPONOFF
286         {"swapoff", swap_on_off_main, _BB_DIR_SBIN},
287 #endif
288 #ifdef BB_TAIL
289         {"tail", tail_main, _BB_DIR_USR_BIN},
290 #endif
291 #ifdef BB_TAR
292         {"tar", tar_main, _BB_DIR_BIN},
293 #endif
294 #ifdef BB_TELNET
295         {"telnet", telnet_main, _BB_DIR_USR_BIN},
296 #endif
297 #ifdef BB_TEST
298         {"test", test_main, _BB_DIR_USR_BIN},
299 #endif
300 #ifdef BB_TEE
301         {"tee", tee_main, _BB_DIR_BIN},
302 #endif
303 #ifdef BB_TOUCH
304         {"touch", touch_main, _BB_DIR_USR_BIN},
305 #endif
306 #ifdef BB_TR
307         {"tr", tr_main, _BB_DIR_USR_BIN},
308 #endif
309 #ifdef BB_TRUE_FALSE
310         {"true", true_main, _BB_DIR_BIN},
311 #endif
312 #ifdef BB_TTY
313         {"tty", tty_main, _BB_DIR_USR_BIN},
314 #endif
315 #ifdef BB_UMOUNT
316         {"umount", umount_main, _BB_DIR_BIN},
317 #endif
318 #ifdef BB_UNAME
319         {"uname", uname_main, _BB_DIR_BIN},
320 #endif
321 #ifdef BB_UNIQ
322         {"uniq", uniq_main, _BB_DIR_USR_BIN},
323 #endif
324 #ifdef BB_UPDATE
325         {"update", update_main, _BB_DIR_SBIN},
326 #endif
327 #ifdef BB_UPTIME
328         {"uptime", uptime_main, _BB_DIR_USR_BIN},
329 #endif
330 #ifdef BB_UUENCODE
331         {"uuencode", uuencode_main, _BB_DIR_USR_BIN},
332 #endif
333 #ifdef BB_UUDECODE
334         {"uudecode", uudecode_main, _BB_DIR_USR_BIN},
335 #endif
336 #ifdef BB_USLEEP
337         {"usleep", usleep_main, _BB_DIR_BIN},
338 #endif
339 #ifdef BB_WC
340         {"wc", wc_main, _BB_DIR_USR_BIN},
341 #endif
342 #ifdef BB_WHICH
343         {"which", which_main, _BB_DIR_USR_BIN},
344 #endif
345 #ifdef BB_WHOAMI
346         {"whoami", whoami_main, _BB_DIR_USR_BIN},
347 #endif
348 #ifdef BB_YES
349         {"yes", yes_main, _BB_DIR_USR_BIN},
350 #endif
351 #ifdef BB_GUNZIP
352         {"zcat", gunzip_main, _BB_DIR_BIN},
353 #endif
354 #ifdef BB_TEST
355         {"[", test_main, _BB_DIR_USR_BIN},
356 #endif
357         {0}
358 };
359
360
361 #ifdef BB_FEATURE_INSTALLER
362 /* 
363  * directory table
364  *      this should be consistent w/ the enum, internal.h::Location,
365  *      or else...
366  */
367 static char* install_dir[] = {
368     "/",
369     "/bin",
370     "/sbin",
371     "/usr/bin",
372     "/usr/sbin",
373         NULL
374 };
375
376 /* abstract link() */
377 typedef int (*__link_f)(const char *, const char *);
378
379 /* 
380  * Where in the filesystem is this busybox?
381  * [return]
382  *              malloc'd string w/ full pathname of busybox's location
383  *              NULL on failure
384  */
385 static char *busybox_fullpath()
386 {
387         pid_t   pid;
388         char    path[256];
389         char    proc[256];
390         int             len;
391
392         pid = getpid();
393         sprintf(proc, "/proc/%d/exe", pid);
394         len = readlink(proc, path, 256);
395         if (len != -1) {
396                 path[len] = 0;
397         } else {
398                 fprintf(stderr, "busybox : %s : %s\n", proc, strerror(errno));
399                 return NULL;
400         }
401         return strdup(path);
402 }
403
404 /* create (sym)links for each applet */
405 static int install_links(const char *busybox, int use_symbolic_links)
406 {
407     __link_f Link = link;
408
409     char        command[256];
410         int             i;
411         int             rc = 0;
412
413         if (use_symbolic_links) Link = symlink;
414
415     for (i = 0; applets[i].name != NULL; i++) {
416         sprintf (
417                         command, 
418                         "%s/%s", 
419                         install_dir[applets[i].location], 
420                         applets[i].name
421                 );
422 #if 1
423         rc |= Link(busybox, command);
424 #else
425         puts(command);
426 #endif
427                 if (rc) {
428                         fprintf(stderr,"busybox : %s : %s\n", command, strerror(errno));
429                 }
430     }
431         return rc;
432 }
433
434 #if 0
435 int uninstall_links() ?
436 #endif
437 #endif /* BB_FEATURE_INSTALLER */
438
439
440 int main(int argc, char **argv)
441 {
442         char                            *s;
443         char                            *name;
444         const struct BB_applet  *a              = applets;
445
446 #ifdef BB_FEATURE_INSTALLER     
447         /* 
448          * This style of argument parsing doesn't scale well 
449          * in the event that busybox starts wanting more --options.
450          * If someone has a cleaner approach, by all means implement it.
451          */
452         if (argc > 1 && (strcmp(argv[1], "--install") == 0)) {
453                 int use_symbolic_links = 0;
454                 int rc = 0;
455                 char *busybox;
456
457                 /* to use symlinks, or not to use symlinks... */
458                 if (argc > 2) {
459                         if ((strcmp(argv[2], "-s") == 0)) { 
460                                 use_symbolic_links = 1; 
461                         }
462                 }
463
464                 /* link */
465                 busybox = busybox_fullpath();
466                 if (busybox) {
467                         install_links(busybox, use_symbolic_links);
468                         free(busybox);
469                 } else {
470                         rc = 1;
471                 }
472                 return rc;
473         }
474 #endif /* BB_FEATURE_INSTALLER */
475
476         for (s = name = argv[0]; *s != '\0';) {
477                 if (*s++ == '/')
478                         name = s;
479         }
480
481         *argv = name;
482
483         while (a->name != 0) {
484                 if (strcmp(name, a->name) == 0) {
485                         exit(((*(a->main)) (argc, argv)));
486                 }
487                 a++;
488         }
489         return(busybox_main(argc, argv));
490 }
491
492
493 int busybox_main(int argc, char **argv)
494 {
495         int col = 0;
496
497         argc--;
498         argv++;
499
500         if (been_there_done_that == 1 || argc < 1) {
501                 const struct BB_applet *a = applets;
502
503                 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n"
504                                 "Usage: busybox [function] [arguments]...\n"
505                                 "   or: [function] [arguments]...\n\n"
506                                 "\tBusyBox is a multi-call binary that combines many common Unix\n"
507                                 "\tutilities into a single executable.  Most people will create a\n"
508                                 "\tlink to busybox for each function they wish to use, and BusyBox\n"
509                                 "\twill act like whatever it was invoked as.\n" 
510                                 "\nCurrently defined functions:\n", BB_VER, BB_BT);
511
512                 while (a->name != 0) {
513                         col +=
514                                 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
515                                                 (a++)->name);
516                         if (col > 60 && a->name != 0) {
517                                 fprintf(stderr, ",\n");
518                                 col = 0;
519                         }
520                 }
521                 fprintf(stderr, "\n\n");
522                 exit(-1);
523         }
524         /* If we've already been here once, exit now */
525         been_there_done_that = 1;
526         return (main(argc, argv));
527 }
528
529 /*
530 Local Variables:
531 c-file-style: "linux"
532 c-basic-offset: 4
533 tab-width: 4
534 End:
535 */