Ubuntu

Merge lp:~smoser/ubuntu/oneiric/busybox/debian-merge-1.18.4 into lp:ubuntu/oneiric/busybox

Proposed by Scott Moser on 2011-05-27
Status: Merged
Merge reported by: Clint Byrum
Merged at revision: not available
Proposed branch: lp:~smoser/ubuntu/oneiric/busybox/debian-merge-1.18.4
Merge into: lp:ubuntu/oneiric/busybox
Diff against target: 131942 lines (+46049/-62971) 1014 files modified
To merge this branch: bzr merge lp:~smoser/ubuntu/oneiric/busybox/debian-merge-1.18.4
Reviewer Review Type Date Requested Status
Ubuntu branches 2011-05-27 Pending
Review via email: mp+62702@code.launchpad.net
To post a comment you must log in.
Clint Byrum (clint-fewbar) wrote :

Scott, this looks great!

It would appear you used merge-changelog to do the changelog. Apparently there are some entries out out of order, so merge-changelog moved a giant block of changes above version 20040623-2 that used to be below it. It also removed the erroneous, duplicate 0.52-2 entry.

I went ahead and restored the changelogs below the new entries to their original state.

Otherwise it looks good for sponsorship. Uploaded.

Preview Diff

1=== modified file '.pc/applets-fallback.patch/Config.in'
2--- .pc/applets-fallback.patch/Config.in 2010-08-03 06:42:39 +0000
3+++ .pc/applets-fallback.patch/Config.in 2011-05-27 16:11:32 +0000
4@@ -47,6 +47,17 @@
5 compiler other than gcc.
6 If you do use gcc, this option may needlessly increase code size.
7
8+config PLATFORM_LINUX
9+ bool "Enable Linux-specific applets and features"
10+ default y
11+ help
12+ For the most part, busybox requires only POSIX compatibility
13+ from the target system, but some applets and features use
14+ Linux-specific interfaces.
15+
16+ Answering 'N' here will disable such applets and hide the
17+ corresponding configuration options.
18+
19 choice
20 prompt "Buffer allocation policy"
21 default FEATURE_BUFFERS_USE_MALLOC
22@@ -112,6 +123,14 @@
23 busybox at runtime to create hard links or symlinks for all the
24 applets that are compiled into busybox.
25
26+config INSTALL_NO_USR
27+ bool "Don't use /usr"
28+ default n
29+ help
30+ Disable use of /usr. busybox --install and "make install"
31+ will install applets only to /bin and /sbin,
32+ never to /usr/bin or /usr/sbin.
33+
34 config LOCALE_SUPPORT
35 bool "Enable locale support (system needs locale for this to work)"
36 default n
37@@ -264,15 +283,6 @@
38 Don't enable this unless you have a really good reason to clean
39 things up manually.
40
41-config FEATURE_UTMP
42- bool "Support utmp file"
43- default y
44- help
45- The file /var/run/utmp is used to track who is currently logged in.
46- With this option on, certain applets (getty, login, telnetd etc)
47- will create and delete entries there.
48- "who" applet requires this option.
49-
50 config FEATURE_WTMP
51 bool "Support wtmp file"
52 default y
53@@ -284,6 +294,15 @@
54 will append new entries there.
55 "last" applet requires this option.
56
57+config FEATURE_UTMP
58+ bool "Support utmp file"
59+ default y
60+ help
61+ The file /var/run/utmp is used to track who is currently logged in.
62+ With this option on, certain applets (getty, login, telnetd etc)
63+ will create and delete entries there.
64+ "who" applet requires this option.
65+
66 config FEATURE_PIDFILE
67 bool "Support writing pidfiles"
68 default y
69@@ -296,14 +315,19 @@
70 default y
71 help
72 With this option you can install the busybox binary belonging
73- to root with the suid bit set, and it will automatically drop
74- priviledges for applets that don't need root access.
75+ to root with the suid bit set, enabling some applets to perform
76+ root-level operations even when run by ordinary users
77+ (for example, mounting of user mounts in fstab needs this).
78+
79+ Busybox will automatically drop priviledges for applets
80+ that don't need root access.
81
82 If you are really paranoid and don't want to do this, build two
83 busybox binaries with different applets in them (and the appropriate
84 symlinks pointing to each binary), and only set the suid bit on the
85- one that needs it. The applets currently marked to need the suid bit
86- are:
87+ one that needs it.
88+
89+ The applets currently marked to need the suid bit are:
90
91 crontab, dnsd, findfs, ipcrm, ipcs, login, passwd, ping, su,
92 traceroute, vlock.
93@@ -353,6 +377,7 @@
94 config SELINUX
95 bool "Support NSA Security Enhanced Linux"
96 default n
97+ depends on PLATFORM_LINUX
98 help
99 Enable support for SELinux in applets ls, ps, and id. Also provide
100 the option of compiling in SELinux applets.
101@@ -639,20 +664,13 @@
102
103 endmenu
104
105-menu 'Installation Options'
106-
107-config INSTALL_NO_USR
108- bool "Don't use /usr"
109- default n
110- help
111- Disable use of /usr. Don't activate this option if you don't know
112- that you really want this behaviour.
113+menu 'Installation Options ("make install" behavior)'
114
115 choice
116- prompt "Applets links"
117+ prompt "What kind of applet links to install"
118 default INSTALL_APPLET_SYMLINKS
119 help
120- Choose how you install applets links.
121+ Choose what kind of links to applets are created by "make install".
122
123 config INSTALL_APPLET_SYMLINKS
124 bool "as soft-links"
125@@ -676,8 +694,9 @@
126 bool "not installed"
127 depends on FEATURE_INSTALLER || FEATURE_SH_STANDALONE || FEATURE_PREFER_APPLETS
128 help
129- Do not install applet links. Useful when using the -install feature
130- or a standalone shell for rescue purposes.
131+ Do not install applet links. Useful when you plan to use
132+ busybox --install for installing links, or plan to use
133+ a standalone shell and thus don't need applet links.
134
135 endchoice
136
137@@ -701,8 +720,8 @@
138 config INSTALL_SH_APPLET_SCRIPT_WRAPPER
139 bool "as script wrapper"
140 help
141- Install /bin/sh applet as script wrapper that call the busybox
142- binary.
143+ Install /bin/sh applet as script wrapper that calls
144+ the busybox binary.
145
146 endchoice
147
148
149=== modified file '.pc/applets-fallback.patch/coreutils/chroot.c'
150--- .pc/applets-fallback.patch/coreutils/chroot.c 2010-10-22 11:37:59 +0000
151+++ .pc/applets-fallback.patch/coreutils/chroot.c 2011-05-27 16:11:32 +0000
152@@ -4,7 +4,7 @@
153 *
154 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
155 *
156- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
157+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
158 */
159
160 /* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
161
162=== modified file '.pc/applets-fallback.patch/include/libbb.h'
163--- .pc/applets-fallback.patch/include/libbb.h 2010-08-03 06:42:39 +0000
164+++ .pc/applets-fallback.patch/include/libbb.h 2011-05-27 16:11:32 +0000
165@@ -3,9 +3,9 @@
166 * Busybox main internal header file
167 *
168 * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
169- * Permission has been granted to redistribute this code under the GPL.
170+ * Permission has been granted to redistribute this code under GPL.
171 *
172- * Licensed under the GPL version 2, see the file LICENSE in this tarball.
173+ * Licensed under GPLv2, see file LICENSE in this source tree.
174 */
175 #ifndef LIBBB_H
176 #define LIBBB_H 1
177@@ -37,20 +37,18 @@
178 #include <termios.h>
179 #include <time.h>
180 #include <unistd.h>
181-/* Try to pull in PATH_MAX */
182-#include <limits.h>
183 #include <sys/param.h>
184 #ifdef HAVE_MNTENT_H
185-#include <mntent.h>
186+# include <mntent.h>
187 #endif
188 #ifdef HAVE_SYS_STATFS_H
189-#include <sys/statfs.h>
190+# include <sys/statfs.h>
191 #endif
192 #if ENABLE_SELINUX
193-#include <selinux/selinux.h>
194-#include <selinux/context.h>
195-#include <selinux/flask.h>
196-#include <selinux/av_permissions.h>
197+# include <selinux/selinux.h>
198+# include <selinux/context.h>
199+# include <selinux/flask.h>
200+# include <selinux/av_permissions.h>
201 #endif
202 #if ENABLE_LOCALE_SUPPORT
203 # include <locale.h>
204@@ -70,7 +68,7 @@
205 # include <shadow.h>
206 # endif
207 #endif
208-#if defined __FreeBSD__
209+#if defined __FreeBSD__ || defined __OpenBSD__
210 # include <netinet/in.h>
211 # include <arpa/inet.h>
212 #elif defined __APPLE__
213@@ -190,7 +188,7 @@
214 /* While sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway.
215 * gcc will throw warnings on printf("%d", off_t). Crap... */
216 typedef unsigned long uoff_t;
217-# define XATOOFF(a) xatoi_u(a)
218+# define XATOOFF(a) xatoi_positive(a)
219 # define BB_STRTOOFF bb_strtou
220 # define STRTOOFF strtol
221 # define OFF_FMT "l"
222@@ -222,11 +220,11 @@
223
224 /* Macros for min/max. */
225 #ifndef MIN
226-#define MIN(a,b) (((a)<(b))?(a):(b))
227+#define MIN(a,b) (((a)<(b))?(a):(b))
228 #endif
229
230 #ifndef MAX
231-#define MAX(a,b) (((a)>(b))?(a):(b))
232+#define MAX(a,b) (((a)>(b))?(a):(b))
233 #endif
234
235 /* buffer allocation schemes */
236@@ -254,6 +252,11 @@
237 #define errno (*bb_errno)
238 #endif
239
240+#if !(ULONG_MAX > 0xffffffff)
241+/* Only 32-bit CPUs need this, 64-bit ones use inlined version */
242+uint64_t bb_bswap_64(uint64_t x) FAST_FUNC;
243+#endif
244+
245 unsigned long long monotonic_ns(void) FAST_FUNC;
246 unsigned long long monotonic_us(void) FAST_FUNC;
247 unsigned long long monotonic_ms(void) FAST_FUNC;
248@@ -321,6 +324,7 @@
249 /* this helper yells "short read!" if param is not -1 */
250 extern void complain_copyfd_and_die(off_t sz) NORETURN FAST_FUNC;
251 extern char bb_process_escape_sequence(const char **ptr) FAST_FUNC;
252+char* strcpy_and_process_escape_sequences(char *dst, const char *src) FAST_FUNC;
253 /* xxxx_strip version can modify its parameter:
254 * "/" -> "/"
255 * "abc" -> "abc"
256@@ -411,15 +415,18 @@
257 void bb_unsetenv_and_free(char *key) FAST_FUNC;
258 void xunlink(const char *pathname) FAST_FUNC;
259 void xstat(const char *pathname, struct stat *buf) FAST_FUNC;
260+void xfstat(int fd, struct stat *buf, const char *errmsg) FAST_FUNC;
261 int xopen(const char *pathname, int flags) FAST_FUNC;
262 int xopen_nonblocking(const char *pathname) FAST_FUNC;
263 int xopen3(const char *pathname, int flags, int mode) FAST_FUNC;
264 int open_or_warn(const char *pathname, int flags) FAST_FUNC;
265 int open3_or_warn(const char *pathname, int flags, int mode) FAST_FUNC;
266 int open_or_warn_stdin(const char *pathname) FAST_FUNC;
267+int xopen_stdin(const char *pathname) FAST_FUNC;
268 void xrename(const char *oldpath, const char *newpath) FAST_FUNC;
269 int rename_or_warn(const char *oldpath, const char *newpath) FAST_FUNC;
270 off_t xlseek(int fd, off_t offset, int whence) FAST_FUNC;
271+int xmkstemp(char *template) FAST_FUNC;
272 off_t fdlength(int fd) FAST_FUNC;
273
274 uoff_t FAST_FUNC get_volume_size_in_bytes(int fd,
275@@ -739,7 +746,7 @@
276 char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC;
277 char *itoa_to_buf(int n, char *buf, unsigned buflen) FAST_FUNC;
278 /* Intelligent formatters of bignums */
279-void smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC;
280+void smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale) FAST_FUNC;
281 void smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC;
282 /* If block_size == 0, display size without fractional part,
283 * else display (size * block_size) with one decimal digit.
284@@ -765,11 +772,16 @@
285 };
286 #include "xatonum.h"
287 /* Specialized: */
288+
289 /* Using xatoi() instead of naive atoi() is not always convenient -
290 * in many places people want *non-negative* values, but store them
291 * in signed int. Therefore we need this one:
292- * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc */
293-int xatoi_u(const char *numstr) FAST_FUNC;
294+ * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc.
295+ * It should really be named xatoi_nonnegative (since it allows 0),
296+ * but that would be too long.
297+ */
298+int xatoi_positive(const char *numstr) FAST_FUNC;
299+
300 /* Useful for reading port numbers */
301 uint16_t xatou16(const char *numstr) FAST_FUNC;
302
303@@ -874,9 +886,9 @@
304 struct nofork_save_area {
305 jmp_buf die_jmp;
306 const char *applet_name;
307- int xfunc_error_retval;
308 uint32_t option_mask32;
309 int die_sleep;
310+ uint8_t xfunc_error_retval;
311 smallint saved;
312 };
313 void save_nofork_data(struct nofork_save_area *save) FAST_FUNC;
314@@ -987,7 +999,7 @@
315 extern const char *msg_eol;
316 extern smallint logmode;
317 extern int die_sleep;
318-extern int xfunc_error_retval;
319+extern uint8_t xfunc_error_retval;
320 extern jmp_buf die_jmp;
321 extern void xfunc_die(void) NORETURN FAST_FUNC;
322 extern void bb_show_usage(void) NORETURN FAST_FUNC;
323@@ -1381,6 +1393,29 @@
324 enum { COMM_LEN = 16 };
325 # endif
326 #endif
327+
328+struct smaprec {
329+ unsigned long mapped_rw;
330+ unsigned long mapped_ro;
331+ unsigned long shared_clean;
332+ unsigned long shared_dirty;
333+ unsigned long private_clean;
334+ unsigned long private_dirty;
335+ unsigned long stack;
336+ unsigned long smap_pss, smap_swap;
337+ unsigned long smap_size;
338+ unsigned long smap_start;
339+ char smap_mode[5];
340+ char *smap_name;
341+};
342+
343+#if !ENABLE_PMAP
344+#define procps_read_smaps(pid, total, cb, data) \
345+ procps_read_smaps(pid, total)
346+#endif
347+int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
348+ void (*cb)(struct smaprec *, void *), void *data);
349+
350 typedef struct procps_status_t {
351 DIR *dir;
352 IF_FEATURE_SHOW_THREADS(DIR *task_dir;)
353@@ -1409,13 +1444,7 @@
354 #endif
355 unsigned tty_major,tty_minor;
356 #if ENABLE_FEATURE_TOPMEM
357- unsigned long mapped_rw;
358- unsigned long mapped_ro;
359- unsigned long shared_clean;
360- unsigned long shared_dirty;
361- unsigned long private_clean;
362- unsigned long private_dirty;
363- unsigned long stack;
364+ struct smaprec smaps;
365 #endif
366 char state[4];
367 /* basename of executable in exec(2), read from /proc/N/stat
368@@ -1474,57 +1503,50 @@
369 void read_cmdline(char *buf, int size, unsigned pid, const char *comm) FAST_FUNC;
370 pid_t *find_pid_by_name(const char* procName) FAST_FUNC;
371 pid_t *pidlist_reverse(pid_t *pidList) FAST_FUNC;
372+int starts_with_cpu(const char *str) FAST_FUNC;
373+unsigned get_cpu_count(void) FAST_FUNC;
374
375
376 extern const char bb_uuenc_tbl_base64[];
377 extern const char bb_uuenc_tbl_std[];
378 void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
379+enum {
380+ BASE64_FLAG_UU_STOP = 0x100,
381+ /* Sign-extends to a value which never matches fgetc result: */
382+ BASE64_FLAG_NO_STOP_CHAR = 0x80,
383+};
384+void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags);
385
386-typedef struct sha1_ctx_t {
387- uint32_t hash[8]; /* 5, +3 elements for sha256 */
388- uint64_t total64;
389- uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
390- void (*process_block)(struct sha1_ctx_t*) FAST_FUNC;
391-} sha1_ctx_t;
392-void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
393-void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx) FAST_FUNC;
394-void sha1_end(void *resbuf, sha1_ctx_t *ctx) FAST_FUNC;
395-typedef struct sha1_ctx_t sha256_ctx_t;
396-void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
397-#define sha256_hash sha1_hash
398-#define sha256_end sha1_end
399+typedef struct md5_ctx_t {
400+ uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */
401+ void (*process_block)(struct md5_ctx_t*) FAST_FUNC;
402+ uint64_t total64; /* must be directly before hash[] */
403+ uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */
404+} md5_ctx_t;
405+typedef struct md5_ctx_t sha1_ctx_t;
406+typedef struct md5_ctx_t sha256_ctx_t;
407 typedef struct sha512_ctx_t {
408+ uint64_t total64[2]; /* must be directly before hash[] */
409 uint64_t hash[8];
410- uint64_t total64[2];
411- uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
412+ uint8_t wbuffer[128]; /* always correctly aligned for uint64_t */
413 } sha512_ctx_t;
414+void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
415+void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
416+void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
417+void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
418+#define sha1_hash md5_hash
419+void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
420+void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
421+#define sha256_hash md5_hash
422+#define sha256_end sha1_end
423 void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
424-void sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) FAST_FUNC;
425-void sha512_end(void *resbuf, sha512_ctx_t *ctx) FAST_FUNC;
426-#if 1
427-typedef struct md5_ctx_t {
428- uint32_t A;
429- uint32_t B;
430- uint32_t C;
431- uint32_t D;
432- uint64_t total;
433- uint32_t buflen;
434- char buffer[128];
435-} md5_ctx_t;
436-#else
437-/* libbb/md5prime.c uses a bit different one: */
438-typedef struct md5_ctx_t {
439- uint32_t state[4]; /* state (ABCD) */
440- uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
441- unsigned char buffer[64]; /* input buffer */
442-} md5_ctx_t;
443-#endif
444-void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
445-void md5_hash(const void *data, size_t length, md5_ctx_t *ctx) FAST_FUNC;
446-void md5_end(void *resbuf, md5_ctx_t *ctx) FAST_FUNC;
447-
448-
449+void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
450+void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
451+
452+extern uint32_t *global_crc32_table;
453 uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
454+uint32_t crc32_block_endian1(uint32_t val, const void *buf, unsigned len, uint32_t *crc_table) FAST_FUNC;
455+uint32_t crc32_block_endian0(uint32_t val, const void *buf, unsigned len, uint32_t *crc_table) FAST_FUNC;
456
457 typedef struct masks_labels_t {
458 const char *labels;
459@@ -1547,12 +1569,22 @@
460 off_t totalsize) FAST_FUNC;
461
462 extern const char *applet_name;
463+
464+/* Some older linkers don't perform string merging, we used to have common strings
465+ * as global arrays to do it by hand. But:
466+ * (1) newer linkers do it themselves,
467+ * (2) however, they DONT merge string constants with global arrays,
468+ * even if the value is the same (!). Thus global arrays actually
469+ * increased size a bit: for example, "/etc/passwd" string from libc
470+ * wasn't merged with bb_path_passwd_file[] array!
471+ * Therefore now we use #defines.
472+ */
473 /* "BusyBox vN.N.N (timestamp or extra_version)" */
474 extern const char bb_banner[];
475 extern const char bb_msg_memory_exhausted[];
476 extern const char bb_msg_invalid_date[];
477-extern const char bb_msg_read_error[];
478-extern const char bb_msg_write_error[];
479+#define bb_msg_read_error "read error"
480+#define bb_msg_write_error "write error"
481 extern const char bb_msg_unknown[];
482 extern const char bb_msg_can_not_create_raw_socket[];
483 extern const char bb_msg_perm_denied_are_you_root[];
484@@ -1562,18 +1594,23 @@
485 extern const char bb_msg_standard_input[];
486 extern const char bb_msg_standard_output[];
487
488-extern const char bb_str_default[];
489 /* NB: (bb_hexdigits_upcase[i] | 0x20) -> lowercase hex digit */
490 extern const char bb_hexdigits_upcase[];
491
492-extern const char bb_path_mtab_file[];
493-extern const char bb_path_passwd_file[];
494-extern const char bb_path_shadow_file[];
495-extern const char bb_path_gshadow_file[];
496-extern const char bb_path_group_file[];
497-extern const char bb_path_motd_file[];
498 extern const char bb_path_wtmp_file[];
499-extern const char bb_dev_null[];
500+
501+/* Busybox mount uses either /proc/mounts or /etc/mtab to
502+ * get the list of currently mounted filesystems */
503+#define bb_path_mtab_file IF_FEATURE_MTAB_SUPPORT("/etc/mtab")IF_NOT_FEATURE_MTAB_SUPPORT("/proc/mounts")
504+
505+#define bb_path_passwd_file "/etc/passwd"
506+#define bb_path_shadow_file "/etc/shadow"
507+#define bb_path_gshadow_file "/etc/gshadow"
508+#define bb_path_group_file "/etc/group"
509+
510+#define bb_path_motd_file "/etc/motd"
511+
512+#define bb_dev_null "/dev/null"
513 extern const char bb_busybox_exec_path[];
514 /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
515 * but I want to save a few bytes here */
516@@ -1613,46 +1650,47 @@
517 /* "sh" */
518 #define DEFAULT_SHELL_SHORT_NAME (bb_default_login_shell+6)
519
520-#if ENABLE_FEATURE_DEVFS
521+/* The following devices are the same on all systems. */
522+#define CURRENT_TTY "/dev/tty"
523+#define DEV_CONSOLE "/dev/console"
524+
525+#if defined(__FreeBSD_kernel__)
526+# define CURRENT_VC CURRENT_TTY
527+# define VC_1 "/dev/ttyv0"
528+# define VC_2 "/dev/ttyv1"
529+# define VC_3 "/dev/ttyv2"
530+# define VC_4 "/dev/ttyv3"
531+# define VC_5 "/dev/ttyv4"
532+# define VC_FORMAT "/dev/ttyv%d"
533+#elif defined(__GNU__)
534+# define CURRENT_VC CURRENT_TTY
535+# define VC_1 "/dev/tty1"
536+# define VC_2 "/dev/tty2"
537+# define VC_3 "/dev/tty3"
538+# define VC_4 "/dev/tty4"
539+# define VC_5 "/dev/tty5"
540+# define VC_FORMAT "/dev/tty%d"
541+#elif ENABLE_FEATURE_DEVFS
542+/*Linux, obsolete devfs names */
543 # define CURRENT_VC "/dev/vc/0"
544 # define VC_1 "/dev/vc/1"
545 # define VC_2 "/dev/vc/2"
546 # define VC_3 "/dev/vc/3"
547 # define VC_4 "/dev/vc/4"
548 # define VC_5 "/dev/vc/5"
549-# if defined(__sh__) || defined(__H8300H__) || defined(__H8300S__)
550-/* Yes, this sucks, but both SH (including sh64) and H8 have a SCI(F) for their
551- respective serial ports .. as such, we can't use the common device paths for
552- these. -- PFM */
553-# define SC_0 "/dev/ttsc/0"
554-# define SC_1 "/dev/ttsc/1"
555-# define SC_FORMAT "/dev/ttsc/%d"
556-# else
557-# define SC_0 "/dev/tts/0"
558-# define SC_1 "/dev/tts/1"
559-# define SC_FORMAT "/dev/tts/%d"
560-# endif
561 # define VC_FORMAT "/dev/vc/%d"
562 # define LOOP_FORMAT "/dev/loop/%d"
563 # define LOOP_NAMESIZE (sizeof("/dev/loop/") + sizeof(int)*3 + 1)
564 # define LOOP_NAME "/dev/loop/"
565 # define FB_0 "/dev/fb/0"
566 #else
567+/*Linux, normal names */
568 # define CURRENT_VC "/dev/tty0"
569 # define VC_1 "/dev/tty1"
570 # define VC_2 "/dev/tty2"
571 # define VC_3 "/dev/tty3"
572 # define VC_4 "/dev/tty4"
573 # define VC_5 "/dev/tty5"
574-# if defined(__sh__) || defined(__H8300H__) || defined(__H8300S__)
575-# define SC_0 "/dev/ttySC0"
576-# define SC_1 "/dev/ttySC1"
577-# define SC_FORMAT "/dev/ttySC%d"
578-# else
579-# define SC_0 "/dev/ttyS0"
580-# define SC_1 "/dev/ttyS1"
581-# define SC_FORMAT "/dev/ttyS%d"
582-# endif
583 # define VC_FORMAT "/dev/tty%d"
584 # define LOOP_FORMAT "/dev/loop%d"
585 # define LOOP_NAMESIZE (sizeof("/dev/loop") + sizeof(int)*3 + 1)
586@@ -1660,10 +1698,6 @@
587 # define FB_0 "/dev/fb0"
588 #endif
589
590-/* The following devices are the same on devfs and non-devfs systems. */
591-#define CURRENT_TTY "/dev/tty"
592-#define DEV_CONSOLE "/dev/console"
593-
594
595 #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
596
597
598=== modified file '.pc/applets-fallback.patch/libbb/execable.c'
599--- .pc/applets-fallback.patch/libbb/execable.c 2010-08-03 06:42:39 +0000
600+++ .pc/applets-fallback.patch/libbb/execable.c 2011-05-27 16:11:32 +0000
601@@ -4,7 +4,7 @@
602 *
603 * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu>
604 *
605- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
606+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
607 */
608
609 #include "libbb.h"
610
611=== modified file '.pc/applets-fallback.patch/libbb/messages.c'
612--- .pc/applets-fallback.patch/libbb/messages.c 2010-08-03 06:42:39 +0000
613+++ .pc/applets-fallback.patch/libbb/messages.c 2011-05-27 16:11:32 +0000
614@@ -2,7 +2,7 @@
615 /*
616 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
617 *
618- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
619+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
620 */
621
622 #include "libbb.h"
623@@ -24,8 +24,6 @@
624
625 const char bb_msg_memory_exhausted[] ALIGN1 = "memory exhausted";
626 const char bb_msg_invalid_date[] ALIGN1 = "invalid date '%s'";
627-const char bb_msg_write_error[] ALIGN1 = "write error";
628-const char bb_msg_read_error[] ALIGN1 = "read error";
629 const char bb_msg_unknown[] ALIGN1 = "(unknown)";
630 const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket";
631 const char bb_msg_perm_denied_are_you_root[] ALIGN1 = "permission denied (are you root?)";
632@@ -35,15 +33,8 @@
633 const char bb_msg_standard_input[] ALIGN1 = "standard input";
634 const char bb_msg_standard_output[] ALIGN1 = "standard output";
635
636-const char bb_str_default[] ALIGN1 = "default";
637 const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF";
638
639-const char bb_path_passwd_file[] ALIGN1 = "/etc/passwd";
640-const char bb_path_shadow_file[] ALIGN1 = "/etc/shadow";
641-const char bb_path_group_file[] ALIGN1 = "/etc/group";
642-const char bb_path_gshadow_file[] ALIGN1 = "/etc/gshadow";
643-const char bb_path_motd_file[] ALIGN1 = "/etc/motd";
644-const char bb_dev_null[] ALIGN1 = "/dev/null";
645 const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH;
646 const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
647 /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
648
649=== modified file '.pc/applets-fallback.patch/shell/ash.c'
650--- .pc/applets-fallback.patch/shell/ash.c 2010-08-03 06:42:39 +0000
651+++ .pc/applets-fallback.patch/shell/ash.c 2011-05-27 16:11:32 +0000
652@@ -13,7 +13,7 @@
653 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
654 * was re-ported from NetBSD and debianized.
655 *
656- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
657+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
658 */
659
660 /*
661@@ -43,7 +43,9 @@
662 #include <sys/times.h>
663
664 #include "shell_common.h"
665-#include "math.h"
666+#if ENABLE_SH_MATH_SUPPORT
667+# include "math.h"
668+#endif
669 #if ENABLE_ASH_RANDOM_SUPPORT
670 # include "random.h"
671 #else
672@@ -70,6 +72,124 @@
673 # error "Do not even bother, ash will not run on NOMMU machine"
674 #endif
675
676+//applet:IF_ASH(APPLET(ash, _BB_DIR_BIN, _BB_SUID_DROP))
677+//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_DROP, sh))
678+//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, _BB_DIR_BIN, _BB_SUID_DROP, bash))
679+
680+//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
681+//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
682+
683+//config:config ASH
684+//config: bool "ash"
685+//config: default y
686+//config: depends on !NOMMU
687+//config: help
688+//config: Tha 'ash' shell adds about 60k in the default configuration and is
689+//config: the most complete and most pedantically correct shell included with
690+//config: busybox. This shell is actually a derivative of the Debian 'dash'
691+//config: shell (by Herbert Xu), which was created by porting the 'ash' shell
692+//config: (written by Kenneth Almquist) from NetBSD.
693+//config:
694+//config:config ASH_BASH_COMPAT
695+//config: bool "bash-compatible extensions"
696+//config: default y
697+//config: depends on ASH
698+//config: help
699+//config: Enable bash-compatible extensions.
700+//config:
701+//config:config ASH_JOB_CONTROL
702+//config: bool "Job control"
703+//config: default y
704+//config: depends on ASH
705+//config: help
706+//config: Enable job control in the ash shell.
707+//config:
708+//config:config ASH_ALIAS
709+//config: bool "alias support"
710+//config: default y
711+//config: depends on ASH
712+//config: help
713+//config: Enable alias support in the ash shell.
714+//config:
715+//config:config ASH_GETOPTS
716+//config: bool "Builtin getopt to parse positional parameters"
717+//config: default y
718+//config: depends on ASH
719+//config: help
720+//config: Enable getopts builtin in the ash shell.
721+//config:
722+//config:config ASH_BUILTIN_ECHO
723+//config: bool "Builtin version of 'echo'"
724+//config: default y
725+//config: depends on ASH
726+//config: help
727+//config: Enable support for echo, builtin to ash.
728+//config:
729+//config:config ASH_BUILTIN_PRINTF
730+//config: bool "Builtin version of 'printf'"
731+//config: default y
732+//config: depends on ASH
733+//config: help
734+//config: Enable support for printf, builtin to ash.
735+//config:
736+//config:config ASH_BUILTIN_TEST
737+//config: bool "Builtin version of 'test'"
738+//config: default y
739+//config: depends on ASH
740+//config: help
741+//config: Enable support for test, builtin to ash.
742+//config:
743+//config:config ASH_CMDCMD
744+//config: bool "'command' command to override shell builtins"
745+//config: default y
746+//config: depends on ASH
747+//config: help
748+//config: Enable support for the ash 'command' builtin, which allows
749+//config: you to run the specified command with the specified arguments,
750+//config: even when there is an ash builtin command with the same name.
751+//config:
752+//config:config ASH_MAIL
753+//config: bool "Check for new mail on interactive shells"
754+//config: default n
755+//config: depends on ASH
756+//config: help
757+//config: Enable "check for new mail" in the ash shell.
758+//config:
759+//config:config ASH_OPTIMIZE_FOR_SIZE
760+//config: bool "Optimize for size instead of speed"
761+//config: default y
762+//config: depends on ASH
763+//config: help
764+//config: Compile ash for reduced size at the price of speed.
765+//config:
766+//config:config ASH_RANDOM_SUPPORT
767+//config: bool "Pseudorandom generator and $RANDOM variable"
768+//config: default y
769+//config: depends on ASH
770+//config: help
771+//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
772+//config: Each read of "$RANDOM" will generate a new pseudorandom value.
773+//config: You can reset the generator by using a specified start value.
774+//config: After "unset RANDOM" the generator will switch off and this
775+//config: variable will no longer have special treatment.
776+//config:
777+//config:config ASH_EXPAND_PRMT
778+//config: bool "Expand prompt string"
779+//config: default y
780+//config: depends on ASH
781+//config: help
782+//config: "PS#" may contain volatile content, such as backquote commands.
783+//config: This option recreates the prompt string from the environment
784+//config: variable each time it is displayed.
785+//config:
786+
787+//usage:#define ash_trivial_usage NOUSAGE_STR
788+//usage:#define ash_full_usage ""
789+//usage:#define sh_trivial_usage NOUSAGE_STR
790+//usage:#define sh_full_usage ""
791+//usage:#define bash_trivial_usage NOUSAGE_STR
792+//usage:#define bash_full_usage ""
793+
794
795 /* ============ Hash table sizes. Configurable. */
796
797@@ -835,7 +955,8 @@
798 for (p = arg->narg.text; *p; p++) {
799 switch ((unsigned char)*p) {
800 case CTLESC:
801- putc(*++p, fp);
802+ p++;
803+ putc(*p, fp);
804 break;
805 case CTLVAR:
806 putc('$', fp);
807@@ -844,8 +965,10 @@
808 if (subtype == VSLENGTH)
809 putc('#', fp);
810
811- while (*p != '=')
812- putc(*p++, fp);
813+ while (*p != '=') {
814+ putc(*p, fp);
815+ p++;
816+ }
817
818 if (subtype & VSNUL)
819 putc(':', fp);
820@@ -1864,37 +1987,35 @@
821 # define optindval() (voptind.var_text + 7)
822 #endif
823
824+#if ENABLE_ASH_GETOPTS
825+static void FAST_FUNC
826+getoptsreset(const char *value)
827+{
828+ shellparam.optind = number(value);
829+ shellparam.optoff = -1;
830+}
831+#endif
832
833+/* math.h has these, otherwise define our private copies */
834+#if !ENABLE_SH_MATH_SUPPORT
835 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
836 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
837-
838-#if ENABLE_ASH_GETOPTS
839-static void FAST_FUNC
840-getoptsreset(const char *value)
841-{
842- shellparam.optind = number(value);
843- shellparam.optoff = -1;
844-}
845-#endif
846-
847 /*
848- * Return of a legal variable name (a letter or underscore followed by zero or
849- * more letters, underscores, and digits).
850+ * Return the pointer to the first char which is not part of a legal variable name
851+ * (a letter or underscore followed by letters, underscores, and digits).
852 */
853-static char* FAST_FUNC
854+static const char*
855 endofname(const char *name)
856 {
857- char *p;
858-
859- p = (char *) name;
860- if (!is_name(*p))
861- return p;
862- while (*++p) {
863- if (!is_in_name(*p))
864+ if (!is_name(*name))
865+ return name;
866+ while (*++name) {
867+ if (!is_in_name(*name))
868 break;
869 }
870- return p;
871+ return name;
872 }
873+#endif
874
875 /*
876 * Compares two strings up to the first = or '\0'. The first
877@@ -2077,9 +2198,10 @@
878 static void
879 setvar(const char *name, const char *val, int flags)
880 {
881- char *p, *q;
882+ const char *q;
883+ char *p;
884+ char *nameeq;
885 size_t namelen;
886- char *nameeq;
887 size_t vallen;
888
889 q = endofname(name);
890@@ -2093,12 +2215,13 @@
891 } else {
892 vallen = strlen(val);
893 }
894+
895 INT_OFF;
896 nameeq = ckmalloc(namelen + vallen + 2);
897- p = (char *)memcpy(nameeq, name, namelen) + namelen;
898+ p = memcpy(nameeq, name, namelen) + namelen;
899 if (val) {
900 *p++ = '=';
901- p = (char *)memcpy(p, val, vallen) + vallen;
902+ p = memcpy(p, val, vallen) + vallen;
903 }
904 *p = '\0';
905 setvareq(nameeq, flags | VNOSAVE);
906@@ -2312,12 +2435,13 @@
907 #endif
908
909 static void
910-setprompt(int whichprompt)
911+setprompt_if(smallint do_set, int whichprompt)
912 {
913 const char *prompt;
914-#if ENABLE_ASH_EXPAND_PRMT
915- struct stackmark smark;
916-#endif
917+ IF_ASH_EXPAND_PRMT(struct stackmark smark;)
918+
919+ if (!do_set)
920+ return;
921
922 needprompt = 0;
923
924@@ -4515,6 +4639,7 @@
925 INT_ON;
926 }
927 }
928+ may_have_traps = 0;
929 }
930
931 /* Lives far away from here, needed for forkchild */
932@@ -4870,9 +4995,13 @@
933 * revealed that it was a regular file, and the file has not been
934 * replaced, return the file descriptor.
935 */
936- if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
937- && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
938+ if (fstat(fd, &finfo2) == 0
939+ && !S_ISREG(finfo2.st_mode)
940+ && finfo.st_dev == finfo2.st_dev
941+ && finfo.st_ino == finfo2.st_ino
942+ ) {
943 return fd;
944+ }
945
946 /* The file has been replaced. badness. */
947 close(fd);
948@@ -5315,25 +5444,17 @@
949 static arith_t
950 ash_arith(const char *s)
951 {
952- arith_eval_hooks_t math_hooks;
953+ arith_state_t math_state;
954 arith_t result;
955- int errcode = 0;
956
957- math_hooks.lookupvar = lookupvar;
958- math_hooks.setvar = setvar2;
959- math_hooks.endofname = endofname;
960+ math_state.lookupvar = lookupvar;
961+ math_state.setvar = setvar2;
962+ //math_state.endofname = endofname;
963
964 INT_OFF;
965- result = arith(s, &errcode, &math_hooks);
966- if (errcode < 0) {
967- if (errcode == -3)
968- ash_msg_and_raise_error("exponent less than 0");
969- if (errcode == -2)
970- ash_msg_and_raise_error("divide by zero");
971- if (errcode == -5)
972- ash_msg_and_raise_error("expression recursion loop detected");
973- raise_error_syntax(s);
974- }
975+ result = arith(&math_state, s);
976+ if (math_state.errmsg)
977+ ash_msg_and_raise_error(math_state.errmsg);
978 INT_ON;
979
980 return result;
981@@ -5391,13 +5512,18 @@
982 /*
983 * Our own itoa().
984 */
985+#if !ENABLE_SH_MATH_SUPPORT
986+/* cvtnum() is used even if math support is off (to prepare $? values and such) */
987+typedef long arith_t;
988+# define ARITH_FMT "%ld"
989+#endif
990 static int
991 cvtnum(arith_t num)
992 {
993 int len;
994
995 expdest = makestrspace(32, expdest);
996- len = fmtstr(expdest, 32, arith_t_fmt, num);
997+ len = fmtstr(expdest, 32, ARITH_FMT, num);
998 STADJUST(len, expdest);
999 return len;
1000 }
1001@@ -5568,7 +5694,7 @@
1002 return;
1003
1004 if (ifsfirst.endoff > endoff) {
1005- while (ifsfirst.next != NULL) {
1006+ while (ifsfirst.next) {
1007 struct ifsregion *ifsp;
1008 INT_OFF;
1009 ifsp = ifsfirst.next->next;
1010@@ -5576,9 +5702,9 @@
1011 ifsfirst.next = ifsp;
1012 INT_ON;
1013 }
1014- if (ifsfirst.begoff > endoff)
1015+ if (ifsfirst.begoff > endoff) {
1016 ifslastp = NULL;
1017- else {
1018+ } else {
1019 ifslastp = &ifsfirst;
1020 ifsfirst.endoff = endoff;
1021 }
1022@@ -5587,8 +5713,8 @@
1023
1024 ifslastp = &ifsfirst;
1025 while (ifslastp->next && ifslastp->next->begoff < endoff)
1026- ifslastp=ifslastp->next;
1027- while (ifslastp->next != NULL) {
1028+ ifslastp = ifslastp->next;
1029+ while (ifslastp->next) {
1030 struct ifsregion *ifsp;
1031 INT_OFF;
1032 ifsp = ifslastp->next->next;
1033@@ -5765,9 +5891,9 @@
1034
1035 if (quoted == 0)
1036 recordregion(startloc, dest - (char *)stackblock(), 0);
1037- TRACE(("evalbackq: size=%d: \"%.*s\"\n",
1038- (dest - (char *)stackblock()) - startloc,
1039- (dest - (char *)stackblock()) - startloc,
1040+ TRACE(("evalbackq: size:%d:'%.*s'\n",
1041+ (int)((dest - (char *)stackblock()) - startloc),
1042+ (int)((dest - (char *)stackblock()) - startloc),
1043 stackblock() + startloc));
1044 }
1045
1046@@ -5882,7 +6008,7 @@
1047 flags &= ~EXP_TILDE;
1048 tilde:
1049 q = p;
1050- if (*q == CTLESC && (flags & EXP_QWORD))
1051+ if ((unsigned char)*q == CTLESC && (flags & EXP_QWORD))
1052 q++;
1053 if (*q == '~')
1054 p = exptilde(p, q, flags);
1055@@ -5896,9 +6022,7 @@
1056 c = p[length];
1057 if (c) {
1058 if (!(c & 0x80)
1059-#if ENABLE_SH_MATH_SUPPORT
1060- || c == CTLENDARI
1061-#endif
1062+ IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
1063 ) {
1064 /* c == '=' || c == ':' || c == CTLENDARI */
1065 length++;
1066@@ -5945,8 +6069,8 @@
1067 /* "$@" syntax adherence hack */
1068 if (!inquotes
1069 && memcmp(p, dolatstr, 4) == 0
1070- && ( p[4] == CTLQUOTEMARK
1071- || (p[4] == CTLENDVAR && p[5] == CTLQUOTEMARK)
1072+ && ( p[4] == (char)CTLQUOTEMARK
1073+ || (p[4] == (char)CTLENDVAR && p[5] == (char)CTLQUOTEMARK)
1074 )
1075 ) {
1076 p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1;
1077@@ -5981,47 +6105,20 @@
1078 #endif
1079 }
1080 }
1081- breakloop:
1082- ;
1083+ breakloop: ;
1084 }
1085
1086 static char *
1087-scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
1088- int zero)
1089+scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
1090+ char *pattern, int quotes, int zero)
1091 {
1092-// This commented out code was added by James Simmons <jsimmons@infradead.org>
1093-// as part of a larger change when he added support for ${var/a/b}.
1094-// However, it broke # and % operators:
1095-//
1096-//var=ababcdcd
1097-// ok bad
1098-//echo ${var#ab} abcdcd abcdcd
1099-//echo ${var##ab} abcdcd abcdcd
1100-//echo ${var#a*b} abcdcd ababcdcd (!)
1101-//echo ${var##a*b} cdcd cdcd
1102-//echo ${var#?} babcdcd ababcdcd (!)
1103-//echo ${var##?} babcdcd babcdcd
1104-//echo ${var#*} ababcdcd babcdcd (!)
1105-//echo ${var##*}
1106-//echo ${var%cd} ababcd ababcd
1107-//echo ${var%%cd} ababcd abab (!)
1108-//echo ${var%c*d} ababcd ababcd
1109-//echo ${var%%c*d} abab ababcdcd (!)
1110-//echo ${var%?} ababcdc ababcdc
1111-//echo ${var%%?} ababcdc ababcdcd (!)
1112-//echo ${var%*} ababcdcd ababcdcd
1113-//echo ${var%%*}
1114-//
1115-// Commenting it back out helped. Remove it completely if it really
1116-// is not needed.
1117-
1118- char *loc, *loc2; //, *full;
1119+ char *loc, *loc2;
1120 char c;
1121
1122 loc = startp;
1123 loc2 = rmesc;
1124 do {
1125- int match; // = strlen(str);
1126+ int match;
1127 const char *s = loc2;
1128
1129 c = *loc2;
1130@@ -6029,35 +6126,22 @@
1131 *loc2 = '\0';
1132 s = rmesc;
1133 }
1134- match = pmatch(str, s); // this line was deleted
1135+ match = pmatch(pattern, s);
1136
1137-// // chop off end if its '*'
1138-// full = strrchr(str, '*');
1139-// if (full && full != str)
1140-// match--;
1141-//
1142-// // If str starts with '*' replace with s.
1143-// if ((*str == '*') && strlen(s) >= match) {
1144-// full = xstrdup(s);
1145-// strncpy(full+strlen(s)-match+1, str+1, match-1);
1146-// } else
1147-// full = xstrndup(str, match);
1148-// match = strncmp(s, full, strlen(full));
1149-// free(full);
1150-//
1151 *loc2 = c;
1152- if (match) // if (!match)
1153+ if (match)
1154 return loc;
1155 if (quotes && (unsigned char)*loc == CTLESC)
1156 loc++;
1157 loc++;
1158 loc2++;
1159 } while (c);
1160- return 0;
1161+ return NULL;
1162 }
1163
1164 static char *
1165-scanright(char *startp, char *rmesc, char *rmescend, char *pattern, int quotes, int match_at_start)
1166+scanright(char *startp, char *rmesc, char *rmescend,
1167+ char *pattern, int quotes, int match_at_start)
1168 {
1169 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
1170 int try2optimize = match_at_start;
1171@@ -6123,7 +6207,7 @@
1172 }
1173 }
1174 }
1175- return 0;
1176+ return NULL;
1177 }
1178
1179 static void varunset(const char *, const char *, const char *, int) NORETURN;
1180@@ -6143,16 +6227,18 @@
1181 msg = umsg;
1182 }
1183 }
1184- ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
1185+ ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
1186 }
1187
1188 #if ENABLE_ASH_BASH_COMPAT
1189 static char *
1190-parse_sub_pattern(char *arg, int inquotes)
1191+parse_sub_pattern(char *arg, int varflags)
1192 {
1193 char *idx, *repl = NULL;
1194 unsigned char c;
1195
1196+ //char *org_arg = arg;
1197+ //bb_error_msg("arg:'%s' varflags:%x", arg, varflags);
1198 idx = arg;
1199 while (1) {
1200 c = *arg;
1201@@ -6166,24 +6252,37 @@
1202 }
1203 }
1204 *idx++ = c;
1205- if (!inquotes && c == '\\' && arg[1] == '\\')
1206- arg++; /* skip both \\, not just first one */
1207 arg++;
1208+ /*
1209+ * Example: v='ab\c'; echo ${v/\\b/_\\_\z_}
1210+ * The result is a_\_z_c (not a\_\_z_c)!
1211+ *
1212+ * Enable debug prints in this function and you'll see:
1213+ * ash: arg:'\\b/_\\_z_' varflags:d
1214+ * ash: pattern:'\\b' repl:'_\_z_'
1215+ * That is, \\b is interpreted as \\b, but \\_ as \_!
1216+ * IOW: search pattern and replace string treat backslashes
1217+ * differently! That is the reason why we check repl below:
1218+ */
1219+ if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE))
1220+ arg++; /* skip both '\', not just first one */
1221 }
1222 *idx = c; /* NUL */
1223+ //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl);
1224
1225 return repl;
1226 }
1227 #endif /* ENABLE_ASH_BASH_COMPAT */
1228
1229 static const char *
1230-subevalvar(char *p, char *str, int strloc, int subtype,
1231+subevalvar(char *p, char *varname, int strloc, int subtype,
1232 int startloc, int varflags, int quotes, struct strlist *var_str_list)
1233 {
1234 struct nodelist *saveargbackq = argbackq;
1235 char *startp;
1236 char *loc;
1237 char *rmesc, *rmescend;
1238+ char *str;
1239 IF_ASH_BASH_COMPAT(const char *repl = NULL;)
1240 IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
1241 int saveherefd = herefd;
1242@@ -6191,6 +6290,9 @@
1243 int zero;
1244 char *(*scan)(char*, char*, char*, char*, int, int);
1245
1246+ //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
1247+ // p, varname, strloc, subtype, startloc, varflags, quotes);
1248+
1249 herefd = -1;
1250 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
1251 var_str_list);
1252@@ -6201,11 +6303,15 @@
1253
1254 switch (subtype) {
1255 case VSASSIGN:
1256- setvar(str, startp, 0);
1257+ setvar(varname, startp, 0);
1258 amount = startp - expdest;
1259 STADJUST(amount, expdest);
1260 return startp;
1261
1262+ case VSQUESTION:
1263+ varunset(p, varname, startp, varflags);
1264+ /* NOTREACHED */
1265+
1266 #if ENABLE_ASH_BASH_COMPAT
1267 case VSSUBSTR:
1268 loc = str = stackblock() + strloc;
1269@@ -6266,11 +6372,8 @@
1270 STADJUST(amount, expdest);
1271 return loc;
1272 #endif
1273+ }
1274
1275- case VSQUESTION:
1276- varunset(p, str, startp, varflags);
1277- /* NOTREACHED */
1278- }
1279 resetloc = expdest - (char *)stackblock();
1280
1281 /* We'll comeback here if we grow the stack while handling
1282@@ -6303,14 +6406,15 @@
1283 char *idx, *end;
1284
1285 if (!repl) {
1286- repl = parse_sub_pattern(str, varflags & VSQUOTE);
1287+ repl = parse_sub_pattern(str, varflags);
1288+ //bb_error_msg("repl:'%s'", repl);
1289 if (!repl)
1290 repl = nullstr;
1291 }
1292
1293 /* If there's no pattern to match, return the expansion unmolested */
1294 if (str[0] == '\0')
1295- return 0;
1296+ return NULL;
1297
1298 len = 0;
1299 idx = startp;
1300@@ -6318,6 +6422,7 @@
1301 while (idx < end) {
1302 try_to_match:
1303 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
1304+ //bb_error_msg("scanright('%s'):'%s'", str, loc);
1305 if (!loc) {
1306 /* No match, advance */
1307 char *restart_detect = stackblock();
1308@@ -6356,6 +6461,7 @@
1309 idx = loc;
1310 }
1311
1312+ //bb_error_msg("repl:'%s'", repl);
1313 for (loc = (char*)repl; *loc; loc++) {
1314 char *restart_detect = stackblock();
1315 if (quotes && *loc == '\\') {
1316@@ -6369,12 +6475,9 @@
1317 }
1318
1319 if (subtype == VSREPLACE) {
1320+ //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
1321 while (*idx) {
1322 char *restart_detect = stackblock();
1323- if (quotes && *idx == '\\') {
1324- STPUTC(CTLESC, expdest);
1325- len++;
1326- }
1327 STPUTC(*idx, expdest);
1328 if (stackblock() != restart_detect)
1329 goto restart;
1330@@ -6391,6 +6494,7 @@
1331 STPUTC('\0', expdest);
1332 startp = (char *)stackblock() + startloc;
1333 memmove(startp, (char *)stackblock() + workloc, len + 1);
1334+ //bb_error_msg("startp:'%s'", startp);
1335 amount = expdest - (startp + len);
1336 STADJUST(-amount, expdest);
1337 return startp;
1338@@ -6620,8 +6724,8 @@
1339 vsplus:
1340 if (varlen < 0) {
1341 argstr(
1342- p, flags | EXP_TILDE |
1343- (quoted ? EXP_QWORD : EXP_WORD),
1344+ p,
1345+ flags | (quoted ? EXP_TILDE|EXP_QWORD : EXP_TILDE|EXP_WORD),
1346 var_str_list
1347 );
1348 goto end;
1349@@ -6691,7 +6795,7 @@
1350 */
1351 STPUTC('\0', expdest);
1352 patloc = expdest - (char *)stackblock();
1353- if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype,
1354+ if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
1355 startloc, varflags,
1356 //TODO: | EXP_REDIR too? All other such places do it too
1357 /* quotes: */ flags & (EXP_FULL | EXP_CASE),
1358@@ -7526,7 +7630,7 @@
1359 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
1360 if (cmdp->cmdtype == CMDNORMAL
1361 || (cmdp->cmdtype == CMDBUILTIN
1362- && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
1363+ && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
1364 && builtinloc > 0)
1365 ) {
1366 cmdp->rehash = 1;
1367@@ -8117,7 +8221,7 @@
1368
1369 /* Called to execute a trap.
1370 * Single callsite - at the end of evaltree().
1371- * If we return non-zero, exaltree raises EXEXIT exception.
1372+ * If we return non-zero, evaltree raises EXEXIT exception.
1373 *
1374 * Perhaps we should avoid entering new trap handlers
1375 * while we are executing a trap handler. [is it a TODO?]
1376@@ -8307,11 +8411,15 @@
1377
1378 out:
1379 exception_handler = savehandler;
1380+
1381 out1:
1382+ /* Order of checks below is important:
1383+ * signal handlers trigger before exit caused by "set -e".
1384+ */
1385+ if (pending_sig && dotrap())
1386+ goto exexit;
1387 if (checkexit & exitstatus)
1388 evalskip |= SKIPEVAL;
1389- else if (pending_sig && dotrap())
1390- goto exexit;
1391
1392 if (flags & EV_EXIT) {
1393 exexit:
1394@@ -8643,7 +8751,7 @@
1395 while ((lvp = localvars) != NULL) {
1396 localvars = lvp->next;
1397 vp = lvp->vp;
1398- TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
1399+ TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
1400 if (vp == NULL) { /* $- saved */
1401 memcpy(optlist, lvp->text, sizeof(optlist));
1402 free((char*)lvp->text);
1403@@ -9301,7 +9409,7 @@
1404 static int
1405 goodname(const char *p)
1406 {
1407- return !*endofname(p);
1408+ return endofname(p)[0] == '\0';
1409 }
1410
1411
1412@@ -10932,7 +11040,6 @@
1413 startlinno = g_parsefile->linno;
1414 bqlist = NULL;
1415 quotef = 0;
1416- oldstyle = 0;
1417 prevsyntax = 0;
1418 #if ENABLE_ASH_EXPAND_PRMT
1419 pssyntax = (syntax == PSSYNTAX);
1420@@ -10948,160 +11055,156 @@
1421 STARTSTACKSTR(out);
1422 loop:
1423 /* For each line, until end of word */
1424- {
1425- CHECKEND(); /* set c to PEOF if at end of here document */
1426- for (;;) { /* until end of line or end of word */
1427- CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
1428- switch (SIT(c, syntax)) {
1429- case CNL: /* '\n' */
1430- if (syntax == BASESYNTAX)
1431- goto endword; /* exit outer loop */
1432- USTPUTC(c, out);
1433- g_parsefile->linno++;
1434- if (doprompt)
1435- setprompt(2);
1436- c = pgetc();
1437- goto loop; /* continue outer loop */
1438- case CWORD:
1439- USTPUTC(c, out);
1440- break;
1441- case CCTL:
1442- if (eofmark == NULL || dblquote)
1443- USTPUTC(CTLESC, out);
1444+ CHECKEND(); /* set c to PEOF if at end of here document */
1445+ for (;;) { /* until end of line or end of word */
1446+ CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
1447+ switch (SIT(c, syntax)) {
1448+ case CNL: /* '\n' */
1449+ if (syntax == BASESYNTAX)
1450+ goto endword; /* exit outer loop */
1451+ USTPUTC(c, out);
1452+ g_parsefile->linno++;
1453+ setprompt_if(doprompt, 2);
1454+ c = pgetc();
1455+ goto loop; /* continue outer loop */
1456+ case CWORD:
1457+ USTPUTC(c, out);
1458+ break;
1459+ case CCTL:
1460+ if (eofmark == NULL || dblquote)
1461+ USTPUTC(CTLESC, out);
1462 #if ENABLE_ASH_BASH_COMPAT
1463- if (c == '\\' && bash_dollar_squote) {
1464- c = decode_dollar_squote();
1465- if (c & 0x100) {
1466- USTPUTC('\\', out);
1467- c = (unsigned char)c;
1468- }
1469+ if (c == '\\' && bash_dollar_squote) {
1470+ c = decode_dollar_squote();
1471+ if (c & 0x100) {
1472+ USTPUTC('\\', out);
1473+ c = (unsigned char)c;
1474 }
1475+ }
1476 #endif
1477- USTPUTC(c, out);
1478- break;
1479- case CBACK: /* backslash */
1480- c = pgetc_without_PEOA();
1481- if (c == PEOF) {
1482- USTPUTC(CTLESC, out);
1483- USTPUTC('\\', out);
1484- pungetc();
1485- } else if (c == '\n') {
1486- if (doprompt)
1487- setprompt(2);
1488- } else {
1489+ USTPUTC(c, out);
1490+ break;
1491+ case CBACK: /* backslash */
1492+ c = pgetc_without_PEOA();
1493+ if (c == PEOF) {
1494+ USTPUTC(CTLESC, out);
1495+ USTPUTC('\\', out);
1496+ pungetc();
1497+ } else if (c == '\n') {
1498+ setprompt_if(doprompt, 2);
1499+ } else {
1500 #if ENABLE_ASH_EXPAND_PRMT
1501- if (c == '$' && pssyntax) {
1502- USTPUTC(CTLESC, out);
1503- USTPUTC('\\', out);
1504- }
1505+ if (c == '$' && pssyntax) {
1506+ USTPUTC(CTLESC, out);
1507+ USTPUTC('\\', out);
1508+ }
1509 #endif
1510- if (dblquote && c != '\\'
1511- && c != '`' && c != '$'
1512- && (c != '"' || eofmark != NULL)
1513- ) {
1514- USTPUTC(CTLESC, out);
1515- USTPUTC('\\', out);
1516- }
1517- if (SIT(c, SQSYNTAX) == CCTL)
1518- USTPUTC(CTLESC, out);
1519- USTPUTC(c, out);
1520- quotef = 1;
1521+ /* Backslash is retained if we are in "str" and next char isn't special */
1522+ if (dblquote
1523+ && c != '\\'
1524+ && c != '`'
1525+ && c != '$'
1526+ && (c != '"' || eofmark != NULL)
1527+ ) {
1528+ USTPUTC(CTLESC, out);
1529+ USTPUTC('\\', out);
1530 }
1531- break;
1532- case CSQUOTE:
1533- syntax = SQSYNTAX;
1534+ if (SIT(c, SQSYNTAX) == CCTL)
1535+ USTPUTC(CTLESC, out);
1536+ USTPUTC(c, out);
1537+ quotef = 1;
1538+ }
1539+ break;
1540+ case CSQUOTE:
1541+ syntax = SQSYNTAX;
1542 quotemark:
1543- if (eofmark == NULL) {
1544- USTPUTC(CTLQUOTEMARK, out);
1545+ if (eofmark == NULL) {
1546+ USTPUTC(CTLQUOTEMARK, out);
1547+ }
1548+ break;
1549+ case CDQUOTE:
1550+ syntax = DQSYNTAX;
1551+ dblquote = 1;
1552+ goto quotemark;
1553+ case CENDQUOTE:
1554+ IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
1555+ if (eofmark != NULL && arinest == 0
1556+ && varnest == 0
1557+ ) {
1558+ USTPUTC(c, out);
1559+ } else {
1560+ if (dqvarnest == 0) {
1561+ syntax = BASESYNTAX;
1562+ dblquote = 0;
1563 }
1564- break;
1565- case CDQUOTE:
1566- syntax = DQSYNTAX;
1567- dblquote = 1;
1568+ quotef = 1;
1569 goto quotemark;
1570- case CENDQUOTE:
1571- IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
1572- if (eofmark != NULL && arinest == 0
1573- && varnest == 0
1574- ) {
1575- USTPUTC(c, out);
1576- } else {
1577- if (dqvarnest == 0) {
1578- syntax = BASESYNTAX;
1579- dblquote = 0;
1580- }
1581- quotef = 1;
1582- goto quotemark;
1583- }
1584- break;
1585- case CVAR: /* '$' */
1586- PARSESUB(); /* parse substitution */
1587- break;
1588- case CENDVAR: /* '}' */
1589- if (varnest > 0) {
1590- varnest--;
1591- if (dqvarnest > 0) {
1592- dqvarnest--;
1593- }
1594- USTPUTC(CTLENDVAR, out);
1595- } else {
1596- USTPUTC(c, out);
1597- }
1598- break;
1599+ }
1600+ break;
1601+ case CVAR: /* '$' */
1602+ PARSESUB(); /* parse substitution */
1603+ break;
1604+ case CENDVAR: /* '}' */
1605+ if (varnest > 0) {
1606+ varnest--;
1607+ if (dqvarnest > 0) {
1608+ dqvarnest--;
1609+ }
1610+ c = CTLENDVAR;
1611+ }
1612+ USTPUTC(c, out);
1613+ break;
1614 #if ENABLE_SH_MATH_SUPPORT
1615- case CLP: /* '(' in arithmetic */
1616- parenlevel++;
1617+ case CLP: /* '(' in arithmetic */
1618+ parenlevel++;
1619+ USTPUTC(c, out);
1620+ break;
1621+ case CRP: /* ')' in arithmetic */
1622+ if (parenlevel > 0) {
1623+ parenlevel--;
1624+ } else {
1625+ if (pgetc() == ')') {
1626+ if (--arinest == 0) {
1627+ syntax = prevsyntax;
1628+ dblquote = (syntax == DQSYNTAX);
1629+ c = CTLENDARI;
1630+ }
1631+ } else {
1632+ /*
1633+ * unbalanced parens
1634+ * (don't 2nd guess - no error)
1635+ */
1636+ pungetc();
1637+ }
1638+ }
1639+ USTPUTC(c, out);
1640+ break;
1641+#endif
1642+ case CBQUOTE: /* '`' */
1643+ PARSEBACKQOLD();
1644+ break;
1645+ case CENDFILE:
1646+ goto endword; /* exit outer loop */
1647+ case CIGN:
1648+ break;
1649+ default:
1650+ if (varnest == 0) {
1651+#if ENABLE_ASH_BASH_COMPAT
1652+ if (c == '&') {
1653+ if (pgetc() == '>')
1654+ c = 0x100 + '>'; /* flag &> */
1655+ pungetc();
1656+ }
1657+#endif
1658+ goto endword; /* exit outer loop */
1659+ }
1660+ IF_ASH_ALIAS(if (c != PEOA))
1661 USTPUTC(c, out);
1662- break;
1663- case CRP: /* ')' in arithmetic */
1664- if (parenlevel > 0) {
1665- USTPUTC(c, out);
1666- --parenlevel;
1667- } else {
1668- if (pgetc() == ')') {
1669- if (--arinest == 0) {
1670- USTPUTC(CTLENDARI, out);
1671- syntax = prevsyntax;
1672- dblquote = (syntax == DQSYNTAX);
1673- } else
1674- USTPUTC(')', out);
1675- } else {
1676- /*
1677- * unbalanced parens
1678- * (don't 2nd guess - no error)
1679- */
1680- pungetc();
1681- USTPUTC(')', out);
1682- }
1683- }
1684- break;
1685-#endif
1686- case CBQUOTE: /* '`' */
1687- PARSEBACKQOLD();
1688- break;
1689- case CENDFILE:
1690- goto endword; /* exit outer loop */
1691- case CIGN:
1692- break;
1693- default:
1694- if (varnest == 0) {
1695-#if ENABLE_ASH_BASH_COMPAT
1696- if (c == '&') {
1697- if (pgetc() == '>')
1698- c = 0x100 + '>'; /* flag &> */
1699- pungetc();
1700- }
1701-#endif
1702- goto endword; /* exit outer loop */
1703- }
1704- IF_ASH_ALIAS(if (c != PEOA))
1705- USTPUTC(c, out);
1706-
1707- }
1708- c = pgetc_fast();
1709- } /* for (;;) */
1710- }
1711+ }
1712+ c = pgetc_fast();
1713+ } /* for (;;) */
1714 endword:
1715+
1716 #if ENABLE_SH_MATH_SUPPORT
1717 if (syntax == ARISYNTAX)
1718 raise_error_syntax("missing '))'");
1719@@ -11262,8 +11365,6 @@
1720 unsigned char subtype;
1721 int typeloc;
1722 int flags;
1723- char *p;
1724- static const char types[] ALIGN1 = "}-+?=";
1725
1726 c = pgetc();
1727 if (c > 255 /* PEOA or PEOF */
1728@@ -11276,7 +11377,8 @@
1729 #endif
1730 USTPUTC('$', out);
1731 pungetc();
1732- } else if (c == '(') { /* $(command) or $((arith)) */
1733+ } else if (c == '(') {
1734+ /* $(command) or $((arith)) */
1735 if (pgetc() == '(') {
1736 #if ENABLE_SH_MATH_SUPPORT
1737 PARSEARITH();
1738@@ -11288,6 +11390,7 @@
1739 PARSEBACKQNEW();
1740 }
1741 } else {
1742+ /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
1743 USTPUTC(CTLVAR, out);
1744 typeloc = out - (char *)stackblock();
1745 USTPUTC(VSNORMAL, out);
1746@@ -11297,76 +11400,90 @@
1747 if (c == '#') {
1748 c = pgetc();
1749 if (c == '}')
1750- c = '#';
1751+ c = '#'; /* ${#} - same as $# */
1752 else
1753- subtype = VSLENGTH;
1754- } else
1755+ subtype = VSLENGTH; /* ${#VAR} */
1756+ } else {
1757 subtype = 0;
1758+ }
1759 }
1760 if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
1761+ /* $[{[#]]NAME[}] */
1762 do {
1763 STPUTC(c, out);
1764 c = pgetc();
1765 } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
1766 } else if (isdigit(c)) {
1767+ /* $[{[#]]NUM[}] */
1768 do {
1769 STPUTC(c, out);
1770 c = pgetc();
1771 } while (isdigit(c));
1772 } else if (is_special(c)) {
1773+ /* $[{[#]]<specialchar>[}] */
1774 USTPUTC(c, out);
1775 c = pgetc();
1776 } else {
1777 badsub:
1778 raise_error_syntax("bad substitution");
1779 }
1780- if (c != '}' && subtype == VSLENGTH)
1781+ if (c != '}' && subtype == VSLENGTH) {
1782+ /* ${#VAR didn't end with } */
1783 goto badsub;
1784+ }
1785
1786 STPUTC('=', out);
1787 flags = 0;
1788 if (subtype == 0) {
1789+ /* ${VAR...} but not $VAR or ${#VAR} */
1790+ /* c == first char after VAR */
1791 switch (c) {
1792 case ':':
1793 c = pgetc();
1794 #if ENABLE_ASH_BASH_COMPAT
1795 if (c == ':' || c == '$' || isdigit(c)) {
1796- pungetc();
1797+//TODO: support more general format ${v:EXPR:EXPR},
1798+// where EXPR follows $(()) rules
1799 subtype = VSSUBSTR;
1800- break;
1801+ pungetc();
1802+ break; /* "goto do_pungetc" is bigger (!) */
1803 }
1804 #endif
1805 flags = VSNUL;
1806 /*FALLTHROUGH*/
1807- default:
1808- p = strchr(types, c);
1809+ default: {
1810+ static const char types[] ALIGN1 = "}-+?=";
1811+ const char *p = strchr(types, c);
1812 if (p == NULL)
1813 goto badsub;
1814 subtype = p - types + VSNORMAL;
1815 break;
1816+ }
1817 case '%':
1818 case '#': {
1819 int cc = c;
1820- subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
1821+ subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
1822 c = pgetc();
1823- if (c == cc)
1824- subtype++;
1825- else
1826- pungetc();
1827+ if (c != cc)
1828+ goto do_pungetc;
1829+ subtype++;
1830 break;
1831 }
1832 #if ENABLE_ASH_BASH_COMPAT
1833 case '/':
1834+ /* ${v/[/]pattern/repl} */
1835+//TODO: encode pattern and repl separately.
1836+// Currently ${v/$var_with_slash/repl} is horribly broken
1837 subtype = VSREPLACE;
1838 c = pgetc();
1839- if (c == '/')
1840- subtype++; /* VSREPLACEALL */
1841- else
1842- pungetc();
1843+ if (c != '/')
1844+ goto do_pungetc;
1845+ subtype++; /* VSREPLACEALL */
1846 break;
1847 #endif
1848 }
1849 } else {
1850+ do_pungetc:
1851 pungetc();
1852 }
1853 if (dblquote || arinest)
1854@@ -11423,16 +11540,14 @@
1855 treatment to some slashes, and then push the string and
1856 reread it as input, interpreting it normally. */
1857 char *pout;
1858- int pc;
1859 size_t psavelen;
1860 char *pstr;
1861
1862-
1863 STARTSTACKSTR(pout);
1864 for (;;) {
1865- if (needprompt) {
1866- setprompt(2);
1867- }
1868+ int pc;
1869+
1870+ setprompt_if(needprompt, 2);
1871 pc = pgetc();
1872 switch (pc) {
1873 case '`':
1874@@ -11442,8 +11557,7 @@
1875 pc = pgetc();
1876 if (pc == '\n') {
1877 g_parsefile->linno++;
1878- if (doprompt)
1879- setprompt(2);
1880+ setprompt_if(doprompt, 2);
1881 /*
1882 * If eating a newline, avoid putting
1883 * the newline into the new character
1884@@ -11606,9 +11720,7 @@
1885 tokpushback = 0;
1886 return lasttoken;
1887 }
1888- if (needprompt) {
1889- setprompt(2);
1890- }
1891+ setprompt_if(needprompt, 2);
1892 startlinno = g_parsefile->linno;
1893 for (;;) { /* until token or start of word found */
1894 c = pgetc_fast();
1895@@ -11625,8 +11737,7 @@
1896 break; /* return readtoken1(...) */
1897 }
1898 startlinno = ++g_parsefile->linno;
1899- if (doprompt)
1900- setprompt(2);
1901+ setprompt_if(doprompt, 2);
1902 } else {
1903 const char *p;
1904
1905@@ -11672,9 +11783,7 @@
1906 tokpushback = 0;
1907 return lasttoken;
1908 }
1909- if (needprompt) {
1910- setprompt(2);
1911- }
1912+ setprompt_if(needprompt, 2);
1913 startlinno = g_parsefile->linno;
1914 for (;;) { /* until token or start of word found */
1915 c = pgetc_fast();
1916@@ -11690,8 +11799,7 @@
1917 case '\\':
1918 if (pgetc() == '\n') {
1919 startlinno = ++g_parsefile->linno;
1920- if (doprompt)
1921- setprompt(2);
1922+ setprompt_if(doprompt, 2);
1923 continue;
1924 }
1925 pungetc();
1926@@ -11817,8 +11925,7 @@
1927
1928 tokpushback = 0;
1929 doprompt = interact;
1930- if (doprompt)
1931- setprompt(doprompt);
1932+ setprompt_if(doprompt, doprompt);
1933 needprompt = 0;
1934 t = readtoken();
1935 if (t == TEOF)
1936@@ -11842,10 +11949,8 @@
1937 heredoclist = NULL;
1938
1939 while (here) {
1940- if (needprompt) {
1941- setprompt(2);
1942- }
1943- readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
1944+ setprompt_if(needprompt, 2);
1945+ readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
1946 here->eofmark, here->striptabs);
1947 n = stzalloc(sizeof(struct narg));
1948 n->narg.type = NARG;
1949@@ -11936,7 +12041,6 @@
1950 p = grabstackstr(concat);
1951 }
1952 evalstring(p, ~SKIPEVAL);
1953-
1954 }
1955 return exitstatus;
1956 }
1957@@ -12228,7 +12332,7 @@
1958 }
1959 if ((act & DO_NOFUNC)
1960 || !prefix(pathopt, "func")
1961- ) { /* ignore unimplemented options */
1962+ ) { /* ignore unimplemented options */
1963 continue;
1964 }
1965 }
1966@@ -12743,7 +12847,7 @@
1967 /* bash re-enables SIGHUP which is SIG_IGNed on entry.
1968 * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
1969 */
1970- signal(SIGHUP, SIG_DFL);
1971+ signal(SIGHUP, SIG_DFL);
1972
1973 /* from var.c: */
1974 {
1975@@ -12916,10 +13020,12 @@
1976 if (e == EXERROR)
1977 exitstatus = 2;
1978 s = state;
1979- if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
1980+ if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
1981 exitshell();
1982- if (e == EXINT)
1983+ }
1984+ if (e == EXINT) {
1985 outcslow('\n', stderr);
1986+ }
1987
1988 popstackmark(&smark);
1989 FORCE_INT_ON; /* enable interrupts */
1990@@ -13012,6 +13118,7 @@
1991 _mcleanup();
1992 }
1993 #endif
1994+ TRACE(("End of main reached\n"));
1995 exitshell();
1996 /* NOTREACHED */
1997 }
1998
1999=== modified file '.pc/applied-patches'
2000--- .pc/applied-patches 2011-02-23 03:14:46 +0000
2001+++ .pc/applied-patches 2011-05-27 16:11:32 +0000
2002@@ -1,31 +1,10 @@
2003-doc-man-name.patch
2004 shell-ash-export-HOME.patch
2005 applets-fallback.patch
2006 version.patch
2007 init-console.patch
2008-strip.patch
2009 make_gen_build_files_skip_quilt.patch
2010-readlink-use-xmalloc_realpath.patch
2011-mark-Linux-specific-configuration-options.patch
2012-init-loginutils-termios-portability-fixes.patch
2013-init-halt-portability-improvements.patch
2014-init-make-the-initial-TERM-value-configurable.patch
2015-libbb.h-add-device-names-for-Hurd-and-FreeBSD.patch
2016-mkdir-fix-p-on-FreeBSD.patch
2017-libbb-conditionalize-AF_-usage-in-error-reporting.patch
2018-tcpsvd-udpsvd-conditionalize-usage-of-SO_ORIGINAL_DS.patch
2019-less-remove-misguided-dependency-on-PLATFORM_LINUX.patch
2020-bootchartd-mounting-tmpfs-is-Linux-specific.patch
2021-vlock-disable-linux-console-calls-on-other-systems.patch
2022-cttyhack-serial-console-detection-is-Linux-specific.patch
2023-klogd-make-it-work-on-non-linux-systems.patch
2024-stty-sort-out-preprocessor-conditionals.patch
2025-update-scripts-kconfig-_shipped.patch
2026-blockdev.patch
2027 u-mount-FreeBSD-support.patch
2028 swaponoff-FreeBSD-support.patch
2029-init-console-CRTSCTS.patch
2030-debian-changes-1:1.17.1-10
2031+dirname-basename-skip-doubledash.diff
2032 test-bin.patch
2033 static-sh-alias.patch
2034-grep-o-loop.patch
2035
2036=== removed directory '.pc/blockdev.patch'
2037=== removed directory '.pc/blockdev.patch/util-linux'
2038=== removed file '.pc/blockdev.patch/util-linux/blockdev.c'
2039=== removed directory '.pc/bootchartd-mounting-tmpfs-is-Linux-specific.patch'
2040=== removed directory '.pc/bootchartd-mounting-tmpfs-is-Linux-specific.patch/init'
2041=== removed file '.pc/bootchartd-mounting-tmpfs-is-Linux-specific.patch/init/bootchartd.c'
2042--- .pc/bootchartd-mounting-tmpfs-is-Linux-specific.patch/init/bootchartd.c 2010-08-03 06:42:39 +0000
2043+++ .pc/bootchartd-mounting-tmpfs-is-Linux-specific.patch/init/bootchartd.c 1970-01-01 00:00:00 +0000
2044@@ -1,443 +0,0 @@
2045-/* vi: set sw=4 ts=4: */
2046-/*
2047- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
2048- */
2049-
2050-//config:config BOOTCHARTD
2051-//config: bool "bootchartd"
2052-//config: default y
2053-//config: depends on PLATFORM_LINUX
2054-//config: help
2055-//config: bootchartd is commonly used to profile the boot process
2056-//config: for the purpose of speeding it up. In this case, it is started
2057-//config: by the kernel as the init process. This is configured by adding
2058-//config: the init=/sbin/bootchartd option to the kernel command line.
2059-//config:
2060-//config: It can also be used to monitor the resource usage of a specific
2061-//config: application or the running system in general. In this case,
2062-//config: bootchartd is started interactively by running bootchartd start
2063-//config: and stopped using bootchartd stop.
2064-//config:
2065-//config:config FEATURE_BOOTCHARTD_BLOATED_HEADER
2066-//config: bool "Compatible, bloated header"
2067-//config: default y
2068-//config: depends on BOOTCHARTD
2069-//config: help
2070-//config: Create extended header file compatible with "big" bootchartd.
2071-//config: "Big" bootchartd is a shell script and it dumps some
2072-//config: "convenient" info int the header, such as:
2073-//config: title = Boot chart for `hostname` (`date`)
2074-//config: system.uname = `uname -srvm`
2075-//config: system.release = `cat /etc/DISTRO-release`
2076-//config: system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
2077-//config: system.kernel.options = `cat /proc/cmdline`
2078-//config: This data is not mandatory for bootchart graph generation,
2079-//config: and is considered bloat. Nevertheless, this option
2080-//config: makes bootchartd applet to dump a subset of it.
2081-//config:
2082-//config:config FEATURE_BOOTCHARTD_CONFIG_FILE
2083-//config: bool "Support bootchartd.conf"
2084-//config: default y
2085-//config: depends on BOOTCHARTD
2086-//config: help
2087-//config: Enable reading and parsing of $PWD/bootchartd.conf
2088-//config: and /etc/bootchartd.conf files.
2089-
2090-#include "libbb.h"
2091-/* After libbb.h, since it needs sys/types.h on some systems */
2092-#include <sys/utsname.h>
2093-#include <sys/mount.h>
2094-#ifndef MS_SILENT
2095-# define MS_SILENT (1 << 15)
2096-#endif
2097-#ifndef MNT_DETACH
2098-# define MNT_DETACH 0x00000002
2099-#endif
2100-
2101-#define BC_VERSION_STR "0.8"
2102-
2103-/* For debugging, set to 0:
2104- * strace won't work with DO_SIGNAL_SYNC set to 1.
2105- */
2106-#define DO_SIGNAL_SYNC 1
2107-
2108-
2109-//$PWD/bootchartd.conf and /etc/bootchartd.conf:
2110-//supported options:
2111-//# Sampling period (in seconds)
2112-//SAMPLE_PERIOD=0.2
2113-//
2114-//not yet supported:
2115-//# tmpfs size
2116-//# (32 MB should suffice for ~20 minutes worth of log data, but YMMV)
2117-//TMPFS_SIZE=32m
2118-//
2119-//# Whether to enable and store BSD process accounting information. The
2120-//# kernel needs to be configured to enable v3 accounting
2121-//# (CONFIG_BSD_PROCESS_ACCT_V3). accton from the GNU accounting utilities
2122-//# is also required.
2123-//PROCESS_ACCOUNTING="no"
2124-//
2125-//# Tarball for the various boot log files
2126-//BOOTLOG_DEST=/var/log/bootchart.tgz
2127-//
2128-//# Whether to automatically stop logging as the boot process completes.
2129-//# The logger will look for known processes that indicate bootup completion
2130-//# at a specific runlevel (e.g. gdm-binary, mingetty, etc.).
2131-//AUTO_STOP_LOGGER="yes"
2132-//
2133-//# Whether to automatically generate the boot chart once the boot logger
2134-//# completes. The boot chart will be generated in $AUTO_RENDER_DIR.
2135-//# Note that the bootchart package must be installed.
2136-//AUTO_RENDER="no"
2137-//
2138-//# Image format to use for the auto-generated boot chart
2139-//# (choose between png, svg and eps).
2140-//AUTO_RENDER_FORMAT="png"
2141-//
2142-//# Output directory for auto-generated boot charts
2143-//AUTO_RENDER_DIR="/var/log"
2144-
2145-
2146-/* Globals */
2147-struct globals {
2148- char jiffy_line[COMMON_BUFSIZE];
2149-} FIX_ALIASING;
2150-#define G (*(struct globals*)&bb_common_bufsiz1)
2151-#define INIT_G() do { } while (0)
2152-
2153-static void dump_file(FILE *fp, const char *filename)
2154-{
2155- int fd = open(filename, O_RDONLY);
2156- if (fd >= 0) {
2157- fputs(G.jiffy_line, fp);
2158- fflush(fp);
2159- bb_copyfd_eof(fd, fileno(fp));
2160- close(fd);
2161- fputc('\n', fp);
2162- }
2163-}
2164-
2165-static int dump_procs(FILE *fp, int look_for_login_process)
2166-{
2167- struct dirent *entry;
2168- DIR *dir = opendir("/proc");
2169- int found_login_process = 0;
2170-
2171- fputs(G.jiffy_line, fp);
2172- while ((entry = readdir(dir)) != NULL) {
2173- char name[sizeof("/proc/%u/cmdline") + sizeof(int)*3];
2174- int stat_fd;
2175- unsigned pid = bb_strtou(entry->d_name, NULL, 10);
2176- if (errno)
2177- continue;
2178-
2179- /* Android's version reads /proc/PID/cmdline and extracts
2180- * non-truncated process name. Do we want to do that? */
2181-
2182- sprintf(name, "/proc/%u/stat", pid);
2183- stat_fd = open(name, O_RDONLY);
2184- if (stat_fd >= 0) {
2185- char *p;
2186- char stat_line[4*1024];
2187- int rd = safe_read(stat_fd, stat_line, sizeof(stat_line)-2);
2188-
2189- close(stat_fd);
2190- if (rd < 0)
2191- continue;
2192- stat_line[rd] = '\0';
2193- p = strchrnul(stat_line, '\n');
2194- *p++ = '\n';
2195- *p = '\0';
2196- fputs(stat_line, fp);
2197- if (!look_for_login_process)
2198- continue;
2199- p = strchr(stat_line, '(');
2200- if (!p)
2201- continue;
2202- p++;
2203- strchrnul(p, ')')[0] = '\0';
2204- /* Is it gdm, kdm or a getty? */
2205- if (((p[0] == 'g' || p[0] == 'k' || p[0] == 'x') && p[1] == 'd' && p[2] == 'm')
2206- || strstr(p, "getty")
2207- ) {
2208- found_login_process = 1;
2209- }
2210- }
2211- }
2212- closedir(dir);
2213- fputc('\n', fp);
2214- return found_login_process;
2215-}
2216-
2217-static char *make_tempdir(void)
2218-{
2219- char template[] = "/tmp/bootchart.XXXXXX";
2220- char *tempdir = xstrdup(mkdtemp(template));
2221- if (!tempdir) {
2222- /* /tmp is not writable (happens when we are used as init).
2223- * Try to mount a tmpfs, them cd and lazily unmount it.
2224- * Since we unmount it at once, we can mount it anywhere.
2225- * Try a few locations which are likely ti exist.
2226- */
2227- static const char dirs[] = "/mnt\0""/tmp\0""/boot\0""/proc\0";
2228- const char *try_dir = dirs;
2229- while (mount("none", try_dir, "tmpfs", MS_SILENT, "size=16m") != 0) {
2230- try_dir += strlen(try_dir) + 1;
2231- if (!try_dir[0])
2232- bb_perror_msg_and_die("can't %smount tmpfs", "");
2233- }
2234- //bb_error_msg("mounted tmpfs on %s", try_dir);
2235- xchdir(try_dir);
2236- if (umount2(try_dir, MNT_DETACH) != 0) {
2237- bb_perror_msg_and_die("can't %smount tmpfs", "un");
2238- }
2239- } else {
2240- xchdir(tempdir);
2241- }
2242- return tempdir;
2243-}
2244-
2245-static void do_logging(unsigned sample_period_us)
2246-{
2247- //# Enable process accounting if configured
2248- //if [ "$PROCESS_ACCOUNTING" = "yes" ]; then
2249- // [ -e kernel_pacct ] || : > kernel_pacct
2250- // accton kernel_pacct
2251- //fi
2252-
2253- FILE *proc_stat = xfopen("proc_stat.log", "w");
2254- FILE *proc_diskstats = xfopen("proc_diskstats.log", "w");
2255- //FILE *proc_netdev = xfopen("proc_netdev.log", "w");
2256- FILE *proc_ps = xfopen("proc_ps.log", "w");
2257- int look_for_login_process = (getppid() == 1);
2258- unsigned count = 60*1000*1000 / sample_period_us; /* ~1 minute */
2259-
2260- while (--count && !bb_got_signal) {
2261- char *p;
2262- int len = open_read_close("/proc/uptime", G.jiffy_line, sizeof(G.jiffy_line)-2);
2263- if (len < 0)
2264- goto wait_more;
2265- /* /proc/uptime has format "NNNNNN.MM NNNNNNN.MM" */
2266- /* we convert it to "NNNNNNMM\n" (using first value) */
2267- G.jiffy_line[len] = '\0';
2268- p = strchr(G.jiffy_line, '.');
2269- if (!p)
2270- goto wait_more;
2271- while (isdigit(*++p))
2272- p[-1] = *p;
2273- p[-1] = '\n';
2274- p[0] = '\0';
2275-
2276- dump_file(proc_stat, "/proc/stat");
2277- dump_file(proc_diskstats, "/proc/diskstats");
2278- //dump_file(proc_netdev, "/proc/net/dev");
2279- if (dump_procs(proc_ps, look_for_login_process)) {
2280- /* dump_procs saw a getty or {g,k,x}dm
2281- * stop logging in 2 seconds:
2282- */
2283- if (count > 2*1000*1000 / sample_period_us)
2284- count = 2*1000*1000 / sample_period_us;
2285- }
2286- fflush_all();
2287- wait_more:
2288- usleep(sample_period_us);
2289- }
2290-
2291- // [ -e kernel_pacct ] && accton off
2292-}
2293-
2294-static void finalize(char *tempdir, const char *prog)
2295-{
2296- //# Stop process accounting if configured
2297- //local pacct=
2298- //[ -e kernel_pacct ] && pacct=kernel_pacct
2299-
2300- FILE *header_fp = xfopen("header", "w");
2301-
2302- if (prog)
2303- fprintf(header_fp, "profile.process = %s\n", prog);
2304-
2305- fputs("version = "BC_VERSION_STR"\n", header_fp);
2306- if (ENABLE_FEATURE_BOOTCHARTD_BLOATED_HEADER) {
2307- char *hostname;
2308- char *kcmdline;
2309- time_t t;
2310- struct tm tm_time;
2311- /* x2 for possible localized weekday/month names */
2312- char date_buf[sizeof("Mon Jun 21 05:29:03 CEST 2010") * 2];
2313- struct utsname unamebuf;
2314-
2315- hostname = safe_gethostname();
2316- time(&t);
2317- localtime_r(&t, &tm_time);
2318- strftime(date_buf, sizeof(date_buf), "%a %b %e %H:%M:%S %Z %Y", &tm_time);
2319- fprintf(header_fp, "title = Boot chart for %s (%s)\n", hostname, date_buf);
2320- if (ENABLE_FEATURE_CLEAN_UP)
2321- free(hostname);
2322-
2323- uname(&unamebuf); /* never fails */
2324- /* same as uname -srvm */
2325- fprintf(header_fp, "system.uname = %s %s %s %s\n",
2326- unamebuf.sysname,
2327- unamebuf.release,
2328- unamebuf.version,
2329- unamebuf.machine
2330- );
2331-
2332- //system.release = `cat /etc/DISTRO-release`
2333- //system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
2334-
2335- kcmdline = xmalloc_open_read_close("/proc/cmdline", NULL);
2336- /* kcmdline includes trailing "\n" */
2337- fprintf(header_fp, "system.kernel.options = %s", kcmdline);
2338- if (ENABLE_FEATURE_CLEAN_UP)
2339- free(kcmdline);
2340- }
2341- fclose(header_fp);
2342-
2343- /* Package log files */
2344- system("tar -zcf /var/log/bootchart.tgz header *.log"); // + $pacct
2345- /* Clean up (if we are not in detached tmpfs) */
2346- if (tempdir) {
2347- unlink("header");
2348- unlink("proc_stat.log");
2349- unlink("proc_diskstats.log");
2350- //unlink("proc_netdev.log");
2351- unlink("proc_ps.log");
2352- rmdir(tempdir);
2353- }
2354-
2355- /* shell-based bootchartd tries to run /usr/bin/bootchart if $AUTO_RENDER=yes:
2356- * /usr/bin/bootchart -o "$AUTO_RENDER_DIR" -f $AUTO_RENDER_FORMAT "$BOOTLOG_DEST"
2357- */
2358-}
2359-
2360-//usage:#define bootchartd_trivial_usage
2361-//usage: "start [PROG ARGS]|stop|init"
2362-//usage:#define bootchartd_full_usage "\n\n"
2363-//usage: "Create /var/log/bootchart.tgz with boot chart data\n"
2364-//usage: "\nOptions:"
2365-//usage: "\nstart: start background logging; with PROG, run PROG, then kill logging with USR1"
2366-//usage: "\nstop: send USR1 to all bootchartd processes"
2367-//usage: "\ninit: start background logging; stop when getty/xdm is seen (for init scripts)"
2368-//usage: "\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
2369-
2370-int bootchartd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2371-int bootchartd_main(int argc UNUSED_PARAM, char **argv)
2372-{
2373- unsigned sample_period_us;
2374- pid_t parent_pid, logger_pid;
2375- smallint cmd;
2376- enum {
2377- CMD_STOP = 0,
2378- CMD_START,
2379- CMD_INIT,
2380- CMD_PID1, /* used to mark pid 1 case */
2381- };
2382-
2383- INIT_G();
2384-
2385- parent_pid = getpid();
2386- if (argv[1]) {
2387- cmd = index_in_strings("stop\0""start\0""init\0", argv[1]);
2388- if (cmd < 0)
2389- bb_show_usage();
2390- if (cmd == CMD_STOP) {
2391- pid_t *pidList = find_pid_by_name("bootchartd");
2392- while (*pidList != 0) {
2393- if (*pidList != parent_pid)
2394- kill(*pidList, SIGUSR1);
2395- pidList++;
2396- }
2397- return EXIT_SUCCESS;
2398- }
2399- } else {
2400- if (parent_pid != 1)
2401- bb_show_usage();
2402- cmd = CMD_PID1;
2403- }
2404-
2405- /* Here we are in START, INIT or CMD_PID1 state */
2406-
2407- /* Read config file: */
2408- sample_period_us = 200 * 1000;
2409- if (ENABLE_FEATURE_BOOTCHARTD_CONFIG_FILE) {
2410- char* token[2];
2411- parser_t *parser = config_open2("/etc/bootchartd.conf" + 5, fopen_for_read);
2412- if (!parser)
2413- parser = config_open2("/etc/bootchartd.conf", fopen_for_read);
2414- while (config_read(parser, token, 2, 0, "#=", PARSE_NORMAL & ~PARSE_COLLAPSE)) {
2415- if (strcmp(token[0], "SAMPLE_PERIOD") == 0 && token[1])
2416- sample_period_us = atof(token[1]) * 1000000;
2417- }
2418- config_close(parser);
2419- }
2420- if ((int)sample_period_us <= 0)
2421- sample_period_us = 1; /* prevent division by 0 */
2422-
2423- /* Create logger child: */
2424- logger_pid = fork_or_rexec(argv);
2425-
2426- if (logger_pid == 0) { /* child */
2427- char *tempdir;
2428-
2429- bb_signals(0
2430- + (1 << SIGUSR1)
2431- + (1 << SIGUSR2)
2432- + (1 << SIGTERM)
2433- + (1 << SIGQUIT)
2434- + (1 << SIGINT)
2435- + (1 << SIGHUP)
2436- , record_signo);
2437-
2438- if (DO_SIGNAL_SYNC)
2439- /* Inform parent that we are ready */
2440- raise(SIGSTOP);
2441-
2442- /* If we are started by kernel, PATH might be unset.
2443- * In order to find "tar", let's set some sane PATH:
2444- */
2445- if (cmd == CMD_PID1 && !getenv("PATH"))
2446- putenv((char*)bb_PATH_root_path);
2447-
2448- tempdir = make_tempdir();
2449- do_logging(sample_period_us);
2450- finalize(tempdir, cmd == CMD_START ? argv[2] : NULL);
2451- return EXIT_SUCCESS;
2452- }
2453-
2454- /* parent */
2455-
2456- if (DO_SIGNAL_SYNC) {
2457- /* Wait for logger child to set handlers, then unpause it.
2458- * Otherwise with short-lived PROG (e.g. "bootchartd start true")
2459- * we might send SIGUSR1 before logger sets its handler.
2460- */
2461- waitpid(logger_pid, NULL, WUNTRACED);
2462- kill(logger_pid, SIGCONT);
2463- }
2464-
2465- if (cmd == CMD_PID1) {
2466- char *bootchart_init = getenv("bootchart_init");
2467- if (bootchart_init)
2468- execl(bootchart_init, bootchart_init, NULL);
2469- execl("/init", "init", NULL);
2470- execl("/sbin/init", "init", NULL);
2471- bb_perror_msg_and_die("can't execute '%s'", "/sbin/init");
2472- }
2473-
2474- if (cmd == CMD_START && argv[2]) { /* "start PROG ARGS" */
2475- pid_t pid = xvfork();
2476- if (pid == 0) { /* child */
2477- argv += 2;
2478- execvp(argv[0], argv);
2479- bb_perror_msg_and_die("can't execute '%s'", argv[0]);
2480- }
2481- /* parent */
2482- waitpid(pid, NULL, 0);
2483- kill(logger_pid, SIGUSR1);
2484- }
2485-
2486- return EXIT_SUCCESS;
2487-}
2488
2489=== removed directory '.pc/cttyhack-serial-console-detection-is-Linux-specific.patch'
2490=== removed directory '.pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell'
2491=== removed file '.pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell/Config.src'
2492--- .pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell/Config.src 2010-08-03 06:42:39 +0000
2493+++ .pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell/Config.src 1970-01-01 00:00:00 +0000
2494@@ -1,402 +0,0 @@
2495-#
2496-# For a description of the syntax of this configuration file,
2497-# see scripts/kbuild/config-language.txt.
2498-#
2499-
2500-menu "Shells"
2501-
2502-INSERT
2503-
2504-config ASH
2505- bool "ash"
2506- default y
2507- depends on !NOMMU
2508- help
2509- Tha 'ash' shell adds about 60k in the default configuration and is
2510- the most complete and most pedantically correct shell included with
2511- busybox. This shell is actually a derivative of the Debian 'dash'
2512- shell (by Herbert Xu), which was created by porting the 'ash' shell
2513- (written by Kenneth Almquist) from NetBSD.
2514-
2515-config ASH_BASH_COMPAT
2516- bool "bash-compatible extensions"
2517- default y
2518- depends on ASH
2519- help
2520- Enable bash-compatible extensions.
2521-
2522-config ASH_JOB_CONTROL
2523- bool "Job control"
2524- default y
2525- depends on ASH
2526- help
2527- Enable job control in the ash shell.
2528-
2529-config ASH_ALIAS
2530- bool "alias support"
2531- default y
2532- depends on ASH
2533- help
2534- Enable alias support in the ash shell.
2535-
2536-config ASH_GETOPTS
2537- bool "Builtin getopt to parse positional parameters"
2538- default y
2539- depends on ASH
2540- help
2541- Enable getopts builtin in the ash shell.
2542-
2543-config ASH_BUILTIN_ECHO
2544- bool "Builtin version of 'echo'"
2545- default y
2546- depends on ASH
2547- help
2548- Enable support for echo, builtin to ash.
2549-
2550-config ASH_BUILTIN_PRINTF
2551- bool "Builtin version of 'printf'"
2552- default y
2553- depends on ASH
2554- help
2555- Enable support for printf, builtin to ash.
2556-
2557-config ASH_BUILTIN_TEST
2558- bool "Builtin version of 'test'"
2559- default y
2560- depends on ASH
2561- help
2562- Enable support for test, builtin to ash.
2563-
2564-config ASH_CMDCMD
2565- bool "'command' command to override shell builtins"
2566- default y
2567- depends on ASH
2568- help
2569- Enable support for the ash 'command' builtin, which allows
2570- you to run the specified command with the specified arguments,
2571- even when there is an ash builtin command with the same name.
2572-
2573-config ASH_MAIL
2574- bool "Check for new mail on interactive shells"
2575- default n
2576- depends on ASH
2577- help
2578- Enable "check for new mail" in the ash shell.
2579-
2580-config ASH_OPTIMIZE_FOR_SIZE
2581- bool "Optimize for size instead of speed"
2582- default y
2583- depends on ASH
2584- help
2585- Compile ash for reduced size at the price of speed.
2586-
2587-config ASH_RANDOM_SUPPORT
2588- bool "Pseudorandom generator and $RANDOM variable"
2589- default y
2590- depends on ASH
2591- help
2592- Enable pseudorandom generator and dynamic variable "$RANDOM".
2593- Each read of "$RANDOM" will generate a new pseudorandom value.
2594- You can reset the generator by using a specified start value.
2595- After "unset RANDOM" the generator will switch off and this
2596- variable will no longer have special treatment.
2597-
2598-config ASH_EXPAND_PRMT
2599- bool "Expand prompt string"
2600- default y
2601- depends on ASH
2602- help
2603- "PS#" may contain volatile content, such as backquote commands.
2604- This option recreates the prompt string from the environment
2605- variable each time it is displayed.
2606-
2607-config HUSH
2608- bool "hush"
2609- default y
2610- help
2611- hush is a small shell (22k). It handles the normal flow control
2612- constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
2613- case/esac. Redirections, here documents, $((arithmetic))
2614- and functions are supported.
2615-
2616- It will compile and work on no-mmu systems.
2617-
2618- It does not handle select, aliases, brace expansion,
2619- tilde expansion, &>file and >&file redirection of stdout+stderr.
2620-
2621-config HUSH_BASH_COMPAT
2622- bool "bash-compatible extensions"
2623- default y
2624- depends on HUSH
2625- help
2626- Enable bash-compatible extensions.
2627-
2628-config HUSH_HELP
2629- bool "help builtin"
2630- default y
2631- depends on HUSH
2632- help
2633- Enable help builtin in hush. Code size + ~1 kbyte.
2634-
2635-config HUSH_INTERACTIVE
2636- bool "Interactive mode"
2637- default y
2638- depends on HUSH
2639- help
2640- Enable interactive mode (prompt and command editing).
2641- Without this, hush simply reads and executes commands
2642- from stdin just like a shell script from a file.
2643- No prompt, no PS1/PS2 magic shell variables.
2644-
2645-config HUSH_JOB
2646- bool "Job control"
2647- default y
2648- depends on HUSH_INTERACTIVE
2649- help
2650- Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
2651- command (not entire shell), fg/bg builtins work. Without this option,
2652- "cmd &" still works by simply spawning a process and immediately
2653- prompting for next command (or executing next command in a script),
2654- but no separate process group is formed.
2655-
2656-config HUSH_TICK
2657- bool "Process substitution"
2658- default y
2659- depends on HUSH
2660- help
2661- Enable process substitution `command` and $(command) in hush.
2662-
2663-config HUSH_IF
2664- bool "Support if/then/elif/else/fi"
2665- default y
2666- depends on HUSH
2667- help
2668- Enable if/then/elif/else/fi in hush.
2669-
2670-config HUSH_LOOPS
2671- bool "Support for, while and until loops"
2672- default y
2673- depends on HUSH
2674- help
2675- Enable for, while and until loops in hush.
2676-
2677-config HUSH_CASE
2678- bool "Support case ... esac statement"
2679- default y
2680- depends on HUSH
2681- help
2682- Enable case ... esac statement in hush. +400 bytes.
2683-
2684-config HUSH_FUNCTIONS
2685- bool "Support funcname() { commands; } syntax"
2686- default y
2687- depends on HUSH
2688- help
2689- Enable support for shell functions in hush. +800 bytes.
2690-
2691-config HUSH_LOCAL
2692- bool "Support local builtin"
2693- default y
2694- depends on HUSH_FUNCTIONS
2695- help
2696- Enable support for local variables in functions.
2697-
2698-config HUSH_EXPORT_N
2699- bool "Support export '-n' option"
2700- default y
2701- depends on HUSH
2702- help
2703- Enable support for export '-n' option in hush. It is a bash extension.
2704-
2705-config HUSH_RANDOM_SUPPORT
2706- bool "Pseudorandom generator and $RANDOM variable"
2707- default y
2708- depends on HUSH
2709- help
2710- Enable pseudorandom generator and dynamic variable "$RANDOM".
2711- Each read of "$RANDOM" will generate a new pseudorandom value.
2712-
2713-
2714-choice
2715- prompt "Choose which shell is aliased to 'sh' name"
2716- default FEATURE_SH_IS_ASH
2717- help
2718- Choose which shell you want to be executed by 'sh' alias.
2719- The ash shell is the most bash compatible and full featured one.
2720-
2721-# note: cannot use "select ASH" here, it breaks "make allnoconfig"
2722-config FEATURE_SH_IS_ASH
2723- depends on ASH
2724- bool "ash"
2725- depends on !NOMMU
2726-
2727-config FEATURE_SH_IS_HUSH
2728- depends on HUSH
2729- bool "hush"
2730-
2731-config FEATURE_SH_IS_NONE
2732- bool "none"
2733-
2734-endchoice
2735-
2736-choice
2737- prompt "Choose which shell is aliased to 'bash' name"
2738- default FEATURE_BASH_IS_NONE
2739- help
2740- Choose which shell you want to be executed by 'bash' alias.
2741- The ash shell is the most bash compatible and full featured one.
2742-
2743- Note that selecting this option does not switch on any bash
2744- compatibility code. It merely makes it possible to install
2745- /bin/bash (sym)link and run scripts which start with
2746- #!/bin/bash line.
2747-
2748- Many systems use it in scripts which use bash-specific features,
2749- even simple ones like $RANDOM. Without this option, busybox
2750- can't be used for running them because it won't recongnize
2751- "bash" as a supported applet name.
2752-
2753-config FEATURE_BASH_IS_ASH
2754- depends on ASH
2755- bool "ash"
2756- depends on !NOMMU
2757-
2758-config FEATURE_BASH_IS_HUSH
2759- depends on HUSH
2760- bool "hush"
2761-
2762-config FEATURE_BASH_IS_NONE
2763- bool "none"
2764-
2765-endchoice
2766-
2767-
2768-config LASH
2769- bool "lash (deprecated: aliased to hush)"
2770- default n
2771- select HUSH
2772- help
2773- lash is deprecated and will be removed, please migrate to hush.
2774-
2775-config MSH
2776- bool "msh (deprecated: please use hush)"
2777- default n
2778- select HUSH
2779- help
2780- msh is deprecated and will be removed, please migrate to hush.
2781- If there is a feature msh has but hush does not, please let us know.
2782-
2783-# The minix shell (adds just 30k) is quite complete and handles things
2784-# like for/do/done, case/esac and all the things you expect a Bourne
2785-# shell to do. It is not always pedantically correct about Bourne
2786-# shell grammar (try running the shell testscript "tests/sh.testcases"
2787-# on it and compare vs bash) but for most things it works quite well.
2788-# It uses only vfork, so it can be used on uClinux systems.
2789-
2790-
2791-config SH_MATH_SUPPORT
2792- bool "POSIX math support"
2793- default y
2794- depends on ASH || HUSH
2795- help
2796- Enable math support in the shell via $((...)) syntax.
2797-
2798-config SH_MATH_SUPPORT_64
2799- bool "Extend POSIX math support to 64 bit"
2800- default y
2801- depends on SH_MATH_SUPPORT
2802- help
2803- Enable 64-bit math support in the shell. This will make the shell
2804- slightly larger, but will allow computation with very large numbers.
2805- This is not in POSIX, so do not rely on this in portable code.
2806-
2807-config FEATURE_SH_EXTRA_QUIET
2808- bool "Hide message on interactive shell startup"
2809- default y
2810- depends on HUSH || ASH
2811- help
2812- Remove the busybox introduction when starting a shell.
2813-
2814-config FEATURE_SH_STANDALONE
2815- bool "Standalone shell"
2816- default n
2817- depends on (HUSH || ASH) && FEATURE_PREFER_APPLETS
2818- help
2819- This option causes busybox shells to use busybox applets
2820- in preference to executables in the PATH whenever possible. For
2821- example, entering the command 'ifconfig' into the shell would cause
2822- busybox to use the ifconfig busybox applet. Specifying the fully
2823- qualified executable name, such as '/sbin/ifconfig' will still
2824- execute the /sbin/ifconfig executable on the filesystem. This option
2825- is generally used when creating a statically linked version of busybox
2826- for use as a rescue shell, in the event that you screw up your system.
2827-
2828- This is implemented by re-execing /proc/self/exe (typically)
2829- with right parameters. Some selected applets ("NOFORK" applets)
2830- can even be executed without creating new process.
2831- Instead, busybox will call <applet>_main() internally.
2832-
2833- However, this causes problems in chroot jails without mounted /proc
2834- and with ps/top (command name can be shown as 'exe' for applets
2835- started this way).
2836-# untrue?
2837-# Note that this will *also* cause applets to take precedence
2838-# over shell builtins of the same name. So turning this on will
2839-# eliminate any performance gained by turning on the builtin "echo"
2840-# and "test" commands in ash.
2841-# untrue?
2842-# Note that when using this option, the shell will attempt to directly
2843-# run '/bin/busybox'. If you do not have the busybox binary sitting in
2844-# that exact location with that exact name, this option will not work at
2845-# all.
2846-
2847-config FEATURE_SH_NOFORK
2848- bool "Run 'nofork' applets directly"
2849- default n
2850- depends on (HUSH || ASH) && FEATURE_PREFER_APPLETS
2851- help
2852- This option causes busybox shells [currently only ash]
2853- to not execute typical fork/exec/wait sequence, but call <applet>_main
2854- directly, if possible. (Sometimes it is not possible: for example,
2855- this is not possible in pipes).
2856-
2857- This will be done only for some applets (those which are marked
2858- NOFORK in include/applets.h).
2859-
2860- This may significantly speed up some shell scripts.
2861-
2862- This feature is relatively new. Use with care.
2863-
2864-config CTTYHACK
2865- bool "cttyhack"
2866- default y
2867- depends on PLATFORM_LINUX
2868- help
2869- One common problem reported on the mailing list is "can't access tty;
2870- job control turned off" error message which typically appears when
2871- one tries to use shell with stdin/stdout opened to /dev/console.
2872- This device is special - it cannot be a controlling tty.
2873-
2874- Proper solution is to use correct device instead of /dev/console.
2875-
2876- cttyhack provides "quick and dirty" solution to this problem.
2877- It analyzes stdin with various ioctls, trying to determine whether
2878- it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
2879- If it detects one, it closes stdin/out/err and reopens that device.
2880- Then it executes given program. Opening the device will make
2881- that device a controlling tty. This may require cttyhack
2882- to be a session leader.
2883-
2884- Example for /etc/inittab (for busybox init):
2885-
2886- ::respawn:/bin/cttyhack /bin/sh
2887-
2888- Giving controlling tty to shell running with PID 1:
2889-
2890- $ exec cttyhack sh
2891-
2892- Starting an interactive shell from boot shell script:
2893-
2894- setsid cttyhack sh
2895-
2896-endmenu
2897
2898=== removed file '.pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell/cttyhack.c'
2899--- .pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell/cttyhack.c 2010-08-03 06:42:39 +0000
2900+++ .pc/cttyhack-serial-console-detection-is-Linux-specific.patch/shell/cttyhack.c 1970-01-01 00:00:00 +0000
2901@@ -1,85 +0,0 @@
2902-/* vi: set sw=4 ts=4: */
2903-/*
2904- * Licensed under GPLv2
2905- *
2906- * Copyright (c) 2007 Denys Vlasenko <vda.linux@googlemail.com>
2907- */
2908-#include "libbb.h"
2909-
2910-/* From <linux/vt.h> */
2911-struct vt_stat {
2912- unsigned short v_active; /* active vt */
2913- unsigned short v_signal; /* signal to send */
2914- unsigned short v_state; /* vt bitmask */
2915-};
2916-enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */
2917-
2918-/* From <linux/serial.h> */
2919-struct serial_struct {
2920- int type;
2921- int line;
2922- unsigned int port;
2923- int irq;
2924- int flags;
2925- int xmit_fifo_size;
2926- int custom_divisor;
2927- int baud_base;
2928- unsigned short close_delay;
2929- char io_type;
2930- char reserved_char[1];
2931- int hub6;
2932- unsigned short closing_wait; /* time to wait before closing */
2933- unsigned short closing_wait2; /* no longer used... */
2934- unsigned char *iomem_base;
2935- unsigned short iomem_reg_shift;
2936- unsigned int port_high;
2937- unsigned long iomap_base; /* cookie passed into ioremap */
2938- int reserved[1];
2939-};
2940-
2941-int cttyhack_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2942-int cttyhack_main(int argc UNUSED_PARAM, char **argv)
2943-{
2944- int fd;
2945- char console[sizeof(int)*3 + 16];
2946- union {
2947- struct vt_stat vt;
2948- struct serial_struct sr;
2949- char paranoia[sizeof(struct serial_struct) * 3];
2950- } u;
2951-
2952- if (!*++argv) {
2953- bb_show_usage();
2954- }
2955-
2956- strcpy(console, "/dev/tty");
2957- fd = open(console, O_RDWR);
2958- if (fd >= 0) {
2959- /* We already have ctty, nothing to do */
2960- close(fd);
2961- } else {
2962- /* We don't have ctty (or don't have "/dev/tty" node...) */
2963- if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
2964- /* this is a serial console */
2965- sprintf(console + 8, "S%d", u.sr.line);
2966- } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
2967- /* this is linux virtual tty */
2968- sprintf(console + 8, "S%d" + 1, u.vt.v_active);
2969- }
2970- if (console[8]) {
2971- fd = xopen(console, O_RDWR);
2972- //bb_error_msg("switching to '%s'", console);
2973- dup2(fd, 0);
2974- dup2(fd, 1);
2975- dup2(fd, 2);
2976- while (fd > 2)
2977- close(fd--);
2978- /* Some other session may have it as ctty,
2979- * steal it from them:
2980- */
2981- ioctl(0, TIOCSCTTY, 1);
2982- }
2983- }
2984-
2985- BB_EXECVP_or_die(argv);
2986-}
2987
2988=== removed directory '.pc/debian-changes-1:1.17.1-10'
2989=== removed directory '.pc/debian-changes-1:1.17.1-10/busybox-1.17.1'
2990=== removed file '.pc/debian-changes-1:1.17.1-10/busybox-1.17.1/.indent.pro'
2991=== added directory '.pc/dirname-basename-skip-doubledash.diff'
2992=== added directory '.pc/dirname-basename-skip-doubledash.diff/coreutils'
2993=== added file '.pc/dirname-basename-skip-doubledash.diff/coreutils/basename.c'
2994--- .pc/dirname-basename-skip-doubledash.diff/coreutils/basename.c 1970-01-01 00:00:00 +0000
2995+++ .pc/dirname-basename-skip-doubledash.diff/coreutils/basename.c 2011-05-27 16:11:32 +0000
2996@@ -0,0 +1,61 @@
2997+/* vi: set sw=4 ts=4: */
2998+/*
2999+ * Mini basename implementation for busybox
3000+ *
3001+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
3002+ *
3003+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
3004+ */
3005+
3006+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
3007+ *
3008+ * Changes:
3009+ * 1) Now checks for too many args. Need at least one and at most two.
3010+ * 2) Don't check for options, as per SUSv3.
3011+ * 3) Save some space by using strcmp(). Calling strncmp() here was silly.
3012+ */
3013+
3014+/* BB_AUDIT SUSv3 compliant */
3015+/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
3016+
3017+//kbuild:lib-$(CONFIG_BASENAME) += basename.o
3018+
3019+//config:config BASENAME
3020+//config: bool "basename"
3021+//config: default y
3022+//config: help
3023+//config: basename is used to strip the directory and suffix from filenames,
3024+//config: leaving just the filename itself. Enable this option if you wish
3025+//config: to enable the 'basename' utility.
3026+
3027+#include "libbb.h"
3028+
3029+/* This is a NOFORK applet. Be very careful! */
3030+
3031+int basename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3032+int basename_main(int argc, char **argv)
3033+{
3034+ size_t m, n;
3035+ char *s;
3036+
3037+ if ((unsigned)(argc-2) >= 2) {
3038+ bb_show_usage();
3039+ }
3040+
3041+ /* It should strip slash: /abc/def/ -> def */
3042+ s = bb_get_last_path_component_strip(*++argv);
3043+
3044+ m = strlen(s);
3045+ if (*++argv) {
3046+ n = strlen(*argv);
3047+ if ((m > n) && (strcmp(s+m-n, *argv) == 0)) {
3048+ m -= n;
3049+ /*s[m] = '\0'; - redundant */
3050+ }
3051+ }
3052+
3053+ /* puts(s) will do, but we can do without stdio this way: */
3054+ s[m++] = '\n';
3055+ /* NB: != is correct here: */
3056+ return full_write(STDOUT_FILENO, s, m) != (ssize_t)m;
3057+}
3058
3059=== added file '.pc/dirname-basename-skip-doubledash.diff/coreutils/dirname.c'
3060--- .pc/dirname-basename-skip-doubledash.diff/coreutils/dirname.c 1970-01-01 00:00:00 +0000
3061+++ .pc/dirname-basename-skip-doubledash.diff/coreutils/dirname.c 2011-05-27 16:11:32 +0000
3062@@ -0,0 +1,22 @@
3063+/* vi: set sw=4 ts=4: */
3064+/*
3065+ * Mini dirname implementation for busybox
3066+ *
3067+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
3068+ *
3069+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
3070+ */
3071+
3072+/* BB_AUDIT SUSv3 compliant */
3073+/* http://www.opengroup.org/onlinepubs/007904975/utilities/dirname.html */
3074+
3075+#include "libbb.h"
3076+
3077+/* This is a NOFORK applet. Be very careful! */
3078+
3079+int dirname_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3080+int dirname_main(int argc UNUSED_PARAM, char **argv)
3081+{
3082+ puts(dirname(single_argv(argv)));
3083+ return fflush_all();
3084+}
3085
3086=== removed directory '.pc/doc-man-name.patch'
3087=== removed file '.pc/doc-man-name.patch/Makefile.custom'
3088--- .pc/doc-man-name.patch/Makefile.custom 2010-08-03 06:42:39 +0000
3089+++ .pc/doc-man-name.patch/Makefile.custom 1970-01-01 00:00:00 +0000
3090@@ -1,177 +0,0 @@
3091-# ==========================================================================
3092-# Build system
3093-# ==========================================================================
3094-
3095-busybox.links: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h include/applets.h
3096- $(Q)-$(SHELL) $^ >$@
3097-
3098-.PHONY: install
3099-ifeq ($(CONFIG_INSTALL_APPLET_SYMLINKS),y)
3100-INSTALL_OPTS:= --symlinks
3101-endif
3102-ifeq ($(CONFIG_INSTALL_APPLET_HARDLINKS),y)
3103-INSTALL_OPTS:= --hardlinks
3104-endif
3105-ifeq ($(CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS),y)
3106-ifeq ($(CONFIG_INSTALL_SH_APPLET_SYMLINK),y)
3107-INSTALL_OPTS:= --sw-sh-sym
3108-endif
3109-ifeq ($(CONFIG_INSTALL_SH_APPLET_HARDLINK),y)
3110-INSTALL_OPTS:= --sw-sh-hard
3111-endif
3112-ifeq ($(CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER),y)
3113-INSTALL_OPTS:= --scriptwrapper
3114-endif
3115-endif
3116-install: $(srctree)/applets/install.sh busybox busybox.links
3117- $(Q)DO_INSTALL_LIBS="$(strip $(LIBBUSYBOX_SONAME) $(DO_INSTALL_LIBS))" \
3118- $(SHELL) $< $(CONFIG_PREFIX) $(INSTALL_OPTS)
3119-ifeq ($(strip $(CONFIG_FEATURE_SUID)),y)
3120- @echo
3121- @echo
3122- @echo --------------------------------------------------
3123- @echo You will probably need to make your busybox binary
3124- @echo setuid root to ensure all configured applets will
3125- @echo work properly.
3126- @echo --------------------------------------------------
3127- @echo
3128-endif
3129-
3130-uninstall: busybox.links
3131- rm -f $(CONFIG_PREFIX)/bin/busybox
3132- for i in `cat busybox.links` ; do rm -f $(CONFIG_PREFIX)$$i; done
3133-ifneq ($(strip $(DO_INSTALL_LIBS)),n)
3134- for i in $(LIBBUSYBOX_SONAME) $(DO_INSTALL_LIBS); do \
3135- rm -f $(CONFIG_PREFIX)$$i; \
3136- done
3137-endif
3138-
3139-# Not very elegant: copies testsuite to objdir...
3140-# (cp -pPR is POSIX-compliant (cp -dpR or cp -a would not be))
3141-.PHONY: check
3142-.PHONY: test
3143-check test: busybox busybox.links
3144- test -d $(objtree)/testsuite || cp -pPR $(srctree)/testsuite $(objtree)
3145- bindir=$(objtree) srcdir=$(srctree)/testsuite \
3146- $(SHELL) -c "cd $(objtree)/testsuite && $(srctree)/testsuite/runtest $(if $(KBUILD_VERBOSE:0=),-v)"
3147-
3148-.PHONY: release
3149-release: distclean
3150- cd ..; \
3151- rm -r -f busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION); \
3152- cp -pPR busybox busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) && { \
3153- find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type d \
3154- -name .svn \
3155- -print \
3156- -exec rm -r -f {} \; ; \
3157- find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type d \
3158- -name .git \
3159- -print \
3160- -exec rm -r -f {} \; ; \
3161- find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type f \
3162- -name .\#* \
3163- -print \
3164- -exec rm -f {} \; ; \
3165- tar -czf busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION).tar.gz \
3166- busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ ; }
3167-
3168-.PHONY: checkhelp
3169-checkhelp:
3170- $(Q)$(srctree)/scripts/checkhelp.awk \
3171- $(patsubst %,$(srctree)/%,$(wildcard $(patsubst %,%/Config.in,$(busybox-dirs) ./)))
3172-
3173-.PHONY: sizes
3174-sizes: busybox_unstripped
3175- $(NM) --size-sort $(<)
3176-
3177-.PHONY: bloatcheck
3178-bloatcheck: busybox_old busybox_unstripped
3179- @$(srctree)/scripts/bloat-o-meter busybox_old busybox_unstripped
3180- @$(CROSS_COMPILE)size busybox_old busybox_unstripped
3181-
3182-.PHONY: baseline
3183-baseline: busybox_unstripped
3184- @mv busybox_unstripped busybox_old
3185-
3186-.PHONY: objsizes
3187-objsizes: busybox_unstripped
3188- $(srctree)/scripts/objsizes
3189-
3190-.PHONY: stksizes
3191-stksizes: busybox_unstripped
3192- $(CROSS_COMPILE)objdump -d busybox_unstripped | $(srctree)/scripts/checkstack.pl $(ARCH) | uniq
3193-
3194-.PHONY: bigdata
3195-bigdata: busybox_unstripped
3196- $(CROSS_COMPILE)nm --size-sort busybox_unstripped | grep -vi ' [trw] '
3197-
3198-# Documentation Targets
3199-.PHONY: doc
3200-doc: docs/busybox.pod docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html
3201-
3202-# FIXME: Doesn't belong here
3203- cmd_doc =
3204- quiet_cmd_doc = $(Q)echo " DOC $(@F)"
3205-silent_cmd_doc =
3206-disp_doc = $($(quiet)cmd_doc)
3207-
3208-# sed adds newlines after "Options:" etc,
3209-# this is needed in order to get good BusyBox.{1,txt,html}
3210-docs/busybox.pod: $(srctree)/docs/busybox_header.pod \
3211- include/usage.h \
3212- $(srctree)/docs/busybox_footer.pod \
3213- applets/usage_pod
3214- $(disp_doc)
3215- $(Q)-mkdir -p docs
3216- $(Q)-( \
3217- cat $(srctree)/docs/busybox_header.pod; \
3218- applets/usage_pod | sed 's/^[A-Za-z][A-Za-z ]*[a-z]:$$/&\n/'; \
3219- cat $(srctree)/docs/busybox_footer.pod; \
3220- ) > docs/busybox.pod
3221-
3222-docs/BusyBox.txt: docs/busybox.pod
3223- $(disp_doc)
3224- $(Q)-mkdir -p docs
3225- $(Q)-pod2text $< > $@
3226-
3227-docs/BusyBox.1: docs/busybox.pod
3228- $(disp_doc)
3229- $(Q)-mkdir -p docs
3230- $(Q)-pod2man --center=BusyBox --release="version $(KERNELVERSION)" $< > $@
3231-
3232-docs/BusyBox.html: docs/busybox.net/BusyBox.html
3233- $(disp_doc)
3234- $(Q)-mkdir -p docs
3235- $(Q)-rm -f docs/BusyBox.html
3236- $(Q)-cp docs/busybox.net/BusyBox.html docs/BusyBox.html
3237-
3238-docs/busybox.net/BusyBox.html: docs/busybox.pod
3239- $(Q)-mkdir -p docs/busybox.net
3240- $(Q)-pod2html --noindex $< > $@
3241- $(Q)-rm -f pod2htm*
3242-
3243-# documentation, cross-reference
3244-# Modern distributions already ship synopsis packages (e.g. debian)
3245-# If you have an old distribution go to http://synopsis.fresco.org/
3246-syn_tgt = $(wildcard $(patsubst %,%/*.c,$(busybox-alldirs)))
3247-syn = $(patsubst %.c, %.syn, $(syn_tgt))
3248-
3249-comma:= ,
3250-brace_open:= (
3251-brace_close:= )
3252-
3253-SYN_CPPFLAGS := $(strip $(CPPFLAGS) $(EXTRA_CPPFLAGS))
3254-SYN_CPPFLAGS := $(subst $(brace_open),\$(brace_open),$(SYN_CPPFLAGS))
3255-SYN_CPPFLAGS := $(subst $(brace_close),\$(brace_close),$(SYN_CPPFLAGS))
3256-#SYN_CPPFLAGS := $(subst ",\",$(SYN_CPPFLAGS))
3257-#")
3258-#SYN_CPPFLAGS := [$(patsubst %,'%'$(comma),$(SYN_CPPFLAGS))'']
3259-
3260-%.syn: %.c
3261- synopsis -p C -l Comments.SSDFilter,Comments.Previous -Wp,preprocess=True,cppflags="'$(SYN_CPPFLAGS)'" -o $@ $<
3262-
3263-.PHONY: html
3264-html: $(syn)
3265- synopsis -f HTML -Wf,title="'BusyBox Documentation'" -o $@ $^
3266-
3267--include $(srctree)/Makefile.local
3268
3269=== removed directory '.pc/grep-o-loop.patch'
3270=== removed directory '.pc/grep-o-loop.patch/findutils'
3271=== removed file '.pc/grep-o-loop.patch/findutils/grep.c'
3272--- .pc/grep-o-loop.patch/findutils/grep.c 2010-10-13 11:03:32 +0000
3273+++ .pc/grep-o-loop.patch/findutils/grep.c 1970-01-01 00:00:00 +0000
3274@@ -1,771 +0,0 @@
3275-/* vi: set sw=4 ts=4: */
3276-/*
3277- * Mini grep implementation for busybox using libc regex.
3278- *
3279- * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley
3280- * Copyright (C) 1999,2000,2001 by Mark Whitley <markw@codepoet.org>
3281- *
3282- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
3283- */
3284-/* BB_AUDIT SUSv3 defects - unsupported option -x "match whole line only". */
3285-/* BB_AUDIT GNU defects - always acts as -a. */
3286-/* http://www.opengroup.org/onlinepubs/007904975/utilities/grep.html */
3287-/*
3288- * 2004,2006 (C) Vladimir Oleynik <dzo@simtreas.ru> -
3289- * correction "-e pattern1 -e pattern2" logic and more optimizations.
3290- * precompiled regex
3291- *
3292- * (C) 2006 Jac Goudsmit added -o option
3293- */
3294-
3295-//applet:IF_GREP(APPLET(grep, _BB_DIR_BIN, _BB_SUID_DROP))
3296-//applet:IF_FEATURE_GREP_EGREP_ALIAS(APPLET_ODDNAME(egrep, grep, _BB_DIR_BIN, _BB_SUID_DROP, egrep))
3297-//applet:IF_FEATURE_GREP_FGREP_ALIAS(APPLET_ODDNAME(fgrep, grep, _BB_DIR_BIN, _BB_SUID_DROP, fgrep))
3298-
3299-//kbuild:lib-$(CONFIG_GREP) += grep.o
3300-
3301-//config:config GREP
3302-//config: bool "grep"
3303-//config: default y
3304-//config: help
3305-//config: grep is used to search files for a specified pattern.
3306-//config:
3307-//config:config FEATURE_GREP_EGREP_ALIAS
3308-//config: bool "Enable extended regular expressions (egrep & grep -E)"
3309-//config: default y
3310-//config: depends on GREP
3311-//config: help
3312-//config: Enabled support for extended regular expressions. Extended
3313-//config: regular expressions allow for alternation (foo|bar), grouping,
3314-//config: and various repetition operators.
3315-//config:
3316-//config:config FEATURE_GREP_FGREP_ALIAS
3317-//config: bool "Alias fgrep to grep -F"
3318-//config: default y
3319-//config: depends on GREP
3320-//config: help
3321-//config: fgrep sees the search pattern as a normal string rather than
3322-//config: regular expressions.
3323-//config: grep -F always works, this just creates the fgrep alias.
3324-//config:
3325-//config:config FEATURE_GREP_CONTEXT
3326-//config: bool "Enable before and after context flags (-A, -B and -C)"
3327-//config: default y
3328-//config: depends on GREP
3329-//config: help
3330-//config: Print the specified number of leading (-B) and/or trailing (-A)
3331-//config: context surrounding our matching lines.
3332-//config: Print the specified number of context lines (-C).
3333-
3334-#include "libbb.h"
3335-#include "xregex.h"
3336-
3337-
3338-/* options */
3339-//usage:#define grep_trivial_usage
3340-//usage: "[-HhnlLoqvsriw"
3341-//usage: "F"
3342-//usage: IF_FEATURE_GREP_EGREP_ALIAS("E")
3343-//usage: IF_EXTRA_COMPAT("z")
3344-//usage: "] [-m N] "
3345-//usage: IF_FEATURE_GREP_CONTEXT("[-A/B/C N] ")
3346-//usage: "PATTERN/-e PATTERN.../-f FILE [FILE]..."
3347-//usage:#define grep_full_usage "\n\n"
3348-//usage: "Search for PATTERN in FILEs (or stdin)\n"
3349-//usage: "\nOptions:"
3350-//usage: "\n -H Add 'filename:' prefix"
3351-//usage: "\n -h Do not add 'filename:' prefix"
3352-//usage: "\n -n Add 'line_no:' prefix"
3353-//usage: "\n -l Show only names of files that match"
3354-//usage: "\n -L Show only names of files that don't match"
3355-//usage: "\n -c Show only count of matching lines"
3356-//usage: "\n -o Show only the matching part of line"
3357-//usage: "\n -q Quiet. Return 0 if PATTERN is found, 1 otherwise"
3358-//usage: "\n -v Select non-matching lines"
3359-//usage: "\n -s Suppress open and read errors"
3360-//usage: "\n -r Recurse"
3361-//usage: "\n -i Ignore case"
3362-//usage: "\n -w Match whole words only"
3363-//usage: "\n -F PATTERN is a literal (not regexp)"
3364-//usage: IF_FEATURE_GREP_EGREP_ALIAS(
3365-//usage: "\n -E PATTERN is an extended regexp"
3366-//usage: )
3367-//usage: IF_EXTRA_COMPAT(
3368-//usage: "\n -z Input is NUL terminated"
3369-//usage: )
3370-//usage: "\n -m N Match up to N times per file"
3371-//usage: IF_FEATURE_GREP_CONTEXT(
3372-//usage: "\n -A N Print N lines of trailing context"
3373-//usage: "\n -B N Print N lines of leading context"
3374-//usage: "\n -C N Same as '-A N -B N'"
3375-//usage: )
3376-//usage: "\n -e PTRN Pattern to match"
3377-//usage: "\n -f FILE Read pattern from file"
3378-//usage:
3379-//usage:#define grep_example_usage
3380-//usage: "$ grep root /etc/passwd\n"
3381-//usage: "root:x:0:0:root:/root:/bin/bash\n"
3382-//usage: "$ grep ^[rR]oo. /etc/passwd\n"
3383-//usage: "root:x:0:0:root:/root:/bin/bash\n"
3384-//usage:
3385-//usage:#define egrep_trivial_usage NOUSAGE_STR
3386-//usage:#define egrep_full_usage ""
3387-//usage:#define fgrep_trivial_usage NOUSAGE_STR
3388-//usage:#define fgrep_full_usage ""
3389-
3390-#define OPTSTR_GREP \
3391- "lnqvscFiHhe:f:Lorm:w" \
3392- IF_FEATURE_GREP_CONTEXT("A:B:C:") \
3393- IF_FEATURE_GREP_EGREP_ALIAS("E") \
3394- IF_EXTRA_COMPAT("z") \
3395- "aI"
3396-/* ignored: -a "assume all files to be text" */
3397-/* ignored: -I "assume binary files have no matches" */
3398-enum {
3399- OPTBIT_l, /* list matched file names only */
3400- OPTBIT_n, /* print line# */
3401- OPTBIT_q, /* quiet - exit(EXIT_SUCCESS) of first match */
3402- OPTBIT_v, /* invert the match, to select non-matching lines */
3403- OPTBIT_s, /* suppress errors about file open errors */
3404- OPTBIT_c, /* count matches per file (suppresses normal output) */
3405- OPTBIT_F, /* literal match */
3406- OPTBIT_i, /* case-insensitive */
3407- OPTBIT_H, /* force filename display */
3408- OPTBIT_h, /* inhibit filename display */
3409- OPTBIT_e, /* -e PATTERN */
3410- OPTBIT_f, /* -f FILE_WITH_PATTERNS */
3411- OPTBIT_L, /* list unmatched file names only */
3412- OPTBIT_o, /* show only matching parts of lines */
3413- OPTBIT_r, /* recurse dirs */
3414- OPTBIT_m, /* -m MAX_MATCHES */
3415- OPTBIT_w, /* -w whole word match */
3416- IF_FEATURE_GREP_CONTEXT( OPTBIT_A ,) /* -A NUM: after-match context */
3417- IF_FEATURE_GREP_CONTEXT( OPTBIT_B ,) /* -B NUM: before-match context */
3418- IF_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */
3419- IF_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */
3420- IF_EXTRA_COMPAT( OPTBIT_z ,) /* input is NUL terminated */
3421- OPT_l = 1 << OPTBIT_l,
3422- OPT_n = 1 << OPTBIT_n,
3423- OPT_q = 1 << OPTBIT_q,
3424- OPT_v = 1 << OPTBIT_v,
3425- OPT_s = 1 << OPTBIT_s,
3426- OPT_c = 1 << OPTBIT_c,
3427- OPT_F = 1 << OPTBIT_F,
3428- OPT_i = 1 << OPTBIT_i,
3429- OPT_H = 1 << OPTBIT_H,
3430- OPT_h = 1 << OPTBIT_h,
3431- OPT_e = 1 << OPTBIT_e,
3432- OPT_f = 1 << OPTBIT_f,
3433- OPT_L = 1 << OPTBIT_L,
3434- OPT_o = 1 << OPTBIT_o,
3435- OPT_r = 1 << OPTBIT_r,
3436- OPT_m = 1 << OPTBIT_m,
3437- OPT_w = 1 << OPTBIT_w,
3438- OPT_A = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_A)) + 0,
3439- OPT_B = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_B)) + 0,
3440- OPT_C = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0,
3441- OPT_E = IF_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0,
3442- OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0,
3443-};
3444-
3445-#define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l)
3446-#define PRINT_LINE_NUM (option_mask32 & OPT_n)
3447-#define BE_QUIET (option_mask32 & OPT_q)
3448-#define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s)
3449-#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c)
3450-#define FGREP_FLAG (option_mask32 & OPT_F)
3451-#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
3452-#define NUL_DELIMITED (option_mask32 & OPT_z)
3453-
3454-struct globals {
3455- int max_matches;
3456-#if !ENABLE_EXTRA_COMPAT
3457- int reflags;
3458-#else
3459- RE_TRANSLATE_TYPE case_fold; /* RE_TRANSLATE_TYPE is [[un]signed] char* */
3460-#endif
3461- smalluint invert_search;
3462- smalluint print_filename;
3463- smalluint open_errors;
3464-#if ENABLE_FEATURE_GREP_CONTEXT
3465- smalluint did_print_line;
3466- int lines_before;
3467- int lines_after;
3468- char **before_buf;
3469- IF_EXTRA_COMPAT(size_t *before_buf_size;)
3470- int last_line_printed;
3471-#endif
3472- /* globals used internally */
3473- llist_t *pattern_head; /* growable list of patterns to match */
3474- const char *cur_file; /* the current file we are reading */
3475-} FIX_ALIASING;
3476-#define G (*(struct globals*)&bb_common_bufsiz1)
3477-#define INIT_G() do { \
3478- struct G_sizecheck { \
3479- char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
3480- }; \
3481-} while (0)
3482-#define max_matches (G.max_matches )
3483-#if !ENABLE_EXTRA_COMPAT
3484-# define reflags (G.reflags )
3485-#else
3486-# define case_fold (G.case_fold )
3487-/* http://www.delorie.com/gnu/docs/regex/regex_46.html */
3488-# define reflags re_syntax_options
3489-# undef REG_NOSUB
3490-# undef REG_EXTENDED
3491-# undef REG_ICASE
3492-# define REG_NOSUB bug:is:here /* should not be used */
3493-/* Just RE_SYNTAX_EGREP is not enough, need to enable {n[,[m]]} too */
3494-# define REG_EXTENDED (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
3495-# define REG_ICASE bug:is:here /* should not be used */
3496-#endif
3497-#define invert_search (G.invert_search )
3498-#define print_filename (G.print_filename )
3499-#define open_errors (G.open_errors )
3500-#define did_print_line (G.did_print_line )
3501-#define lines_before (G.lines_before )
3502-#define lines_after (G.lines_after )
3503-#define before_buf (G.before_buf )
3504-#define before_buf_size (G.before_buf_size )
3505-#define last_line_printed (G.last_line_printed )
3506-#define pattern_head (G.pattern_head )
3507-#define cur_file (G.cur_file )
3508-
3509-
3510-typedef struct grep_list_data_t {
3511- char *pattern;
3512-/* for GNU regex, matched_range must be persistent across grep_file() calls */
3513-#if !ENABLE_EXTRA_COMPAT
3514- regex_t compiled_regex;
3515- regmatch_t matched_range;
3516-#else
3517- struct re_pattern_buffer compiled_regex;
3518- struct re_registers matched_range;
3519-#endif
3520-#define ALLOCATED 1
3521-#define COMPILED 2
3522- int flg_mem_alocated_compiled;
3523-} grep_list_data_t;
3524-
3525-#if !ENABLE_EXTRA_COMPAT
3526-#define print_line(line, line_len, linenum, decoration) \
3527- print_line(line, linenum, decoration)
3528-#endif
3529-static void print_line(const char *line, size_t line_len, int linenum, char decoration)
3530-{
3531-#if ENABLE_FEATURE_GREP_CONTEXT
3532- /* Happens when we go to next file, immediately hit match
3533- * and try to print prev context... from prev file! Don't do it */
3534- if (linenum < 1)
3535- return;
3536- /* possibly print the little '--' separator */
3537- if ((lines_before || lines_after) && did_print_line
3538- && last_line_printed != linenum - 1
3539- ) {
3540- puts("--");
3541- }
3542- /* guard against printing "--" before first line of first file */
3543- did_print_line = 1;
3544- last_line_printed = linenum;
3545-#endif
3546- if (print_filename)
3547- printf("%s%c", cur_file, decoration);
3548- if (PRINT_LINE_NUM)
3549- printf("%i%c", linenum, decoration);
3550- /* Emulate weird GNU grep behavior with -ov */
3551- if ((option_mask32 & (OPT_v|OPT_o)) != (OPT_v|OPT_o)) {
3552-#if !ENABLE_EXTRA_COMPAT
3553- puts(line);
3554-#else
3555- fwrite(line, 1, line_len, stdout);
3556- putchar(NUL_DELIMITED ? '\0' : '\n');
3557-#endif
3558- }
3559-}
3560-
3561-#if ENABLE_EXTRA_COMPAT
3562-/* Unlike getline, this one removes trailing '\n' */
3563-static ssize_t FAST_FUNC bb_getline(char **line_ptr, size_t *line_alloc_len, FILE *file)
3564-{
3565- ssize_t res_sz;
3566- char *line;
3567- int delim = (NUL_DELIMITED ? '\0' : '\n');
3568-
3569- res_sz = getdelim(line_ptr, line_alloc_len, delim, file);
3570- line = *line_ptr;
3571-
3572- if (res_sz > 0) {
3573- if (line[res_sz - 1] == delim)
3574- line[--res_sz] = '\0';
3575- } else {
3576- free(line); /* uclibc allocates a buffer even on EOF. WTF? */
3577- }
3578- return res_sz;
3579-}
3580-#endif
3581-
3582-static int grep_file(FILE *file)
3583-{
3584- smalluint found;
3585- int linenum = 0;
3586- int nmatches = 0;
3587-#if !ENABLE_EXTRA_COMPAT
3588- char *line;
3589-#else
3590- char *line = NULL;
3591- ssize_t line_len;
3592- size_t line_alloc_len;
3593-# define rm_so start[0]
3594-# define rm_eo end[0]
3595-#endif
3596-#if ENABLE_FEATURE_GREP_CONTEXT
3597- int print_n_lines_after = 0;
3598- int curpos = 0; /* track where we are in the circular 'before' buffer */
3599- int idx = 0; /* used for iteration through the circular buffer */
3600-#else
3601- enum { print_n_lines_after = 0 };
3602-#endif
3603-
3604- while (
3605-#if !ENABLE_EXTRA_COMPAT
3606- (line = xmalloc_fgetline(file)) != NULL
3607-#else
3608- (line_len = bb_getline(&line, &line_alloc_len, file)) >= 0
3609-#endif
3610- ) {
3611- llist_t *pattern_ptr = pattern_head;
3612- grep_list_data_t *gl = gl; /* for gcc */
3613-
3614- linenum++;
3615- found = 0;
3616- while (pattern_ptr) {
3617- gl = (grep_list_data_t *)pattern_ptr->data;
3618- if (FGREP_FLAG) {
3619- found |= (((option_mask32 & OPT_i)
3620- ? strcasestr(line, gl->pattern)
3621- : strstr(line, gl->pattern)
3622- ) != NULL);
3623- } else {
3624- if (!(gl->flg_mem_alocated_compiled & COMPILED)) {
3625- gl->flg_mem_alocated_compiled |= COMPILED;
3626-#if !ENABLE_EXTRA_COMPAT
3627- xregcomp(&gl->compiled_regex, gl->pattern, reflags);
3628-#else
3629- memset(&gl->compiled_regex, 0, sizeof(gl->compiled_regex));
3630- gl->compiled_regex.translate = case_fold; /* for -i */
3631- if (re_compile_pattern(gl->pattern, strlen(gl->pattern), &gl->compiled_regex))
3632- bb_error_msg_and_die("bad regex '%s'", gl->pattern);
3633-#endif
3634- }
3635-#if !ENABLE_EXTRA_COMPAT
3636- gl->matched_range.rm_so = 0;
3637- gl->matched_range.rm_eo = 0;
3638-#endif
3639- if (
3640-#if !ENABLE_EXTRA_COMPAT
3641- regexec(&gl->compiled_regex, line, 1, &gl->matched_range, 0) == 0
3642-#else
3643- re_search(&gl->compiled_regex, line, line_len,
3644- /*start:*/ 0, /*range:*/ line_len,
3645- &gl->matched_range) >= 0
3646-#endif
3647- ) {
3648- if (!(option_mask32 & OPT_w))
3649- found = 1;
3650- else {
3651- char c = ' ';
3652- if (gl->matched_range.rm_so)
3653- c = line[gl->matched_range.rm_so - 1];
3654- if (!isalnum(c) && c != '_') {
3655- c = line[gl->matched_range.rm_eo];
3656- if (!c || (!isalnum(c) && c != '_'))
3657- found = 1;
3658- }
3659- }
3660- }
3661- }
3662- /* If it's non-inverted search, we can stop
3663- * at first match */
3664- if (found && !invert_search)
3665- goto do_found;
3666- pattern_ptr = pattern_ptr->link;
3667- } /* while (pattern_ptr) */
3668-
3669- if (found ^ invert_search) {
3670- do_found:
3671- /* keep track of matches */
3672- nmatches++;
3673-
3674- /* quiet/print (non)matching file names only? */
3675- if (option_mask32 & (OPT_q|OPT_l|OPT_L)) {
3676- free(line); /* we don't need line anymore */
3677- if (BE_QUIET) {
3678- /* manpage says about -q:
3679- * "exit immediately with zero status
3680- * if any match is found,
3681- * even if errors were detected" */
3682- exit(EXIT_SUCCESS);
3683- }
3684- /* if we're just printing filenames, we stop after the first match */
3685- if (PRINT_FILES_WITH_MATCHES) {
3686- puts(cur_file);
3687- /* fall through to "return 1" */
3688- }
3689- /* OPT_L aka PRINT_FILES_WITHOUT_MATCHES: return early */
3690- return 1; /* one match */
3691- }
3692-
3693-#if ENABLE_FEATURE_GREP_CONTEXT
3694- /* Were we printing context and saw next (unwanted) match? */
3695- if ((option_mask32 & OPT_m) && nmatches > max_matches)
3696- break;
3697-#endif
3698-
3699- /* print the matched line */
3700- if (PRINT_MATCH_COUNTS == 0) {
3701-#if ENABLE_FEATURE_GREP_CONTEXT
3702- int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1;
3703-
3704- /* if we were told to print 'before' lines and there is at least
3705- * one line in the circular buffer, print them */
3706- if (lines_before && before_buf[prevpos] != NULL) {
3707- int first_buf_entry_line_num = linenum - lines_before;
3708-
3709- /* advance to the first entry in the circular buffer, and
3710- * figure out the line number is of the first line in the
3711- * buffer */
3712- idx = curpos;
3713- while (before_buf[idx] == NULL) {
3714- idx = (idx + 1) % lines_before;
3715- first_buf_entry_line_num++;
3716- }
3717-
3718- /* now print each line in the buffer, clearing them as we go */
3719- while (before_buf[idx] != NULL) {
3720- print_line(before_buf[idx], before_buf_size[idx], first_buf_entry_line_num, '-');
3721- free(before_buf[idx]);
3722- before_buf[idx] = NULL;
3723- idx = (idx + 1) % lines_before;
3724- first_buf_entry_line_num++;
3725- }
3726- }
3727-
3728- /* make a note that we need to print 'after' lines */
3729- print_n_lines_after = lines_after;
3730-#endif
3731- if (option_mask32 & OPT_o) {
3732- if (FGREP_FLAG) {
3733- /* -Fo just prints the pattern
3734- * (unless -v: -Fov doesnt print anything at all) */
3735- if (found)
3736- print_line(gl->pattern, strlen(gl->pattern), linenum, ':');
3737- } else while (1) {
3738- unsigned end = gl->matched_range.rm_eo;
3739- char old = line[end];
3740- line[end] = '\0';
3741- print_line(line + gl->matched_range.rm_so,
3742- end - gl->matched_range.rm_so,
3743- linenum, ':');
3744- if (old == '\0')
3745- break;
3746- line[end] = old;
3747-#if !ENABLE_EXTRA_COMPAT
3748- if (regexec(&gl->compiled_regex, line + end,
3749- 1, &gl->matched_range, REG_NOTBOL) != 0)
3750- break;
3751- gl->matched_range.rm_so += end;
3752- gl->matched_range.rm_eo += end;
3753-#else
3754- if (re_search(&gl->compiled_regex, line, line_len,
3755- end, line_len - end,
3756- &gl->matched_range) < 0)
3757- break;
3758-#endif
3759- }
3760- } else {
3761- print_line(line, line_len, linenum, ':');
3762- }
3763- }
3764- }
3765-#if ENABLE_FEATURE_GREP_CONTEXT
3766- else { /* no match */
3767- /* if we need to print some context lines after the last match, do so */
3768- if (print_n_lines_after) {
3769- print_line(line, strlen(line), linenum, '-');
3770- print_n_lines_after--;
3771- } else if (lines_before) {
3772- /* Add the line to the circular 'before' buffer */
3773- free(before_buf[curpos]);
3774- before_buf[curpos] = line;
3775- IF_EXTRA_COMPAT(before_buf_size[curpos] = line_len;)
3776- curpos = (curpos + 1) % lines_before;
3777- /* avoid free(line) - we took the line */
3778- line = NULL;
3779- }
3780- }
3781-
3782-#endif /* ENABLE_FEATURE_GREP_CONTEXT */
3783-#if !ENABLE_EXTRA_COMPAT
3784- free(line);
3785-#endif
3786- /* Did we print all context after last requested match? */
3787- if ((option_mask32 & OPT_m)
3788- && !print_n_lines_after
3789- && nmatches == max_matches
3790- ) {
3791- break;
3792- }
3793- } /* while (read line) */
3794-
3795- /* special-case file post-processing for options where we don't print line
3796- * matches, just filenames and possibly match counts */
3797-
3798- /* grep -c: print [filename:]count, even if count is zero */
3799- if (PRINT_MATCH_COUNTS) {
3800- if (print_filename)
3801- printf("%s:", cur_file);
3802- printf("%d\n", nmatches);
3803- }
3804-
3805- /* grep -L: print just the filename */
3806- if (PRINT_FILES_WITHOUT_MATCHES) {
3807- /* nmatches is zero, no need to check it:
3808- * we return 1 early if we detected a match
3809- * and PRINT_FILES_WITHOUT_MATCHES is set */
3810- puts(cur_file);
3811- }
3812-
3813- return nmatches;
3814-}
3815-
3816-#if ENABLE_FEATURE_CLEAN_UP
3817-#define new_grep_list_data(p, m) add_grep_list_data(p, m)
3818-static char *add_grep_list_data(char *pattern, int flg_used_mem)
3819-#else
3820-#define new_grep_list_data(p, m) add_grep_list_data(p)
3821-static char *add_grep_list_data(char *pattern)
3822-#endif
3823-{
3824- grep_list_data_t *gl = xzalloc(sizeof(*gl));
3825- gl->pattern = pattern;
3826-#if ENABLE_FEATURE_CLEAN_UP
3827- gl->flg_mem_alocated_compiled = flg_used_mem;
3828-#else
3829- /*gl->flg_mem_alocated_compiled = 0;*/
3830-#endif
3831- return (char *)gl;
3832-}
3833-
3834-static void load_regexes_from_file(llist_t *fopt)
3835-{
3836- char *line;
3837- FILE *f;
3838-
3839- while (fopt) {
3840- llist_t *cur = fopt;
3841- char *ffile = cur->data;
3842-
3843- fopt = cur->link;
3844- free(cur);
3845- f = xfopen_stdin(ffile);
3846- while ((line = xmalloc_fgetline(f)) != NULL) {
3847- llist_add_to(&pattern_head,
3848- new_grep_list_data(line, ALLOCATED));
3849- }
3850- }
3851-}
3852-
3853-static int FAST_FUNC file_action_grep(const char *filename,
3854- struct stat *statbuf UNUSED_PARAM,
3855- void* matched,
3856- int depth UNUSED_PARAM)
3857-{
3858- FILE *file = fopen_for_read(filename);
3859- if (file == NULL) {
3860- if (!SUPPRESS_ERR_MSGS)
3861- bb_simple_perror_msg(filename);
3862- open_errors = 1;
3863- return 0;
3864- }
3865- cur_file = filename;
3866- *(int*)matched += grep_file(file);
3867- fclose(file);
3868- return 1;
3869-}
3870-
3871-static int grep_dir(const char *dir)
3872-{
3873- int matched = 0;
3874- recursive_action(dir,
3875- /* recurse=yes */ ACTION_RECURSE |
3876- /* followLinks=no */
3877- /* depthFirst=yes */ ACTION_DEPTHFIRST,
3878- /* fileAction= */ file_action_grep,
3879- /* dirAction= */ NULL,
3880- /* userData= */ &matched,
3881- /* depth= */ 0);
3882- return matched;
3883-}
3884-
3885-int grep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3886-int grep_main(int argc UNUSED_PARAM, char **argv)
3887-{
3888- FILE *file;
3889- int matched;
3890- llist_t *fopt = NULL;
3891-
3892- /* do normal option parsing */
3893-#if ENABLE_FEATURE_GREP_CONTEXT
3894- int Copt;
3895-
3896- /* -H unsets -h; -C unsets -A,-B; -e,-f are lists;
3897- * -m,-A,-B,-C have numeric param */
3898- opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+";
3899- getopt32(argv,
3900- OPTSTR_GREP,
3901- &pattern_head, &fopt, &max_matches,
3902- &lines_after, &lines_before, &Copt);
3903-
3904- if (option_mask32 & OPT_C) {
3905- /* -C unsets prev -A and -B, but following -A or -B
3906- may override it */
3907- if (!(option_mask32 & OPT_A)) /* not overridden */
3908- lines_after = Copt;
3909- if (!(option_mask32 & OPT_B)) /* not overridden */
3910- lines_before = Copt;
3911- }
3912- /* sanity checks */
3913- if (option_mask32 & (OPT_c|OPT_q|OPT_l|OPT_L)) {
3914- option_mask32 &= ~OPT_n;
3915- lines_before = 0;
3916- lines_after = 0;
3917- } else if (lines_before > 0) {
3918- before_buf = xzalloc(lines_before * sizeof(before_buf[0]));
3919- IF_EXTRA_COMPAT(before_buf_size = xzalloc(lines_before * sizeof(before_buf_size[0]));)
3920- }
3921-#else
3922- /* with auto sanity checks */
3923- /* -H unsets -h; -c,-q or -l unset -n; -e,-f are lists; -m N */
3924- opt_complementary = "H-h:c-n:q-n:l-n:e::f::m+";
3925- getopt32(argv, OPTSTR_GREP,
3926- &pattern_head, &fopt, &max_matches);
3927-#endif
3928- invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */
3929-
3930- if (pattern_head != NULL) {
3931- /* convert char **argv to grep_list_data_t */
3932- llist_t *cur;
3933-
3934- for (cur = pattern_head; cur; cur = cur->link)
3935- cur->data = new_grep_list_data(cur->data, 0);
3936- }
3937- if (option_mask32 & OPT_f)
3938- load_regexes_from_file(fopt);
3939-
3940- if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f')
3941- option_mask32 |= OPT_F;
3942-
3943-#if !ENABLE_EXTRA_COMPAT
3944- if (!(option_mask32 & (OPT_o | OPT_w)))
3945- reflags = REG_NOSUB;
3946-#endif
3947-
3948- if (ENABLE_FEATURE_GREP_EGREP_ALIAS
3949- && (applet_name[0] == 'e' || (option_mask32 & OPT_E))
3950- ) {
3951- reflags |= REG_EXTENDED;
3952- }
3953-#if ENABLE_EXTRA_COMPAT
3954- else {
3955- reflags = RE_SYNTAX_GREP;
3956- }
3957-#endif
3958-
3959- if (option_mask32 & OPT_i) {
3960-#if !ENABLE_EXTRA_COMPAT
3961- reflags |= REG_ICASE;
3962-#else
3963- int i;
3964- case_fold = xmalloc(256);
3965- for (i = 0; i < 256; i++)
3966- case_fold[i] = (unsigned char)i;
3967- for (i = 'a'; i <= 'z'; i++)
3968- case_fold[i] = (unsigned char)(i - ('a' - 'A'));
3969-#endif
3970- }
3971-
3972- argv += optind;
3973-
3974- /* if we didn't get a pattern from -e and no command file was specified,
3975- * first parameter should be the pattern. no pattern, no worky */
3976- if (pattern_head == NULL) {
3977- char *pattern;
3978- if (*argv == NULL)
3979- bb_show_usage();
3980- pattern = new_grep_list_data(*argv++, 0);
3981- llist_add_to(&pattern_head, pattern);
3982- }
3983-
3984- /* argv[0..(argc-1)] should be names of file to grep through. If
3985- * there is more than one file to grep, we will print the filenames. */
3986- if (argv[0] && argv[1])
3987- print_filename = 1;
3988- /* -H / -h of course override */
3989- if (option_mask32 & OPT_H)
3990- print_filename = 1;
3991- if (option_mask32 & OPT_h)
3992- print_filename = 0;
3993-
3994- /* If no files were specified, or '-' was specified, take input from
3995- * stdin. Otherwise, we grep through all the files specified. */
3996- matched = 0;
3997- do {
3998- cur_file = *argv;
3999- file = stdin;
4000- if (!cur_file || LONE_DASH(cur_file)) {
4001- cur_file = "(standard input)";
4002- } else {
4003- if (option_mask32 & OPT_r) {
4004- struct stat st;
4005- if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) {
4006- if (!(option_mask32 & OPT_h))
4007- print_filename = 1;
4008- matched += grep_dir(cur_file);
4009- goto grep_done;
4010- }
4011- }
4012- /* else: fopen(dir) will succeed, but reading won't */
4013- file = fopen_for_read(cur_file);
4014- if (file == NULL) {
4015- if (!SUPPRESS_ERR_MSGS)
4016- bb_simple_perror_msg(cur_file);
4017- open_errors = 1;
4018- continue;
4019- }
4020- }
4021- matched += grep_file(file);
4022- fclose_if_not_stdin(file);
4023- grep_done: ;
4024- } while (*argv && *++argv);
4025-
4026- /* destroy all the elments in the pattern list */
4027- if (ENABLE_FEATURE_CLEAN_UP) {
4028- while (pattern_head) {
4029- llist_t *pattern_head_ptr = pattern_head;
4030- grep_list_data_t *gl = (grep_list_data_t *)pattern_head_ptr->data;
4031-
4032- pattern_head = pattern_head->link;
4033- if (gl->flg_mem_alocated_compiled & ALLOCATED)
4034- free(gl->pattern);
4035- if (gl->flg_mem_alocated_compiled & COMPILED)
4036- regfree(&gl->compiled_regex);
4037- free(gl);
4038- free(pattern_head_ptr);
4039- }
4040- }
4041- /* 0 = success, 1 = failed, 2 = error */
4042- if (open_errors)
4043- return 2;
4044- return !matched; /* invert return value: 0 = success, 1 = failed */
4045-}
4046
4047=== removed directory '.pc/grep-o-loop.patch/testsuite'
4048=== removed file '.pc/grep-o-loop.patch/testsuite/grep.tests'
4049--- .pc/grep-o-loop.patch/testsuite/grep.tests 2010-10-13 11:03:32 +0000
4050+++ .pc/grep-o-loop.patch/testsuite/grep.tests 1970-01-01 00:00:00 +0000
4051@@ -1,102 +0,0 @@
4052-#!/bin/sh
4053-
4054-# Copyright 2005 by Rob Landley <rob@landley.net>
4055-# Licensed under GPL v2, see file LICENSE for details.
4056-
4057-# AUDIT:
4058-
4059-. ./testing.sh
4060-
4061-# testing "test name" "options" "expected result" "file input" "stdin"
4062-# file input will be file called "input"
4063-# test can create a file "actual" instead of writing to stdout
4064-
4065-# Test exit status
4066-
4067-testing "grep (exit with error)" "grep nonexistent 2> /dev/null ; echo \$?" \
4068- "1\n" "" ""
4069-testing "grep (exit success)" "grep grep $0 > /dev/null 2>&1 ; echo \$?" "0\n" \
4070- "" ""
4071-# Test various data sources and destinations
4072-
4073-testing "grep (default to stdin)" "grep two" "two\n" "" \
4074- "one\ntwo\nthree\nthree\nthree\n"
4075-testing "grep - (specify stdin)" "grep two -" "two\n" "" \
4076- "one\ntwo\nthree\nthree\nthree\n"
4077-testing "grep input (specify file)" "grep two input" "two\n" \
4078- "one\ntwo\nthree\nthree\nthree\n" ""
4079-
4080-# GNU grep 2.5.3 outputs a new line character after the located string
4081-# even if there is no new line character in the input
4082-testing "grep (no newline at EOL)" "grep bug input" "bug\n" "bug" ""
4083-
4084->empty
4085-testing "grep two files" "grep two input empty 2>/dev/null" \
4086- "input:two\n" "one\ntwo\nthree\nthree\nthree\n" ""
4087-rm empty
4088-
4089-testing "grep - infile (specify stdin and file)" "grep two - input" \
4090- "(standard input):two\ninput:two\n" "one\ntwo\nthree\n" \
4091- "one\ntwo\ntoo\nthree\nthree\n"
4092-
4093-# Check if we see the correct return value if both stdin and non-existing file
4094-# are given.
4095-testing "grep - nofile (specify stdin and nonexisting file)" \
4096- "grep two - nonexistent 2> /dev/null ; echo \$?" \
4097- "(standard input):two\n(standard input):two\n2\n" \
4098- "" "one\ntwo\ntwo\nthree\nthree\nthree\n"
4099-testing "grep -q - nofile (specify stdin and nonexisting file, no match)" \
4100- "grep -q nomatch - nonexistent 2> /dev/null ; echo \$?" \
4101- "2\n" "" "one\ntwo\ntwo\nthree\nthree\nthree\n"
4102-# SUSv3: If the -q option is specified, the exit status shall be zero
4103-# if an input line is selected, even if an error was detected.
4104-testing "grep -q - nofile (specify stdin and nonexisting file, match)" \
4105- "grep -q two - nonexistent ; echo \$?" \
4106- "0\n" "" "one\ntwo\ntwo\nthree\nthree\nthree\n"
4107-
4108-# Test various command line options
4109-# -s no error messages
4110-testing "grep -s nofile (nonexisting file, no match)" \
4111- "grep -s nomatch nonexistent ; echo \$?" "2\n" "" ""
4112-testing "grep -s nofile - (stdin and nonexisting file, match)" \
4113- "grep -s domatch nonexistent - ; echo \$?" \
4114- "(standard input):domatch\n2\n" "" "nomatch\ndomatch\nend\n"
4115-
4116-optional EXTRA_COMPAT
4117-testing "grep handles NUL in files" "grep -a foo input" "\0foo\n" "\0foo\n\n" ""
4118-testing "grep handles NUL on stdin" "grep -a foo" "\0foo\n" "" "\0foo\n\n"
4119-
4120-testing "grep matches NUL" "grep . input > /dev/null 2>&1 ; echo \$?" \
4121- "0\n" "\0\n" ""
4122-SKIP=
4123-
4124-# -e regex
4125-testing "grep handles multiple regexps" "grep -e one -e two input ; echo \$?" \
4126- "one\ntwo\n0\n" "one\ntwo\n" ""
4127-testing "grep -F handles multiple expessions" "grep -F -e one -e two input ; echo \$?" \
4128- "one\ntwo\n0\n" "one\ntwo\n" ""
4129-testing "grep -F handles -i" "grep -F -i foo input ; echo \$?" \
4130- "FOO\n0\n" "FOO\n" ""
4131-
4132-# -f file/-
4133-testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \
4134- "two\nthree\n0\n" "tw\ntwo\nthree\n" "tw.\nthr\n"
4135-
4136-optional FEATURE_GREP_EGREP_ALIAS
4137-testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \
4138- "b\ar\nfoo\nbaz"
4139-testing "grep is also egrep" "egrep foo" "foo\n" "" "foo\nbar\n"
4140-testing "egrep is not case insensitive" \
4141- "egrep foo ; [ \$? -ne 0 ] && echo yes" "yes\n" "" "FOO\n"
4142-testing "grep -E -o prints all matches" \
4143- "grep -E -o '([[:xdigit:]]{2}[:-]){5}[[:xdigit:]]{2}'" \
4144- "00:19:3E:00:AA:5E\n00:1D:60:3D:3A:FB\n00:22:43:49:FB:AA\n" \
4145- "" "00:19:3E:00:AA:5E 00:1D:60:3D:3A:FB 00:22:43:49:FB:AA\n"
4146-SKIP=
4147-
4148-testing "grep -o does not loop forever" \
4149- 'grep -o "[^/]*$"' \
4150- "test\n" \
4151- "" "/var/test\n"
4152-
4153-exit $FAILCOUNT
4154
4155=== removed directory '.pc/init-console-CRTSCTS.patch'
4156=== removed directory '.pc/init-console-CRTSCTS.patch/init'
4157=== removed file '.pc/init-console-CRTSCTS.patch/init/init.c'
4158--- .pc/init-console-CRTSCTS.patch/init/init.c 2010-10-21 16:17:03 +0000
4159+++ .pc/init-console-CRTSCTS.patch/init/init.c 1970-01-01 00:00:00 +0000
4160@@ -1,1047 +0,0 @@
4161-/* vi: set sw=4 ts=4: */
4162-/*
4163- * Mini init implementation for busybox
4164- *
4165- * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
4166- * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4167- * Adjusted by so many folks, it's impossible to keep track.
4168- *
4169- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4170- */
4171-
4172-#include "libbb.h"
4173-#include <syslog.h>
4174-#include <paths.h>
4175-#include <sys/resource.h>
4176-#ifdef __linux__
4177-#include <linux/vt.h>
4178-#endif
4179-#if ENABLE_FEATURE_UTMP
4180-# include <utmp.h> /* DEAD_PROCESS */
4181-#endif
4182-#include "reboot.h" /* reboot() constants */
4183-
4184-/* Used only for sanitizing purposes in set_sane_term() below. On systems where
4185- * the baud rate is stored in a separate field, we can safely disable them. */
4186-#ifndef CBAUD
4187-# define CBAUD 0
4188-# define CBAUDEX 0
4189-#endif
4190-
4191-/* Was a CONFIG_xxx option. A lot of people were building
4192- * not fully functional init by switching it on! */
4193-#define DEBUG_INIT 0
4194-
4195-#define COMMAND_SIZE 256
4196-#define CONSOLE_NAME_SIZE 32
4197-
4198-/* Default sysinit script. */
4199-#ifndef INIT_SCRIPT
4200-#define INIT_SCRIPT "/etc/init.d/rcS"
4201-#endif
4202-
4203-/* Each type of actions can appear many times. They will be
4204- * handled in order. RESTART is an exception, only 1st is used.
4205- */
4206-/* Start these actions first and wait for completion */
4207-#define SYSINIT 0x01
4208-/* Start these after SYSINIT and wait for completion */
4209-#define WAIT 0x02
4210-/* Start these after WAIT and *dont* wait for completion */
4211-#define ONCE 0x04
4212-/*
4213- * NB: while SYSINIT/WAIT/ONCE are being processed,
4214- * SIGHUP ("reread /etc/inittab") will be processed only after
4215- * each group of actions. If new inittab adds, say, a SYSINIT action,
4216- * it will not be run, since init is already "past SYSINIT stage".
4217- */
4218-/* Start these after ONCE are started, restart on exit */
4219-#define RESPAWN 0x08
4220-/* Like RESPAWN, but wait for <Enter> to be pressed on tty */
4221-#define ASKFIRST 0x10
4222-/*
4223- * Start these on SIGINT, and wait for completion.
4224- * Then go back to respawning RESPAWN and ASKFIRST actions.
4225- * NB: kernel sends SIGINT to us if Ctrl-Alt-Del was pressed.
4226- */
4227-#define CTRLALTDEL 0x20
4228-/*
4229- * Start these before killing all processes in preparation for
4230- * running RESTART actions or doing low-level halt/reboot/poweroff
4231- * (initiated by SIGUSR1/SIGTERM/SIGUSR2).
4232- * Wait for completion before proceeding.
4233- */
4234-#define SHUTDOWN 0x40
4235-/*
4236- * exec() on SIGQUIT. SHUTDOWN actions are started and waited for,
4237- * then all processes are killed, then init exec's 1st RESTART action,
4238- * replacing itself by it. If no RESTART action specified,
4239- * SIGQUIT has no effect.
4240- */
4241-#define RESTART 0x80
4242-
4243-
4244-/* A linked list of init_actions, to be read from inittab */
4245-struct init_action {
4246- struct init_action *next;
4247- pid_t pid;
4248- uint8_t action_type;
4249- char terminal[CONSOLE_NAME_SIZE];
4250- char command[COMMAND_SIZE];
4251-};
4252-
4253-static struct init_action *init_action_list = NULL;
4254-
4255-static const char *log_console = VC_5;
4256-
4257-enum {
4258- L_LOG = 0x1,
4259- L_CONSOLE = 0x2,
4260-};
4261-
4262-/* Print a message to the specified device.
4263- * "where" may be bitwise-or'd from L_LOG | L_CONSOLE
4264- * NB: careful, we can be called after vfork!
4265- */
4266-#define dbg_message(...) do { if (DEBUG_INIT) message(__VA_ARGS__); } while (0)
4267-static void message(int where, const char *fmt, ...)
4268- __attribute__ ((format(printf, 2, 3)));
4269-static void message(int where, const char *fmt, ...)
4270-{
4271- va_list arguments;
4272- unsigned l;
4273- char msg[128];
4274-
4275- msg[0] = '\r';
4276- va_start(arguments, fmt);
4277- l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
4278- if (l > sizeof(msg) - 1)
4279- l = sizeof(msg) - 1;
4280- va_end(arguments);
4281-
4282-#if ENABLE_FEATURE_INIT_SYSLOG
4283- msg[l] = '\0';
4284- if (where & L_LOG) {
4285- /* Log the message to syslogd */
4286- openlog(applet_name, 0, LOG_DAEMON);
4287- /* don't print "\r" */
4288- syslog(LOG_INFO, "%s", msg + 1);
4289- closelog();
4290- }
4291- msg[l++] = '\n';
4292- msg[l] = '\0';
4293-#else
4294- {
4295- static int log_fd = -1;
4296-
4297- msg[l++] = '\n';
4298- msg[l] = '\0';
4299- /* Take full control of the log tty, and never close it.
4300- * It's mine, all mine! Muhahahaha! */
4301- if (log_fd < 0) {
4302- if (!log_console) {
4303- log_fd = STDERR_FILENO;
4304- } else {
4305- log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY);
4306- if (log_fd < 0) {
4307- bb_error_msg("can't log to %s", log_console);
4308- where = L_CONSOLE;
4309- } else {
4310- close_on_exec_on(log_fd);
4311- }
4312- }
4313- }
4314- if (where & L_LOG) {
4315- full_write(log_fd, msg, l);
4316- if (log_fd == STDERR_FILENO)
4317- return; /* don't print dup messages */
4318- }
4319- }
4320-#endif
4321-
4322- if (where & L_CONSOLE) {
4323- /* Send console messages to console so people will see them. */
4324- full_write(STDERR_FILENO, msg, l);
4325- }
4326-}
4327-
4328-static void console_init(void)
4329-{
4330-#ifdef VT_OPENQRY
4331- int vtno;
4332-#endif
4333- char *s;
4334-
4335- s = getenv("CONSOLE");
4336- if (!s)
4337- s = getenv("console");
4338- if (s) {
4339- int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY);
4340- if (fd >= 0) {
4341- dup2(fd, STDIN_FILENO);
4342- dup2(fd, STDOUT_FILENO);
4343- xmove_fd(fd, STDERR_FILENO);
4344- }
4345- dbg_message(L_LOG, "console='%s'", s);
4346- } else {
4347- /* Make sure fd 0,1,2 are not closed
4348- * (so that they won't be used by future opens) */
4349- bb_sanitize_stdio();
4350-// Users report problems
4351-// /* Make sure init can't be blocked by writing to stderr */
4352-// fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK);
4353- }
4354-
4355- s = getenv("TERM");
4356-#ifdef VT_OPENQRY
4357- if (ioctl(STDIN_FILENO, VT_OPENQRY, &vtno) != 0) {
4358- /* Not a linux terminal, probably serial console.
4359- * Force the TERM setting to vt102
4360- * if TERM is set to linux (the default) */
4361- if (!s || strcmp(s, "linux") == 0)
4362- putenv((char*)"TERM=vt102");
4363- if (!ENABLE_FEATURE_INIT_SYSLOG)
4364- log_console = NULL;
4365- } else
4366-#endif
4367- if (!s)
4368- putenv((char*)"TERM=" CONFIG_INIT_TERMINAL_TYPE);
4369-}
4370-
4371-/* Set terminal settings to reasonable defaults.
4372- * NB: careful, we can be called after vfork! */
4373-static void set_sane_term(void)
4374-{
4375- struct termios tty;
4376-
4377- tcgetattr(STDIN_FILENO, &tty);
4378-
4379- /* set control chars */
4380- tty.c_cc[VINTR] = 3; /* C-c */
4381- tty.c_cc[VQUIT] = 28; /* C-\ */
4382- tty.c_cc[VERASE] = 127; /* C-? */
4383- tty.c_cc[VKILL] = 21; /* C-u */
4384- tty.c_cc[VEOF] = 4; /* C-d */
4385- tty.c_cc[VSTART] = 17; /* C-q */
4386- tty.c_cc[VSTOP] = 19; /* C-s */
4387- tty.c_cc[VSUSP] = 26; /* C-z */
4388-
4389-#ifdef __linux__
4390- /* use line discipline 0 */
4391- tty.c_line = 0;
4392-#endif
4393-
4394- /* Make it be sane */
4395- tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
4396- tty.c_cflag |= CREAD | HUPCL | CLOCAL;
4397-
4398- /* input modes */
4399- tty.c_iflag = ICRNL | IXON | IXOFF;
4400-
4401- /* output modes */
4402- tty.c_oflag = OPOST | ONLCR;
4403-
4404- /* local modes */
4405- tty.c_lflag =
4406- ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
4407-
4408- tcsetattr_stdin_TCSANOW(&tty);
4409-}
4410-
4411-/* Open the new terminal device.
4412- * NB: careful, we can be called after vfork! */
4413-static int open_stdio_to_tty(const char* tty_name)
4414-{
4415- /* empty tty_name means "use init's tty", else... */
4416- if (tty_name[0]) {
4417- int fd;
4418-
4419- close(STDIN_FILENO);
4420- /* fd can be only < 0 or 0: */
4421- fd = device_open(tty_name, O_RDWR);
4422- if (fd) {
4423- message(L_LOG | L_CONSOLE, "can't open %s: %s",
4424- tty_name, strerror(errno));
4425- return 0; /* failure */
4426- }
4427- dup2(STDIN_FILENO, STDOUT_FILENO);
4428- dup2(STDIN_FILENO, STDERR_FILENO);
4429- }
4430- set_sane_term();
4431- return 1; /* success */
4432-}
4433-
4434-static void reset_sighandlers_and_unblock_sigs(void)
4435-{
4436- bb_signals(0
4437- + (1 << SIGUSR1)
4438- + (1 << SIGUSR2)
4439- + (1 << SIGTERM)
4440- + (1 << SIGQUIT)
4441- + (1 << SIGINT)
4442- + (1 << SIGHUP)
4443- + (1 << SIGTSTP)
4444- + (1 << SIGSTOP)
4445- , SIG_DFL);
4446- sigprocmask_allsigs(SIG_UNBLOCK);
4447-}
4448-
4449-/* Wrapper around exec:
4450- * Takes string (max COMMAND_SIZE chars).
4451- * If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'.
4452- * Otherwise splits words on whitespace, deals with leading dash,
4453- * and uses plain exec().
4454- * NB: careful, we can be called after vfork!
4455- */
4456-static void init_exec(const char *command)
4457-{
4458- char *cmd[COMMAND_SIZE / 2];
4459- char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */
4460- int dash = (command[0] == '-' /* maybe? && command[1] == '/' */);
4461-
4462- /* See if any special /bin/sh requiring characters are present */
4463- if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
4464- strcpy(buf, "exec ");
4465- strcpy(buf + 5, command + dash); /* excluding "-" */
4466- /* NB: LIBBB_DEFAULT_LOGIN_SHELL define has leading dash */
4467- cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash);
4468- cmd[1] = (char*)"-c";
4469- cmd[2] = buf;
4470- cmd[3] = NULL;
4471- } else {
4472- /* Convert command (char*) into cmd (char**, one word per string) */
4473- char *word, *next;
4474- int i = 0;
4475- next = strcpy(buf, command); /* including "-" */
4476- while ((word = strsep(&next, " \t")) != NULL) {
4477- if (*word != '\0') { /* not two spaces/tabs together? */
4478- cmd[i] = word;
4479- i++;
4480- }
4481- }
4482- cmd[i] = NULL;
4483- }
4484- /* If we saw leading "-", it is interactive shell.
4485- * Try harder to give it a controlling tty.
4486- * And skip "-" in actual exec call. */
4487- if (dash) {
4488- /* _Attempt_ to make stdin a controlling tty. */
4489- if (ENABLE_FEATURE_INIT_SCTTY)
4490- ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/);
4491- }
4492- BB_EXECVP(cmd[0] + dash, cmd);
4493- message(L_LOG | L_CONSOLE, "can't run '%s': %s", cmd[0], strerror(errno));
4494- /* returns if execvp fails */
4495-}
4496-
4497-/* Used only by run_actions */
4498-static pid_t run(const struct init_action *a)
4499-{
4500- pid_t pid;
4501-
4502- /* Careful: don't be affected by a signal in vforked child */
4503- sigprocmask_allsigs(SIG_BLOCK);
4504- if (BB_MMU && (a->action_type & ASKFIRST))
4505- pid = fork();
4506- else
4507- pid = vfork();
4508- if (pid < 0)
4509- message(L_LOG | L_CONSOLE, "can't fork");
4510- if (pid) {
4511- sigprocmask_allsigs(SIG_UNBLOCK);
4512- return pid; /* Parent or error */
4513- }
4514-
4515- /* Child */
4516-
4517- /* Reset signal handlers that were set by the parent process */
4518- reset_sighandlers_and_unblock_sigs();
4519-
4520- /* Create a new session and make ourself the process group leader */
4521- setsid();
4522-
4523- /* Open the new terminal device */
4524- if (!open_stdio_to_tty(a->terminal))
4525- _exit(EXIT_FAILURE);
4526-
4527- /* NB: on NOMMU we can't wait for input in child, so
4528- * "askfirst" will work the same as "respawn". */
4529- if (BB_MMU && (a->action_type & ASKFIRST)) {
4530- static const char press_enter[] ALIGN1 =
4531-#ifdef CUSTOMIZED_BANNER
4532-#include CUSTOMIZED_BANNER
4533-#endif
4534- "\nPlease press Enter to activate this console. ";
4535- char c;
4536- /*
4537- * Save memory by not exec-ing anything large (like a shell)
4538- * before the user wants it. This is critical if swap is not
4539- * enabled and the system has low memory. Generally this will
4540- * be run on the second virtual console, and the first will
4541- * be allowed to start a shell or whatever an init script
4542- * specifies.
4543- */
4544- dbg_message(L_LOG, "waiting for enter to start '%s'"
4545- "(pid %d, tty '%s')\n",
4546- a->command, getpid(), a->terminal);
4547- full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1);
4548- while (safe_read(STDIN_FILENO, &c, 1) == 1 && c != '\n')
4549- continue;
4550- }
4551-
4552- /*
4553- * When a file named /.init_enable_core exists, setrlimit is called
4554- * before processes are spawned to set core file size as unlimited.
4555- * This is for debugging only. Don't use this is production, unless
4556- * you want core dumps lying about....
4557- */
4558- if (ENABLE_FEATURE_INIT_COREDUMPS) {
4559- if (access("/.init_enable_core", F_OK) == 0) {
4560- struct rlimit limit;
4561- limit.rlim_cur = RLIM_INFINITY;
4562- limit.rlim_max = RLIM_INFINITY;
4563- setrlimit(RLIMIT_CORE, &limit);
4564- }
4565- }
4566-
4567- /* Log the process name and args */
4568- message(L_LOG, "starting pid %d, tty '%s': '%s'",
4569- getpid(), a->terminal, a->command);
4570-
4571- /* Now run it. The new program will take over this PID,
4572- * so nothing further in init.c should be run. */
4573- init_exec(a->command);
4574- /* We're still here? Some error happened. */
4575- _exit(-1);
4576-}
4577-
4578-static struct init_action *mark_terminated(pid_t pid)
4579-{
4580- struct init_action *a;
4581-
4582- if (pid > 0) {
4583- for (a = init_action_list; a; a = a->next) {
4584- if (a->pid == pid) {
4585- a->pid = 0;
4586- return a;
4587- }
4588- }
4589- update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
4590- }
4591- return NULL;
4592-}
4593-
4594-static void waitfor(pid_t pid)
4595-{
4596- /* waitfor(run(x)): protect against failed fork inside run() */
4597- if (pid <= 0)
4598- return;
4599-
4600- /* Wait for any child (prevent zombies from exiting orphaned processes)
4601- * but exit the loop only when specified one has exited. */
4602- while (1) {
4603- pid_t wpid = wait(NULL);
4604- mark_terminated(wpid);
4605- /* Unsafe. SIGTSTP handler might have wait'ed it already */
4606- /*if (wpid == pid) break;*/
4607- /* More reliable: */
4608- if (kill(pid, 0))
4609- break;
4610- }
4611-}
4612-
4613-/* Run all commands of a particular type */
4614-static void run_actions(int action_type)
4615-{
4616- struct init_action *a;
4617-
4618- for (a = init_action_list; a; a = a->next) {
4619- if (!(a->action_type & action_type))
4620- continue;
4621- if (a->terminal[0] && access(a->terminal, R_OK | W_OK))
4622- continue;
4623-
4624- if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
4625- pid_t pid = run(a);
4626- if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
4627- waitfor(pid);
4628- }
4629- if (a->action_type & (RESPAWN | ASKFIRST)) {
4630- /* Only run stuff with pid == 0. If pid != 0,
4631- * it is already running
4632- */
4633- if (a->pid == 0)
4634- a->pid = run(a);
4635- }
4636- }
4637-}
4638-
4639-static void new_init_action(uint8_t action_type, const char *command, const char *cons)
4640-{
4641- struct init_action *a, **nextp;
4642-
4643- /* Scenario:
4644- * old inittab:
4645- * ::shutdown:umount -a -r
4646- * ::shutdown:swapoff -a
4647- * new inittab:
4648- * ::shutdown:swapoff -a
4649- * ::shutdown:umount -a -r
4650- * On reload, we must ensure entries end up in correct order.
4651- * To achieve that, if we find a matching entry, we move it
4652- * to the end.
4653- */
4654- nextp = &init_action_list;
4655- while ((a = *nextp) != NULL) {
4656- /* Don't enter action if it's already in the list,
4657- * This prevents losing running RESPAWNs.
4658- */
4659- if (strcmp(a->command, command) == 0
4660- && strcmp(a->terminal, cons) == 0
4661- ) {
4662- /* Remove from list */
4663- *nextp = a->next;
4664- /* Find the end of the list */
4665- while (*nextp != NULL)
4666- nextp = &(*nextp)->next;
4667- a->next = NULL;
4668- break;
4669- }
4670- nextp = &a->next;
4671- }
4672-
4673- if (!a)
4674- a = xzalloc(sizeof(*a));
4675- /* Append to the end of the list */
4676- *nextp = a;
4677- a->action_type = action_type;
4678- safe_strncpy(a->command, command, sizeof(a->command));
4679- safe_strncpy(a->terminal, cons, sizeof(a->terminal));
4680- dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
4681- a->command, a->action_type, a->terminal);
4682-}
4683-
4684-/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
4685- * then parse_inittab() simply adds in some default
4686- * actions(i.e., runs INIT_SCRIPT and then starts a pair
4687- * of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB
4688- * _is_ defined, but /etc/inittab is missing, this
4689- * results in the same set of default behaviors.
4690- */
4691-static void parse_inittab(void)
4692-{
4693-#if ENABLE_FEATURE_USE_INITTAB
4694- char *token[4];
4695- parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
4696-
4697- if (parser == NULL)
4698-#endif
4699- {
4700- /* No inittab file - set up some default behavior */
4701- /* Reboot on Ctrl-Alt-Del */
4702- new_init_action(CTRLALTDEL, "reboot", "");
4703- /* Umount all filesystems on halt/reboot */
4704- new_init_action(SHUTDOWN, "umount -a -r", "");
4705- /* Swapoff on halt/reboot */
4706- if (ENABLE_SWAPONOFF)
4707- new_init_action(SHUTDOWN, "swapoff -a", "");
4708- /* Prepare to restart init when a QUIT is received */
4709- new_init_action(RESTART, "init", "");
4710- /* Askfirst shell on tty1-4 */
4711- new_init_action(ASKFIRST, bb_default_login_shell, "");
4712-//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
4713- new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
4714- new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
4715- new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
4716- /* sysinit */
4717- new_init_action(SYSINIT, INIT_SCRIPT, "");
4718- return;
4719- }
4720-
4721-#if ENABLE_FEATURE_USE_INITTAB
4722- /* optional_tty:ignored_runlevel:action:command
4723- * Delims are not to be collapsed and need exactly 4 tokens
4724- */
4725- while (config_read(parser, token, 4, 0, "#:",
4726- PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
4727- /* order must correspond to SYSINIT..RESTART constants */
4728- static const char actions[] ALIGN1 =
4729- "sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
4730- "ctrlaltdel\0""shutdown\0""restart\0";
4731- int action;
4732- char *tty = token[0];
4733-
4734- if (!token[3]) /* less than 4 tokens */
4735- goto bad_entry;
4736- action = index_in_strings(actions, token[2]);
4737- if (action < 0 || !token[3][0]) /* token[3]: command */
4738- goto bad_entry;
4739- /* turn .*TTY -> /dev/TTY */
4740- if (tty[0]) {
4741- tty = concat_path_file("/dev/", skip_dev_pfx(tty));
4742- }
4743- new_init_action(1 << action, token[3], tty);
4744- if (tty[0])
4745- free(tty);
4746- continue;
4747- bad_entry:
4748- message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d",
4749- parser->lineno);
4750- }
4751- config_close(parser);
4752-#endif
4753-}
4754-
4755-static void pause_and_low_level_reboot(unsigned magic) NORETURN;
4756-static void pause_and_low_level_reboot(unsigned magic)
4757-{
4758- pid_t pid;
4759-
4760- /* Allow time for last message to reach serial console, etc */
4761- sleep(1);
4762-
4763- /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
4764- * in linux/kernel/sys.c, which can cause the machine to panic when
4765- * the init process exits... */
4766- pid = vfork();
4767- if (pid == 0) { /* child */
4768- reboot(magic);
4769- _exit(EXIT_SUCCESS);
4770- }
4771- while (1)
4772- sleep(1);
4773-}
4774-
4775-static void run_shutdown_and_kill_processes(void)
4776-{
4777- /* Run everything to be run at "shutdown". This is done _prior_
4778- * to killing everything, in case people wish to use scripts to
4779- * shut things down gracefully... */
4780- run_actions(SHUTDOWN);
4781-
4782- message(L_CONSOLE | L_LOG, "The system is going down NOW!");
4783-
4784- /* Send signals to every process _except_ pid 1 */
4785- kill(-1, SIGTERM);
4786- message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM");
4787- sync();
4788- sleep(1);
4789-
4790- kill(-1, SIGKILL);
4791- message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
4792- sync();
4793- /*sleep(1); - callers take care about making a pause */
4794-}
4795-
4796-/* Signal handling by init:
4797- *
4798- * For process with PID==1, on entry kernel sets all signals to SIG_DFL
4799- * and unmasks all signals. However, for process with PID==1,
4800- * default action (SIG_DFL) on any signal is to ignore it,
4801- * even for special signals SIGKILL and SIGCONT.
4802- * Also, any signal can be caught or blocked.
4803- * (but SIGSTOP is still handled specially, at least in 2.6.20)
4804- *
4805- * We install two kinds of handlers, "immediate" and "delayed".
4806- *
4807- * Immediate handlers execute at any time, even while, say, sysinit
4808- * is running.
4809- *
4810- * Delayed handlers just set a flag variable. The variable is checked
4811- * in the main loop and acted upon.
4812- *
4813- * halt/poweroff/reboot and restart have immediate handlers.
4814- * They only traverse linked list of struct action's, never modify it,
4815- * this should be safe to do even in signal handler. Also they
4816- * never return.
4817- *
4818- * SIGSTOP and SIGTSTP have immediate handlers. They just wait
4819- * for SIGCONT to happen.
4820- *
4821- * SIGHUP has a delayed handler, because modifying linked list
4822- * of struct action's from a signal handler while it is manipulated
4823- * by the program may be disastrous.
4824- *
4825- * Ctrl-Alt-Del has a delayed handler. Not a must, but allowing
4826- * it to happen even somewhere inside "sysinit" would be a bit awkward.
4827- *
4828- * There is a tiny probability that SIGHUP and Ctrl-Alt-Del will collide
4829- * and only one will be remembered and acted upon.
4830- */
4831-
4832-/* The SIGUSR[12]/SIGTERM handler */
4833-static void halt_reboot_pwoff(int sig) NORETURN;
4834-static void halt_reboot_pwoff(int sig)
4835-{
4836- const char *m;
4837- unsigned rb;
4838-
4839- /* We may call run() and it unmasks signals,
4840- * including the one masked inside this signal handler.
4841- * Testcase which would start multiple reboot scripts:
4842- * while true; do reboot; done
4843- * Preventing it:
4844- */
4845- reset_sighandlers_and_unblock_sigs();
4846-
4847- run_shutdown_and_kill_processes();
4848-
4849- m = "halt";
4850- rb = RB_HALT_SYSTEM;
4851- if (sig == SIGTERM) {
4852- m = "reboot";
4853- rb = RB_AUTOBOOT;
4854- } else if (sig == SIGUSR2) {
4855- m = "poweroff";
4856- rb = RB_POWER_OFF;
4857- }
4858- message(L_CONSOLE, "Requesting system %s", m);
4859- pause_and_low_level_reboot(rb);
4860- /* not reached */
4861-}
4862-
4863-/* Handler for QUIT - exec "restart" action,
4864- * else (no such action defined) do nothing */
4865-static void restart_handler(int sig UNUSED_PARAM)
4866-{
4867- struct init_action *a;
4868-
4869- for (a = init_action_list; a; a = a->next) {
4870- if (!(a->action_type & RESTART))
4871- continue;
4872-
4873- /* Starting from here, we won't return.
4874- * Thus don't need to worry about preserving errno
4875- * and such.
4876- */
4877-
4878- reset_sighandlers_and_unblock_sigs();
4879-
4880- run_shutdown_and_kill_processes();
4881-
4882-#ifdef RB_ENABLE_CAD
4883- /* Allow Ctrl-Alt-Del to reboot the system.
4884- * This is how kernel sets it up for init, we follow suit.
4885- */
4886- reboot(RB_ENABLE_CAD); /* misnomer */
4887-#endif
4888-
4889- if (open_stdio_to_tty(a->terminal)) {
4890- dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);
4891- /* Theoretically should be safe.
4892- * But in practice, kernel bugs may leave
4893- * unkillable processes, and wait() may block forever.
4894- * Oh well. Hoping "new" init won't be too surprised
4895- * by having children it didn't create.
4896- */
4897- //while (wait(NULL) > 0)
4898- // continue;
4899- init_exec(a->command);
4900- }
4901- /* Open or exec failed */
4902- pause_and_low_level_reboot(RB_HALT_SYSTEM);
4903- /* not reached */
4904- }
4905-}
4906-
4907-/* The SIGSTOP/SIGTSTP handler
4908- * NB: inside it, all signals except SIGCONT are masked
4909- * via appropriate setup in sigaction().
4910- */
4911-static void stop_handler(int sig UNUSED_PARAM)
4912-{
4913- smallint saved_bb_got_signal;
4914- int saved_errno;
4915-
4916- saved_bb_got_signal = bb_got_signal;
4917- saved_errno = errno;
4918- signal(SIGCONT, record_signo);
4919-
4920- while (1) {
4921- pid_t wpid;
4922-
4923- if (bb_got_signal == SIGCONT)
4924- break;
4925- /* NB: this can accidentally wait() for a process
4926- * which we waitfor() elsewhere! waitfor() must have
4927- * code which is resilient against this.
4928- */
4929- wpid = wait_any_nohang(NULL);
4930- mark_terminated(wpid);
4931- sleep(1);
4932- }
4933-
4934- signal(SIGCONT, SIG_DFL);
4935- errno = saved_errno;
4936- bb_got_signal = saved_bb_got_signal;
4937-}
4938-
4939-#if ENABLE_FEATURE_USE_INITTAB
4940-static void reload_inittab(void)
4941-{
4942- struct init_action *a, **nextp;
4943-
4944- message(L_LOG, "reloading /etc/inittab");
4945-
4946- /* Disable old entries */
4947- for (a = init_action_list; a; a = a->next)
4948- a->action_type = 0;
4949-
4950- /* Append new entries, or modify existing entries
4951- * (incl. setting a->action_type) if cmd and device name
4952- * match new ones. End result: only entries with
4953- * a->action_type == 0 are stale.
4954- */
4955- parse_inittab();
4956-
4957-#if ENABLE_FEATURE_KILL_REMOVED
4958- /* Kill stale entries */
4959- /* Be nice and send SIGTERM first */
4960- for (a = init_action_list; a; a = a->next)
4961- if (a->action_type == 0 && a->pid != 0)
4962- kill(a->pid, SIGTERM);
4963- if (CONFIG_FEATURE_KILL_DELAY) {
4964- /* NB: parent will wait in NOMMU case */
4965- if ((BB_MMU ? fork() : vfork()) == 0) { /* child */
4966- sleep(CONFIG_FEATURE_KILL_DELAY);
4967- for (a = init_action_list; a; a = a->next)
4968- if (a->action_type == 0 && a->pid != 0)
4969- kill(a->pid, SIGKILL);
4970- _exit(EXIT_SUCCESS);
4971- }
4972- }
4973-#endif
4974-
4975- /* Remove stale entries and SYSINIT entries.
4976- * We never rerun SYSINIT entries anyway,
4977- * removing them too saves a few bytes */
4978- nextp = &init_action_list;
4979- while ((a = *nextp) != NULL) {
4980- if ((a->action_type & ~SYSINIT) == 0) {
4981- *nextp = a->next;
4982- free(a);
4983- } else {
4984- nextp = &a->next;
4985- }
4986- }
4987-
4988- /* Not needed: */
4989- /* run_actions(RESPAWN | ASKFIRST); */
4990- /* - we return to main loop, which does this automagically */
4991-}
4992-#endif
4993-
4994-static int check_delayed_sigs(void)
4995-{
4996- int sigs_seen = 0;
4997-
4998- while (1) {
4999- smallint sig = bb_got_signal;
5000-
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: