- struct stat st;
- char *err = 0;
- FILE *f = 0;
- int lc = 0;
-
- suid_config = 0;
-
- // is there a config file ?
- if ( stat ( CONFIG_FILE, &st ) == 0 ) {
- // is it owned by root with no write perm. for group and others ?
- if ( S_ISREG( st. st_mode ) && ( st. st_uid == 0 ) && (!( st. st_mode & ( S_IWGRP | S_IWOTH )))) {
- // that's ok .. then try to open it
- f = fopen ( CONFIG_FILE, "r" );
-
- if ( f ) {
- char buffer [256];
- int section = 0;
-
- while ( fgets ( buffer, sizeof( buffer ) - 1, f )) {
- char c = buffer [0];
- char *p;
-
- lc++;
-
- p = strchr ( buffer, '#' );
- if ( p )
- *p = 0;
- p = buffer + xstrlen ( buffer );
- while (( p > buffer ) && isspace ( *--p ))
- *p = 0;
-
- if ( p == buffer )
- continue;
-
- if ( c == '[' ) {
- p = strchr ( buffer, ']' );
-
- if ( !p || ( p == ( buffer + 1 ))) // no matching ] or empty []
- parse_error ( "malformed section header" );
-
- *p = 0;
-
- if ( strcasecmp ( buffer + 1, "SUID" ) == 0 )
- section = 1;
- else
- section = -1; // unknown section - just skip
- }
- else if ( section ) {
- switch ( section ) {
- case 1: { // SUID
- int l;
- struct BB_applet *applet;
-
- p = strchr ( buffer, '=' ); // <key>[::space::]*=[::space::]*<value>
-
- if ( !p || ( p == ( buffer + 1 ))) // no = or key is empty
- parse_error ( "malformed keyword" );
-
- l = p - buffer;
- while ( isspace ( buffer [--l] )) { } // skip whitespace
-
- buffer [l+1] = 0;
-
- if (( applet = find_applet_by_name ( buffer ))) {
- struct BB_suid_config *sct = xmalloc ( sizeof( struct BB_suid_config ));
-
- sct-> m_applet = applet;
- sct-> m_next = suid_config;
- suid_config = sct;
-
- while ( isspace ( *++p )) { } // skip whitespace
-
- sct-> m_mode = 0;
-
- switch ( *p++ ) {
- case 'S': sct-> m_mode |= S_ISUID; break;
- case 's': sct-> m_mode |= S_ISUID; // no break
- case 'x': sct-> m_mode |= S_IXUSR; break;
- case '-': break;
- default : parse_error ( "invalid user mode" );
- }
-
- switch ( *p++ ) {
- case 's': sct-> m_mode |= S_ISGID; // no break
- case 'x': sct-> m_mode |= S_IXGRP; break;
- case 'S': break;
- case '-': break;
- default : parse_error ( "invalid group mode" );
- }
-
- switch ( *p ) {
- case 't':
- case 'x': sct-> m_mode |= S_IXOTH; break;
- case 'T':
- case '-': break;
- default : parse_error ( "invalid other mode" );
- }
-
- while ( isspace ( *++p )) { } // skip whitespace
-
- if ( isdigit ( *p )) {
- sct-> m_uid = strtol ( p, &p, 10 );
- if ( *p++ != '.' )
- parse_error ( "parsing <uid>.<gid>" );
- }
- else {
- struct passwd *pwd;
- char *p2 = strchr ( p, '.' );
-
- if ( !p2 )
- parse_error ( "parsing <uid>.<gid>" );
-
- *p2 = 0;
- pwd = getpwnam ( p );
-
- if ( !pwd )
- parse_error ( "invalid user name" );
-
- sct-> m_uid = pwd-> pw_uid;
- p = p2 + 1;
- }
- if ( isdigit ( *p ))
- sct-> m_gid = strtol ( p, &p, 10 );
- else {
- struct group *grp = getgrnam ( p );
-
- if ( !grp )
- parse_error ( "invalid group name" );
-
- sct-> m_gid = grp-> gr_gid;
- }
- }
- break;
- }
- default: // unknown - skip
- break;
- }
- }
- else
- parse_error ( "keyword not within section" );
- }
- fclose ( f );
+ if (ENABLE_SHOW_USAGE) {
+ const char *format_string;
+ const char *p;
+ const char *usage_string = p = unpack_usage_messages();
+ int i;
+
+ i = current_applet - applets;
+ while (i) {
+ while (*p++) continue;
+ i--;
+ }
+
+ format_string = "%s\n\nUsage: %s %s\n\n";
+ if (*p == '\b')
+ format_string = "%s\n\nNo help available.\n\n";
+ fprintf(stderr, format_string, bb_msg_full_version,
+ applet_name, p);
+ dealloc_usage_messages((char*)usage_string);
+ }
+ xfunc_die();
+}
+
+
+static int applet_name_compare(const void *name, const void *vapplet)
+{
+ const struct bb_applet *applet = vapplet;
+
+ return strcmp(name, applet->name);
+}
+
+const struct bb_applet *find_applet_by_name(const char *name)
+{
+ /* Do a binary search to find the applet entry given the name. */
+ return bsearch(name, applets, NUM_APPLETS, sizeof(applets[0]),
+ applet_name_compare);
+}
+
+
+#if ENABLE_FEATURE_INSTALLER
+/* create (sym)links for each applet */
+static void install_links(const char *busybox, int use_symbolic_links)
+{
+ /* directory table
+ * this should be consistent w/ the enum,
+ * busybox.h::bb_install_loc_t, or else... */
+ static const char usr_bin [] = "/usr/bin";
+ static const char usr_sbin[] = "/usr/sbin";
+ static const char *const install_dir[] = {
+ &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
+ &usr_bin [4], /* "/bin" */
+ &usr_sbin[4], /* "/sbin" */
+ usr_bin,
+ usr_sbin
+ };
+
+ int (*lf)(const char *, const char *) = link;
+ char *fpc;
+ int i;
+ int rc;
+
+ if (use_symbolic_links)
+ lf = symlink;
+
+ for (i = 0; applets[i].name != NULL; i++) {
+ fpc = concat_path_file(
+ install_dir[applets[i].install_loc],
+ applets[i].name);
+ rc = lf(busybox, fpc);
+ if (rc != 0 && errno != EEXIST) {
+ bb_perror_msg("%s", fpc);
+ }
+ free(fpc);
+ }
+}
+#else
+#define install_links(x,y) ((void)0)
+#endif /* FEATURE_INSTALLER */
+
+
+/* If we were called as "busybox..." */
+static int busybox_main(int argc, char **argv)
+{
+ if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) {
+ int use_symbolic_links = 0;
+ char *busybox;
+
+ /* to use symlinks, or not to use symlinks... */
+ if (argc > 2)
+ if (strcmp(argv[2], "-s") == 0)
+ use_symbolic_links = 1;
+
+ /* link */
+ busybox = xmalloc_readlink_or_warn("/proc/self/exe");
+ if (!busybox)
+ return 1;
+ install_links(busybox, use_symbolic_links);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(busybox);
+ return 0;
+ }
+
+ /* Deal with --help. Also print help when called with no arguments */
+
+ if (argc == 1 || !strcmp(argv[1], "--help") ) {
+ if (argc > 2) {
+ /* set name for proper "<name>: applet not found" */
+ applet_name = argv[2];
+ run_applet_and_exit(applet_name, 2, argv);
+ } else {
+ const struct bb_applet *a;
+ int col, output_width;
+
+ output_width = 80 - sizeof("start-stop-daemon, ") - 8;
+ if (ENABLE_FEATURE_AUTOWIDTH) {
+ /* Obtain the terminal width. */
+ get_terminal_width_height(0, &output_width, NULL);
+ /* leading tab and room to wrap */
+ output_width -= sizeof("start-stop-daemon, ") + 8;