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