aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Nottingham <notting@redhat.com>1999-09-02 00:57:26 +0000
committerBill Nottingham <notting@redhat.com>1999-09-02 00:57:26 +0000
commite6d28cc5aaeabd53ed652eec63c2c22bb3f7e97c (patch)
tree519a94d0646687a868681da20d91e311c54f023f
parentacd1b3af175819b9209cde675deb4a88af32e506 (diff)
downloadinitscripts-e6d28cc5aaeabd53ed652eec63c2c22bb3f7e97c.tar
initscripts-e6d28cc5aaeabd53ed652eec63c2c22bb3f7e97c.tar.gz
initscripts-e6d28cc5aaeabd53ed652eec63c2c22bb3f7e97c.tar.bz2
initscripts-e6d28cc5aaeabd53ed652eec63c2c22bb3f7e97c.tar.xz
initscripts-e6d28cc5aaeabd53ed652eec63c2c22bb3f7e97c.zip
add interactive prompt to make Cristian & Preston happy
-rwxr-xr-xrc.d/init.d/functions3
-rwxr-xr-xrc.d/rc5
-rwxr-xr-xrc.d/rc.sysinit16
-rw-r--r--src/Makefile3
-rw-r--r--src/getkey.c47
5 files changed, 72 insertions, 2 deletions
diff --git a/rc.d/init.d/functions b/rc.d/init.d/functions
index eca7f56f..54e3a556 100755
--- a/rc.d/init.d/functions
+++ b/rc.d/init.d/functions
@@ -230,6 +230,7 @@ echo_success() {
echo -n "OK"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n " ]"
+ echo -ne "\r"
return 0
}
@@ -240,6 +241,7 @@ echo_failure() {
echo -n "FAILED"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
+ echo -ne "\r"
return 1
}
@@ -250,6 +252,7 @@ echo_passed() {
echo -n "PASSED"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
+ echo -ne "\r"
return 1
}
diff --git a/rc.d/rc b/rc.d/rc
index bd0448c7..994814a8 100755
--- a/rc.d/rc
+++ b/rc.d/rc
@@ -21,10 +21,13 @@ export runlevel previous
# See if we want to be in user confirmation mode
if [ "$previous" = "N" ]; then
- if grep -i confirm /proc/cmdline >/dev/null ; then
+ if grep -i confirm /proc/cmdline >/dev/null || [ -f /tmp/confirm ] ; then
+ rm -f /tmp/confirm
CONFIRM=yes
+ echo "Entering interactive startup"
else
CONFIRM=
+ echo "Entering non-interactive startup"
fi
fi
diff --git a/rc.d/rc.sysinit b/rc.d/rc.sysinit
index 1b323314..7295b3a2 100755
--- a/rc.d/rc.sysinit
+++ b/rc.d/rc.sysinit
@@ -25,6 +25,16 @@ fi
# Source functions
. /etc/rc.d/init.d/functions
+# Print a banner. ;)
+echo -en "\t\t\tWelcome to "
+[ "$BOOTUP" != "serial" ] && echo -en "\\033[1;31m
+echo -en "Red Hat"
+[ "$BOOTUP" != "serial" ] && echo -en "\\033[0;39m"
+echo " Linux"
+echo -en "\t\tPress 'I' to enter interactive startup."
+echo
+sleep 2
+
# Fix console loglevel
/sbin/loglevel $LOGLEVEL
@@ -367,6 +377,8 @@ if [ ! -f /fastboot ]; then
fi
fi
+
+{
# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.
@@ -453,3 +465,7 @@ EOF
# Now that we have all of our basic modules loaded and the kernel going,
# let's dump the syslog ring somewhere so we can find it later
dmesg > /var/log/dmesg
+killall -TERM getkey >/dev/null 2>&1
+} &
+/sbin/getkey i && touch /tmp/confirm
+wait
diff --git a/src/Makefile b/src/Makefile
index 389c8b1c..8b9616ad 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
CFLAGS+=-Wall -D_GNU_SOURCE -g
-PROGS=usernetctl doexec netreport testd usleep ipcalc initlog minilogd loglevel
+PROGS=usernetctl doexec netreport testd usleep ipcalc initlog minilogd loglevel getkey
INITLOG_OBJS=initlog.o process.o
USLEEP_OBJS=usleep.o
@@ -19,6 +19,7 @@ install:
install -s -m 755 initlog $(ROOT)/sbin/initlog
install -s -m 755 minilogd $(ROOT)/sbin/minilogd
install -s -m 755 loglevel $(ROOT)/sbin/loglevel
+ install -s -m 755 getkey $(ROOT)/sbin/getkey
install -m 644 initlog.1 $(ROOT)/usr/man/man1
install -m 644 doexec.1 $(ROOT)/usr/man/man1
install -m 644 netreport.1 $(ROOT)/usr/man/man1
diff --git a/src/getkey.c b/src/getkey.c
new file mode 100644
index 00000000..b17558a3
--- /dev/null
+++ b/src/getkey.c
@@ -0,0 +1,47 @@
+
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* A very simple keygrabber. */
+
+struct termios tp;
+
+void reset_term(int x) {
+ tcsetattr(0,TCSANOW,&tp);
+ exit(x);
+}
+
+int main(int argc, char **argv) {
+ char foo[2];
+ int tp_if,tp_of,tp_lf;
+ int x;
+
+ if (argc>1) {
+ for (x=0;argv[1][x];x++) argv[1][x]=toupper(argv[1][x]);
+ }
+ foo[0]=foo[1]='\0';
+ signal(SIGTERM,reset_term);
+ tcgetattr(0,&tp);
+ tp_if=tp.c_iflag;
+ tp_of=tp.c_oflag;
+ tp_lf=tp.c_lflag;
+ tp.c_iflag=0;
+ tp.c_oflag &= ~OPOST;
+ tp.c_lflag &= ~(ISIG | ICANON);
+ tcsetattr(0,TCSANOW,&tp);
+ tp.c_iflag=tp_if;
+ tp.c_oflag=tp_of;
+ tp.c_lflag=tp_lf;
+ while (1) {
+ read(0,foo,1);
+ foo[0]=toupper(foo[0]);
+ /* Die if we get a control-c or control-d */
+ if (foo[0]==3 || foo[0]==4) reset_term(1);
+ if ((!argv[1]) || strstr(argv[1],foo)) {
+ reset_term(0);
+ }
+ }
+}
ef='#n331'>331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
package common;

