mv: implement -n option
[oweals/busybox.git] / libbb / appletlib.c
index 48a8bb6f341e62a35e336265211b827a224e869c..b32ff8808ca1a120ead2efd0cb92e2e079073831 100644 (file)
@@ -7,9 +7,9 @@
  * here, please feel free to acknowledge your work.
  *
  * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
- * Permission has been granted to redistribute this code under the GPL.
+ * Permission has been granted to redistribute this code under GPL.
  *
- * Licensed under GPLv2 or later, see file License in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
 /* We are trying to not use printf, this benefits the case when selected
  *
  * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :(
  */
-
-#include <assert.h>
 #include "busybox.h"
+#include <assert.h>
+#include <malloc.h>
+/* Try to pull in PAGE_SIZE */
+#ifdef __linux__
+# include <sys/user.h>
+#endif
+#ifdef __GNU__ /* Hurd */
+# include <mach/vm_param.h>
+#endif
 
 
 /* Declare <applet>_main() */
 #include "applets.h"
 #undef PROTOTYPES
 
-#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
-/* Define usage_messages[] */
-static const char usage_messages[] ALIGN1 = ""
-#define MAKE_USAGE
-#include "usage.h"
-#include "applets.h"
-;
-#undef MAKE_USAGE
-#else
-#define usage_messages 0
-#endif /* SHOW_USAGE */
-
 
 /* Include generated applet names, pointers to <applet>_main, etc */
 #include "applet_tables.h"
 /* ...and if applet_tables generator says we have only one applet... */
 #ifdef SINGLE_APPLET_MAIN
-#undef ENABLE_FEATURE_INDIVIDUAL
-#define ENABLE_FEATURE_INDIVIDUAL 1
-#undef IF_FEATURE_INDIVIDUAL
-#define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__
+# undef ENABLE_FEATURE_INDIVIDUAL
+# define ENABLE_FEATURE_INDIVIDUAL 1
+# undef IF_FEATURE_INDIVIDUAL
+# define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__
 #endif
 
 
-#if ENABLE_FEATURE_COMPRESS_USAGE
-
 #include "usage_compressed.h"
-#include "unarchive.h"
 
+#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
+static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
+#else
+# define usage_messages 0
+#endif
+
+#if ENABLE_FEATURE_COMPRESS_USAGE
+
+static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
+# include "unarchive.h"
 static const char *unpack_usage_messages(void)
 {
        char *outbuf = NULL;
@@ -79,28 +81,23 @@ static const char *unpack_usage_messages(void)
         * end up here with i != 0 on read data errors! Not trivial */
        if (!i) {
                /* Cannot use xmalloc: will leak bd in NOFORK case! */
-               outbuf = malloc_or_warn(SIZEOF_usage_messages);
+               outbuf = malloc_or_warn(sizeof(UNPACKED_USAGE));
                if (outbuf)
-                       read_bunzip(bd, outbuf, SIZEOF_usage_messages);
+                       read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE));
        }
        dealloc_bunzip(bd);
        return outbuf;
 }
-#define dealloc_usage_messages(s) free(s)
+# define dealloc_usage_messages(s) free(s)
 
 #else
 
-#define unpack_usage_messages() usage_messages
-#define dealloc_usage_messages(s) ((void)(s))
+# define unpack_usage_messages() usage_messages
+# define dealloc_usage_messages(s) ((void)(s))
 
 #endif /* FEATURE_COMPRESS_USAGE */
 
 
-static void full_write2_str(const char *str)
-{
-       xwrite_str(STDERR_FILENO, str);
-}
-
 void FAST_FUNC bb_show_usage(void)
 {
        if (ENABLE_SHOW_USAGE) {
@@ -116,7 +113,8 @@ void FAST_FUNC bb_show_usage(void)
                        full_write2_str(p);
                        full_write2_str("\n\n");
                }
-               dealloc_usage_messages((char*)usage_string);
+               if (ENABLE_FEATURE_CLEAN_UP)
+                       dealloc_usage_messages((char*)usage_string);
 #else
                const char *p;
                const char *usage_string = p = unpack_usage_messages();
@@ -129,7 +127,7 @@ void FAST_FUNC bb_show_usage(void)
                        ap--;
                }
                full_write2_str(bb_banner);
-               full_write2_str(" multi-call binary\n");
+               full_write2_str(" multi-call binary.\n");
                if (*p == '\b')
                        full_write2_str("\nNo help available.\n\n");
                else {
@@ -139,7 +137,8 @@ void FAST_FUNC bb_show_usage(void)
                        full_write2_str(p);
                        full_write2_str("\n\n");
                }
-               dealloc_usage_messages((char*)usage_string);
+               if (ENABLE_FEATURE_CLEAN_UP)
+                       dealloc_usage_messages((char*)usage_string);
 #endif
        }
        xfunc_die();
