aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-01-04 01:10:25 +0000
committerErik Andersen <andersen@codepoet.org>2000-01-04 01:10:25 +0000
commit7dc160721ee3ceb76240a43d1454b45aaa9dbee4 (patch)
tree7532471be456e2c9f11eab88cb34f1e38abd184f
parent9c88cac5cbfb2ff70f800ee5bb3289e925aaa65f (diff)
downloadbusybox-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--Changelog19
-rw-r--r--Makefile2
-rw-r--r--applets/busybox.c6
-rw-r--r--archival/gunzip.c32
-rw-r--r--archival/tar.c121
-rw-r--r--busybox.c6
-rw-r--r--busybox.def.h6
-rw-r--r--busybox_functions.h11
-rw-r--r--coreutils/cp.c2
-rw-r--r--cp.c2
-rw-r--r--editors/sed.c2
-rw-r--r--gunzip.c32
-rw-r--r--init.c483
-rw-r--r--init/init.c483
-rw-r--r--internal.h3
-rw-r--r--kill.c3
-rw-r--r--procps/kill.c3
-rw-r--r--sed.c2
-rw-r--r--tar.c121
-rw-r--r--utility.c16
20 files changed, 779 insertions, 576 deletions
diff --git a/Changelog b/Changelog
index 37570d292..54fd3ca34 100644
--- a/Changelog
+++ b/Changelog
@@ -1,11 +1,11 @@
10.40 10.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
diff --git a/Makefile b/Makefile
index 73aa2fc90..4215b291b 100644
--- a/Makefile
+++ b/Makefile
@@ -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.
25DODEBUG=false 25DODEBUG=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
656int force = 0; /* don't ask questions, compress links (-f) */ 657int test_mode = 0; /* check file integrity option */
657int foreground; /* set if program run in foreground */ 658int foreground; /* set if program run in foreground */
658int maxbits = BITS; /* max bits per code for LZW */ 659int maxbits = BITS; /* max bits per code for LZW */
659int method = DEFLATED;/* compression method */ 660int 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;
106static int eofFlag; 107static int eofFlag;
107static long dataCc; 108static long dataCc;
108static int outFd; 109static int outFd;
109static char outName[TAR_NAME_SIZE]; 110static const char *outName;
110 111
112static int mode;
113static int uid;
114static int gid;
115static 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)
378static void 384static void
379readHeader (const TarHeader * hp, int fileCount, char **fileTable) 385readHeader (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)
720static void saveFile (const char *fileName, int seeLinks) 752static 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)
diff --git a/busybox.c b/busybox.c
index 403b14008..a35306915 100644
--- a/busybox.c
+++ b/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/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
4int
5mkswap(char *device_name, int pages, int check);
6/* pages = 0 for autodetection */
7
8int
9fdflush(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
diff --git a/cp.c b/cp.c
index 83460190a..4af73c274 100644
--- a/cp.c
+++ b/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
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"
diff --git a/gunzip.c b/gunzip.c
index 61391a33f..84f5d02b7 100644
--- a/gunzip.c
+++ b/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
656int force = 0; /* don't ask questions, compress links (-f) */ 657int test_mode = 0; /* check file integrity option */
657int foreground; /* set if program run in foreground */ 658int foreground; /* set if program run in foreground */
658int maxbits = BITS; /* max bits per code for LZW */ 659int maxbits = BITS; /* max bits per code for LZW */
659int method = DEFLATED;/* compression method */ 660int 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/init.c b/init.c
index b71c9f74e..be04ec34f 100644
--- a/init.c
+++ b/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 */
73typedef 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 */
83typedef struct initActionType{
84 const char* name;
85 initActionEnum action;
86} initActionType;
87
88static 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 */
99typedef struct initActionTag initAction;
100struct initActionTag {
101 pid_t pid;
102 char process[256];
103 char *console;
104 initAction *nextPtr;
105 initActionEnum action;
106};
107initAction* initActionList = NULL;
108
109
74static char *console = _PATH_CONSOLE; 110static char *console = _PATH_CONSOLE;
75static char *second_console = VT_SECONDARY; 111static char *second_console = VT_SECONDARY;
76static char *log = VT_LOG; 112static 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 */
101void message(int device, char *fmt, ...) 137void 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
301static pid_t run(const char * const* command, 338static 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,
365static void check_memory() 415static 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
388static void shutdown_system(void) 437static 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
491static 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
503void 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
520void 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
532void 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
452extern int init_main(int argc, char **argv) 612extern 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
619void 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
671choke:
672 //message(CONSOLE, "Bad entry:");
673 fprintf(stderr, "Bad inittab entry: %s", buf);
674 while (1) sleep(1);
675
676}
677
678
679extern 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 */
73typedef 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 */
83typedef struct initActionType{
84 const char* name;
85 initActionEnum action;
86} initActionType;
87
88static 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 */
99typedef struct initActionTag initAction;
100struct initActionTag {
101 pid_t pid;
102 char process[256];
103 char *console;
104 initAction *nextPtr;
105 initActionEnum action;
106};
107initAction* initActionList = NULL;
108
109
74static char *console = _PATH_CONSOLE; 110static char *console = _PATH_CONSOLE;
75static char *second_console = VT_SECONDARY; 111static char *second_console = VT_SECONDARY;
76static char *log = VT_LOG; 112static 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 */
101void message(int device, char *fmt, ...) 137void 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
301static pid_t run(const char * const* command, 338static 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,
365static void check_memory() 415static 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
388static void shutdown_system(void) 437static 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
491static 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
503void 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
520void 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
532void 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
452extern int init_main(int argc, char **argv) 612extern 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
619void 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
671choke:
672 //message(CONSOLE, "Bad entry:");
673 fprintf(stderr, "Bad inittab entry: %s", buf);
674 while (1) sleep(1);
675
676}
677
678
679extern 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);
169extern long getNum (const char *cp); 169extern long getNum (const char *cp);
170extern pid_t findInitPid(); 170extern pid_t findInitPid();
171 171
172#if (__GLIBC__ < 2) && defined BB_SYSLOGD
173extern 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() {}
diff --git a/kill.c b/kill.c
index 0ba6d76ce..e72b73493 100644
--- a/kill.c
+++ b/kill.c
@@ -183,7 +183,7 @@ extern int kill_main (int argc, char **argv)
183 183
184do_it_now: 184do_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
184do_it_now: 184do_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/sed.c b/sed.c
index 8e5f695c4..25777243d 100644
--- a/sed.c
+++ b/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"
diff --git a/tar.c b/tar.c
index 7167d95cd..a53370e85 100644
--- a/tar.c
+++ b/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;
106static int eofFlag; 107static int eofFlag;
107static long dataCc; 108static long dataCc;
108static int outFd; 109static int outFd;
109static char outName[TAR_NAME_SIZE]; 110static const char *outName;
110 111
112static int mode;
113static int uid;
114static int gid;
115static 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)
378static void 384static void
379readHeader (const TarHeader * hp, int fileCount, char **fileTable) 385readHeader (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)
720static void saveFile (const char *fileName, int seeLinks) 752static 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)
diff --git a/utility.c b/utility.c
index 2a840f78e..c20025cd2 100644
--- a/utility.c
+++ b/utility.c
@@ -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)
1114extern 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 */