use diagnostics;
use strict;
use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK $printable_chars $sizeof_int $bitof_int $cancel $SECTORSIZE);

@ISA = qw(Exporter);
%EXPORT_TAGS = (
    common     => [ qw(__ even odd min max sqr sum and_ or_ sign product bool invbool listlength bool2text text2bool to_int to_float ikeys member divide is_empty_array_ref is_empty_hash_ref add2hash add2hash_ set_new set_add round round_up round_down first second top uniq translate untranslate warp_text formatAlaTeX formatLines deref) ],
    functional => [ qw(fold_left compose map_index grep_index map_each grep_each map_tab_hash mapn mapn_ difference2 before_leaving catch_cdie cdie) ],
    file       => [ qw(dirname basename touch all glob_ cat_ output symlinkf chop_ mode typeFromMagic) ],
    system     => [ qw(sync makedev unmakedev psizeof strcpy gettimeofday syscall_ salt getVarsFromSh setVarsInSh setVarsInCsh substInFile availableRam availableMemory removeXiBSuffix template2file formatTime) ],
    constant   => [ qw($printable_chars $sizeof_int $bitof_int $SECTORSIZE) ],
);
@EXPORT_OK = map { @$_ } values %EXPORT_TAGS;


#-#####################################################################################
#- Globals
#-#####################################################################################
$printable_chars = "\x20-\x7E";
$sizeof_int      = psizeof("i");
$bitof_int       = $sizeof_int * 8;
$SECTORSIZE      = 512;

#-#####################################################################################
#- Functions
#-#####################################################################################

sub fold_left(&@) {
    my $f = shift;
    local $a = shift;
    foreach $b (@_) { $a = &$f() }
    $a
}

