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