diff options
author | Erik Andersen <andersen@codepoet.org> | 2000-01-04 01:10:25 +0000 |
---|---|---|
committer | Erik Andersen <andersen@codepoet.org> | 2000-01-04 01:10:25 +0000 |
commit | 7dc160721ee3ceb76240a43d1454b45aaa9dbee4 (patch) | |
tree | 7532471be456e2c9f11eab88cb34f1e38abd184f | |
parent | 9c88cac5cbfb2ff70f800ee5bb3289e925aaa65f (diff) | |
download | busybox-w32-7dc160721ee3ceb76240a43d1454b45aaa9dbee4.tar.gz busybox-w32-7dc160721ee3ceb76240a43d1454b45aaa9dbee4.tar.bz2 busybox-w32-7dc160721ee3ceb76240a43d1454b45aaa9dbee4.zip |
Bunches of fixes. Typos, bugs, etc.
Added 'gunzip -t'. inittab support _almost_ works (but it isn't
ready for prime time useage yet).
-Erik
-rw-r--r-- | Changelog | 19 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | applets/busybox.c | 6 | ||||
-rw-r--r-- | archival/gunzip.c | 32 | ||||
-rw-r--r-- | archival/tar.c | 121 | ||||
-rw-r--r-- | busybox.c | 6 | ||||
-rw-r--r-- | busybox.def.h | 6 | ||||
-rw-r--r-- | busybox_functions.h | 11 | ||||
-rw-r--r-- | coreutils/cp.c | 2 | ||||
-rw-r--r-- | cp.c | 2 | ||||
-rw-r--r-- | editors/sed.c | 2 | ||||
-rw-r--r-- | gunzip.c | 32 | ||||
-rw-r--r-- | init.c | 483 | ||||
-rw-r--r-- | init/init.c | 483 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | kill.c | 3 | ||||
-rw-r--r-- | procps/kill.c | 3 | ||||
-rw-r--r-- | sed.c | 2 | ||||
-rw-r--r-- | tar.c | 121 | ||||
-rw-r--r-- | utility.c | 16 |
20 files changed, 779 insertions, 576 deletions
@@ -1,11 +1,11 @@ | |||
1 | 0.40 | 1 | 0.40 |
2 | * Added the -s option to du -beppu | 2 | * Added the -s option to du -beppu |
3 | * Fixed an embarrasing segfault in head -beppu | 3 | * Fixed an embarrasing segfault in head -beppu |
4 | * Fixed an bug in syslogd causing it to stop logging after 20 minutes. -erik | 4 | * Fixed an bug in syslogd causing it to stop after 20 minutes. -erik |
5 | * New Apps: lsmod, rmmod -erik | 5 | * New Apps: lsmod, rmmod -erik |
6 | * New Apps: fbset contributed by Randolph Chung <tausq@debian.org>. | 6 | * New Apps: fbset contributed by Randolph Chung <tausq@debian.org>. |
7 | * Fixed the embarrasing failure of the -p opition in the logger app. -erik | 7 | * Fixed the embarrasing failure of 'logger -p'. -erik |
8 | * Re-worked the whole source tree a bit so it will compile under glibc 2.0.7 | 8 | * Re-worked the source tree a bit so it will compile under glibc 2.0.7 |
9 | with the 2.0.x Linux kernel. | 9 | with the 2.0.x Linux kernel. |
10 | * Added 'grep -q' thanks to a patch from "Konstantin Boldyshev" | 10 | * Added 'grep -q' thanks to a patch from "Konstantin Boldyshev" |
11 | <konst@voshod.com>. | 11 | <konst@voshod.com>. |
@@ -13,15 +13,24 @@ | |||
13 | * Fixed a bug where tar would set, and then clear SGID and SUID bits. | 13 | * Fixed a bug where tar would set, and then clear SGID and SUID bits. |
14 | * Fixed a bug where tar would not set the user and group on device | 14 | * Fixed a bug where tar would not set the user and group on device |
15 | special files. | 15 | special files. |
16 | * cp and mv were quite broken when moving directories. I have rewritten | 16 | * cp and mv were very broken when moving directories. I have rewritten |
17 | them so they should now work as expected. | 17 | them so they should now work as expected. |
18 | * New app: loadacm contributed by Peter Novodvorsky <petya@logic.ru> | 18 | * New app: loadacm contributed by Peter Novodvorsky <petya@logic.ru> |
19 | for loading application character maps for working with Unicode fonts. | 19 | for loading application character maps for Unicode fonts. |
20 | * sed now supports addresses (numeric or regexp, with negation) and | 20 | * sed now supports addresses (numeric or regexp, with negation) and |
21 | has an append command, thanks to Marco Pantaleoni <panta@prosa.it> | 21 | has an append command, thanks to Marco Pantaleoni <panta@prosa.it> |
22 | * Fixed dmesg. It wasn't parsing its options (-n or -s) properly. | 22 | * Fixed dmesg. It wasn't parsing its options (-n or -s) properly. |
23 | * Some cosmetic fixes to ls output formatting to make it behave more | 23 | * Some cosmetic fixes to ls output formatting to make it behave more |
24 | like GNU ls. | 24 | like GNU ls. |
25 | * Fixed a bug where tar would not restore the time to files. | ||
26 | * Fixed a major security problem with tar -- it changed ownership | ||
27 | of any file pointed to by a symlink to 777 (like say libc....) | ||
28 | Ouch!!! | ||
29 | * Fixed a stupid segfault in kill. | ||
30 | * Several fixes from Friedrich Vedder <fwv@myrtle.lahn.de>: | ||
31 | - Added gunzip -t, removed gunzip.c dead code, | ||
32 | - fixed several typos | ||
33 | - Glibc 2.0.7 and libc5 compile fixes | ||
25 | 34 | ||
26 | 35 | ||
27 | -Erik Andersen | 36 | -Erik Andersen |
@@ -22,7 +22,7 @@ BUILDTIME=$(shell date "+%Y%m%d-%H%M") | |||
22 | 22 | ||
23 | # Comment out the following to make a debuggable build | 23 | # Comment out the following to make a debuggable build |
24 | # Leave this off for production use. | 24 | # Leave this off for production use. |
25 | DODEBUG=false | 25 | DODEBUG=true |
26 | # If you want a static binary, turn this on. I can't think | 26 | # If you want a static binary, turn this on. I can't think |
27 | # of many situations where anybody would ever want it static, | 27 | # of many situations where anybody would ever want it static, |
28 | # but... | 28 | # but... |
diff --git a/applets/busybox.c b/applets/busybox.c index 403b14008..a35306915 100644 --- a/applets/busybox.c +++ b/applets/busybox.c | |||
@@ -102,6 +102,9 @@ static const struct Applet applets[] = { | |||
102 | #ifdef BB_LN //bin | 102 | #ifdef BB_LN //bin |
103 | {"ln", ln_main}, | 103 | {"ln", ln_main}, |
104 | #endif | 104 | #endif |
105 | #ifdef BB_LOADACM //usr/bin | ||
106 | {"loadacm", loadacm_main}, | ||
107 | #endif | ||
105 | #ifdef BB_LOADFONT //usr/bin | 108 | #ifdef BB_LOADFONT //usr/bin |
106 | {"loadfont", loadfont_main}, | 109 | {"loadfont", loadfont_main}, |
107 | #endif | 110 | #endif |
@@ -232,9 +235,6 @@ static const struct Applet applets[] = { | |||
232 | #ifdef BB_GZIP //bin | 235 | #ifdef BB_GZIP //bin |
233 | {"gzip", gzip_main}, | 236 | {"gzip", gzip_main}, |
234 | #endif | 237 | #endif |
235 | #ifdef BB_LOADACM //usr/bin | ||
236 | {"loadacm", loadacm_main}, | ||
237 | #endif | ||
238 | {0} | 238 | {0} |
239 | }; | 239 | }; |
240 | 240 | ||
diff --git a/archival/gunzip.c b/archival/gunzip.c index 61391a33f..84f5d02b7 100644 --- a/archival/gunzip.c +++ b/archival/gunzip.c | |||
@@ -8,7 +8,8 @@ static const char gunzip_usage[] = | |||
8 | "gunzip [OPTION]... FILE\n\n" | 8 | "gunzip [OPTION]... FILE\n\n" |
9 | "Uncompress FILE (or standard input if FILE is '-').\n\n" | 9 | "Uncompress FILE (or standard input if FILE is '-').\n\n" |
10 | "Options:\n" | 10 | "Options:\n" |
11 | "\t-c\tWrite output to standard output\n"; | 11 | "\t-c\tWrite output to standard output\n" |
12 | "\t-t\tTest compressed file integrity\n"; | ||
12 | 13 | ||
13 | /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface | 14 | /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface |
14 | * Copyright (C) 1992-1993 Jean-loup Gailly | 15 | * Copyright (C) 1992-1993 Jean-loup Gailly |
@@ -653,7 +654,7 @@ DECLARE(uch, window, 2L*WSIZE); | |||
653 | 654 | ||
654 | /* local variables */ | 655 | /* local variables */ |
655 | 656 | ||
656 | int force = 0; /* don't ask questions, compress links (-f) */ | 657 | int test_mode = 0; /* check file integrity option */ |
657 | int foreground; /* set if program run in foreground */ | 658 | int foreground; /* set if program run in foreground */ |
658 | int maxbits = BITS; /* max bits per code for LZW */ | 659 | int maxbits = BITS; /* max bits per code for LZW */ |
659 | int method = DEFLATED;/* compression method */ | 660 | int method = DEFLATED;/* compression method */ |
@@ -714,6 +715,10 @@ int gunzip_main (int argc, char** argv) | |||
714 | case 'c': | 715 | case 'c': |
715 | to_stdout = 1; | 716 | to_stdout = 1; |
716 | break; | 717 | break; |
718 | case 't': | ||
719 | test_mode = 1; | ||
720 | break; | ||
721 | |||
717 | default: | 722 | default: |
718 | usage(gunzip_usage); | 723 | usage(gunzip_usage); |
719 | } | 724 | } |
@@ -786,6 +791,9 @@ int gunzip_main (int argc, char** argv) | |||
786 | /* Actually do the compression/decompression. */ | 791 | /* Actually do the compression/decompression. */ |
787 | unzip(inFileNum, outFileNum); | 792 | unzip(inFileNum, outFileNum); |
788 | 793 | ||
794 | } else if (test_mode) { | ||
795 | /* Actually do the compression/decompression. */ | ||
796 | unzip(inFileNum, 2); | ||
789 | } else { | 797 | } else { |
790 | char* pos; | 798 | char* pos; |
791 | 799 | ||
@@ -857,17 +865,8 @@ local int get_method(in) | |||
857 | uch flags; /* compression flags */ | 865 | uch flags; /* compression flags */ |
858 | char magic[2]; /* magic header */ | 866 | char magic[2]; /* magic header */ |
859 | 867 | ||
860 | /* If --force and --stdout, zcat == cat, so do not complain about | 868 | magic[0] = (char)get_byte(); |
861 | * premature end of file: use try_byte instead of get_byte. | 869 | magic[1] = (char)get_byte(); |
862 | */ | ||
863 | if (force) { | ||
864 | magic[0] = (char)try_byte(); | ||
865 | magic[1] = (char)try_byte(); | ||
866 | /* If try_byte returned EOF, magic[1] == 0xff */ | ||
867 | } else { | ||
868 | magic[0] = (char)get_byte(); | ||
869 | magic[1] = (char)get_byte(); | ||
870 | } | ||
871 | method = -1; /* unknown yet */ | 870 | method = -1; /* unknown yet */ |
872 | part_nb++; /* number of parts in gzip file */ | 871 | part_nb++; /* number of parts in gzip file */ |
873 | header_bytes = 0; | 872 | header_bytes = 0; |
@@ -1188,7 +1187,8 @@ void flush_outbuf() | |||
1188 | { | 1187 | { |
1189 | if (outcnt == 0) return; | 1188 | if (outcnt == 0) return; |
1190 | 1189 | ||
1191 | write_buf(ofd, (char *)outbuf, outcnt); | 1190 | if (!test_mode) |
1191 | write_buf(ofd, (char *)outbuf, outcnt); | ||
1192 | bytes_out += (ulg)outcnt; | 1192 | bytes_out += (ulg)outcnt; |
1193 | outcnt = 0; | 1193 | outcnt = 0; |
1194 | } | 1194 | } |
@@ -1202,8 +1202,8 @@ void flush_window() | |||
1202 | if (outcnt == 0) return; | 1202 | if (outcnt == 0) return; |
1203 | updcrc(window, outcnt); | 1203 | updcrc(window, outcnt); |
1204 | 1204 | ||
1205 | write_buf(ofd, (char *)window, outcnt); | 1205 | if (!test_mode) |
1206 | 1206 | write_buf(ofd, (char *)window, outcnt); | |
1207 | bytes_out += (ulg)outcnt; | 1207 | bytes_out += (ulg)outcnt; |
1208 | outcnt = 0; | 1208 | outcnt = 0; |
1209 | } | 1209 | } |
diff --git a/archival/tar.c b/archival/tar.c index 7167d95cd..a53370e85 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <fcntl.h> | 37 | #include <fcntl.h> |
38 | #include <signal.h> | 38 | #include <signal.h> |
39 | #include <time.h> | 39 | #include <time.h> |
40 | #include <utime.h> | ||
40 | #include <sys/types.h> | 41 | #include <sys/types.h> |
41 | #include <sys/sysmacros.h> | 42 | #include <sys/sysmacros.h> |
42 | 43 | ||
@@ -106,8 +107,12 @@ static int warnedRoot; | |||
106 | static int eofFlag; | 107 | static int eofFlag; |
107 | static long dataCc; | 108 | static long dataCc; |
108 | static int outFd; | 109 | static int outFd; |
109 | static char outName[TAR_NAME_SIZE]; | 110 | static const char *outName; |
110 | 111 | ||
112 | static int mode; | ||
113 | static int uid; | ||
114 | static int gid; | ||
115 | static time_t mtime; | ||
111 | 116 | ||
112 | /* | 117 | /* |
113 | * Static data associated with the tar file. | 118 | * Static data associated with the tar file. |
@@ -364,8 +369,9 @@ static void readTarFile (int fileCount, char **fileTable) | |||
364 | * message is required on errors. | 369 | * message is required on errors. |
365 | */ | 370 | */ |
366 | if (tostdoutFlag == FALSE) { | 371 | if (tostdoutFlag == FALSE) { |
367 | if (outFd >= 0) | 372 | if (outFd >= 0) { |
368 | (void) close (outFd); | 373 | close (outFd); |
374 | } | ||
369 | } | 375 | } |
370 | } | 376 | } |
371 | 377 | ||
@@ -378,29 +384,25 @@ static void readTarFile (int fileCount, char **fileTable) | |||
378 | static void | 384 | static void |
379 | readHeader (const TarHeader * hp, int fileCount, char **fileTable) | 385 | readHeader (const TarHeader * hp, int fileCount, char **fileTable) |
380 | { | 386 | { |
381 | int mode; | ||
382 | int uid; | ||
383 | int gid; | ||
384 | int checkSum; | 387 | int checkSum; |
385 | unsigned int major; | ||
386 | unsigned int minor; | ||
387 | long size; | ||
388 | time_t mtime; | ||
389 | const char *name; | ||
390 | int cc; | 388 | int cc; |
391 | int hardLink; | 389 | int hardLink; |
392 | int softLink; | 390 | int softLink; |
393 | int devFileFlag; | 391 | int devFileFlag; |
392 | unsigned int major; | ||
393 | unsigned int minor; | ||
394 | long size; | ||
395 | struct utimbuf utb; | ||
394 | 396 | ||
395 | /* | 397 | /* |
396 | * If the block is completely empty, then this is the end of the | 398 | * If the block is completely empty, then this is the end of the |
397 | * archive file. If the name is null, then just skip this header. | 399 | * archive file. If the name is null, then just skip this header. |
398 | */ | 400 | */ |
399 | name = hp->name; | 401 | outName = hp->name; |
400 | 402 | ||
401 | if (*name == '\0') { | 403 | if (*outName == '\0') { |
402 | for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { | 404 | for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { |
403 | if (*name++) | 405 | if (*outName++) |
404 | return; | 406 | return; |
405 | } | 407 | } |
406 | 408 | ||
@@ -447,16 +449,16 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
447 | /* | 449 | /* |
448 | * Check for a directory. | 450 | * Check for a directory. |
449 | */ | 451 | */ |
450 | if (name[strlen (name) - 1] == '/') | 452 | if (outName[strlen (outName) - 1] == '/') |
451 | mode |= S_IFDIR; | 453 | mode |= S_IFDIR; |
452 | 454 | ||
453 | /* | 455 | /* |
454 | * Check for absolute paths in the file. | 456 | * Check for absolute paths in the file. |
455 | * If we find any, then warn the user and make them relative. | 457 | * If we find any, then warn the user and make them relative. |
456 | */ | 458 | */ |
457 | if (*name == '/') { | 459 | if (*outName == '/') { |
458 | while (*name == '/') | 460 | while (*outName == '/') |
459 | name++; | 461 | outName++; |
460 | 462 | ||
461 | if (warnedRoot==FALSE) { | 463 | if (warnedRoot==FALSE) { |
462 | fprintf (stderr, | 464 | fprintf (stderr, |
@@ -470,7 +472,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
470 | * See if we want this file to be restored. | 472 | * See if we want this file to be restored. |
471 | * If not, then set up to skip it. | 473 | * If not, then set up to skip it. |
472 | */ | 474 | */ |
473 | if (wantFileName (name, fileCount, fileTable) == FALSE) { | 475 | if (wantFileName (outName, fileCount, fileTable) == FALSE) { |
474 | if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode) | 476 | if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode) |
475 | || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) { | 477 | || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) { |
476 | inHeader = (size == 0)? TRUE : FALSE; | 478 | inHeader = (size == 0)? TRUE : FALSE; |
@@ -494,7 +496,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
494 | else | 496 | else |
495 | printf ("%9ld %s ", size, timeString (mtime)); | 497 | printf ("%9ld %s ", size, timeString (mtime)); |
496 | } | 498 | } |
497 | printf ("%s", name); | 499 | printf ("%s", outName); |
498 | 500 | ||
499 | if (hardLink) | 501 | if (hardLink) |
500 | printf (" (link to \"%s\")", hp->linkName); | 502 | printf (" (link to \"%s\")", hp->linkName); |
@@ -515,22 +517,35 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
515 | * We really want to extract the file. | 517 | * We really want to extract the file. |
516 | */ | 518 | */ |
517 | if (verboseFlag==TRUE) | 519 | if (verboseFlag==TRUE) |
518 | printf ("x %s\n", name); | 520 | printf ("x %s\n", outName); |
519 | 521 | ||
520 | if (hardLink) { | 522 | if (hardLink) { |
521 | if (link (hp->linkName, name) < 0) | 523 | if (link (hp->linkName, outName) < 0) |
522 | perror (name); | 524 | perror (outName); |
523 | chown(name, uid, gid); | 525 | /* Set the file time */ |
524 | chmod(name, mode); | 526 | utb.actime = mtime; |
527 | utb.modtime = mtime; | ||
528 | utime (outName, &utb); | ||
529 | /* Set the file permissions */ | ||
530 | chown(outName, uid, gid); | ||
531 | chmod(outName, mode); | ||
525 | return; | 532 | return; |
526 | } | 533 | } |
527 | 534 | ||
528 | if (softLink) { | 535 | if (softLink) { |
529 | #ifdef S_ISLNK | 536 | #ifdef S_ISLNK |
530 | if (symlink (hp->linkName, name) < 0) | 537 | if (symlink (hp->linkName, outName) < 0) |
531 | perror (name); | 538 | perror (outName); |
532 | chown(name, uid, gid); | 539 | /* Try to change ownership of the symlink. |
533 | chmod(name, mode); | 540 | * If libs doesn't support that, don't bother. |
541 | * Changing the pointed-to file is the Wrong Thing(tm). | ||
542 | */ | ||
543 | #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) | ||
544 | lchown(outName, uid, gid); | ||
545 | #endif | ||
546 | |||
547 | /* Do not change permissions or date on symlink, | ||
548 | * since it changes the pointed to file instead. duh. */ | ||
534 | #else | 549 | #else |
535 | fprintf (stderr, "Cannot create symbolic links\n"); | 550 | fprintf (stderr, "Cannot create symbolic links\n"); |
536 | #endif | 551 | #endif |
@@ -545,10 +560,14 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
545 | * If the file is a directory, then just create the path. | 560 | * If the file is a directory, then just create the path. |
546 | */ | 561 | */ |
547 | if (S_ISDIR (mode)) { | 562 | if (S_ISDIR (mode)) { |
548 | createPath (name, mode); | 563 | createPath (outName, mode); |
549 | chown(name, uid, gid); | 564 | /* Set the file time */ |
550 | chmod(name, mode); | 565 | utb.actime = mtime; |
551 | 566 | utb.modtime = mtime; | |
567 | utime (outName, &utb); | ||
568 | /* Set the file permissions */ | ||
569 | chown(outName, uid, gid); | ||
570 | chmod(outName, mode); | ||
552 | return; | 571 | return; |
553 | } | 572 | } |
554 | 573 | ||
@@ -556,7 +575,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
556 | * There is a file to write. | 575 | * There is a file to write. |
557 | * First create the path to it if necessary with default permissions. | 576 | * First create the path to it if necessary with default permissions. |
558 | */ | 577 | */ |
559 | createPath (name, 0777); | 578 | createPath (outName, 0777); |
560 | 579 | ||
561 | inHeader = (size == 0)? TRUE : FALSE; | 580 | inHeader = (size == 0)? TRUE : FALSE; |
562 | dataCc = size; | 581 | dataCc = size; |
@@ -569,21 +588,26 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
569 | else { | 588 | else { |
570 | if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { | 589 | if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { |
571 | devFileFlag = TRUE; | 590 | devFileFlag = TRUE; |
572 | outFd = mknod (name, mode, makedev(major, minor) ); | 591 | outFd = mknod (outName, mode, makedev(major, minor) ); |
573 | } | 592 | } |
574 | else if (S_ISFIFO(mode) ) { | 593 | else if (S_ISFIFO(mode) ) { |
575 | devFileFlag = TRUE; | 594 | devFileFlag = TRUE; |
576 | outFd = mkfifo(name, mode); | 595 | outFd = mkfifo(outName, mode); |
577 | } else { | 596 | } else { |
578 | outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode); | 597 | outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode); |
579 | } | 598 | } |
580 | if (outFd < 0) { | 599 | if (outFd < 0) { |
581 | perror (name); | 600 | perror (outName); |
582 | skipFileFlag = TRUE; | 601 | skipFileFlag = TRUE; |
583 | return; | 602 | return; |
584 | } | 603 | } |
585 | chown(name, uid, gid); | 604 | /* Set the file time */ |
586 | chmod(name, mode); | 605 | utb.actime = mtime; |
606 | utb.modtime = mtime; | ||
607 | utime (outName, &utb); | ||
608 | /* Set the file permissions */ | ||
609 | chown(outName, uid, gid); | ||
610 | chmod(outName, mode); | ||
587 | } | 611 | } |
588 | 612 | ||
589 | 613 | ||
@@ -591,7 +615,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
591 | * If the file is empty, then that's all we need to do. | 615 | * If the file is empty, then that's all we need to do. |
592 | */ | 616 | */ |
593 | if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) { | 617 | if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) { |
594 | (void) close (outFd); | 618 | close (outFd); |
595 | outFd = -1; | 619 | outFd = -1; |
596 | } | 620 | } |
597 | } | 621 | } |
@@ -625,7 +649,7 @@ static void readData (const char *cp, int count) | |||
625 | if (fullWrite (outFd, cp, count) < 0) { | 649 | if (fullWrite (outFd, cp, count) < 0) { |
626 | perror (outName); | 650 | perror (outName); |
627 | if (tostdoutFlag == FALSE) { | 651 | if (tostdoutFlag == FALSE) { |
628 | (void) close (outFd); | 652 | close (outFd); |
629 | outFd = -1; | 653 | outFd = -1; |
630 | } | 654 | } |
631 | skipFileFlag = TRUE; | 655 | skipFileFlag = TRUE; |
@@ -633,13 +657,21 @@ static void readData (const char *cp, int count) | |||
633 | } | 657 | } |
634 | 658 | ||
635 | /* | 659 | /* |
636 | * If the write failed, close the file and disable further | 660 | * Check if we are done writing to the file now. |
637 | * writes to this file. | ||
638 | */ | 661 | */ |
639 | if (dataCc <= 0 && tostdoutFlag == FALSE) { | 662 | if (dataCc <= 0 && tostdoutFlag == FALSE) { |
663 | struct utimbuf utb; | ||
640 | if (close (outFd)) | 664 | if (close (outFd)) |
641 | perror (outName); | 665 | perror (outName); |
642 | 666 | ||
667 | /* Set the file time */ | ||
668 | utb.actime = mtime; | ||
669 | utb.modtime = mtime; | ||
670 | utime (outName, &utb); | ||
671 | /* Set the file permissions */ | ||
672 | chown(outName, uid, gid); | ||
673 | chmod(outName, mode); | ||
674 | |||
643 | outFd = -1; | 675 | outFd = -1; |
644 | } | 676 | } |
645 | } | 677 | } |
@@ -720,7 +752,6 @@ static void writeTarFile (int fileCount, char **fileTable) | |||
720 | static void saveFile (const char *fileName, int seeLinks) | 752 | static void saveFile (const char *fileName, int seeLinks) |
721 | { | 753 | { |
722 | int status; | 754 | int status; |
723 | int mode; | ||
724 | struct stat statbuf; | 755 | struct stat statbuf; |
725 | 756 | ||
726 | if (verboseFlag==TRUE) | 757 | if (verboseFlag==TRUE) |
@@ -102,6 +102,9 @@ static const struct Applet applets[] = { | |||
102 | #ifdef BB_LN //bin | 102 | #ifdef BB_LN //bin |
103 | {"ln", ln_main}, | 103 | {"ln", ln_main}, |
104 | #endif | 104 | #endif |
105 | #ifdef BB_LOADACM //usr/bin | ||
106 | {"loadacm", loadacm_main}, | ||
107 | #endif | ||
105 | #ifdef BB_LOADFONT //usr/bin | 108 | #ifdef BB_LOADFONT //usr/bin |
106 | {"loadfont", loadfont_main}, | 109 | {"loadfont", loadfont_main}, |
107 | #endif | 110 | #endif |
@@ -232,9 +235,6 @@ static const struct Applet applets[] = { | |||
232 | #ifdef BB_GZIP //bin | 235 | #ifdef BB_GZIP //bin |
233 | {"gzip", gzip_main}, | 236 | {"gzip", gzip_main}, |
234 | #endif | 237 | #endif |
235 | #ifdef BB_LOADACM //usr/bin | ||
236 | {"loadacm", loadacm_main}, | ||
237 | #endif | ||
238 | {0} | 238 | {0} |
239 | }; | 239 | }; |
240 | 240 | ||
diff --git a/busybox.def.h b/busybox.def.h index 3982a1c83..503410f1a 100644 --- a/busybox.def.h +++ b/busybox.def.h | |||
@@ -36,7 +36,7 @@ | |||
36 | //#define BB_LOADACM | 36 | //#define BB_LOADACM |
37 | //#define BB_LOADFONT | 37 | //#define BB_LOADFONT |
38 | //#define BB_LOADKMAP | 38 | //#define BB_LOADKMAP |
39 | #define BB_LOGGER | 39 | //#define BB_LOGGER |
40 | #define BB_LS | 40 | #define BB_LS |
41 | #define BB_LSMOD | 41 | #define BB_LSMOD |
42 | //#define BB_MAKEDEVS | 42 | //#define BB_MAKEDEVS |
@@ -68,7 +68,7 @@ | |||
68 | #define BB_SORT | 68 | #define BB_SORT |
69 | #define BB_SWAPONOFF | 69 | #define BB_SWAPONOFF |
70 | #define BB_SYNC | 70 | #define BB_SYNC |
71 | #define BB_SYSLOGD | 71 | //#define BB_SYSLOGD |
72 | #define BB_TAIL | 72 | #define BB_TAIL |
73 | #define BB_TAR | 73 | #define BB_TAR |
74 | #define BB_TEE | 74 | #define BB_TEE |
@@ -90,8 +90,6 @@ | |||
90 | // pretty/useful). | 90 | // pretty/useful). |
91 | // | 91 | // |
92 | // | 92 | // |
93 | // enable a second console on TTY2 in init | ||
94 | #define BB_FEATURE_INIT_SECOND_CONSOLE | ||
95 | // enable features that use the /proc filesystem | 93 | // enable features that use the /proc filesystem |
96 | #define BB_FEATURE_USE_PROCFS | 94 | #define BB_FEATURE_USE_PROCFS |
97 | //Enable init being called as /linuxrc | 95 | //Enable init being called as /linuxrc |
diff --git a/busybox_functions.h b/busybox_functions.h deleted file mode 100644 index 61fc48438..000000000 --- a/busybox_functions.h +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | #ifndef __BUSYBOX_FUNCTIONS_H__ | ||
2 | #define __BUSYBOX_FUNCTIONS_H__ | ||
3 | |||
4 | int | ||
5 | mkswap(char *device_name, int pages, int check); | ||
6 | /* pages = 0 for autodetection */ | ||
7 | |||
8 | int | ||
9 | fdflush(char *filename); | ||
10 | |||
11 | #endif /* __BUSYBOX_FUNCTIONS_H__ */ | ||
diff --git a/coreutils/cp.c b/coreutils/cp.c index 83460190a..4af73c274 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c | |||
@@ -33,7 +33,7 @@ static const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" | |||
33 | "\n" | 33 | "\n" |
34 | "\t-a\tsame as -dpR\n" | 34 | "\t-a\tsame as -dpR\n" |
35 | "\t-d\tpreserve links\n" | 35 | "\t-d\tpreserve links\n" |
36 | "\t-p\tpreserve file attributes if possable\n" | 36 | "\t-p\tpreserve file attributes if possible\n" |
37 | "\t-R\tcopy directories recursively\n"; | 37 | "\t-R\tcopy directories recursively\n"; |
38 | 38 | ||
39 | 39 | ||
@@ -33,7 +33,7 @@ static const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" | |||
33 | "\n" | 33 | "\n" |
34 | "\t-a\tsame as -dpR\n" | 34 | "\t-a\tsame as -dpR\n" |
35 | "\t-d\tpreserve links\n" | 35 | "\t-d\tpreserve links\n" |
36 | "\t-p\tpreserve file attributes if possable\n" | 36 | "\t-p\tpreserve file attributes if possible\n" |
37 | "\t-R\tcopy directories recursively\n"; | 37 | "\t-R\tcopy directories recursively\n"; |
38 | 38 | ||
39 | 39 | ||
diff --git a/editors/sed.c b/editors/sed.c index 8e5f695c4..25777243d 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -46,7 +46,7 @@ static const char sed_usage[] = | |||
46 | "\t /REGEXP/ Match specified regexp\n" | 46 | "\t /REGEXP/ Match specified regexp\n" |
47 | "\t (! inverts the meaning of the match)\n\n" | 47 | "\t (! inverts the meaning of the match)\n\n" |
48 | "\tand COMMAND can be:\n" | 48 | "\tand COMMAND can be:\n" |
49 | "\t s/regexp/replacement/[gp]\n" | 49 | "\t s/regexp/replacement/[igp]\n" |
50 | "\t which attempt to match regexp against the pattern space\n" | 50 | "\t which attempt to match regexp against the pattern space\n" |
51 | "\t and if successful replaces the matched portion with replacement.\n\n" | 51 | "\t and if successful replaces the matched portion with replacement.\n\n" |
52 | "\t aTEXT\n" | 52 | "\t aTEXT\n" |
@@ -8,7 +8,8 @@ static const char gunzip_usage[] = | |||
8 | "gunzip [OPTION]... FILE\n\n" | 8 | "gunzip [OPTION]... FILE\n\n" |
9 | "Uncompress FILE (or standard input if FILE is '-').\n\n" | 9 | "Uncompress FILE (or standard input if FILE is '-').\n\n" |
10 | "Options:\n" | 10 | "Options:\n" |
11 | "\t-c\tWrite output to standard output\n"; | 11 | "\t-c\tWrite output to standard output\n" |
12 | "\t-t\tTest compressed file integrity\n"; | ||
12 | 13 | ||
13 | /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface | 14 | /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface |
14 | * Copyright (C) 1992-1993 Jean-loup Gailly | 15 | * Copyright (C) 1992-1993 Jean-loup Gailly |
@@ -653,7 +654,7 @@ DECLARE(uch, window, 2L*WSIZE); | |||
653 | 654 | ||
654 | /* local variables */ | 655 | /* local variables */ |
655 | 656 | ||
656 | int force = 0; /* don't ask questions, compress links (-f) */ | 657 | int test_mode = 0; /* check file integrity option */ |
657 | int foreground; /* set if program run in foreground */ | 658 | int foreground; /* set if program run in foreground */ |
658 | int maxbits = BITS; /* max bits per code for LZW */ | 659 | int maxbits = BITS; /* max bits per code for LZW */ |
659 | int method = DEFLATED;/* compression method */ | 660 | int method = DEFLATED;/* compression method */ |
@@ -714,6 +715,10 @@ int gunzip_main (int argc, char** argv) | |||
714 | case 'c': | 715 | case 'c': |
715 | to_stdout = 1; | 716 | to_stdout = 1; |
716 | break; | 717 | break; |
718 | case 't': | ||
719 | test_mode = 1; | ||
720 | break; | ||
721 | |||
717 | default: | 722 | default: |
718 | usage(gunzip_usage); | 723 | usage(gunzip_usage); |
719 | } | 724 | } |
@@ -786,6 +791,9 @@ int gunzip_main (int argc, char** argv) | |||
786 | /* Actually do the compression/decompression. */ | 791 | /* Actually do the compression/decompression. */ |
787 | unzip(inFileNum, outFileNum); | 792 | unzip(inFileNum, outFileNum); |
788 | 793 | ||
794 | } else if (test_mode) { | ||
795 | /* Actually do the compression/decompression. */ | ||
796 | unzip(inFileNum, 2); | ||
789 | } else { | 797 | } else { |
790 | char* pos; | 798 | char* pos; |
791 | 799 | ||
@@ -857,17 +865,8 @@ local int get_method(in) | |||
857 | uch flags; /* compression flags */ | 865 | uch flags; /* compression flags */ |
858 | char magic[2]; /* magic header */ | 866 | char magic[2]; /* magic header */ |
859 | 867 | ||
860 | /* If --force and --stdout, zcat == cat, so do not complain about | 868 | magic[0] = (char)get_byte(); |
861 | * premature end of file: use try_byte instead of get_byte. | 869 | magic[1] = (char)get_byte(); |
862 | */ | ||
863 | if (force) { | ||
864 | magic[0] = (char)try_byte(); | ||
865 | magic[1] = (char)try_byte(); | ||
866 | /* If try_byte returned EOF, magic[1] == 0xff */ | ||
867 | } else { | ||
868 | magic[0] = (char)get_byte(); | ||
869 | magic[1] = (char)get_byte(); | ||
870 | } | ||
871 | method = -1; /* unknown yet */ | 870 | method = -1; /* unknown yet */ |
872 | part_nb++; /* number of parts in gzip file */ | 871 | part_nb++; /* number of parts in gzip file */ |
873 | header_bytes = 0; | 872 | header_bytes = 0; |
@@ -1188,7 +1187,8 @@ void flush_outbuf() | |||
1188 | { | 1187 | { |
1189 | if (outcnt == 0) return; | 1188 | if (outcnt == 0) return; |
1190 | 1189 | ||
1191 | write_buf(ofd, (char *)outbuf, outcnt); | 1190 | if (!test_mode) |
1191 | write_buf(ofd, (char *)outbuf, outcnt); | ||
1192 | bytes_out += (ulg)outcnt; | 1192 | bytes_out += (ulg)outcnt; |
1193 | outcnt = 0; | 1193 | outcnt = 0; |
1194 | } | 1194 | } |
@@ -1202,8 +1202,8 @@ void flush_window() | |||
1202 | if (outcnt == 0) return; | 1202 | if (outcnt == 0) return; |
1203 | updcrc(window, outcnt); | 1203 | updcrc(window, outcnt); |
1204 | 1204 | ||
1205 | write_buf(ofd, (char *)window, outcnt); | 1205 | if (!test_mode) |
1206 | 1206 | write_buf(ofd, (char *)window, outcnt); | |
1207 | bytes_out += (ulg)outcnt; | 1207 | bytes_out += (ulg)outcnt; |
1208 | outcnt = 0; | 1208 | outcnt = 0; |
1209 | } | 1209 | } |
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | #include <stdio.h> | 25 | #include <stdio.h> |
26 | #include <string.h> | ||
26 | #include <stdlib.h> | 27 | #include <stdlib.h> |
27 | #include <stdarg.h> | 28 | #include <stdarg.h> |
28 | #include <unistd.h> | 29 | #include <unistd.h> |
@@ -55,22 +56,57 @@ | |||
55 | #endif | 56 | #endif |
56 | 57 | ||
57 | 58 | ||
58 | #define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ | 59 | #define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ |
59 | #define VT_SECONDARY "/dev/tty2" /* Virtual console */ | 60 | #define VT_SECONDARY "/dev/tty2" /* Virtual console */ |
60 | #define VT_LOG "/dev/tty3" /* Virtual console */ | 61 | #define VT_LOG "/dev/tty3" /* Virtual console */ |
61 | #define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ | 62 | #define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ |
62 | #define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ | 63 | #define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ |
63 | #define GETTY "/sbin/getty" /* Default location of getty */ | 64 | #define SHELL "/bin/sh" /* Default shell */ |
64 | #define SHELL "/bin/sh" /* Default shell */ | 65 | #define REBOOT "/sbin/reboot" /* Default ctrl-alt-del command */ |
65 | #define INITTAB "/etc/inittab" /* inittab file location */ | 66 | #define INITTAB "/etc/inittab" /* inittab file location */ |
66 | #ifndef BB_INIT_SCRIPT | 67 | #define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ |
67 | #define BB_INIT_SCRIPT "/etc/init.d/rcS" /* Initscript. */ | ||
68 | #endif | ||
69 | |||
70 | #if 1 | ||
71 | 68 | ||
72 | #define LOG 0x1 | 69 | #define LOG 0x1 |
73 | #define CONSOLE 0x2 | 70 | #define CONSOLE 0x2 |
71 | |||
72 | /* Allowed init action types */ | ||
73 | typedef enum { | ||
74 | SYSINIT=1, | ||
75 | CTRLALTDEL, | ||
76 | RESPAWN, | ||
77 | ASKFIRST, | ||
78 | WAIT, | ||
79 | ONCE | ||
80 | } initActionEnum; | ||
81 | |||
82 | /* And now a list of the actions we support in the version of init */ | ||
83 | typedef struct initActionType{ | ||
84 | const char* name; | ||
85 | initActionEnum action; | ||
86 | } initActionType; | ||
87 | |||
88 | static const struct initActionType actions[] = { | ||
89 | {"sysinit", SYSINIT}, | ||
90 | {"ctrlaltdel", CTRLALTDEL}, | ||
91 | {"respawn", RESPAWN}, | ||
92 | {"askfirst", ASKFIRST}, | ||
93 | {"wait", WAIT}, | ||
94 | {"once", ONCE}, | ||
95 | {0} | ||
96 | }; | ||
97 | |||
98 | /* Set up a linked list of initactions, to be read from inittab */ | ||
99 | typedef struct initActionTag initAction; | ||
100 | struct initActionTag { | ||
101 | pid_t pid; | ||
102 | char process[256]; | ||
103 | char *console; | ||
104 | initAction *nextPtr; | ||
105 | initActionEnum action; | ||
106 | }; | ||
107 | initAction* initActionList = NULL; | ||
108 | |||
109 | |||
74 | static char *console = _PATH_CONSOLE; | 110 | static char *console = _PATH_CONSOLE; |
75 | static char *second_console = VT_SECONDARY; | 111 | static char *second_console = VT_SECONDARY; |
76 | static char *log = VT_LOG; | 112 | static char *log = VT_LOG; |
@@ -100,8 +136,9 @@ int device_open(char *device, int mode) | |||
100 | * device may be bitwise-or'd from LOG | CONSOLE */ | 136 | * device may be bitwise-or'd from LOG | CONSOLE */ |
101 | void message(int device, char *fmt, ...) | 137 | void message(int device, char *fmt, ...) |
102 | { | 138 | { |
103 | int fd; | ||
104 | va_list arguments; | 139 | va_list arguments; |
140 | int fd; | ||
141 | |||
105 | #ifdef BB_SYSLOGD | 142 | #ifdef BB_SYSLOGD |
106 | 143 | ||
107 | /* Log the message to syslogd */ | 144 | /* Log the message to syslogd */ |
@@ -298,16 +335,18 @@ static int waitfor(int pid) | |||
298 | } | 335 | } |
299 | 336 | ||
300 | 337 | ||
301 | static pid_t run(const char * const* command, | 338 | static pid_t run(char* command, |
302 | char *terminal, int get_enter) | 339 | char *terminal, int get_enter) |
303 | { | 340 | { |
304 | int fd; | 341 | int i; |
305 | pid_t pid; | 342 | pid_t pid; |
306 | const char * const* cmd = command+1; | 343 | char* tmpCmd; |
344 | char* cmd[255]; | ||
307 | static const char press_enter[] = | 345 | static const char press_enter[] = |
308 | "\nPlease press Enter to activate this console. "; | 346 | "\nPlease press Enter to activate this console. "; |
309 | 347 | ||
310 | if ((pid = fork()) == 0) { | 348 | if ((pid = fork()) == 0) { |
349 | int fd; | ||
311 | /* Clean up */ | 350 | /* Clean up */ |
312 | close(0); | 351 | close(0); |
313 | close(1); | 352 | close(1); |
@@ -321,7 +360,7 @@ static pid_t run(const char * const* command, | |||
321 | signal(SIGTERM, SIG_DFL); | 360 | signal(SIGTERM, SIG_DFL); |
322 | 361 | ||
323 | if ((fd = device_open(terminal, O_RDWR)) < 0) { | 362 | if ((fd = device_open(terminal, O_RDWR)) < 0) { |
324 | message(LOG, "Bummer, can't open %s\r\n", terminal); | 363 | message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); |
325 | exit(-1); | 364 | exit(-1); |
326 | } | 365 | } |
327 | dup(fd); | 366 | dup(fd); |
@@ -340,21 +379,32 @@ static pid_t run(const char * const* command, | |||
340 | */ | 379 | */ |
341 | char c; | 380 | char c; |
342 | message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", | 381 | message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", |
343 | *cmd, getpid(), terminal ); | 382 | command, getpid(), terminal ); |
344 | write(1, press_enter, sizeof(press_enter) - 1); | 383 | write(fileno(stdout), press_enter, sizeof(press_enter) - 1); |
345 | read(0, &c, 1); | 384 | read(fileno(stdin), &c, 1); |
346 | } | 385 | } |
347 | 386 | ||
387 | /* Convert command (char*) into cmd (char**, one word per string) */ | ||
388 | for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) { | ||
389 | if (*tmpCmd != '\0') { | ||
390 | cmd[i] = tmpCmd; | ||
391 | tmpCmd++; | ||
392 | i++; | ||
393 | } | ||
394 | } | ||
395 | cmd[i] = NULL; | ||
396 | |||
348 | /* Log the process name and args */ | 397 | /* Log the process name and args */ |
349 | message(LOG|CONSOLE, "Starting pid %d, console %s: '", getpid(), terminal); | 398 | message(LOG, "Starting pid %d, console %s: '%s'\r\n", |
350 | while ( *cmd) message(LOG|CONSOLE, "%s ", *cmd++); | 399 | getpid(), terminal, cmd[0]); |
351 | message(LOG|CONSOLE, "'\r\n"); | 400 | |
352 | |||
353 | /* Now run it. The new program will take over this PID, | 401 | /* Now run it. The new program will take over this PID, |
354 | * so nothing further in init.c should be run. */ | 402 | * so nothing further in init.c should be run. */ |
355 | execvp(*command, (char**)command+1); | 403 | execvp(cmd[0], cmd); |
356 | 404 | ||
357 | message(LOG, "Bummer, could not run '%s'\n", command); | 405 | /* We're still here? Some error happened. */ |
406 | message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0], | ||
407 | strerror(errno)); | ||
358 | exit(-1); | 408 | exit(-1); |
359 | } | 409 | } |
360 | return pid; | 410 | return pid; |
@@ -365,15 +415,13 @@ static pid_t run(const char * const* command, | |||
365 | static void check_memory() | 415 | static void check_memory() |
366 | { | 416 | { |
367 | struct stat statbuf; | 417 | struct stat statbuf; |
368 | const char* const swap_on_cmd[] = | ||
369 | { "/bin/swapon", "swapon", "-a", 0}; | ||
370 | 418 | ||
371 | if (mem_total() > 3500) | 419 | if (mem_total() > 3500) |
372 | return; | 420 | return; |
373 | 421 | ||
374 | if (stat("/etc/fstab", &statbuf) == 0) { | 422 | if (stat("/etc/fstab", &statbuf) == 0) { |
375 | /* Try to turn on swap */ | 423 | /* Try to turn on swap */ |
376 | waitfor(run(swap_on_cmd, log, FALSE)); | 424 | waitfor(run("/bin/swapon swapon -a", log, FALSE)); |
377 | if (mem_total() < 3500) | 425 | if (mem_total() < 3500) |
378 | goto goodnight; | 426 | goto goodnight; |
379 | } else | 427 | } else |
@@ -385,33 +433,28 @@ goodnight: | |||
385 | while (1) sleep(1); | 433 | while (1) sleep(1); |
386 | } | 434 | } |
387 | 435 | ||
436 | #ifndef DEBUG_INIT | ||
388 | static void shutdown_system(void) | 437 | static void shutdown_system(void) |
389 | { | 438 | { |
390 | const char* const swap_off_cmd[] = { "swapoff", "swapoff", "-a", 0}; | ||
391 | const char* const umount_cmd[] = { "umount", "umount", "-a", 0}; | ||
392 | |||
393 | #ifndef DEBUG_INIT | ||
394 | /* Allow Ctrl-Alt-Del to reboot system. */ | 439 | /* Allow Ctrl-Alt-Del to reboot system. */ |
395 | reboot(RB_ENABLE_CAD); | 440 | reboot(RB_ENABLE_CAD); |
396 | #endif | ||
397 | message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); | 441 | message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); |
398 | sync(); | 442 | sync(); |
443 | |||
399 | /* Send signals to every process _except_ pid 1 */ | 444 | /* Send signals to every process _except_ pid 1 */ |
400 | message(CONSOLE, "Sending SIGHUP to all processes.\r\n"); | 445 | message(CONSOLE, "Sending SIGHUP to all processes.\r\n"); |
401 | #ifndef DEBUG_INIT | ||
402 | kill(-1, SIGHUP); | 446 | kill(-1, SIGHUP); |
403 | #endif | ||
404 | sleep(2); | 447 | sleep(2); |
405 | sync(); | 448 | sync(); |
449 | |||
406 | message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); | 450 | message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); |
407 | #ifndef DEBUG_INIT | ||
408 | kill(-1, SIGKILL); | 451 | kill(-1, SIGKILL); |
409 | #endif | ||
410 | sleep(1); | 452 | sleep(1); |
453 | |||
411 | message(CONSOLE, "Disabling swap.\r\n"); | 454 | message(CONSOLE, "Disabling swap.\r\n"); |
412 | waitfor(run( swap_off_cmd, console, FALSE)); | 455 | waitfor(run( "swapoff -a", console, FALSE)); |
413 | message(CONSOLE, "Unmounting filesystems.\r\n"); | 456 | message(CONSOLE, "Unmounting filesystems.\r\n"); |
414 | waitfor(run( umount_cmd, console, FALSE)); | 457 | waitfor(run( "umount -a", console, FALSE)); |
415 | sync(); | 458 | sync(); |
416 | if (kernel_version > 0 && kernel_version <= 2 * 65536 + 2 * 256 + 11) { | 459 | if (kernel_version > 0 && kernel_version <= 2 * 65536 + 2 * 256 + 11) { |
417 | /* bdflush, kupdate not needed for kernels >2.2.11 */ | 460 | /* bdflush, kupdate not needed for kernels >2.2.11 */ |
@@ -427,14 +470,12 @@ static void halt_signal(int sig) | |||
427 | message(CONSOLE, | 470 | message(CONSOLE, |
428 | "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); | 471 | "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); |
429 | sync(); | 472 | sync(); |
430 | #ifndef DEBUG_INIT | ||
431 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) | 473 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) |
432 | if (sig == SIGUSR2) | 474 | if (sig == SIGUSR2) |
433 | reboot(RB_POWER_OFF); | 475 | reboot(RB_POWER_OFF); |
434 | else | 476 | else |
435 | #endif | 477 | #endif |
436 | reboot(RB_HALT_SYSTEM); | 478 | reboot(RB_HALT_SYSTEM); |
437 | #endif | ||
438 | exit(0); | 479 | exit(0); |
439 | } | 480 | } |
440 | 481 | ||
@@ -443,64 +484,157 @@ static void reboot_signal(int sig) | |||
443 | shutdown_system(); | 484 | shutdown_system(); |
444 | message(CONSOLE, "Please stand by while rebooting the system.\r\n"); | 485 | message(CONSOLE, "Please stand by while rebooting the system.\r\n"); |
445 | sync(); | 486 | sync(); |
446 | #ifndef DEBUG_INIT | ||
447 | reboot(RB_AUTOBOOT); | 487 | reboot(RB_AUTOBOOT); |
448 | #endif | ||
449 | exit(0); | 488 | exit(0); |
450 | } | 489 | } |
451 | 490 | ||
491 | static void ctrl_alt_del_signal(int sig) | ||
492 | { | ||
493 | initAction* a; | ||
494 | /* Run whatever we are supposed to run */ | ||
495 | for( a=initActionList ; a; a=a->nextPtr) { | ||
496 | if (a->action == CTRLALTDEL) { | ||
497 | waitfor(run(a->process, console, FALSE)); | ||
498 | } | ||
499 | } | ||
500 | } | ||
501 | #endif | ||
502 | |||
503 | void new_initAction (const struct initActionType *a, | ||
504 | char* process, char* console) | ||
505 | { | ||
506 | initAction* newAction; | ||
507 | newAction = calloc ((size_t)(1), sizeof(initAction)); | ||
508 | if (!newAction) { | ||
509 | fprintf(stderr, "Memory allocation failure\n"); | ||
510 | while (1) sleep(1); | ||
511 | } | ||
512 | newAction->nextPtr = initActionList; | ||
513 | initActionList = newAction; | ||
514 | strncpy( newAction->process, process, 255); | ||
515 | newAction->action = a->action; | ||
516 | newAction->console = console; | ||
517 | newAction->pid = 0; | ||
518 | } | ||
519 | |||
520 | void delete_initAction (initAction *action) | ||
521 | { | ||
522 | initAction *a, *b=NULL; | ||
523 | for( a=initActionList ; a; b=a, a=a->nextPtr) { | ||
524 | if (a == action && b != NULL) { | ||
525 | b->nextPtr=a->nextPtr; | ||
526 | free( a); | ||
527 | break; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | |||
532 | void parse_inittab(void) | ||
533 | { | ||
534 | FILE* file; | ||
535 | char buf[256]; | ||
536 | char *p, *q, *r; | ||
537 | const struct initActionType *a = actions; | ||
538 | int foundIt; | ||
539 | |||
540 | |||
541 | file = fopen(INITTAB, "r"); | ||
542 | if (file == NULL) { | ||
543 | /* No inittab file -- set up some default behavior */ | ||
544 | |||
545 | /* Askfirst shell on tty1 */ | ||
546 | new_initAction( &(actions[3]), SHELL, console ); | ||
547 | /* Askfirst shell on tty2 */ | ||
548 | if (second_console != NULL) | ||
549 | new_initAction( &(actions[3]), SHELL, second_console ); | ||
550 | /* Control-alt-del */ | ||
551 | new_initAction( &(actions[1]), REBOOT, console ); | ||
552 | /* sysinit */ | ||
553 | new_initAction( &(actions[0]), INIT_SCRIPT, console ); | ||
554 | |||
555 | return; | ||
556 | } | ||
557 | |||
558 | while ( fgets(buf, 255, file) != NULL) { | ||
559 | foundIt=FALSE; | ||
560 | for(p = buf; *p == ' ' || *p == '\t'; p++); | ||
561 | if (*p == '#' || *p == '\n') continue; | ||
562 | |||
563 | /* Trim the trailing \n */ | ||
564 | q = strrchr( p, '\n'); | ||
565 | if (q != NULL) | ||
566 | *q='\0'; | ||
567 | |||
568 | /* Skip past the ID field and the runlevel | ||
569 | * field (both are ignored) */ | ||
570 | p = strchr( p, ':'); | ||
571 | |||
572 | /* Now peal off the process field from the end | ||
573 | * of the string */ | ||
574 | q = strrchr( p, ':'); | ||
575 | if ( q == NULL || *(q+1) == '\0' ) { | ||
576 | fprintf(stderr, "Bad inittab entry: %s\n", buf); | ||
577 | continue; | ||
578 | } else { | ||
579 | *q='\0'; | ||
580 | ++q; | ||
581 | } | ||
582 | |||
583 | /* Now peal off the action field */ | ||
584 | r = strrchr( p, ':'); | ||
585 | if ( r == NULL || *(r+1) == '\0') { | ||
586 | fprintf(stderr, "Bad inittab entry: %s\n", buf); | ||
587 | continue; | ||
588 | } else { | ||
589 | ++r; | ||
590 | } | ||
591 | |||
592 | /* Ok, now process it */ | ||
593 | a = actions; | ||
594 | while (a->name != 0) { | ||
595 | if (strcmp(a->name, r) == 0) { | ||
596 | new_initAction( a, q, NULL); | ||
597 | foundIt=TRUE; | ||
598 | } | ||
599 | a++; | ||
600 | } | ||
601 | if (foundIt==TRUE) | ||
602 | continue; | ||
603 | else { | ||
604 | /* Choke on an unknown action */ | ||
605 | fprintf(stderr, "Bad inittab entry: %s\n", buf); | ||
606 | } | ||
607 | } | ||
608 | return; | ||
609 | } | ||
610 | |||
611 | |||
452 | extern int init_main(int argc, char **argv) | 612 | extern int init_main(int argc, char **argv) |
453 | { | 613 | { |
454 | int run_rc = FALSE; | 614 | initAction *a; |
615 | pid_t wpid; | ||
616 | int status; | ||
455 | int single = FALSE; | 617 | int single = FALSE; |
456 | int wait_for_enter_tty1 = TRUE; | ||
457 | int wait_for_enter_tty2 = TRUE; | ||
458 | pid_t pid1 = 0; | ||
459 | pid_t pid2 = 0; | ||
460 | struct stat statbuf; | ||
461 | char which_vt1[30]; | ||
462 | char which_vt2[30]; | ||
463 | const char* const rc_script_command[] = { BB_INIT_SCRIPT, BB_INIT_SCRIPT, 0}; | ||
464 | const char* const getty1_command[] = { GETTY, GETTY, "38400", which_vt1, 0}; | ||
465 | const char* const getty2_command[] = { GETTY, GETTY, "38400", which_vt2, 0}; | ||
466 | const char* const shell_command[] = { SHELL, "-" SHELL, 0}; | ||
467 | const char* const* tty1_command = shell_command; | ||
468 | const char* const* tty2_command = shell_command; | ||
469 | #ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS | ||
470 | const char* const rc_exit_command[] = { "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", | ||
471 | "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", 0 }; | ||
472 | #endif | ||
473 | 618 | ||
474 | #ifdef DEBUG_INIT | ||
475 | char *hello_msg_format = | ||
476 | "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n"; | ||
477 | #else | ||
478 | char *hello_msg_format = | ||
479 | "init started: BusyBox v%s (%s) multi-call binary\r\n"; | ||
480 | #endif | ||
481 | 619 | ||
482 | |||
483 | #ifndef DEBUG_INIT | 620 | #ifndef DEBUG_INIT |
484 | /* Expect to be PID 1 iff we are run as init (not linuxrc) */ | 621 | /* Expect to be PID 1 iff we are run as init (not linuxrc) */ |
485 | if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { | 622 | if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { |
486 | usage( "init\n\nInit is the parent of all processes.\n\n" | 623 | usage( "init\n\nInit is the parent of all processes.\n\n" |
487 | "This version of init is designed to be run only by the kernel\n"); | 624 | "This version of init is designed to be run only by the kernel\n"); |
488 | } | 625 | } |
489 | #endif | ||
490 | 626 | ||
491 | /* Set up sig handlers -- be sure to | 627 | /* Set up sig handlers -- be sure to clear all of these in run() */ |
492 | * clear all of these in run() */ | ||
493 | signal(SIGUSR1, halt_signal); | 628 | signal(SIGUSR1, halt_signal); |
494 | signal(SIGUSR2, reboot_signal); | 629 | signal(SIGUSR2, reboot_signal); |
495 | signal(SIGINT, reboot_signal); | 630 | signal(SIGINT, ctrl_alt_del_signal); |
496 | signal(SIGTERM, reboot_signal); | 631 | signal(SIGTERM, reboot_signal); |
497 | 632 | ||
498 | /* Turn off rebooting via CTL-ALT-DEL -- we get a | 633 | /* Turn off rebooting via CTL-ALT-DEL -- we get a |
499 | * SIGINT on CAD so we can shut things down gracefully... */ | 634 | * SIGINT on CAD so we can shut things down gracefully... */ |
500 | #ifndef DEBUG_INIT | ||
501 | reboot(RB_DISABLE_CAD); | 635 | reboot(RB_DISABLE_CAD); |
502 | #endif | 636 | #endif |
503 | 637 | ||
504 | /* Figure out where the default console should be */ | 638 | /* Figure out where the default console should be */ |
505 | console_init(); | 639 | console_init(); |
506 | 640 | ||
@@ -517,9 +651,13 @@ extern int init_main(int argc, char **argv) | |||
517 | 651 | ||
518 | /* Hello world */ | 652 | /* Hello world */ |
519 | #ifndef DEBUG_INIT | 653 | #ifndef DEBUG_INIT |
520 | message(CONSOLE|LOG, hello_msg_format, BB_VER, BB_BT); | 654 | message(CONSOLE|LOG, |
655 | "init started: BusyBox v%s (%s) multi-call binary\r\n", | ||
656 | BB_VER, BB_BT); | ||
521 | #else | 657 | #else |
522 | message(CONSOLE|LOG, hello_msg_format, getpid(), BB_VER, BB_BT); | 658 | message(CONSOLE|LOG, |
659 | "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n", | ||
660 | getpid(), BB_VER, BB_BT); | ||
523 | #endif | 661 | #endif |
524 | 662 | ||
525 | 663 | ||
@@ -537,150 +675,77 @@ extern int init_main(int argc, char **argv) | |||
537 | if ( argc > 1 && (!strcmp(argv[1], "single") || | 675 | if ( argc > 1 && (!strcmp(argv[1], "single") || |
538 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { | 676 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { |
539 | single = TRUE; | 677 | single = TRUE; |
540 | tty1_command = shell_command; | 678 | /* Ask first then start a shell on tty2 */ |
541 | tty2_command = shell_command; | 679 | if (second_console != NULL) |
680 | new_initAction( &(actions[3]), SHELL, second_console); | ||
681 | /* Ask first then start a shell on tty1 */ | ||
682 | new_initAction( &(actions[3]), SHELL, console); | ||
683 | } else { | ||
684 | /* Not in single user mode -- see what inittab says */ | ||
685 | parse_inittab(); | ||
542 | } | 686 | } |
543 | 687 | ||
544 | /* Make sure an init script exists before trying to run it */ | 688 | /* Now run everything that needs to be run */ |
545 | if (single==FALSE && stat(BB_INIT_SCRIPT, &statbuf)==0) { | 689 | |
546 | run_rc = TRUE; | 690 | /* First run sysinit */ |
547 | wait_for_enter_tty1 = FALSE; | 691 | for( a=initActionList ; a; a=a->nextPtr) { |
548 | tty1_command = rc_script_command; | 692 | if (a->action == SYSINIT) { |
693 | waitfor(run(a->process, console, FALSE)); | ||
694 | /* Now remove the "sysinit" entry from the list */ | ||
695 | delete_initAction( a); | ||
696 | } | ||
549 | } | 697 | } |
550 | 698 | /* Next run anything that wants to block */ | |
551 | /* Make sure /sbin/getty exists before trying to run it */ | 699 | for( a=initActionList ; a; a=a->nextPtr) { |
552 | if (stat(GETTY, &statbuf)==0) { | 700 | if (a->action == WAIT) { |
553 | char* where; | 701 | waitfor(run(a->process, console, FALSE)); |
554 | /* First do tty2 */ | 702 | /* Now remove the "wait" entry from the list */ |
555 | wait_for_enter_tty2 = FALSE; | 703 | delete_initAction( a); |
556 | where = strrchr( second_console, '/'); | ||
557 | if ( where != NULL) { | ||
558 | where++; | ||
559 | strncpy( which_vt2, where, sizeof(which_vt2)); | ||
560 | } | 704 | } |
561 | tty2_command = getty2_command; | 705 | } |
562 | 706 | /* Next run anything to be run only once */ | |
563 | /* Check on hooking a getty onto tty1 */ | 707 | for( a=initActionList ; a; a=a->nextPtr) { |
564 | if (run_rc == FALSE && single==FALSE) { | 708 | if (a->action == ONCE) { |
565 | wait_for_enter_tty1 = FALSE; | 709 | run(a->process, console, FALSE); |
566 | where = strrchr( console, '/'); | 710 | /* Now remove the "once" entry from the list */ |
567 | if ( where != NULL) { | 711 | delete_initAction( a); |
568 | where++; | ||
569 | strncpy( which_vt1, where, sizeof(which_vt1)); | ||
570 | } | ||
571 | tty1_command = getty1_command; | ||
572 | } | 712 | } |
573 | } | 713 | } |
574 | |||
575 | 714 | ||
576 | /* Ok, now launch the tty1_command and tty2_command */ | 715 | /* Now run the looping stuff */ |
577 | for (;;) { | 716 | for (;;) { |
578 | pid_t wpid; | 717 | for( a=initActionList ; a; a=a->nextPtr) { |
579 | int status; | 718 | /* Only run stuff with pid==0. If they have |
580 | 719 | * a pid, that means they are still running */ | |
581 | if (pid1 == 0 && tty1_command) { | 720 | if (a->pid == 0) { |
582 | pid1 = run(tty1_command, console, wait_for_enter_tty1); | 721 | switch(a->action) { |
583 | } | 722 | case RESPAWN: |
584 | #ifdef BB_FEATURE_INIT_SECOND_CONSOLE | 723 | /* run the respawn stuff */ |
585 | if (pid2 == 0 && tty2_command && second_console) { | 724 | a->pid = run(a->process, console, FALSE); |
586 | pid2 = run(tty2_command, second_console, wait_for_enter_tty2); | 725 | break; |
726 | case ASKFIRST: | ||
727 | /* run the askfirst stuff */ | ||
728 | a->pid = waitfor(run(a->process, console, TRUE)); | ||
729 | break; | ||
730 | /* silence the compiler's whining */ | ||
731 | default: | ||
732 | break; | ||
733 | } | ||
734 | } | ||
587 | } | 735 | } |
588 | #endif | 736 | |
589 | wpid = wait(&status); | 737 | wpid = wait(&status); |
738 | /* Find out who died and clean up their corpse */ | ||
590 | if (wpid > 0 ) { | 739 | if (wpid > 0 ) { |
591 | message(LOG, "pid %d exited, status=%x.\n", wpid, status); | 740 | message(LOG, "pid %d exited, status=%x.\n", wpid, status); |
592 | } | 741 | for( a=initActionList ; a; a=a->nextPtr) { |
593 | /* Don't respawn init script if it exits */ | 742 | if (a->pid==wpid) { |
594 | if (wpid == pid1) { | 743 | a->pid=0; |
595 | if (run_rc == FALSE) { | 744 | } |
596 | pid1 = 0; | ||
597 | } | 745 | } |
598 | #ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS | ||
599 | else { | ||
600 | pid1 = 0; | ||
601 | run_rc=FALSE; | ||
602 | wait_for_enter_tty1=TRUE; | ||
603 | tty1_command=rc_exit_command; | ||
604 | } | ||
605 | #endif | ||
606 | } | 746 | } |
607 | #ifdef BB_FEATURE_INIT_SECOND_CONSOLE | ||
608 | if (wpid == pid2) { | ||
609 | pid2 = 0; | ||
610 | } | ||
611 | #endif | ||
612 | sleep(1); | ||
613 | } | ||
614 | } | ||
615 | |||
616 | #else | ||
617 | |||
618 | |||
619 | void parse_inittab(void) | ||
620 | { | ||
621 | FILE* file; | ||
622 | char buf[256]; | ||
623 | char action[256]=""; | ||
624 | char process[256]=""; | ||
625 | char *p, *q; | ||
626 | |||
627 | |||
628 | if ((file = fopen(INITTAB, "r")) < 0) { | ||
629 | /* No inittab file -- set up some default behavior */ | ||
630 | |||
631 | /* FIXME */ | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | while ( fgets(buf, 255, file) != NULL) { | ||
636 | for(p = buf; *p == ' ' || *p == '\t'; p++); | ||
637 | if (*p == '#' || *p == '\n') continue; | ||
638 | |||
639 | /* Trim the trailing \n */ | ||
640 | q = strrchr( p, '\n'); | ||
641 | if (q != NULL) | ||
642 | *q='\0'; | ||
643 | |||
644 | /* Skip past the ID field and the runlevel | ||
645 | * field (both are ignored) */ | ||
646 | p = strchr( p, ':'); | ||
647 | |||
648 | /* Now peal off the process field from the end | ||
649 | * of the string */ | ||
650 | q = strrchr( p, ':'); | ||
651 | if ( q == NULL || q+1 == NULL) | ||
652 | goto choke; | ||
653 | *q='\0'; | ||
654 | strcpy( process, ++q); | ||
655 | fprintf(stderr, "process=%s\n", process); | ||
656 | |||
657 | |||
658 | /* Now peal off the action field */ | ||
659 | q = strrchr( p, ':'); | ||
660 | if ( q == NULL || q+1 == NULL) | ||
661 | goto choke; | ||
662 | strcpy( action, ++q); | ||
663 | fprintf(stderr, "action=%s\n", action); | ||
664 | |||
665 | |||
666 | /* Ok, now do the right thing */ | ||
667 | 747 | ||
748 | sleep(1); | ||
668 | } | 749 | } |
669 | return; | ||
670 | |||
671 | choke: | ||
672 | //message(CONSOLE, "Bad entry:"); | ||
673 | fprintf(stderr, "Bad inittab entry: %s", buf); | ||
674 | while (1) sleep(1); | ||
675 | |||
676 | } | ||
677 | |||
678 | |||
679 | extern int init_main(int argc, char **argv) | ||
680 | { | ||
681 | parse_inittab(); | ||
682 | exit( TRUE); | ||
683 | } | 750 | } |
684 | 751 | ||
685 | |||
686 | #endif | ||
diff --git a/init/init.c b/init/init.c index b71c9f74e..be04ec34f 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | #include <stdio.h> | 25 | #include <stdio.h> |
26 | #include <string.h> | ||
26 | #include <stdlib.h> | 27 | #include <stdlib.h> |
27 | #include <stdarg.h> | 28 | #include <stdarg.h> |
28 | #include <unistd.h> | 29 | #include <unistd.h> |
@@ -55,22 +56,57 @@ | |||
55 | #endif | 56 | #endif |
56 | 57 | ||
57 | 58 | ||
58 | #define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ | 59 | #define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ |
59 | #define VT_SECONDARY "/dev/tty2" /* Virtual console */ | 60 | #define VT_SECONDARY "/dev/tty2" /* Virtual console */ |
60 | #define VT_LOG "/dev/tty3" /* Virtual console */ | 61 | #define VT_LOG "/dev/tty3" /* Virtual console */ |
61 | #define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ | 62 | #define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ |
62 | #define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ | 63 | #define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ |
63 | #define GETTY "/sbin/getty" /* Default location of getty */ | 64 | #define SHELL "/bin/sh" /* Default shell */ |
64 | #define SHELL "/bin/sh" /* Default shell */ | 65 | #define REBOOT "/sbin/reboot" /* Default ctrl-alt-del command */ |
65 | #define INITTAB "/etc/inittab" /* inittab file location */ | 66 | #define INITTAB "/etc/inittab" /* inittab file location */ |
66 | #ifndef BB_INIT_SCRIPT | 67 | #define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ |
67 | #define BB_INIT_SCRIPT "/etc/init.d/rcS" /* Initscript. */ | ||
68 | #endif | ||
69 | |||
70 | #if 1 | ||
71 | 68 | ||
72 | #define LOG 0x1 | 69 | #define LOG 0x1 |
73 | #define CONSOLE 0x2 | 70 | #define CONSOLE 0x2 |
71 | |||
72 | /* Allowed init action types */ | ||
73 | typedef enum { | ||
74 | SYSINIT=1, | ||
75 | CTRLALTDEL, | ||
76 | RESPAWN, | ||
77 | ASKFIRST, | ||
78 | WAIT, | ||
79 | ONCE | ||
80 | } initActionEnum; | ||
81 | |||
82 | /* And now a list of the actions we support in the version of init */ | ||
83 | typedef struct initActionType{ | ||
84 | const char* name; | ||
85 | initActionEnum action; | ||
86 | } initActionType; | ||
87 | |||
88 | static const struct initActionType actions[] = { | ||
89 | {"sysinit", SYSINIT}, | ||
90 | {"ctrlaltdel", CTRLALTDEL}, | ||
91 | {"respawn", RESPAWN}, | ||
92 | {"askfirst", ASKFIRST}, | ||
93 | {"wait", WAIT}, | ||
94 | {"once", ONCE}, | ||
95 | {0} | ||
96 | }; | ||
97 | |||
98 | /* Set up a linked list of initactions, to be read from inittab */ | ||
99 | typedef struct initActionTag initAction; | ||
100 | struct initActionTag { | ||
101 | pid_t pid; | ||
102 | char process[256]; | ||
103 | char *console; | ||
104 | initAction *nextPtr; | ||
105 | initActionEnum action; | ||
106 | }; | ||
107 | initAction* initActionList = NULL; | ||
108 | |||
109 | |||
74 | static char *console = _PATH_CONSOLE; | 110 | static char *console = _PATH_CONSOLE; |
75 | static char *second_console = VT_SECONDARY; | 111 | static char *second_console = VT_SECONDARY; |
76 | static char *log = VT_LOG; | 112 | static char *log = VT_LOG; |
@@ -100,8 +136,9 @@ int device_open(char *device, int mode) | |||
100 | * device may be bitwise-or'd from LOG | CONSOLE */ | 136 | * device may be bitwise-or'd from LOG | CONSOLE */ |
101 | void message(int device, char *fmt, ...) | 137 | void message(int device, char *fmt, ...) |
102 | { | 138 | { |
103 | int fd; | ||
104 | va_list arguments; | 139 | va_list arguments; |
140 | int fd; | ||
141 | |||
105 | #ifdef BB_SYSLOGD | 142 | #ifdef BB_SYSLOGD |
106 | 143 | ||
107 | /* Log the message to syslogd */ | 144 | /* Log the message to syslogd */ |
@@ -298,16 +335,18 @@ static int waitfor(int pid) | |||
298 | } | 335 | } |
299 | 336 | ||
300 | 337 | ||
301 | static pid_t run(const char * const* command, | 338 | static pid_t run(char* command, |
302 | char *terminal, int get_enter) | 339 | char *terminal, int get_enter) |
303 | { | 340 | { |
304 | int fd; | 341 | int i; |
305 | pid_t pid; | 342 | pid_t pid; |
306 | const char * const* cmd = command+1; | 343 | char* tmpCmd; |
344 | char* cmd[255]; | ||
307 | static const char press_enter[] = | 345 | static const char press_enter[] = |
308 | "\nPlease press Enter to activate this console. "; | 346 | "\nPlease press Enter to activate this console. "; |
309 | 347 | ||
310 | if ((pid = fork()) == 0) { | 348 | if ((pid = fork()) == 0) { |
349 | int fd; | ||
311 | /* Clean up */ | 350 | /* Clean up */ |
312 | close(0); | 351 | close(0); |
313 | close(1); | 352 | close(1); |
@@ -321,7 +360,7 @@ static pid_t run(const char * const* command, | |||
321 | signal(SIGTERM, SIG_DFL); | 360 | signal(SIGTERM, SIG_DFL); |
322 | 361 | ||
323 | if ((fd = device_open(terminal, O_RDWR)) < 0) { | 362 | if ((fd = device_open(terminal, O_RDWR)) < 0) { |
324 | message(LOG, "Bummer, can't open %s\r\n", terminal); | 363 | message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); |
325 | exit(-1); | 364 | exit(-1); |
326 | } | 365 | } |
327 | dup(fd); | 366 | dup(fd); |
@@ -340,21 +379,32 @@ static pid_t run(const char * const* command, | |||
340 | */ | 379 | */ |
341 | char c; | 380 | char c; |
342 | message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", | 381 | message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", |
343 | *cmd, getpid(), terminal ); | 382 | command, getpid(), terminal ); |
344 | write(1, press_enter, sizeof(press_enter) - 1); | 383 | write(fileno(stdout), press_enter, sizeof(press_enter) - 1); |
345 | read(0, &c, 1); | 384 | read(fileno(stdin), &c, 1); |
346 | } | 385 | } |
347 | 386 | ||
387 | /* Convert command (char*) into cmd (char**, one word per string) */ | ||
388 | for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) { | ||
389 | if (*tmpCmd != '\0') { | ||
390 | cmd[i] = tmpCmd; | ||
391 | tmpCmd++; | ||
392 | i++; | ||
393 | } | ||
394 | } | ||
395 | cmd[i] = NULL; | ||
396 | |||
348 | /* Log the process name and args */ | 397 | /* Log the process name and args */ |
349 | message(LOG|CONSOLE, "Starting pid %d, console %s: '", getpid(), terminal); | 398 | message(LOG, "Starting pid %d, console %s: '%s'\r\n", |
350 | while ( *cmd) message(LOG|CONSOLE, "%s ", *cmd++); | 399 | getpid(), terminal, cmd[0]); |
351 | message(LOG|CONSOLE, "'\r\n"); | 400 | |
352 | |||
353 | /* Now run it. The new program will take over this PID, | 401 | /* Now run it. The new program will take over this PID, |
354 | * so nothing further in init.c should be run. */ | 402 | * so nothing further in init.c should be run. */ |
355 | execvp(*command, (char**)command+1); | 403 | execvp(cmd[0], cmd); |
356 | 404 | ||
357 | message(LOG, "Bummer, could not run '%s'\n", command); | 405 | /* We're still here? Some error happened. */ |
406 | message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0], | ||
407 | strerror(errno)); | ||
358 | exit(-1); | 408 | exit(-1); |
359 | } | 409 | } |
360 | return pid; | 410 | return pid; |
@@ -365,15 +415,13 @@ static pid_t run(const char * const* command, | |||
365 | static void check_memory() | 415 | static void check_memory() |
366 | { | 416 | { |
367 | struct stat statbuf; | 417 | struct stat statbuf; |
368 | const char* const swap_on_cmd[] = | ||
369 | { "/bin/swapon", "swapon", "-a", 0}; | ||
370 | 418 | ||
371 | if (mem_total() > 3500) | 419 | if (mem_total() > 3500) |
372 | return; | 420 | return; |
373 | 421 | ||
374 | if (stat("/etc/fstab", &statbuf) == 0) { | 422 | if (stat("/etc/fstab", &statbuf) == 0) { |
375 | /* Try to turn on swap */ | 423 | /* Try to turn on swap */ |
376 | waitfor(run(swap_on_cmd, log, FALSE)); | 424 | waitfor(run("/bin/swapon swapon -a", log, FALSE)); |
377 | if (mem_total() < 3500) | 425 | if (mem_total() < 3500) |
378 | goto goodnight; | 426 | goto goodnight; |
379 | } else | 427 | } else |
@@ -385,33 +433,28 @@ goodnight: | |||
385 | while (1) sleep(1); | 433 | while (1) sleep(1); |
386 | } | 434 | } |
387 | 435 | ||
436 | #ifndef DEBUG_INIT | ||
388 | static void shutdown_system(void) | 437 | static void shutdown_system(void) |
389 | { | 438 | { |
390 | const char* const swap_off_cmd[] = { "swapoff", "swapoff", "-a", 0}; | ||
391 | const char* const umount_cmd[] = { "umount", "umount", "-a", 0}; | ||
392 | |||
393 | #ifndef DEBUG_INIT | ||
394 | /* Allow Ctrl-Alt-Del to reboot system. */ | 439 | /* Allow Ctrl-Alt-Del to reboot system. */ |
395 | reboot(RB_ENABLE_CAD); | 440 | reboot(RB_ENABLE_CAD); |
396 | #endif | ||
397 | message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); | 441 | message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); |
398 | sync(); | 442 | sync(); |
443 | |||
399 | /* Send signals to every process _except_ pid 1 */ | 444 | /* Send signals to every process _except_ pid 1 */ |
400 | message(CONSOLE, "Sending SIGHUP to all processes.\r\n"); | 445 | message(CONSOLE, "Sending SIGHUP to all processes.\r\n"); |
401 | #ifndef DEBUG_INIT | ||
402 | kill(-1, SIGHUP); | 446 | kill(-1, SIGHUP); |
403 | #endif | ||
404 | sleep(2); | 447 | sleep(2); |
405 | sync(); | 448 | sync(); |
449 | |||
406 | message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); | 450 | message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); |
407 | #ifndef DEBUG_INIT | ||
408 | kill(-1, SIGKILL); | 451 | kill(-1, SIGKILL); |
409 | #endif | ||
410 | sleep(1); | 452 | sleep(1); |
453 | |||
411 | message(CONSOLE, "Disabling swap.\r\n"); | 454 | message(CONSOLE, "Disabling swap.\r\n"); |
412 | waitfor(run( swap_off_cmd, console, FALSE)); | 455 | waitfor(run( "swapoff -a", console, FALSE)); |
413 | message(CONSOLE, "Unmounting filesystems.\r\n"); | 456 | message(CONSOLE, "Unmounting filesystems.\r\n"); |
414 | waitfor(run( umount_cmd, console, FALSE)); | 457 | waitfor(run( "umount -a", console, FALSE)); |
415 | sync(); | 458 | sync(); |
416 | if (kernel_version > 0 && kernel_version <= 2 * 65536 + 2 * 256 + 11) { | 459 | if (kernel_version > 0 && kernel_version <= 2 * 65536 + 2 * 256 + 11) { |
417 | /* bdflush, kupdate not needed for kernels >2.2.11 */ | 460 | /* bdflush, kupdate not needed for kernels >2.2.11 */ |
@@ -427,14 +470,12 @@ static void halt_signal(int sig) | |||
427 | message(CONSOLE, | 470 | message(CONSOLE, |
428 | "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); | 471 | "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); |
429 | sync(); | 472 | sync(); |
430 | #ifndef DEBUG_INIT | ||
431 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) | 473 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) |
432 | if (sig == SIGUSR2) | 474 | if (sig == SIGUSR2) |
433 | reboot(RB_POWER_OFF); | 475 | reboot(RB_POWER_OFF); |
434 | else | 476 | else |
435 | #endif | 477 | #endif |
436 | reboot(RB_HALT_SYSTEM); | 478 | reboot(RB_HALT_SYSTEM); |
437 | #endif | ||
438 | exit(0); | 479 | exit(0); |
439 | } | 480 | } |
440 | 481 | ||
@@ -443,64 +484,157 @@ static void reboot_signal(int sig) | |||
443 | shutdown_system(); | 484 | shutdown_system(); |
444 | message(CONSOLE, "Please stand by while rebooting the system.\r\n"); | 485 | message(CONSOLE, "Please stand by while rebooting the system.\r\n"); |
445 | sync(); | 486 | sync(); |
446 | #ifndef DEBUG_INIT | ||
447 | reboot(RB_AUTOBOOT); | 487 | reboot(RB_AUTOBOOT); |
448 | #endif | ||
449 | exit(0); | 488 | exit(0); |
450 | } | 489 | } |
451 | 490 | ||
491 | static void ctrl_alt_del_signal(int sig) | ||
492 | { | ||
493 | initAction* a; | ||
494 | /* Run whatever we are supposed to run */ | ||
495 | for( a=initActionList ; a; a=a->nextPtr) { | ||
496 | if (a->action == CTRLALTDEL) { | ||
497 | waitfor(run(a->process, console, FALSE)); | ||
498 | } | ||
499 | } | ||
500 | } | ||
501 | #endif | ||
502 | |||
503 | void new_initAction (const struct initActionType *a, | ||
504 | char* process, char* console) | ||
505 | { | ||
506 | initAction* newAction; | ||
507 | newAction = calloc ((size_t)(1), sizeof(initAction)); | ||
508 | if (!newAction) { | ||
509 | fprintf(stderr, "Memory allocation failure\n"); | ||
510 | while (1) sleep(1); | ||
511 | } | ||
512 | newAction->nextPtr = initActionList; | ||
513 | initActionList = newAction; | ||
514 | strncpy( newAction->process, process, 255); | ||
515 | newAction->action = a->action; | ||
516 | newAction->console = console; | ||
517 | newAction->pid = 0; | ||
518 | } | ||
519 | |||
520 | void delete_initAction (initAction *action) | ||
521 | { | ||
522 | initAction *a, *b=NULL; | ||
523 | for( a=initActionList ; a; b=a, a=a->nextPtr) { | ||
524 | if (a == action && b != NULL) { | ||
525 | b->nextPtr=a->nextPtr; | ||
526 | free( a); | ||
527 | break; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | |||
532 | void parse_inittab(void) | ||
533 | { | ||
534 | FILE* file; | ||
535 | char buf[256]; | ||
536 | char *p, *q, *r; | ||
537 | const struct initActionType *a = actions; | ||
538 | int foundIt; | ||
539 | |||
540 | |||
541 | file = fopen(INITTAB, "r"); | ||
542 | if (file == NULL) { | ||
543 | /* No inittab file -- set up some default behavior */ | ||
544 | |||
545 | /* Askfirst shell on tty1 */ | ||
546 | new_initAction( &(actions[3]), SHELL, console ); | ||
547 | /* Askfirst shell on tty2 */ | ||
548 | if (second_console != NULL) | ||
549 | new_initAction( &(actions[3]), SHELL, second_console ); | ||
550 | /* Control-alt-del */ | ||
551 | new_initAction( &(actions[1]), REBOOT, console ); | ||
552 | /* sysinit */ | ||
553 | new_initAction( &(actions[0]), INIT_SCRIPT, console ); | ||
554 | |||
555 | return; | ||
556 | } | ||
557 | |||
558 | while ( fgets(buf, 255, file) != NULL) { | ||
559 | foundIt=FALSE; | ||
560 | for(p = buf; *p == ' ' || *p == '\t'; p++); | ||
561 | if (*p == '#' || *p == '\n') continue; | ||
562 | |||
563 | /* Trim the trailing \n */ | ||
564 | q = strrchr( p, '\n'); | ||
565 | if (q != NULL) | ||
566 | *q='\0'; | ||
567 | |||
568 | /* Skip past the ID field and the runlevel | ||
569 | * field (both are ignored) */ | ||
570 | p = strchr( p, ':'); | ||
571 | |||
572 | /* Now peal off the process field from the end | ||
573 | * of the string */ | ||
574 | q = strrchr( p, ':'); | ||
575 | if ( q == NULL || *(q+1) == '\0' ) { | ||
576 | fprintf(stderr, "Bad inittab entry: %s\n", buf); | ||
577 | continue; | ||
578 | } else { | ||
579 | *q='\0'; | ||
580 | ++q; | ||
581 | } | ||
582 | |||
583 | /* Now peal off the action field */ | ||
584 | r = strrchr( p, ':'); | ||
585 | if ( r == NULL || *(r+1) == '\0') { | ||
586 | fprintf(stderr, "Bad inittab entry: %s\n", buf); | ||
587 | continue; | ||
588 | } else { | ||
589 | ++r; | ||
590 | } | ||
591 | |||
592 | /* Ok, now process it */ | ||
593 | a = actions; | ||
594 | while (a->name != 0) { | ||
595 | if (strcmp(a->name, r) == 0) { | ||
596 | new_initAction( a, q, NULL); | ||
597 | foundIt=TRUE; | ||
598 | } | ||
599 | a++; | ||
600 | } | ||
601 | if (foundIt==TRUE) | ||
602 | continue; | ||
603 | else { | ||
604 | /* Choke on an unknown action */ | ||
605 | fprintf(stderr, "Bad inittab entry: %s\n", buf); | ||
606 | } | ||
607 | } | ||
608 | return; | ||
609 | } | ||
610 | |||
611 | |||
452 | extern int init_main(int argc, char **argv) | 612 | extern int init_main(int argc, char **argv) |
453 | { | 613 | { |
454 | int run_rc = FALSE; | 614 | initAction *a; |
615 | pid_t wpid; | ||
616 | int status; | ||
455 | int single = FALSE; | 617 | int single = FALSE; |
456 | int wait_for_enter_tty1 = TRUE; | ||
457 | int wait_for_enter_tty2 = TRUE; | ||
458 | pid_t pid1 = 0; | ||
459 | pid_t pid2 = 0; | ||
460 | struct stat statbuf; | ||
461 | char which_vt1[30]; | ||
462 | char which_vt2[30]; | ||
463 | const char* const rc_script_command[] = { BB_INIT_SCRIPT, BB_INIT_SCRIPT, 0}; | ||
464 | const char* const getty1_command[] = { GETTY, GETTY, "38400", which_vt1, 0}; | ||
465 | const char* const getty2_command[] = { GETTY, GETTY, "38400", which_vt2, 0}; | ||
466 | const char* const shell_command[] = { SHELL, "-" SHELL, 0}; | ||
467 | const char* const* tty1_command = shell_command; | ||
468 | const char* const* tty2_command = shell_command; | ||
469 | #ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS | ||
470 | const char* const rc_exit_command[] = { "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", | ||
471 | "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", 0 }; | ||
472 | #endif | ||
473 | 618 | ||
474 | #ifdef DEBUG_INIT | ||
475 | char *hello_msg_format = | ||
476 | "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n"; | ||
477 | #else | ||
478 | char *hello_msg_format = | ||
479 | "init started: BusyBox v%s (%s) multi-call binary\r\n"; | ||
480 | #endif | ||
481 | 619 | ||
482 | |||
483 | #ifndef DEBUG_INIT | 620 | #ifndef DEBUG_INIT |
484 | /* Expect to be PID 1 iff we are run as init (not linuxrc) */ | 621 | /* Expect to be PID 1 iff we are run as init (not linuxrc) */ |
485 | if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { | 622 | if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { |
486 | usage( "init\n\nInit is the parent of all processes.\n\n" | 623 | usage( "init\n\nInit is the parent of all processes.\n\n" |
487 | "This version of init is designed to be run only by the kernel\n"); | 624 | "This version of init is designed to be run only by the kernel\n"); |
488 | } | 625 | } |
489 | #endif | ||
490 | 626 | ||
491 | /* Set up sig handlers -- be sure to | 627 | /* Set up sig handlers -- be sure to clear all of these in run() */ |
492 | * clear all of these in run() */ | ||
493 | signal(SIGUSR1, halt_signal); | 628 | signal(SIGUSR1, halt_signal); |
494 | signal(SIGUSR2, reboot_signal); | 629 | signal(SIGUSR2, reboot_signal); |
495 | signal(SIGINT, reboot_signal); | 630 | signal(SIGINT, ctrl_alt_del_signal); |
496 | signal(SIGTERM, reboot_signal); | 631 | signal(SIGTERM, reboot_signal); |
497 | 632 | ||
498 | /* Turn off rebooting via CTL-ALT-DEL -- we get a | 633 | /* Turn off rebooting via CTL-ALT-DEL -- we get a |
499 | * SIGINT on CAD so we can shut things down gracefully... */ | 634 | * SIGINT on CAD so we can shut things down gracefully... */ |
500 | #ifndef DEBUG_INIT | ||
501 | reboot(RB_DISABLE_CAD); | 635 | reboot(RB_DISABLE_CAD); |
502 | #endif | 636 | #endif |
503 | 637 | ||
504 | /* Figure out where the default console should be */ | 638 | /* Figure out where the default console should be */ |
505 | console_init(); | 639 | console_init(); |
506 | 640 | ||
@@ -517,9 +651,13 @@ extern int init_main(int argc, char **argv) | |||
517 | 651 | ||
518 | /* Hello world */ | 652 | /* Hello world */ |
519 | #ifndef DEBUG_INIT | 653 | #ifndef DEBUG_INIT |
520 | message(CONSOLE|LOG, hello_msg_format, BB_VER, BB_BT); | 654 | message(CONSOLE|LOG, |
655 | "init started: BusyBox v%s (%s) multi-call binary\r\n", | ||
656 | BB_VER, BB_BT); | ||
521 | #else | 657 | #else |
522 | message(CONSOLE|LOG, hello_msg_format, getpid(), BB_VER, BB_BT); | 658 | message(CONSOLE|LOG, |
659 | "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n", | ||
660 | getpid(), BB_VER, BB_BT); | ||
523 | #endif | 661 | #endif |
524 | 662 | ||
525 | 663 | ||
@@ -537,150 +675,77 @@ extern int init_main(int argc, char **argv) | |||
537 | if ( argc > 1 && (!strcmp(argv[1], "single") || | 675 | if ( argc > 1 && (!strcmp(argv[1], "single") || |
538 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { | 676 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { |
539 | single = TRUE; | 677 | single = TRUE; |
540 | tty1_command = shell_command; | 678 | /* Ask first then start a shell on tty2 */ |
541 | tty2_command = shell_command; | 679 | if (second_console != NULL) |
680 | new_initAction( &(actions[3]), SHELL, second_console); | ||
681 | /* Ask first then start a shell on tty1 */ | ||
682 | new_initAction( &(actions[3]), SHELL, console); | ||
683 | } else { | ||
684 | /* Not in single user mode -- see what inittab says */ | ||
685 | parse_inittab(); | ||
542 | } | 686 | } |
543 | 687 | ||
544 | /* Make sure an init script exists before trying to run it */ | 688 | /* Now run everything that needs to be run */ |
545 | if (single==FALSE && stat(BB_INIT_SCRIPT, &statbuf)==0) { | 689 | |
546 | run_rc = TRUE; | 690 | /* First run sysinit */ |
547 | wait_for_enter_tty1 = FALSE; | 691 | for( a=initActionList ; a; a=a->nextPtr) { |
548 | tty1_command = rc_script_command; | 692 | if (a->action == SYSINIT) { |
693 | waitfor(run(a->process, console, FALSE)); | ||
694 | /* Now remove the "sysinit" entry from the list */ | ||
695 | delete_initAction( a); | ||
696 | } | ||
549 | } | 697 | } |
550 | 698 | /* Next run anything that wants to block */ | |
551 | /* Make sure /sbin/getty exists before trying to run it */ | 699 | for( a=initActionList ; a; a=a->nextPtr) { |
552 | if (stat(GETTY, &statbuf)==0) { | 700 | if (a->action == WAIT) { |
553 | char* where; | 701 | waitfor(run(a->process, console, FALSE)); |
554 | /* First do tty2 */ | 702 | /* Now remove the "wait" entry from the list */ |
555 | wait_for_enter_tty2 = FALSE; | 703 | delete_initAction( a); |
556 | where = strrchr( second_console, '/'); | ||
557 | if ( where != NULL) { | ||
558 | where++; | ||
559 | strncpy( which_vt2, where, sizeof(which_vt2)); | ||
560 | } | 704 | } |
561 | tty2_command = getty2_command; | 705 | } |
562 | 706 | /* Next run anything to be run only once */ | |
563 | /* Check on hooking a getty onto tty1 */ | 707 | for( a=initActionList ; a; a=a->nextPtr) { |
564 | if (run_rc == FALSE && single==FALSE) { | 708 | if (a->action == ONCE) { |
565 | wait_for_enter_tty1 = FALSE; | 709 | run(a->process, console, FALSE); |
566 | where = strrchr( console, '/'); | 710 | /* Now remove the "once" entry from the list */ |
567 | if ( where != NULL) { | 711 | delete_initAction( a); |
568 | where++; | ||
569 | strncpy( which_vt1, where, sizeof(which_vt1)); | ||
570 | } | ||
571 | tty1_command = getty1_command; | ||
572 | } | 712 | } |
573 | } | 713 | } |
574 | |||
575 | 714 | ||
576 | /* Ok, now launch the tty1_command and tty2_command */ | 715 | /* Now run the looping stuff */ |
577 | for (;;) { | 716 | for (;;) { |
578 | pid_t wpid; | 717 | for( a=initActionList ; a; a=a->nextPtr) { |
579 | int status; | 718 | /* Only run stuff with pid==0. If they have |
580 | 719 | * a pid, that means they are still running */ | |
581 | if (pid1 == 0 && tty1_command) { | 720 | if (a->pid == 0) { |
582 | pid1 = run(tty1_command, console, wait_for_enter_tty1); | 721 | switch(a->action) { |
583 | } | 722 | case RESPAWN: |
584 | #ifdef BB_FEATURE_INIT_SECOND_CONSOLE | 723 | /* run the respawn stuff */ |
585 | if (pid2 == 0 && tty2_command && second_console) { | 724 | a->pid = run(a->process, console, FALSE); |
586 | pid2 = run(tty2_command, second_console, wait_for_enter_tty2); | 725 | break; |
726 | case ASKFIRST: | ||
727 | /* run the askfirst stuff */ | ||
728 | a->pid = waitfor(run(a->process, console, TRUE)); | ||
729 | break; | ||
730 | /* silence the compiler's whining */ | ||
731 | default: | ||
732 | break; | ||
733 | } | ||
734 | } | ||
587 | } | 735 | } |
588 | #endif | 736 | |
589 | wpid = wait(&status); | 737 | wpid = wait(&status); |
738 | /* Find out who died and clean up their corpse */ | ||
590 | if (wpid > 0 ) { | 739 | if (wpid > 0 ) { |
591 | message(LOG, "pid %d exited, status=%x.\n", wpid, status); | 740 | message(LOG, "pid %d exited, status=%x.\n", wpid, status); |
592 | } | 741 | for( a=initActionList ; a; a=a->nextPtr) { |
593 | /* Don't respawn init script if it exits */ | 742 | if (a->pid==wpid) { |
594 | if (wpid == pid1) { | 743 | a->pid=0; |
595 | if (run_rc == FALSE) { | 744 | } |
596 | pid1 = 0; | ||
597 | } | 745 | } |
598 | #ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS | ||
599 | else { | ||
600 | pid1 = 0; | ||
601 | run_rc=FALSE; | ||
602 | wait_for_enter_tty1=TRUE; | ||
603 | tty1_command=rc_exit_command; | ||
604 | } | ||
605 | #endif | ||
606 | } | 746 | } |
607 | #ifdef BB_FEATURE_INIT_SECOND_CONSOLE | ||
608 | if (wpid == pid2) { | ||
609 | pid2 = 0; | ||
610 | } | ||
611 | #endif | ||
612 | sleep(1); | ||
613 | } | ||
614 | } | ||
615 | |||
616 | #else | ||
617 | |||
618 | |||
619 | void parse_inittab(void) | ||
620 | { | ||
621 | FILE* file; | ||
622 | char buf[256]; | ||
623 | char action[256]=""; | ||
624 | char process[256]=""; | ||
625 | char *p, *q; | ||
626 | |||
627 | |||
628 | if ((file = fopen(INITTAB, "r")) < 0) { | ||
629 | /* No inittab file -- set up some default behavior */ | ||
630 | |||
631 | /* FIXME */ | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | while ( fgets(buf, 255, file) != NULL) { | ||
636 | for(p = buf; *p == ' ' || *p == '\t'; p++); | ||
637 | if (*p == '#' || *p == '\n') continue; | ||
638 | |||
639 | /* Trim the trailing \n */ | ||
640 | q = strrchr( p, '\n'); | ||
641 | if (q != NULL) | ||
642 | *q='\0'; | ||
643 | |||
644 | /* Skip past the ID field and the runlevel | ||
645 | * field (both are ignored) */ | ||
646 | p = strchr( p, ':'); | ||
647 | |||
648 | /* Now peal off the process field from the end | ||
649 | * of the string */ | ||
650 | q = strrchr( p, ':'); | ||
651 | if ( q == NULL || q+1 == NULL) | ||
652 | goto choke; | ||
653 | *q='\0'; | ||
654 | strcpy( process, ++q); | ||
655 | fprintf(stderr, "process=%s\n", process); | ||
656 | |||
657 | |||
658 | /* Now peal off the action field */ | ||
659 | q = strrchr( p, ':'); | ||
660 | if ( q == NULL || q+1 == NULL) | ||
661 | goto choke; | ||
662 | strcpy( action, ++q); | ||
663 | fprintf(stderr, "action=%s\n", action); | ||
664 | |||
665 | |||
666 | /* Ok, now do the right thing */ | ||
667 | 747 | ||
748 | sleep(1); | ||
668 | } | 749 | } |
669 | return; | ||
670 | |||
671 | choke: | ||
672 | //message(CONSOLE, "Bad entry:"); | ||
673 | fprintf(stderr, "Bad inittab entry: %s", buf); | ||
674 | while (1) sleep(1); | ||
675 | |||
676 | } | ||
677 | |||
678 | |||
679 | extern int init_main(int argc, char **argv) | ||
680 | { | ||
681 | parse_inittab(); | ||
682 | exit( TRUE); | ||
683 | } | 750 | } |
684 | 751 | ||
685 | |||
686 | #endif | ||
diff --git a/internal.h b/internal.h index 1e42982d3..6804e2da8 100644 --- a/internal.h +++ b/internal.h | |||
@@ -169,6 +169,9 @@ extern int check_wildcard_match(const char* text, const char* pattern); | |||
169 | extern long getNum (const char *cp); | 169 | extern long getNum (const char *cp); |
170 | extern pid_t findInitPid(); | 170 | extern pid_t findInitPid(); |
171 | 171 | ||
172 | #if (__GLIBC__ < 2) && defined BB_SYSLOGD | ||
173 | extern int vdprintf(int d, const char *format, va_list ap); | ||
174 | #endif | ||
172 | 175 | ||
173 | #if defined BB_MTAB | 176 | #if defined BB_MTAB |
174 | #define whine_if_fstab_is_missing() {} | 177 | #define whine_if_fstab_is_missing() {} |
@@ -183,7 +183,7 @@ extern int kill_main (int argc, char **argv) | |||
183 | 183 | ||
184 | do_it_now: | 184 | do_it_now: |
185 | 185 | ||
186 | while (argc >= 1) { | 186 | while (--argc >= 0) { |
187 | int pid; | 187 | int pid; |
188 | struct stat statbuf; | 188 | struct stat statbuf; |
189 | char pidpath[20]="/proc/"; | 189 | char pidpath[20]="/proc/"; |
@@ -198,6 +198,7 @@ do_it_now: | |||
198 | fprintf(stderr, "kill: (%d) - No such pid\n", pid); | 198 | fprintf(stderr, "kill: (%d) - No such pid\n", pid); |
199 | exit( FALSE); | 199 | exit( FALSE); |
200 | } | 200 | } |
201 | fprintf(stderr, "sig = %d\n", sig); | ||
201 | if (kill (pid, sig) != 0) { | 202 | if (kill (pid, sig) != 0) { |
202 | perror (*argv); | 203 | perror (*argv); |
203 | exit ( FALSE); | 204 | exit ( FALSE); |
diff --git a/procps/kill.c b/procps/kill.c index 0ba6d76ce..e72b73493 100644 --- a/procps/kill.c +++ b/procps/kill.c | |||
@@ -183,7 +183,7 @@ extern int kill_main (int argc, char **argv) | |||
183 | 183 | ||
184 | do_it_now: | 184 | do_it_now: |
185 | 185 | ||
186 | while (argc >= 1) { | 186 | while (--argc >= 0) { |
187 | int pid; | 187 | int pid; |
188 | struct stat statbuf; | 188 | struct stat statbuf; |
189 | char pidpath[20]="/proc/"; | 189 | char pidpath[20]="/proc/"; |
@@ -198,6 +198,7 @@ do_it_now: | |||
198 | fprintf(stderr, "kill: (%d) - No such pid\n", pid); | 198 | fprintf(stderr, "kill: (%d) - No such pid\n", pid); |
199 | exit( FALSE); | 199 | exit( FALSE); |
200 | } | 200 | } |
201 | fprintf(stderr, "sig = %d\n", sig); | ||
201 | if (kill (pid, sig) != 0) { | 202 | if (kill (pid, sig) != 0) { |
202 | perror (*argv); | 203 | perror (*argv); |
203 | exit ( FALSE); | 204 | exit ( FALSE); |
@@ -46,7 +46,7 @@ static const char sed_usage[] = | |||
46 | "\t /REGEXP/ Match specified regexp\n" | 46 | "\t /REGEXP/ Match specified regexp\n" |
47 | "\t (! inverts the meaning of the match)\n\n" | 47 | "\t (! inverts the meaning of the match)\n\n" |
48 | "\tand COMMAND can be:\n" | 48 | "\tand COMMAND can be:\n" |
49 | "\t s/regexp/replacement/[gp]\n" | 49 | "\t s/regexp/replacement/[igp]\n" |
50 | "\t which attempt to match regexp against the pattern space\n" | 50 | "\t which attempt to match regexp against the pattern space\n" |
51 | "\t and if successful replaces the matched portion with replacement.\n\n" | 51 | "\t and if successful replaces the matched portion with replacement.\n\n" |
52 | "\t aTEXT\n" | 52 | "\t aTEXT\n" |
@@ -37,6 +37,7 @@ | |||
37 | #include <fcntl.h> | 37 | #include <fcntl.h> |
38 | #include <signal.h> | 38 | #include <signal.h> |
39 | #include <time.h> | 39 | #include <time.h> |
40 | #include <utime.h> | ||
40 | #include <sys/types.h> | 41 | #include <sys/types.h> |
41 | #include <sys/sysmacros.h> | 42 | #include <sys/sysmacros.h> |
42 | 43 | ||
@@ -106,8 +107,12 @@ static int warnedRoot; | |||
106 | static int eofFlag; | 107 | static int eofFlag; |
107 | static long dataCc; | 108 | static long dataCc; |
108 | static int outFd; | 109 | static int outFd; |
109 | static char outName[TAR_NAME_SIZE]; | 110 | static const char *outName; |
110 | 111 | ||
112 | static int mode; | ||
113 | static int uid; | ||
114 | static int gid; | ||
115 | static time_t mtime; | ||
111 | 116 | ||
112 | /* | 117 | /* |
113 | * Static data associated with the tar file. | 118 | * Static data associated with the tar file. |
@@ -364,8 +369,9 @@ static void readTarFile (int fileCount, char **fileTable) | |||
364 | * message is required on errors. | 369 | * message is required on errors. |
365 | */ | 370 | */ |
366 | if (tostdoutFlag == FALSE) { | 371 | if (tostdoutFlag == FALSE) { |
367 | if (outFd >= 0) | 372 | if (outFd >= 0) { |
368 | (void) close (outFd); | 373 | close (outFd); |
374 | } | ||
369 | } | 375 | } |
370 | } | 376 | } |
371 | 377 | ||
@@ -378,29 +384,25 @@ static void readTarFile (int fileCount, char **fileTable) | |||
378 | static void | 384 | static void |
379 | readHeader (const TarHeader * hp, int fileCount, char **fileTable) | 385 | readHeader (const TarHeader * hp, int fileCount, char **fileTable) |
380 | { | 386 | { |
381 | int mode; | ||
382 | int uid; | ||
383 | int gid; | ||
384 | int checkSum; | 387 | int checkSum; |
385 | unsigned int major; | ||
386 | unsigned int minor; | ||
387 | long size; | ||
388 | time_t mtime; | ||
389 | const char *name; | ||
390 | int cc; | 388 | int cc; |
391 | int hardLink; | 389 | int hardLink; |
392 | int softLink; | 390 | int softLink; |
393 | int devFileFlag; | 391 | int devFileFlag; |
392 | unsigned int major; | ||
393 | unsigned int minor; | ||
394 | long size; | ||
395 | struct utimbuf utb; | ||
394 | 396 | ||
395 | /* | 397 | /* |
396 | * If the block is completely empty, then this is the end of the | 398 | * If the block is completely empty, then this is the end of the |
397 | * archive file. If the name is null, then just skip this header. | 399 | * archive file. If the name is null, then just skip this header. |
398 | */ | 400 | */ |
399 | name = hp->name; | 401 | outName = hp->name; |
400 | 402 | ||
401 | if (*name == '\0') { | 403 | if (*outName == '\0') { |
402 | for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { | 404 | for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { |
403 | if (*name++) | 405 | if (*outName++) |
404 | return; | 406 | return; |
405 | } | 407 | } |
406 | 408 | ||
@@ -447,16 +449,16 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
447 | /* | 449 | /* |
448 | * Check for a directory. | 450 | * Check for a directory. |
449 | */ | 451 | */ |
450 | if (name[strlen (name) - 1] == '/') | 452 | if (outName[strlen (outName) - 1] == '/') |
451 | mode |= S_IFDIR; | 453 | mode |= S_IFDIR; |
452 | 454 | ||
453 | /* | 455 | /* |
454 | * Check for absolute paths in the file. | 456 | * Check for absolute paths in the file. |
455 | * If we find any, then warn the user and make them relative. | 457 | * If we find any, then warn the user and make them relative. |
456 | */ | 458 | */ |
457 | if (*name == '/') { | 459 | if (*outName == '/') { |
458 | while (*name == '/') | 460 | while (*outName == '/') |
459 | name++; | 461 | outName++; |
460 | 462 | ||
461 | if (warnedRoot==FALSE) { | 463 | if (warnedRoot==FALSE) { |
462 | fprintf (stderr, | 464 | fprintf (stderr, |
@@ -470,7 +472,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
470 | * See if we want this file to be restored. | 472 | * See if we want this file to be restored. |
471 | * If not, then set up to skip it. | 473 | * If not, then set up to skip it. |
472 | */ | 474 | */ |
473 | if (wantFileName (name, fileCount, fileTable) == FALSE) { | 475 | if (wantFileName (outName, fileCount, fileTable) == FALSE) { |
474 | if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode) | 476 | if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode) |
475 | || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) { | 477 | || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) { |
476 | inHeader = (size == 0)? TRUE : FALSE; | 478 | inHeader = (size == 0)? TRUE : FALSE; |
@@ -494,7 +496,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
494 | else | 496 | else |
495 | printf ("%9ld %s ", size, timeString (mtime)); | 497 | printf ("%9ld %s ", size, timeString (mtime)); |
496 | } | 498 | } |
497 | printf ("%s", name); | 499 | printf ("%s", outName); |
498 | 500 | ||
499 | if (hardLink) | 501 | if (hardLink) |
500 | printf (" (link to \"%s\")", hp->linkName); | 502 | printf (" (link to \"%s\")", hp->linkName); |
@@ -515,22 +517,35 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
515 | * We really want to extract the file. | 517 | * We really want to extract the file. |
516 | */ | 518 | */ |
517 | if (verboseFlag==TRUE) | 519 | if (verboseFlag==TRUE) |
518 | printf ("x %s\n", name); | 520 | printf ("x %s\n", outName); |
519 | 521 | ||
520 | if (hardLink) { | 522 | if (hardLink) { |
521 | if (link (hp->linkName, name) < 0) | 523 | if (link (hp->linkName, outName) < 0) |
522 | perror (name); | 524 | perror (outName); |
523 | chown(name, uid, gid); | 525 | /* Set the file time */ |
524 | chmod(name, mode); | 526 | utb.actime = mtime; |
527 | utb.modtime = mtime; | ||
528 | utime (outName, &utb); | ||
529 | /* Set the file permissions */ | ||
530 | chown(outName, uid, gid); | ||
531 | chmod(outName, mode); | ||
525 | return; | 532 | return; |
526 | } | 533 | } |
527 | 534 | ||
528 | if (softLink) { | 535 | if (softLink) { |
529 | #ifdef S_ISLNK | 536 | #ifdef S_ISLNK |
530 | if (symlink (hp->linkName, name) < 0) | 537 | if (symlink (hp->linkName, outName) < 0) |
531 | perror (name); | 538 | perror (outName); |
532 | chown(name, uid, gid); | 539 | /* Try to change ownership of the symlink. |
533 | chmod(name, mode); | 540 | * If libs doesn't support that, don't bother. |
541 | * Changing the pointed-to file is the Wrong Thing(tm). | ||
542 | */ | ||
543 | #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) | ||
544 | lchown(outName, uid, gid); | ||
545 | #endif | ||
546 | |||
547 | /* Do not change permissions or date on symlink, | ||
548 | * since it changes the pointed to file instead. duh. */ | ||
534 | #else | 549 | #else |
535 | fprintf (stderr, "Cannot create symbolic links\n"); | 550 | fprintf (stderr, "Cannot create symbolic links\n"); |
536 | #endif | 551 | #endif |
@@ -545,10 +560,14 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
545 | * If the file is a directory, then just create the path. | 560 | * If the file is a directory, then just create the path. |
546 | */ | 561 | */ |
547 | if (S_ISDIR (mode)) { | 562 | if (S_ISDIR (mode)) { |
548 | createPath (name, mode); | 563 | createPath (outName, mode); |
549 | chown(name, uid, gid); | 564 | /* Set the file time */ |
550 | chmod(name, mode); | 565 | utb.actime = mtime; |
551 | 566 | utb.modtime = mtime; | |
567 | utime (outName, &utb); | ||
568 | /* Set the file permissions */ | ||
569 | chown(outName, uid, gid); | ||
570 | chmod(outName, mode); | ||
552 | return; | 571 | return; |
553 | } | 572 | } |
554 | 573 | ||
@@ -556,7 +575,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
556 | * There is a file to write. | 575 | * There is a file to write. |
557 | * First create the path to it if necessary with default permissions. | 576 | * First create the path to it if necessary with default permissions. |
558 | */ | 577 | */ |
559 | createPath (name, 0777); | 578 | createPath (outName, 0777); |
560 | 579 | ||
561 | inHeader = (size == 0)? TRUE : FALSE; | 580 | inHeader = (size == 0)? TRUE : FALSE; |
562 | dataCc = size; | 581 | dataCc = size; |
@@ -569,21 +588,26 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
569 | else { | 588 | else { |
570 | if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { | 589 | if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { |
571 | devFileFlag = TRUE; | 590 | devFileFlag = TRUE; |
572 | outFd = mknod (name, mode, makedev(major, minor) ); | 591 | outFd = mknod (outName, mode, makedev(major, minor) ); |
573 | } | 592 | } |
574 | else if (S_ISFIFO(mode) ) { | 593 | else if (S_ISFIFO(mode) ) { |
575 | devFileFlag = TRUE; | 594 | devFileFlag = TRUE; |
576 | outFd = mkfifo(name, mode); | 595 | outFd = mkfifo(outName, mode); |
577 | } else { | 596 | } else { |
578 | outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode); | 597 | outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode); |
579 | } | 598 | } |
580 | if (outFd < 0) { | 599 | if (outFd < 0) { |
581 | perror (name); | 600 | perror (outName); |
582 | skipFileFlag = TRUE; | 601 | skipFileFlag = TRUE; |
583 | return; | 602 | return; |
584 | } | 603 | } |
585 | chown(name, uid, gid); | 604 | /* Set the file time */ |
586 | chmod(name, mode); | 605 | utb.actime = mtime; |
606 | utb.modtime = mtime; | ||
607 | utime (outName, &utb); | ||
608 | /* Set the file permissions */ | ||
609 | chown(outName, uid, gid); | ||
610 | chmod(outName, mode); | ||
587 | } | 611 | } |
588 | 612 | ||
589 | 613 | ||
@@ -591,7 +615,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable) | |||
591 | * If the file is empty, then that's all we need to do. | 615 | * If the file is empty, then that's all we need to do. |
592 | */ | 616 | */ |
593 | if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) { | 617 | if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) { |
594 | (void) close (outFd); | 618 | close (outFd); |
595 | outFd = -1; | 619 | outFd = -1; |
596 | } | 620 | } |
597 | } | 621 | } |
@@ -625,7 +649,7 @@ static void readData (const char *cp, int count) | |||
625 | if (fullWrite (outFd, cp, count) < 0) { | 649 | if (fullWrite (outFd, cp, count) < 0) { |
626 | perror (outName); | 650 | perror (outName); |
627 | if (tostdoutFlag == FALSE) { | 651 | if (tostdoutFlag == FALSE) { |
628 | (void) close (outFd); | 652 | close (outFd); |
629 | outFd = -1; | 653 | outFd = -1; |
630 | } | 654 | } |
631 | skipFileFlag = TRUE; | 655 | skipFileFlag = TRUE; |
@@ -633,13 +657,21 @@ static void readData (const char *cp, int count) | |||
633 | } | 657 | } |
634 | 658 | ||
635 | /* | 659 | /* |
636 | * If the write failed, close the file and disable further | 660 | * Check if we are done writing to the file now. |
637 | * writes to this file. | ||
638 | */ | 661 | */ |
639 | if (dataCc <= 0 && tostdoutFlag == FALSE) { | 662 | if (dataCc <= 0 && tostdoutFlag == FALSE) { |
663 | struct utimbuf utb; | ||
640 | if (close (outFd)) | 664 | if (close (outFd)) |
641 | perror (outName); | 665 | perror (outName); |
642 | 666 | ||
667 | /* Set the file time */ | ||
668 | utb.actime = mtime; | ||
669 | utb.modtime = mtime; | ||
670 | utime (outName, &utb); | ||
671 | /* Set the file permissions */ | ||
672 | chown(outName, uid, gid); | ||
673 | chmod(outName, mode); | ||
674 | |||
643 | outFd = -1; | 675 | outFd = -1; |
644 | } | 676 | } |
645 | } | 677 | } |
@@ -720,7 +752,6 @@ static void writeTarFile (int fileCount, char **fileTable) | |||
720 | static void saveFile (const char *fileName, int seeLinks) | 752 | static void saveFile (const char *fileName, int seeLinks) |
721 | { | 753 | { |
722 | int status; | 754 | int status; |
723 | int mode; | ||
724 | struct stat statbuf; | 755 | struct stat statbuf; |
725 | 756 | ||
726 | if (verboseFlag==TRUE) | 757 | if (verboseFlag==TRUE) |
@@ -379,7 +379,7 @@ int fullRead(int fd, char *buf, int len) | |||
379 | #endif | 379 | #endif |
380 | 380 | ||
381 | 381 | ||
382 | #if defined (BB_CHOWN) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS) || defined (BB_INSMOD) | 382 | #if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS) || defined (BB_INSMOD) |
383 | /* | 383 | /* |
384 | * Walk down all the directories under the specified | 384 | * Walk down all the directories under the specified |
385 | * location, and do something (something specified | 385 | * location, and do something (something specified |
@@ -969,7 +969,7 @@ check_wildcard_match(const char* text, const char* pattern) | |||
969 | 969 | ||
970 | 970 | ||
971 | 971 | ||
972 | #if defined BB_DF | defined BB_MTAB | 972 | #if defined BB_DF || defined BB_MTAB |
973 | /* | 973 | /* |
974 | * Given a block device, find the mount table entry if that block device | 974 | * Given a block device, find the mount table entry if that block device |
975 | * is mounted. | 975 | * is mounted. |
@@ -1008,7 +1008,6 @@ extern struct mntent *findMountPoint(const char *name, const char *table) | |||
1008 | endmntent(mountTable); | 1008 | endmntent(mountTable); |
1009 | return mountEntry; | 1009 | return mountEntry; |
1010 | } | 1010 | } |
1011 | |||
1012 | #endif | 1011 | #endif |
1013 | 1012 | ||
1014 | 1013 | ||
@@ -1111,4 +1110,15 @@ findInitPid() | |||
1111 | } | 1110 | } |
1112 | #endif | 1111 | #endif |
1113 | 1112 | ||
1113 | #if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT) | ||
1114 | extern int vdprintf(int d, const char *format, va_list ap) | ||
1115 | { | ||
1116 | char buf[BUF_SIZE]; | ||
1117 | int len; | ||
1118 | |||
1119 | len = vsprintf(buf, format, ap); | ||
1120 | return write(d, buf, len); | ||
1121 | } | ||
1122 | #endif | ||
1123 | |||
1114 | /* END CODE */ | 1124 | /* END CODE */ |