sub _ { my $s = shift @_; sprintf translate($s), @_ }
#-delete $main::{'_'};
sub __ { $_[0] }
sub even($) { $_[0] % 2 == 0 }
sub odd($)  { $_[0] % 2 == 1 }
sub min { fold_left { $a < $b ? $a : $b } @_ }
sub max { fold_left { $a > $b ? $a : $b } @_ }
sub sum { fold_left { $a + $b } @_ }
sub and_{ fold_left { $a && $b } @_ }
sub or_ { fold_left { $a || $b } @_ }
sub sqr { $_[0] * $_[0] }
sub sign { $_[0] <=> 0 }
sub product { fold_left { $a * $b } @_ }
sub first { $_[0] }
sub second { $_[1] }
sub top { $_[-1] }
sub uniq { my %l; @l{@_} = (); keys %l }
sub to_int { $_[0] =~ /(\d*)/; $1 }
sub to_float { $_[0] =~ /(\d*(\.\d*)?)/; $1 }
sub ikeys { my %l = @_; sort { $a <=> $b } keys %l }
sub add2hash($$)  { my ($a, $b) = @_; while (my ($k, $v) = each %{$b || {}}) { $a->{$k} ||= $v } }
sub add2hash_($$) { my ($a, $b) = @_; while (my ($k, $v) = each %{$b || {}}) { exists $a->{$k} or $a->{$k} = $v } }
sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 }
sub dirname { @_ == 1 or die "usage: dirname <name>\n"; local $_ = shift; s|[^/]*/*\s*$||; s|(.)/*$|$1|; $_ || '.' }
sub basename { @_ == 1 or die "usage: basename <name>\n"; local $_ = shift; s|/*\s*$||; s|.*/||; $_ }
sub bool($) { $_[0] ? 1 : 0 }
sub invbool { my $a = shift; $$a = !$$a; $$a }
sub listlength { scalar @_ }
sub bool2text { $_[0] ? "true" : "false" }
sub text2bool { my $t = lc($_[0]); $t eq "true" || $t eq "yes" ? 1 : 0 }
sub strcpy { substr($_[0], $_[2] || 0, length $_[1]) = $_[1] }
sub cat_ { local *F; open F, $_[0] or $_[1] ? die "cat of file $_[0] failed: $!\n" : return; my @l = <F>; wantarray ? @l : join '', @l }
sub output { my $f = shift; local *F; open F, ">$f" or die "output in file $f failed: $!\n"; print F foreach @_; }
sub deref { ref $_[0] eq "ARRAY" ? @{$_[0]} : ref $_[0] eq "HASH" ? %{$_[0]} : $_[0] }
sub linkf { unlink $_[1]; link $_[0], $_[1] }
sub symlinkf { unlink $_[1]; symlink $_[0], $_[1] }
sub chop_ { map { my $l = $_; chomp $l; $l } @_ }
sub divide { my $d = int $_[0] / $_[1]; wantarray ? ($d, $_[0] % $_[1]) : $d }
sub round { int ($_[0] + 0.5) }
sub round_up { my ($i, $r) = @_; $i += $r - ($i + $r - 1) % $r - 1; }
sub round_down { my ($i, $r) = @_; $i -= $i % $r; }
sub is_empty_array_ref { my $a = shift; !defined $a || @$a == 0 }
sub is_empty_hash_ref { my $a = shift; !defined $a || keys(%$a) == 0 }
sub difference2 { my %l; @l{@{$_[1]}} = (); grep { !exists $l{$_} } @{$_[0]} }
sub intersection { my (%l, @m); @l{@{shift @_}} = (); foreach (@_) { @m = grep { exists $l{$_} } @$_; %l = (); @l{@m} = (); } keys %l }

sub set_new(@) { my %l; @l{@_} = undef; { list => [ @_ ], hash => \%l } }
sub set_add($@) { my $o = shift; foreach (@_) { exists $o->{hash}{$_} and next; push @{$o->{list}}, $_; $o->{hash}{$_} = undef } }

sub sync { syscall_('sync') }
sub gettimeofday { my $t = pack "LL"; syscall_('gettimeofday', $t, 0) or die "gettimeofday failed: $!\n"; unpack("LL", $t) }

