busybox.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* vi: set sw=4 ts=4: */
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <stdlib.h>
  7. #include "busybox.h"
  8. #ifdef CONFIG_LOCALE_SUPPORT
  9. #include <locale.h>
  10. #endif
  11. int been_there_done_that = 0; /* Also used in applets.c */
  12. const char *bb_applet_name;
  13. #ifdef CONFIG_FEATURE_INSTALLER
  14. /*
  15. * directory table
  16. * this should be consistent w/ the enum, busybox.h::Location,
  17. * or else...
  18. */
  19. static const char usr_bin [] ="/usr/bin";
  20. static const char usr_sbin[] ="/usr/sbin";
  21. static const char* const install_dir[] = {
  22. &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
  23. &usr_bin [4], /* "/bin" */
  24. &usr_sbin[4], /* "/sbin" */
  25. usr_bin,
  26. usr_sbin
  27. };
  28. /* abstract link() */
  29. typedef int (*__link_f)(const char *, const char *);
  30. /*
  31. * Where in the filesystem is this busybox?
  32. * [return]
  33. * malloc'd string w/ full pathname of busybox's location
  34. * NULL on failure
  35. */
  36. static inline char *busybox_fullpath(void)
  37. {
  38. return xreadlink("/proc/self/exe");
  39. }
  40. /* create (sym)links for each applet */
  41. static void install_links(const char *busybox, int use_symbolic_links)
  42. {
  43. __link_f Link = link;
  44. char *fpc;
  45. int i;
  46. int rc;
  47. if (use_symbolic_links)
  48. Link = symlink;
  49. for (i = 0; applets[i].name != NULL; i++) {
  50. fpc = concat_path_file(
  51. install_dir[applets[i].location], applets[i].name);
  52. rc = Link(busybox, fpc);
  53. if (rc!=0 && errno!=EEXIST) {
  54. bb_perror_msg("%s", fpc);
  55. }
  56. free(fpc);
  57. }
  58. }
  59. #endif /* CONFIG_FEATURE_INSTALLER */
  60. int main(int argc, char **argv)
  61. {
  62. const char *s;
  63. bb_applet_name = argv[0];
  64. if (bb_applet_name[0] == '-')
  65. bb_applet_name++;
  66. for (s = bb_applet_name; *s != '\0';) {
  67. if (*s++ == '/')
  68. bb_applet_name = s;
  69. }
  70. #ifdef CONFIG_LOCALE_SUPPORT
  71. #ifdef CONFIG_INIT
  72. if(getpid()!=1) /* Do not set locale for `init' */
  73. #endif
  74. {
  75. setlocale(LC_ALL, "");
  76. }
  77. #endif
  78. run_applet_by_name(bb_applet_name, argc, argv);
  79. bb_error_msg_and_die("applet not found");
  80. }
  81. int busybox_main(int argc, char **argv)
  82. {
  83. int col = 0, len, i;
  84. #ifdef CONFIG_FEATURE_INSTALLER
  85. /*
  86. * This style of argument parsing doesn't scale well
  87. * in the event that busybox starts wanting more --options.
  88. * If someone has a cleaner approach, by all means implement it.
  89. */
  90. if (argc > 1 && (strcmp(argv[1], "--install") == 0)) {
  91. int use_symbolic_links = 0;
  92. int rc = 0;
  93. char *busybox;
  94. /* to use symlinks, or not to use symlinks... */
  95. if (argc > 2) {
  96. if ((strcmp(argv[2], "-s") == 0)) {
  97. use_symbolic_links = 1;
  98. }
  99. }
  100. /* link */
  101. busybox = busybox_fullpath();
  102. if (busybox) {
  103. install_links(busybox, use_symbolic_links);
  104. free(busybox);
  105. } else {
  106. rc = 1;
  107. }
  108. return rc;
  109. }
  110. #endif /* CONFIG_FEATURE_INSTALLER */
  111. argc--;
  112. /* If we've already been here once, exit now */
  113. if (been_there_done_that == 1 || argc < 1) {
  114. const struct BB_applet *a = applets;
  115. int output_width = 60;
  116. #ifdef CONFIG_FEATURE_AUTOWIDTH
  117. /* Obtain the terminal width. */
  118. get_terminal_width_height(0, &output_width, NULL);
  119. /* leading tab and room to wrap */
  120. output_width -= 20;
  121. #endif
  122. printf("%s\n\n"
  123. "Usage: busybox [function] [arguments]...\n"
  124. " or: [function] [arguments]...\n\n"
  125. "\tBusyBox is a multi-call binary that combines many common Unix\n"
  126. "\tutilities into a single executable. Most people will create a\n"
  127. "\tlink to busybox for each function they wish to use and BusyBox\n"
  128. "\twill act like whatever it was invoked as!\n"
  129. "\nCurrently defined functions:\n", bb_msg_full_version);
  130. while (a->name != 0) {
  131. col +=
  132. printf("%s%s", ((col == 0) ? "\t" : ", "),
  133. (a++)->name);
  134. if (col > output_width && a->name != 0) {
  135. printf(",\n");
  136. col = 0;
  137. }
  138. }
  139. printf("\n\n");
  140. exit(0);
  141. }
  142. /* Flag that we've been here already */
  143. been_there_done_that = 1;
  144. /* Move the command line down a notch */
  145. /* Preserve pointers so setproctitle() works consistently */
  146. len = argv[argc] + strlen(argv[argc]) - argv[1];
  147. memmove(argv[0], argv[1], len);
  148. memset(argv[0] + len, 0, argv[1] - argv[0]);
  149. /* Fix up the argv pointers */
  150. len = argv[1] - argv[0];
  151. memmove(argv, argv + 1, sizeof(char *) * (argc + 1));
  152. for (i = 0; i < argc; i++)
  153. argv[i] -= len;
  154. return (main(argc, argv));
  155. }
  156. /*
  157. Local Variables:
  158. c-file-style: "linux"
  159. c-basic-offset: 4
  160. tab-width: 4
  161. End:
  162. */