aboutsummaryrefslogtreecommitdiff
path: root/applets
diff options
context:
space:
mode:
Diffstat (limited to 'applets')
-rw-r--r--applets/Kbuild21
-rw-r--r--applets/applets.c483
-rw-r--r--applets/busybox.c148
-rwxr-xr-xapplets/busybox.mkll24
-rw-r--r--applets/individual.c27
-rwxr-xr-xapplets/install.sh94
-rw-r--r--applets/usage.c17
-rwxr-xr-xapplets/usage_compressed19
8 files changed, 833 insertions, 0 deletions
diff --git a/applets/Kbuild b/applets/Kbuild
new file mode 100644
index 000000000..c95c09d97
--- /dev/null
+++ b/applets/Kbuild
@@ -0,0 +1,21 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6
7obj-y:=
8obj-y += applets.o
9obj-y += busybox.o
10
11# Generated file needs additional love
12
13applets/applets.o: include/usage_compressed.h
14
15hostprogs-y += usage
16always := $(hostprogs-y)
17HOSTCFLAGS_usage.o = -I$(srctree)/include
18
19include/usage_compressed.h: $(srctree)/include/usage.h applets/usage
20 @echo ' GEN include/usage_compressed.h'
21 @$(srctree)/applets/usage_compressed include/usage_compressed.h applets
diff --git a/applets/applets.c b/applets/applets.c
new file mode 100644
index 000000000..23f9e4f92
--- /dev/null
+++ b/applets/applets.c
@@ -0,0 +1,483 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright (C) tons of folks. Tracking down who wrote what
6 * isn't something I'm going to worry about... If you wrote something
7 * here, please feel free to acknowledge your work.
8 *
9 * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
10 * Permission has been granted to redistribute this code under the GPL.
11 *
12 * Licensed under GPLv2 or later, see file License in this tarball for details.
13 */
14
15#include "busybox.h"
16#include <unistd.h>
17#include <string.h>
18#include <assert.h>
19
20/* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */
21#if ENABLE_STATIC && defined(__GLIBC__) && !defined(__UCLIBC__)
22#warning Static linking against glibc produces buggy executables
23#warning (glibc does not cope well with ld --gc-sections).
24#warning See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
25#warning Note that glibc is utterly unsuitable for static linking anyway.
26#endif
27
28#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
29static const char usage_messages[] =
30#define MAKE_USAGE
31#include "usage.h"
32#include "applets.h"
33;
34#undef MAKE_USAGE
35#else
36#define usage_messages 0
37#endif /* ENABLE_SHOW_USAGE */
38
39#undef APPLET
40#undef APPLET_NOUSAGE
41#undef PROTOTYPES
42#include "applets.h"
43
44static struct BB_applet *applet_using;
45
46/* The -1 arises because of the {0,NULL,0,-1} entry above. */
47const size_t NUM_APPLETS = (sizeof (applets) / sizeof (struct BB_applet) - 1);
48
49
50#ifdef CONFIG_FEATURE_SUID_CONFIG
51
52#include <ctype.h>
53
54#define CONFIG_FILE "/etc/busybox.conf"
55
56/* applets [] is const, so we have to define this "override" structure */
57static struct BB_suid_config
58{
59 struct BB_applet *m_applet;
60
61 uid_t m_uid;
62 gid_t m_gid;
63 mode_t m_mode;
64
65 struct BB_suid_config *m_next;
66} *suid_config;
67
68static int suid_cfg_readable;
69
70/* check if u is member of group g */
71static int ingroup(uid_t u, gid_t g)
72{
73 struct group *grp = getgrgid(g);
74
75 if (grp) {
76 char **mem;
77
78 for (mem = grp->gr_mem; *mem; mem++) {
79 struct passwd *pwd = getpwnam(*mem);
80
81 if (pwd && (pwd->pw_uid == u))
82 return 1;
83 }
84 }
85 return 0;
86}
87
88/* This should probably be a libbb routine. In that case,
89 * I'd probably rename it to something like bb_trimmed_slice.
90 */
91static char *get_trimmed_slice(char *s, char *e)
92{
93 /* First, consider the value at e to be nul and back up until we
94 * reach a non-space char. Set the char after that (possibly at
95 * the original e) to nul. */
96 while (e-- > s) {
97 if (!isspace(*e)) {
98 break;
99 }
100 }
101 e[1] = 0;
102
103 /* Next, advance past all leading space and return a ptr to the
104 * first non-space char; possibly the terminating nul. */
105 return skip_whitespace(s);
106}
107
108
109#define parse_error(x) { err=x; goto pe_label; }
110
111/* Don't depend on the tools to combine strings. */
112static const char config_file[] = CONFIG_FILE;
113
114/* There are 4 chars + 1 nul for each of user/group/other. */
115static const char mode_chars[] = "Ssx-\0Ssx-\0Ttx-";
116
117/* We don't supply a value for the nul, so an index adjustment is
118 * necessary below. Also, we use unsigned short here to save some
119 * space even though these are really mode_t values. */
120static const unsigned short mode_mask[] = {
121 /* SST sst xxx --- */
122 S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* user */
123 S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* group */
124 0, S_IXOTH, S_IXOTH, 0 /* other */
125};
126
127static void parse_config_file(void)
128{
129 struct BB_suid_config *sct_head;
130 struct BB_suid_config *sct;
131 struct BB_applet *applet;
132 FILE *f;
133 char *err;
134 char *s;
135 char *e;
136 int i, lc, section;
137 char buffer[256];
138 struct stat st;
139
140 assert(!suid_config); /* Should be set to NULL by bss init. */
141
142 if ((stat(config_file, &st) != 0) /* No config file? */
143 || !S_ISREG(st.st_mode) /* Not a regular file? */
144 || (st.st_uid != 0) /* Not owned by root? */
145 || (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */
146 || !(f = fopen(config_file, "r")) /* Cannot open? */
147 ) {
148 return;
149 }
150
151 suid_cfg_readable = 1;
152 sct_head = NULL;
153 section = lc = 0;
154
155 do {
156 s = buffer;
157
158 if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */
159 if (ferror(f)) { /* Make sure it wasn't a read error. */
160 parse_error("reading");
161 }
162 fclose(f);
163 suid_config = sct_head; /* Success, so set the pointer. */
164 return;
165 }
166
167 lc++; /* Got a (partial) line. */
168
169 /* If a line is too long for our buffer, we consider it an error.
170 * The following test does mistreat one corner case though.
171 * If the final line of the file does not end with a newline and
172 * yet exactly fills the buffer, it will be treated as too long
173 * even though there isn't really a problem. But it isn't really
174 * worth adding code to deal with such an unlikely situation, and
175 * we do err on the side of caution. Besides, the line would be
176 * too long if it did end with a newline. */
177 if (!strchr(s, '\n') && !feof(f)) {
178 parse_error("line too long");
179 }
180
181 /* Trim leading and trailing whitespace, ignoring comments, and
182 * check if the resulting string is empty. */
183 if (!*(s = get_trimmed_slice(s, strchrnul(s, '#')))) {
184 continue;
185 }
186
187 /* Check for a section header. */
188
189 if (*s == '[') {
190 /* Unlike the old code, we ignore leading and trailing
191 * whitespace for the section name. We also require that
192 * there are no stray characters after the closing bracket. */
193 if (!(e = strchr(s, ']')) /* Missing right bracket? */
194 || e[1] /* Trailing characters? */
195 || !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */
196 ) {
197 parse_error("section header");
198 }
199 /* Right now we only have one section so just check it.
200 * If more sections are added in the future, please don't
201 * resort to cascading ifs with multiple strcasecmp calls.
202 * That kind of bloated code is all too common. A loop
203 * and a string table would be a better choice unless the
204 * number of sections is very small. */
205 if (strcasecmp(s, "SUID") == 0) {
206 section = 1;
207 continue;
208 }
209 section = -1; /* Unknown section so set to skip. */
210 continue;
211 }
212
213 /* Process sections. */
214
215 if (section == 1) { /* SUID */
216 /* Since we trimmed leading and trailing space above, we're
217 * now looking for strings of the form
218 * <key>[::space::]*=[::space::]*<value>
219 * where both key and value could contain inner whitespace. */
220
221 /* First get the key (an applet name in our case). */
222 if (!!(e = strchr(s, '='))) {
223 s = get_trimmed_slice(s, e);
224 }
225 if (!e || !*s) { /* Missing '=' or empty key. */
226 parse_error("keyword");
227 }
228
229 /* Ok, we have an applet name. Process the rhs if this
230 * applet is currently built in and ignore it otherwise.
231 * Note: This can hide config file bugs which only pop
232 * up when the busybox configuration is changed. */
233 if ((applet = find_applet_by_name(s))) {
234 /* Note: We currently don't check for duplicates!
235 * The last config line for each applet will be the
236 * one used since we insert at the head of the list.
237 * I suppose this could be considered a feature. */
238 sct = xmalloc(sizeof(struct BB_suid_config));
239 sct->m_applet = applet;
240 sct->m_mode = 0;
241 sct->m_next = sct_head;
242 sct_head = sct;
243
244 /* Get the specified mode. */
245
246 e = skip_whitespace(e+1);
247
248 for (i=0 ; i < 3 ; i++) {
249 const char *q;
250 if (!*(q = strchrnul(mode_chars + 5*i, *e++))) {
251 parse_error("mode");
252 }
253 /* Adjust by -i to account for nul. */
254 sct->m_mode |= mode_mask[(q - mode_chars) - i];
255 }
256
257 /* Now get the the user/group info. */
258
259 s = skip_whitespace(e);
260
261 /* Note: We require whitespace between the mode and the
262 * user/group info. */
263 if ((s == e) || !(e = strchr(s, '.'))) {
264 parse_error("<uid>.<gid>");
265 }
266 *e++ = 0;
267
268 /* We can't use get_ug_id here since it would exit()
269 * if a uid or gid was not found. Oh well... */
270 {
271 char *e2;
272
273 sct->m_uid = strtoul(s, &e2, 10);
274 if (*e2 || (s == e2)) {
275 struct passwd *pwd = getpwnam(s);
276 if (!pwd) {
277 parse_error("user");
278 }
279 sct->m_uid = pwd->pw_uid;
280 }
281
282 sct->m_gid = strtoul(e, &e2, 10);
283 if (*e2 || (e == e2)) {
284 struct group *grp;
285 if (!(grp = getgrnam(e))) {
286 parse_error("group");
287 }
288 sct->m_gid = grp->gr_gid;
289 }
290 }
291 }
292 continue;
293 }
294
295 /* Unknown sections are ignored. */
296
297 /* Encountering configuration lines prior to seeing a
298 * section header is treated as an error. This is how
299 * the old code worked, but it may not be desirable.
300 * We may want to simply ignore such lines in case they
301 * are used in some future version of busybox. */
302 if (!section) {
303 parse_error("keyword outside section");
304 }
305
306 } while (1);
307
308 pe_label:
309 fprintf(stderr, "Parse error in %s, line %d: %s\n",
310 config_file, lc, err);
311
312 fclose(f);
313 /* Release any allocated memory before returning. */
314 while (sct_head) {
315 sct = sct_head->m_next;
316 free(sct_head);
317 sct_head = sct;
318 }
319 return;
320}
321
322#else
323#define parse_config_file()
324#endif /* CONFIG_FEATURE_SUID_CONFIG */
325
326#ifdef CONFIG_FEATURE_SUID
327static void check_suid(struct BB_applet *applet)
328{
329 uid_t ruid = getuid(); /* real [ug]id */
330 uid_t rgid = getgid();
331
332#ifdef CONFIG_FEATURE_SUID_CONFIG
333 if (suid_cfg_readable) {
334 struct BB_suid_config *sct;
335
336 for (sct = suid_config; sct; sct = sct->m_next) {
337 if (sct->m_applet == applet)
338 break;
339 }
340 if (sct) {
341 mode_t m = sct->m_mode;
342
343 if (sct->m_uid == ruid) /* same uid */
344 m >>= 6;
345 else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid)) /* same group / in group */
346 m >>= 3;
347
348 if (!(m & S_IXOTH)) /* is x bit not set ? */
349 bb_error_msg_and_die("you have no permission to run this applet!");
350
351 if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { /* *both* have to be set for sgid */
352 xsetgid(sct->m_gid);
353 } else xsetgid(rgid); /* no sgid -> drop */
354
355 if (sct->m_mode & S_ISUID) xsetuid(sct->m_uid);
356 else xsetuid(ruid); /* no suid -> drop */
357 } else {
358 /* default: drop all privileges */
359 xsetgid(rgid);
360 xsetuid(ruid);
361 }
362 return;
363 } else {
364#ifndef CONFIG_FEATURE_SUID_CONFIG_QUIET
365 static int onetime = 0;
366
367 if (!onetime) {
368 onetime = 1;
369 fprintf(stderr, "Using fallback suid method\n");
370 }
371#endif
372 }
373#endif
374
375 if (applet->need_suid == _BB_SUID_ALWAYS) {
376 if (geteuid()) bb_error_msg_and_die("applet requires root privileges!");
377 } else if (applet->need_suid == _BB_SUID_NEVER) {
378 xsetgid(rgid); /* drop all privileges */
379 xsetuid(ruid);
380 }
381}
382#else
383#define check_suid(x)
384#endif /* CONFIG_FEATURE_SUID */
385
386
387
388#ifdef CONFIG_FEATURE_COMPRESS_USAGE
389
390#include "usage_compressed.h"
391#include "unarchive.h"
392
393static const char *unpack_usage_messages(void)
394{
395 int input[2], output[2], pid;
396 char *buf;
397
398 if(pipe(input) < 0 || pipe(output) < 0)
399 exit(1);
400
401 pid = fork();
402 switch (pid) {
403 case -1: /* error */
404 exit(1);
405 case 0: /* child */
406 close(input[1]);
407 close(output[0]);
408 uncompressStream(input[0], output[1]);
409 exit(0);
410 }
411 /* parent */
412
413 close(input[0]);
414 close(output[1]);
415 pid = fork();
416 switch (pid) {
417 case -1: /* error */
418 exit(1);
419 case 0: /* child */
420 full_write(input[1], packed_usage, sizeof(packed_usage));
421 exit(0);
422 }
423 /* parent */
424 close(input[1]);
425
426 buf = xmalloc(SIZEOF_usage_messages);
427 full_read(output[0], buf, SIZEOF_usage_messages);
428 return buf;
429}
430
431#else
432#define unpack_usage_messages() usage_messages
433#endif /* ENABLE_FEATURE_COMPRESS_USAGE */
434
435void bb_show_usage(void)
436{
437 if (ENABLE_SHOW_USAGE) {
438 const char *format_string;
439 const char *usage_string = unpack_usage_messages();
440 int i;
441
442 for (i = applet_using - applets; i > 0;)
443 if (!*usage_string++) --i;
444
445 format_string = "%s\n\nUsage: %s %s\n\n";
446 if (*usage_string == '\b')
447 format_string = "%s\n\nNo help available.\n\n";
448 fprintf(stderr, format_string, bb_msg_full_version,
449 applet_using->name, usage_string);
450 }
451
452 exit(xfunc_error_retval);
453}
454
455static int applet_name_compare(const void *name, const void *vapplet)
456{
457 const struct BB_applet *applet = vapplet;
458
459 return strcmp(name, applet->name);
460}
461
462extern const size_t NUM_APPLETS;
463
464struct BB_applet *find_applet_by_name(const char *name)
465{
466 return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet),
467 applet_name_compare);
468}
469
470void run_applet_by_name(const char *name, int argc, char **argv)
471{
472 if (ENABLE_FEATURE_SUID_CONFIG) parse_config_file();
473
474 if (!strncmp(name, "busybox", 7)) busybox_main(argc, argv);
475 /* Do a binary search to find the applet entry given the name. */
476 applet_using = find_applet_by_name(name);
477 if (applet_using) {
478 applet_name = applet_using->name;
479 if(argc==2 && !strcmp(argv[1], "--help")) bb_show_usage();
480 if(ENABLE_FEATURE_SUID) check_suid(applet_using);
481 exit((*(applet_using->main))(argc, argv));
482 }
483}
diff --git a/applets/busybox.c b/applets/busybox.c
new file mode 100644
index 000000000..bb9eb3af7
--- /dev/null
+++ b/applets/busybox.c
@@ -0,0 +1,148 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * BusyBox' main applet dispatcher.
4 *
5 * Licensed under GPLv2, see file LICENSE in this tarball for details.
6 */
7#include "busybox.h"
8
9const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE;
10
11#ifdef CONFIG_FEATURE_INSTALLER
12/*
13 * directory table
14 * this should be consistent w/ the enum, busybox.h::Location,
15 * or else...
16 */
17static const char usr_bin [] ="/usr/bin";
18static const char usr_sbin[] ="/usr/sbin";
19
20static const char* const install_dir[] = {
21 &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
22 &usr_bin [4], /* "/bin" */
23 &usr_sbin[4], /* "/sbin" */
24 usr_bin,
25 usr_sbin
26};
27
28/* abstract link() */
29typedef int (*__link_f)(const char *, const char *);
30
31/* create (sym)links for each applet */
32static void install_links(const char *busybox, int use_symbolic_links)
33{
34 __link_f Link = link;
35
36 char *fpc;
37 int i;
38 int rc;
39
40 if (use_symbolic_links)
41 Link = symlink;
42
43 for (i = 0; applets[i].name != NULL; i++) {
44 fpc = concat_path_file(
45 install_dir[applets[i].location], applets[i].name);
46 rc = Link(busybox, fpc);
47 if (rc!=0 && errno!=EEXIST) {
48 bb_perror_msg("%s", fpc);
49 }
50 free(fpc);
51 }
52}
53
54#else
55#define install_links(x,y)
56#endif /* CONFIG_FEATURE_INSTALLER */
57
58int main(int argc, char **argv)
59{
60 const char *s;
61
62 applet_name=argv[0];
63 if (*applet_name == '-') applet_name++;
64 for (s = applet_name; *s ;)
65 if (*(s++) == '/') applet_name = s;
66
67 /* Set locale for everybody except 'init' */
68 if (ENABLE_LOCALE_SUPPORT && getpid() != 1)
69 setlocale(LC_ALL, "");
70
71 run_applet_by_name(applet_name, argc, argv);
72 bb_error_msg_and_die("applet not found");
73}
74
75int busybox_main(int argc, char **argv)
76{
77 /*
78 * This style of argument parsing doesn't scale well
79 * in the event that busybox starts wanting more --options.
80 * If someone has a cleaner approach, by all means implement it.
81 */
82 if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) {
83 int use_symbolic_links = 0;
84 int rc = 0;
85 char *busybox;
86
87 /* to use symlinks, or not to use symlinks... */
88 if (argc > 2) {
89 if ((strcmp(argv[2], "-s") == 0)) {
90 use_symbolic_links = 1;
91 }
92 }
93
94 /* link */
95// XXX: FIXME: this is broken. Why not just use argv[0] ?
96 busybox = xreadlink("/proc/self/exe");
97 if (busybox) {
98 install_links(busybox, use_symbolic_links);
99 free(busybox);
100 } else {
101 rc = 1;
102 }
103 return rc;
104 }
105
106 /* Deal with --help. (Also print help when called with no arguments) */
107
108 if (argc==1 || !strcmp(argv[1],"--help") ) {
109 if (argc>2) {
110 applet_name = argv[2];
111 run_applet_by_name(applet_name, 2, argv);
112 } else {
113 const struct BB_applet *a;
114 int col, output_width;
115
116 if (ENABLE_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 -= sizeof("start-stop-daemon, ") + 8;
121 } else output_width = 80 - sizeof("start-stop-daemon, ") - 8;
122
123 printf("%s\n"
124 "Copyright (C) 1998-2006  Erik Andersen, Rob Landley, and others.\n"
125 "Licensed under GPLv2.  See source distribution for full notice.\n\n"
126 "Usage: busybox [function] [arguments]...\n"
127 " or: [function] [arguments]...\n\n"
128 "\tBusyBox is a multi-call binary that combines many common Unix\n"
129 "\tutilities into a single executable. Most people will create a\n"
130 "\tlink to busybox for each function they wish to use and BusyBox\n"
131 "\twill act like whatever it was invoked as!\n"
132 "\nCurrently defined functions:\n", bb_msg_full_version);
133
134 col=0;
135 for(a = applets; a->name;) {
136 col += printf("%s%s", (col ? ", " : "\t"), (a++)->name);
137 if (col > output_width && a->name) {
138 printf(",\n");
139 col = 0;
140 }
141 }
142 printf("\n\n");
143 exit(0);
144 }
145 } else run_applet_by_name(argv[1], argc-1, argv+1);
146
147 bb_error_msg_and_die("applet not found");
148}
diff --git a/applets/busybox.mkll b/applets/busybox.mkll
new file mode 100755
index 000000000..6d61f7e82
--- /dev/null
+++ b/applets/busybox.mkll
@@ -0,0 +1,24 @@
1#!/bin/sh
2# Make busybox links list file.
3
4# input $1: full path to Config.h
5# input $2: full path to applets.h
6# output (stdout): list of pathnames that should be linked to busybox
7
8# Maintainer: Larry Doolittle <ldoolitt@recycle.lbl.gov>
9
10export LC_ALL=POSIX
11export LC_CTYPE=POSIX
12
13CONFIG_H=${1:-include/autoconf.h}
14APPLETS_H=${2:-include/applets.h}
15$HOSTCC -E -DMAKE_LINKS -include $CONFIG_H $APPLETS_H |
16 awk '/^[ \t]*LINK/{
17 dir=substr($2,8)
18 gsub("_","/",dir)
19 if(dir=="/ROOT") dir=""
20 file=$3
21 gsub("\"","",file)
22 if (file=="busybox") next
23 print tolower(dir) "/" file
24 }'
diff --git a/applets/individual.c b/applets/individual.c
new file mode 100644
index 000000000..072168352
--- /dev/null
+++ b/applets/individual.c
@@ -0,0 +1,27 @@
1/* Minimal wrapper to build an individual busybox applet.
2 *
3 * Copyright 2005 Rob Landley <rob@landley.net
4 *
5 * Licensed under GPL version 2, see file LICENSE in this tarball for details
6 */
7
8const char *applet_name;
9
10#include <stdio.h>
11#include <stdlib.h>
12//Ok to remove? #include "bb_config.h"
13#include "usage.h"
14
15int main(int argc, char *argv[])
16{
17 applet_name=argv[0];
18
19 return APPLET_main(argc,argv);
20}
21
22void bb_show_usage(void)
23{
24 printf(APPLET_full_usage "\n");
25
26 exit(1);
27}
diff --git a/applets/install.sh b/applets/install.sh
new file mode 100755
index 000000000..4ec96c254
--- /dev/null
+++ b/applets/install.sh
@@ -0,0 +1,94 @@
1#!/bin/sh
2
3export LC_ALL=POSIX
4export LC_CTYPE=POSIX
5
6prefix=${1}
7if [ -z "$prefix" ]; then
8 echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks]"
9 exit 1;
10fi
11h=`sort busybox.links | uniq`
12cleanup="0"
13noclobber="0"
14case "$2" in
15 --hardlinks) linkopts="-f";;
16 --symlinks) linkopts="-fs";;
17 --cleanup) cleanup="1";;
18 --noclobber) noclobber="1";;
19 "") h="";;
20 *) echo "Unknown install option: $2"; exit 1;;
21esac
22
23if [ -n "$DO_INSTALL_LIBS" ] && [ "$DO_INSTALL_LIBS" != "n" ]; then
24 # get the target dir for the libs
25 # assume it starts with lib
26 libdir=$($CC -print-file-name=libc.so | \
27 sed -n 's%^.*\(/lib[^\/]*\)/libc.so%\1%p')
28 if test -z "$libdir"; then
29 libdir=/lib
30 fi
31
32 mkdir -p $prefix/$libdir || exit 1
33 for i in $DO_INSTALL_LIBS; do
34 rm -f $prefix/$libdir/$i || exit 1
35 if [ -f $i ]; then
36 cp -a $i $prefix/$libdir/ || exit 1
37 chmod 0644 $prefix/$libdir/$i || exit 1
38 fi
39 done
40fi
41
42if [ "$cleanup" = "1" ] && [ -e "$prefix/bin/busybox" ]; then
43 inode=`ls -i "$prefix/bin/busybox" | awk '{print $1}'`
44 sub_shell_it=`
45 cd "$prefix"
46 for d in usr/sbin usr/bin sbin bin ; do
47 pd=$PWD
48 if [ -d "$d" ]; then
49 cd $d
50 ls -iL . | grep "^ *$inode" | awk '{print $2}' | env -i xargs rm -f
51 fi
52 cd "$pd"
53 done
54 `
55fi
56
57rm -f $prefix/bin/busybox || exit 1
58mkdir -p $prefix/bin || exit 1
59install -m 755 busybox $prefix/bin/busybox || exit 1
60
61for i in $h ; do
62 appdir=`dirname $i`
63 mkdir -p $prefix/$appdir || exit 1
64 if [ "$2" = "--hardlinks" ]; then
65 bb_path="$prefix/bin/busybox"
66 else
67 case "$appdir" in
68 /)
69 bb_path="bin/busybox"
70 ;;
71 /bin)
72 bb_path="busybox"
73 ;;
74 /sbin)
75 bb_path="../bin/busybox"
76 ;;
77 /usr/bin|/usr/sbin)
78 bb_path="../../bin/busybox"
79 ;;
80 *)
81 echo "Unknown installation directory: $appdir"
82 exit 1
83 ;;
84 esac
85 fi
86 if [ "$noclobber" = "0" ] || [ ! -e "$prefix$i" ]; then
87 echo " $prefix$i -> $bb_path"
88 ln $linkopts $bb_path $prefix$i || exit 1
89 else
90 echo " $prefix$i already exists"
91 fi
92done
93
94exit 0
diff --git a/applets/usage.c b/applets/usage.c
new file mode 100644
index 000000000..d888fa93d
--- /dev/null
+++ b/applets/usage.c
@@ -0,0 +1,17 @@
1/* vi: set sw=4 ts=4: */
2#include <unistd.h>
3
4#include "../include/autoconf.h"
5#include "../include/busybox.h"
6
7static const char usage_messages[] =
8#define MAKE_USAGE
9#include "usage.h"
10#include "applets.h"
11;
12
13int main(void)
14{
15 write(1, usage_messages, sizeof(usage_messages));
16 return 0;
17}
diff --git a/applets/usage_compressed b/applets/usage_compressed
new file mode 100755
index 000000000..ab164aa12
--- /dev/null
+++ b/applets/usage_compressed
@@ -0,0 +1,19 @@
1#!/bin/sh
2
3target="$1"
4loc="$2"
5
6test "$target" || exit 1
7test "$loc" || loc=.
8test -x "$loc/usage" || exit 1
9test "$SED" || SED=sed
10
11sz=`"$loc/usage" | wc -c` || exit 1
12
13exec >"$target"
14
15echo 'static const char packed_usage[] = '
16"$loc/usage" | bzip2 -1 | od -v -t x1 \
17| $SED -e 's/^[^ ]*//' -e 's/ \(..\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/'
18echo ';'
19echo '#define SIZEOF_usage_messages' `expr 0 + $sz`