@@ -196,7 +195,11 @@ void lbb_prepare(const char *applet
 #if ENABLE_FEATURE_INDIVIDUAL
        /* Redundant for busybox (run_applet_and_exit covers that case)
         * but needed for "individual applet" mode */
-       if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) {
+       if (argv[1]
+        && !argv[2]
+        && strcmp(argv[1], "--help") == 0
+        && strncmp(applet, "busybox", 7) != 0
+       ) {
                /* Special case. POSIX says "test --help"
                 * should be no different from e.g. "test --foo".  */
                if (!ENABLE_TEST || strcmp(applet_name, "test") != 0)
@@ -584,6 +587,19 @@ static void check_suid(int applet_no)
 
 
 #if ENABLE_FEATURE_INSTALLER
+static const char usr_bin [] ALIGN1 = "/usr/bin/";
+static const char usr_sbin[] ALIGN1 = "/usr/sbin/";
+static const char *const install_dir[] = {
+       &usr_bin [8], /* "/" */
+       &usr_bin [4], /* "/bin/" */
+       &usr_sbin[4]  /* "/sbin/" */
+# if !ENABLE_INSTALL_NO_USR
+       ,usr_bin
+       ,usr_sbin
+# endif
+};
+
+
 /* create (sym)links for each applet */
 static void install_links(const char *busybox, int use_symbolic_links,
                char *custom_install_dir)
@@ -591,16 +607,6 @@ 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 [] ALIGN1 = "/usr/bin";
-       static const char usr_sbin[] ALIGN1 = "/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 *);
        char *fpc;
        unsigned i;
@@ -624,8 +630,8 @@ static void install_links(const char *busybox, int use_symbolic_links,
        }
 }
 #else
-#define install_links(x,y,z) ((void)0)
-#endif /* FEATURE_INSTALLER */
+# define install_links(x,y,z) ((void)0)
+#endif
 
 /* If we were called as "busybox..." */
 static int busybox_main(char **argv)
@@ -643,21 +649,24 @@ static int busybox_main(char **argv)
                }
 
                dup2(1, 2);
-               full_write2_str(bb_banner); /* reuse const string... */
-               full_write2_str(" multi-call binary\n"
-                      "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n"
-                      "and others. Licensed under GPLv2.\n"
-                      "See source distribution for full notice.\n"
-                      "\n"
-                      "Usage: busybox [function] [arguments]...\n"
-                      "   or: function [arguments]...\n"
-                      "\n"
-                      "\tBusyBox is a multi-call binary that combines many common Unix\n"
-                      "\tutilities into a single executable.  Most people will create a\n"
-                      "\tlink to busybox for each function they wish to use and BusyBox\n"
-                      "\twill act like whatever it was invoked as!\n"
-                      "\n"
-                      "Currently defined functions:\n");
+               full_write2_str(bb_banner); /* reuse const string */
+               full_write2_str(" multi-call binary.\n"); /* reuse */
+               full_write2_str(
+                       "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n"
+                       "and others. Licensed under GPLv2.\n"
+                       "See source distribution for full notice.\n"
+                       "\n"
+                       "Usage: busybox [function] [arguments]...\n"
+                       "   or: busybox --list[-full]\n"
+                       "   or: function [arguments]...\n"
+                       "\n"
+                       "\tBusyBox is a multi-call binary that combines many common Unix\n"
+                       "\tutilities into a single executable.  Most people will create a\n"
+                       "\tlink to busybox for each function they wish to use and BusyBox\n"
+                       "\twill act like whatever it was invoked as.\n"
+                       "\n"
+                       "Currently defined functions:\n"
+               );
                col = 0;
                a = applet_names;
                /* prevent last comma to be in the very last pos */
@@ -682,6 +691,23 @@ static int busybox_main(char **argv)
                return 0;
        }
 
+       if (strncmp(argv[1], "--list", 6) == 0) {
+               unsigned i = 0;
+               const char *a = applet_names;
+               dup2(1, 2);
+               while (*a) {
+#if ENABLE_FEATURE_INSTALLER
+                       if (argv[1][6]) /* --list-path? */
+                               full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
+#endif
+                       full_write2_str(a);
+                       full_write2_str("\n");
+                       i++;
+                       a += strlen(a) + 1;
+               }
+               return 0;
+       }
+
        if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) {
                int use_symbolic_links;
                const char *busybox;
@@ -760,6 +786,24 @@ int lbb_main(char **argv)
 int main(int argc UNUSED_PARAM, char **argv)
 #endif
 {
+       /* Tweak malloc for reduced memory consumption */
+#ifndef PAGE_SIZE
+# define PAGE_SIZE (4*1024) /* guess */
+#endif
+#ifdef M_TRIM_THRESHOLD
+       /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory
+        * to keep before releasing to the OS
+        * Default is way too big: 256k
+        */
+       mallopt(M_TRIM_THRESHOLD, 2 * PAGE_SIZE);
+#endif
+#ifdef M_MMAP_THRESHOLD
+       /* M_MMAP_THRESHOLD is the request size threshold for using mmap()
+        * Default is too big: 256k
+        */
+       mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256);
+#endif
+
 #if defined(SINGLE_APPLET_MAIN)
        /* Only one applet is selected by the user! */
        /* applet_names in this case is just "applet\0\0" */