sub remove_spaces { local $_ = shift; s/^ +//; s/ +$//; $_ }
sub mode { my @l = stat $_[0] or die "unable to get mode of file $_[0]: $!\n"; $l[2] }
sub psizeof { length pack $_[0] }

sub touch {
    my ($f) = @_;
    unless (-e $f) {
	local *F;
	open F, ">$f";
    }
    my $now = time;
    utime $now, $now, $f;
}

sub map_index(&@) {
    my $f = shift;
    my $v; local $::i = 0;
    map { $v = &$f($::i); $::i++; $v } @_;
}
sub grep_index(&@) {
    my $f = shift;
    my $v; local $::i = 0;
    grep { $v = &$f($::i); $::i++; $v } @_;
}
sub map_each(&%) {
    my ($f, %h) = @_;
    my @l;
    local ($::a, $::b);
    while (($::a, $::b) = each %h) { push @l, &$f($::a, $::b) }
    @l;
}
sub grep_each(&%) {
    my ($f, %h) = @_;
    my %l;
    local ($::a, $::b);
    while (($::a, $::b) = each %h) { $l{$::a} = $::b if &$f($::a, $::b) }
    %l;
}

#- pseudo-array-hash :)
sub map_tab_hash(&$@) {
    my ($f, $fields, @tab_hash) = @_;
    my %hash;
    my $key = { map_index {($_, $::i + 1)} @{$fields} };

    for (my $i = 0; $i < @tab_hash; $i += 2) {
	my $h = [$key, @{$tab_hash[$i + 1]}];
	&$f($i, $h) if $f;
	$hash{ $tab_hash[$i] } = $h;
      }
    %hash;
}

sub smapn {
    my $f = shift;
    my $n = shift;
    my @r = ();
    for (my $i = 0; $i < $n; $i++) { push @r, &$f(map { $_->[$i] } @_); }
    @r
}
sub mapn(&@) {
    my $f = shift;
    smapn($f, min(map { scalar @$_ } @_), @_);
}
sub mapn_(&@) {
    my $f = shift;
    smapn($f, max(map { scalar @$_ } @_), @_);
}


sub add_f4before_leaving {
    my ($f, $b, $name) = @_;

    unless ($common::before_leaving::{$name}) {
	no strict 'refs';
	${"common::before_leaving::$name"} = 1;
	${"common::before_leaving::list"} = 1;
    }
    local *N = *{$common::before_leaving::{$name}};
    my $list = *common::before_leaving::list;
    $list->{$b}{$name} = $f;
    *N = sub {
	my $f = $list->{$_[0]}{$name} or die '';
	$name eq 'DESTROY' and delete $list->{$_[0]};
	goto $f;
    } unless defined &{*N};

}

#- ! the functions are not called in the order wanted, in case of multiple before_leaving :(
sub before_leaving(&) {
    my ($f) = @_;
    my $b = bless {}, 'common::before_leaving';
    add_f4before_leaving($f, $b, 'DESTROY');
    $b;
}

sub catch_cdie(&&) {
    my ($f, $catch) = @_;

    local @common::cdie_catches;
    unshift @common::cdie_catches, $catch;
    &$f();
}

sub cdie($;&) {
    my ($err, $f) = @_;
    foreach (@common::cdie_catches) {
	$@ = $err;
	&{$_}(\$err) and return;
    }
    die $err;
}

sub all {
    my $d = shift;

    local *F;
    opendir F, $d or die "all: can't open dir $d: $!\n";
    my @l = grep { $_ ne '.' && $_ ne '..' } readdir F;
    closedir F;

    @l;
}

sub glob_ {
    my ($d, $f) = ($_[0] =~ /\*/) ? (dirname($_[0]), basename($_[0])) : ($_[0], '*');

    $d =~ /\*/ and die "glob_: wildcard in directory not handled ($_[0])\n";
    ($f = quotemeta $f) =~ s/\\\*/.*/g;

    $d =~ m|/$| or $d .= '/';
    map { $d eq './' ? $_ : "$d$_" } grep { /^$f$/ } all($d);
}


sub syscall_ {
    my $f = shift;

    require 'syscall.ph';
    syscall(&{$common::{"SYS_$f"}}, @_) == 0;
}

sub salt($) {
    my ($nb) = @_;