27 |
* FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( |
* FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( |
28 |
*/ |
*/ |
29 |
|
|
|
#include <assert.h> |
|
30 |
#include "busybox.h" |
#include "busybox.h" |
31 |
|
#include <assert.h> |
32 |
|
#include <malloc.h> |
33 |
|
#include <sys/user.h> /* PAGE_SIZE */ |
34 |
|
|
35 |
|
|
36 |
/* Declare <applet>_main() */ |
/* Declare <applet>_main() */ |
57 |
#ifdef SINGLE_APPLET_MAIN |
#ifdef SINGLE_APPLET_MAIN |
58 |
#undef ENABLE_FEATURE_INDIVIDUAL |
#undef ENABLE_FEATURE_INDIVIDUAL |
59 |
#define ENABLE_FEATURE_INDIVIDUAL 1 |
#define ENABLE_FEATURE_INDIVIDUAL 1 |
60 |
#undef USE_FEATURE_INDIVIDUAL |
#undef IF_FEATURE_INDIVIDUAL |
61 |
#define USE_FEATURE_INDIVIDUAL(...) __VA_ARGS__ |
#define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__ |
62 |
#endif |
#endif |
63 |
|
|
64 |
|
|
75 |
|
|
76 |
i = start_bunzip(&bd, |
i = start_bunzip(&bd, |
77 |
/* src_fd: */ -1, |
/* src_fd: */ -1, |
78 |
//FIXME: can avoid storing these 2 bytes! |
/* inbuf: */ (void *)packed_usage, |
|
/* inbuf: */ (void *)packed_usage + 2, |
|
79 |
/* len: */ sizeof(packed_usage)); |
/* len: */ sizeof(packed_usage)); |
80 |
/* read_bunzip can longjmp to start_bunzip, and ultimately |
/* read_bunzip can longjmp to start_bunzip, and ultimately |
81 |
* end up here with i != 0 on read data errors! Not trivial */ |
* end up here with i != 0 on read data errors! Not trivial */ |
100 |
|
|
101 |
static void full_write2_str(const char *str) |
static void full_write2_str(const char *str) |
102 |
{ |
{ |
103 |
full_write(STDERR_FILENO, str, strlen(str)); |
xwrite_str(STDERR_FILENO, str); |
104 |
} |
} |
105 |
|
|
106 |
void FAST_FUNC bb_show_usage(void) |
void FAST_FUNC bb_show_usage(void) |
112 |
const char *usage_string = p = unpack_usage_messages(); |
const char *usage_string = p = unpack_usage_messages(); |
113 |
|
|
114 |
if (*p == '\b') { |
if (*p == '\b') { |
115 |
full_write2_str("\nNo help available.\n\n"); |
full_write2_str("No help available.\n\n"); |
116 |
} else { |
} else { |
117 |
full_write2_str("\nUsage: "SINGLE_APPLET_STR" "); |
full_write2_str("Usage: "SINGLE_APPLET_STR" "); |
118 |
full_write2_str(p); |
full_write2_str(p); |
119 |
full_write2_str("\n\n"); |
full_write2_str("\n\n"); |
120 |
} |
} |
121 |
dealloc_usage_messages((char*)usage_string); |
if (ENABLE_FEATURE_CLEAN_UP) |
122 |
|
dealloc_usage_messages((char*)usage_string); |
123 |
#else |
#else |
124 |
const char *p; |
const char *p; |
125 |
const char *usage_string = p = unpack_usage_messages(); |
const char *usage_string = p = unpack_usage_messages(); |
132 |
ap--; |
ap--; |
133 |
} |
} |
134 |
full_write2_str(bb_banner); |
full_write2_str(bb_banner); |
135 |
full_write2_str(" multi-call binary\n"); |
full_write2_str(" multi-call binary.\n"); |
136 |
if (*p == '\b') |
if (*p == '\b') |
137 |
full_write2_str("\nNo help available.\n\n"); |
full_write2_str("\nNo help available.\n\n"); |
138 |
else { |
else { |
142 |
full_write2_str(p); |
full_write2_str(p); |
143 |
full_write2_str("\n\n"); |
full_write2_str("\n\n"); |
144 |
} |
} |
145 |
dealloc_usage_messages((char*)usage_string); |
if (ENABLE_FEATURE_CLEAN_UP) |
146 |
|
dealloc_usage_messages((char*)usage_string); |
147 |
#endif |
#endif |
148 |
} |
} |
149 |
xfunc_die(); |
xfunc_die(); |
182 |
|
|
183 |
|
|
184 |
void lbb_prepare(const char *applet |
void lbb_prepare(const char *applet |
185 |
USE_FEATURE_INDIVIDUAL(, char **argv)) |
IF_FEATURE_INDIVIDUAL(, char **argv)) |
186 |
MAIN_EXTERNALLY_VISIBLE; |
MAIN_EXTERNALLY_VISIBLE; |
187 |
void lbb_prepare(const char *applet |
void lbb_prepare(const char *applet |
188 |
USE_FEATURE_INDIVIDUAL(, char **argv)) |
IF_FEATURE_INDIVIDUAL(, char **argv)) |
189 |
{ |
{ |
190 |
#ifdef __GLIBC__ |
#ifdef __GLIBC__ |
191 |
(*(int **)&bb_errno) = __errno_location(); |
(*(int **)&bb_errno) = __errno_location(); |
227 |
/* If not built as a single-applet executable... */ |
/* If not built as a single-applet executable... */ |
228 |
#if !defined(SINGLE_APPLET_MAIN) |
#if !defined(SINGLE_APPLET_MAIN) |
229 |
|
|
230 |
USE_FEATURE_SUID(static uid_t ruid;) /* real uid */ |
IF_FEATURE_SUID(static uid_t ruid;) /* real uid */ |
231 |
|
|
232 |
#if ENABLE_FEATURE_SUID_CONFIG |
#if ENABLE_FEATURE_SUID_CONFIG |
233 |
|
|
503 |
#else |
#else |
504 |
static inline void parse_config_file(void) |
static inline void parse_config_file(void) |
505 |
{ |
{ |
506 |
USE_FEATURE_SUID(ruid = getuid();) |
IF_FEATURE_SUID(ruid = getuid();) |
507 |
} |
} |
508 |
#endif /* FEATURE_SUID_CONFIG */ |
#endif /* FEATURE_SUID_CONFIG */ |
509 |
|
|
572 |
#endif |
#endif |
573 |
check_need_suid: |
check_need_suid: |
574 |
#endif |
#endif |
575 |
if (APPLET_SUID(applet_no) == _BB_SUID_ALWAYS) { |
if (APPLET_SUID(applet_no) == _BB_SUID_REQUIRE) { |
576 |
/* Real uid is not 0. If euid isn't 0 too, suid bit |
/* Real uid is not 0. If euid isn't 0 too, suid bit |
577 |
* is most probably not set on our executable */ |
* is most probably not set on our executable */ |
578 |
if (geteuid()) |
if (geteuid()) |
579 |
bb_error_msg_and_die("must be suid to work properly"); |
bb_error_msg_and_die("must be suid to work properly"); |
580 |
} else if (APPLET_SUID(applet_no) == _BB_SUID_NEVER) { |
} else if (APPLET_SUID(applet_no) == _BB_SUID_DROP) { |
581 |
xsetgid(rgid); /* drop all privileges */ |
xsetgid(rgid); /* drop all privileges */ |
582 |
xsetuid(ruid); |
xsetuid(ruid); |
583 |
} |
} |
589 |
|
|
590 |
#if ENABLE_FEATURE_INSTALLER |
#if ENABLE_FEATURE_INSTALLER |
591 |
/* create (sym)links for each applet */ |
/* create (sym)links for each applet */ |
592 |
static void install_links(const char *busybox, int use_symbolic_links) |
static void install_links(const char *busybox, int use_symbolic_links, |
593 |
|
char *custom_install_dir) |
594 |
{ |
{ |
595 |
/* directory table |
/* directory table |
596 |
* this should be consistent w/ the enum, |
* this should be consistent w/ the enum, |
616 |
|
|
617 |
for (i = 0; i < ARRAY_SIZE(applet_main); i++) { |
for (i = 0; i < ARRAY_SIZE(applet_main); i++) { |
618 |
fpc = concat_path_file( |
fpc = concat_path_file( |
619 |
install_dir[APPLET_INSTALL_LOC(i)], |
custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], |
620 |
APPLET_NAME(i)); |
APPLET_NAME(i)); |
621 |
// debug: bb_error_msg("%slinking %s to busybox", |
// debug: bb_error_msg("%slinking %s to busybox", |
622 |
// use_symbolic_links ? "sym" : "", fpc); |
// use_symbolic_links ? "sym" : "", fpc); |
628 |
} |
} |
629 |
} |
} |
630 |
#else |
#else |
631 |
#define install_links(x,y) ((void)0) |
#define install_links(x,y,z) ((void)0) |
632 |
#endif /* FEATURE_INSTALLER */ |
#endif /* FEATURE_INSTALLER */ |
633 |
|
|
634 |
/* If we were called as "busybox..." */ |
/* If we were called as "busybox..." */ |
637 |
if (!argv[1]) { |
if (!argv[1]) { |
638 |
/* Called without arguments */ |
/* Called without arguments */ |
639 |
const char *a; |
const char *a; |
640 |
unsigned col, output_width; |
int col; |
641 |
|
unsigned output_width; |
642 |
help: |
help: |
643 |
output_width = 80; |
output_width = 80; |
644 |
if (ENABLE_FEATURE_AUTOWIDTH) { |
if (ENABLE_FEATURE_AUTOWIDTH) { |
645 |
/* Obtain the terminal width */ |
/* Obtain the terminal width */ |
646 |
get_terminal_width_height(0, &output_width, NULL); |
get_terminal_width_height(0, &output_width, NULL); |
647 |
} |
} |
|
/* leading tab and room to wrap */ |
|
|
output_width -= MAX_APPLET_NAME_LEN + 8; |
|
648 |
|
|
649 |
dup2(1, 2); |
dup2(1, 2); |
650 |
full_write2_str(bb_banner); /* reuse const string... */ |
full_write2_str(bb_banner); /* reuse const string */ |
651 |
full_write2_str(" multi-call binary\n" |
full_write2_str(" multi-call binary.\n"); /* reuse */ |
652 |
"Copyright (C) 1998-2008 Erik Andersen, Rob Landley, Denys Vlasenko\n" |
full_write2_str( |
653 |
|
"Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n" |
654 |
"and others. Licensed under GPLv2.\n" |
"and others. Licensed under GPLv2.\n" |
655 |
"See source distribution for full notice.\n" |
"See source distribution for full notice.\n" |
656 |
"\n" |
"\n" |
660 |
"\tBusyBox is a multi-call binary that combines many common Unix\n" |
"\tBusyBox is a multi-call binary that combines many common Unix\n" |
661 |
"\tutilities into a single executable. Most people will create a\n" |
"\tutilities into a single executable. Most people will create a\n" |
662 |
"\tlink to busybox for each function they wish to use and BusyBox\n" |
"\tlink to busybox for each function they wish to use and BusyBox\n" |
663 |
"\twill act like whatever it was invoked as!\n" |
"\twill act like whatever it was invoked as.\n" |
664 |
"\n" |
"\n" |
665 |
"Currently defined functions:\n"); |
"Currently defined functions:\n"); |
666 |
col = 0; |
col = 0; |
667 |
a = applet_names; |
a = applet_names; |
668 |
|
/* prevent last comma to be in the very last pos */ |
669 |
|
output_width--; |
670 |
while (*a) { |
while (*a) { |
671 |
int len; |
int len2 = strlen(a) + 2; |
672 |
if (col > output_width) { |
if (col >= (int)output_width - len2) { |
673 |
full_write2_str(",\n"); |
full_write2_str(",\n"); |
674 |
col = 0; |
col = 0; |
675 |
} |
} |
676 |
full_write2_str(col ? ", " : "\t"); |
if (col == 0) { |
677 |
|
col = 6; |
678 |
|
full_write2_str("\t"); |
679 |
|
} else { |
680 |
|
full_write2_str(", "); |
681 |
|
} |
682 |
full_write2_str(a); |
full_write2_str(a); |
683 |
len = strlen(a); |
col += len2; |
684 |
col += len + 2; |
a += len2 - 1; |
|
a += len + 1; |
|
685 |
} |
} |
686 |
full_write2_str("\n\n"); |
full_write2_str("\n\n"); |
687 |
return 0; |
return 0; |
688 |
} |
} |
689 |
|
|
690 |
if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { |
if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { |
691 |
|
int use_symbolic_links; |
692 |
const char *busybox; |
const char *busybox; |
693 |
busybox = xmalloc_readlink(bb_busybox_exec_path); |
busybox = xmalloc_readlink(bb_busybox_exec_path); |
694 |
if (!busybox) |
if (!busybox) |
695 |
busybox = bb_busybox_exec_path; |
busybox = bb_busybox_exec_path; |
696 |
/* -s makes symlinks */ |
/* busybox --install [-s] [DIR]: */ |
697 |
install_links(busybox, argv[2] && strcmp(argv[2], "-s") == 0); |
/* -s: make symlinks */ |
698 |
|
/* DIR: directory to install links to */ |
699 |
|
use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && argv++); |
700 |
|
install_links(busybox, use_symbolic_links, argv[2]); |
701 |
return 0; |
return 0; |
702 |
} |
} |
703 |
|
|
765 |
int main(int argc UNUSED_PARAM, char **argv) |
int main(int argc UNUSED_PARAM, char **argv) |
766 |
#endif |
#endif |
767 |
{ |
{ |
768 |
|
/* Tweak malloc for reduced memory consumption */ |
769 |
|
#ifndef PAGE_SIZE |
770 |
|
# define PAGE_SIZE (4*1024) /* guess */ |
771 |
|
#endif |
772 |
|
#ifdef M_TRIM_THRESHOLD |
773 |
|
/* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory |
774 |
|
* to keep before releasing to the OS |
775 |
|
* Default is way too big: 256k |
776 |
|
*/ |
777 |
|
mallopt(M_TRIM_THRESHOLD, 2 * PAGE_SIZE); |
778 |
|
#endif |
779 |
|
#ifdef M_MMAP_THRESHOLD |
780 |
|
/* M_MMAP_THRESHOLD is the request size threshold for using mmap() |
781 |
|
* Default is too big: 256k |
782 |
|
*/ |
783 |
|
mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256); |
784 |
|
#endif |
785 |
|
|
786 |
#if defined(SINGLE_APPLET_MAIN) |
#if defined(SINGLE_APPLET_MAIN) |
787 |
/* Only one applet is selected by the user! */ |
/* Only one applet is selected by the user! */ |
788 |
/* applet_names in this case is just "applet\0\0" */ |
/* applet_names in this case is just "applet\0\0" */ |
789 |
lbb_prepare(applet_names USE_FEATURE_INDIVIDUAL(, argv)); |
lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv)); |
790 |
return SINGLE_APPLET_MAIN(argc, argv); |
return SINGLE_APPLET_MAIN(argc, argv); |
791 |
#else |
#else |
792 |
lbb_prepare("busybox" USE_FEATURE_INDIVIDUAL(, argv)); |
lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); |
793 |
|
|
794 |
#if !BB_MMU |
#if !BB_MMU |
795 |
/* NOMMU re-exec trick sets high-order bit in first byte of name */ |
/* NOMMU re-exec trick sets high-order bit in first byte of name */ |