151
190
for my $key (split(/\|/, lc($lsbheaders))) {
152
191
if (!exists $lsbinfo{$key}) {
153
print STDERR "update-rc.d: warning: $initdscript missing LSB keyword '$key'\n";
192
warning "$initdscript missing LSB keyword '$key'\n";
199
# Process the arguments after the "enable" or "disable" keyword.
203
my ($action, %lvls, @start, @stop, @xstartlinks);
206
print " System start/stop links for $initd/$bn do not exist.\n";
212
while ($#argv > 0 && shift @argv) {
213
if ($argv[0] =~ /^[S2-5]$/) {
216
&usage ("expected 'S' '2' '3' '4' or '5'");
220
$lvls{$_}++ for ('S', '2', '3', '4', '5');
223
push(@start, glob($etcd . '[2-5S].d/[KS][0-9][0-9]' . $bn));
226
my $islink = &is_link (undef, $_, $bn);
229
next unless my ($lvl, $sk, $seq) = m/^$etcd([2-5S])\.d\/([SK])([0-9]{2})$bn$/;
230
$startlinks[$lvl] = $sk . $seq;
232
if ($action eq 'disable' and $sk eq 'S' and $lvls{$lvl}) {
233
$xstartlinks[$lvl] = 'K' . sprintf "%02d", (100 - $seq);
234
} elsif ($action eq 'enable' and $sk eq 'K' and $lvls{$lvl}) {
235
$xstartlinks[$lvl] = 'S' . sprintf "%02d", -($seq - 100);
237
$xstartlinks[$lvl] = $sk . $seq;
241
push(@stop, glob($etcd . '[016].d/[KS][0-9][0-9]' . $bn));
244
my $islink = &is_link (undef, $_, $bn);
247
next unless my ($lvl, $sk, $seq) = m/^$etcd([016])\.d\/([SK])([0-9]{2})$bn$/;
248
$stoplinks[$lvl] = $sk . $seq;
251
if ($action eq 'disable') {
252
print " Disabling system startup links for $initd/$bn ...\n";
253
} elsif ($action eq 'enable') {
254
print " Enabling system startup links for $initd/$bn ...\n";
257
&checklinks ("remove");
258
@startlinks = @xstartlinks;
160
263
# Process the arguments after the "defaults" keyword.
163
267
my ($start, $stop) = (20, 20);
165
&usage ("defaults takes only one or two codenumbers") if ($#ARGV > 2);
166
$start = $stop = $ARGV[1] if ($#ARGV >= 1);
167
$stop = $ARGV[2] if ($#ARGV >= 2);
269
&usage ("defaults takes only one or two codenumbers") if ($#argv > 2);
270
$start = $stop = $argv[1] if ($#argv >= 1);
271
$stop = $argv[2] if ($#argv >= 2);
168
272
&usage ("codenumber must be a number between 0 and 99")
169
273
if ($start !~ /^\d\d?$/ || $stop !~ /^\d\d?$/);
180
# Process the arguments after the "multiuser" keyword.
183
my ($start, $stop) = (20, 20);
185
print STDERR "update-rc.d: warning: multiuser is deprecated; specify runlevels manually\n";
186
&usage ("multiuser takes only one or two codenumbers") if ($#ARGV > 2);
187
$start = $stop = $ARGV[1] if ($#ARGV >= 1);
188
$stop = $ARGV[2] if ($#ARGV >= 2);
189
&usage ("codenumber must be a number between 0 and 99")
190
if ($start !~ /^\d\d?$/ || $stop !~ /^\d\d?$/);
192
$start = sprintf("%02d", $start);
193
$stop = sprintf("%02d", $stop);
195
$stoplinks[1] = "K$stop";
196
$startlinks[2] = $startlinks[3] =
197
$startlinks[4] = $startlinks[5] = "S$start";
202
284
# Process the arguments after the start or stop keyword.
206
288
my($letter, $NN, $level);
208
while ($#ARGV >= 0) {
209
if ($ARGV[0] eq 'start') { $letter = 'S'; }
210
elsif ($ARGV[0] eq 'stop') { $letter = 'K' }
290
while ($#argv >= 0) {
291
if ($argv[0] eq 'start') { $letter = 'S'; }
292
elsif ($argv[0] eq 'stop') { $letter = 'K'; }
212
294
&usage("expected start|stop");
215
if ($ARGV[1] !~ /^\d\d?$/) {
216
&usage("expected NN after $ARGV[0]");
218
$NN = sprintf("%02d", $ARGV[1]);
220
shift @ARGV; shift @ARGV;
221
$level = shift @ARGV;
222
&usage("action with list of runlevels not terminated by \".\"")
223
if ($ARGV[$#ARGV] ne '.');
297
if ($argv[1] !~ /^\d\d?$/) {
298
&usage("expected NN after $argv[0]");
300
$NN = sprintf("%02d", $argv[1]);
302
if ($argv[-1] ne '.') {
303
&usage("start|stop arguments not terminated by \".\"");
306
shift @argv; shift @argv;
307
$level = shift @argv;
225
309
if ($level !~ m/^[0-9S]$/) {
357
sub insserv_updatercd {
364
my @orig_argv = @args;
366
while($#args >= 0 && ($_ = $args[0]) =~ /^-/) {
368
if (/^-n$/) { push(@opts, $_); $notreally++; next }
369
if (/^-f$/) { push(@opts, $_); next }
370
if (/^-h|--help$/) { &usage; }
371
usage("unknown option");
374
usage("not enough arguments") if ($#args < 1);
376
$scriptname = shift @args;
377
$action = shift @args;
378
if ("remove" eq $action) {
379
if ( -f "/etc/init.d/$scriptname" ) {
380
my $rc = system "insserv", @opts, "-r", $scriptname;
381
if (0 == $rc && !$notreally) {
382
save_last_action($scriptname, @orig_argv);
386
# insserv removes all dangling symlinks, no need to tell it
388
my $rc = system "insserv", @opts;
389
if (0 == $rc && !$notreally) {
390
save_last_action($scriptname, @orig_argv);
394
} elsif ("defaults" eq $action || "start" eq $action ||
396
# All start/stop/defaults arguments are discarded so emit a
397
# message if arguments have been given and are in conflict
398
# with Default-Start/Default-Stop values of LSB comment.
399
cmp_args_with_defaults($scriptname, $action, @args);
401
if ( -f "/etc/init.d/$scriptname" ) {
402
my $rc = system "insserv", @opts, $scriptname;
403
if (0 == $rc && !$notreally) {
404
save_last_action($scriptname, @orig_argv);
408
error("initscript does not exist: /etc/init.d/$scriptname");
410
} elsif ("disable" eq $action || "enable" eq $action) {
411
insserv_toggle($notreally, $action, $scriptname, @args);
412
# Call insserv to resequence modified links
413
my $rc = system "insserv", @opts, $scriptname;
414
if (0 == $rc && !$notreally) {
415
save_last_action($scriptname, @orig_argv);
423
sub parse_def_start_stop {
425
my (%lsb, @def_start_lvls, @def_stop_lvls);
427
open my $fh, '<', $script or error("unable to read $script");
430
if (m/^### BEGIN INIT INFO$/) {
433
elsif (m/^### END INIT INFO$/) {
437
elsif ($lsb{'begin'} and not $lsb{'end'}) {
438
if (m/^# Default-Start:\s*(\S?.*)$/) {
439
@def_start_lvls = split(' ', $1);
441
if (m/^# Default-Stop:\s*(\S?.*)$/) {
442
@def_stop_lvls = split(' ', $1);
448
return (\@def_start_lvls, \@def_stop_lvls);
451
sub lsb_header_for_script {
454
foreach my $file ("/etc/insserv/overrides/$name", "/etc/init.d/$name",
455
"/usr/share/insserv/overrides/$name") {
456
return $file if -s $file;
459
error("cannot find a LSB script for $name");
462
sub cmp_args_with_defaults {
463
my ($name, $act) = (shift, shift);
464
my ($lsb_start_ref, $lsb_stop_ref, $arg_str, $lsb_str);
465
my (@arg_start_lvls, @arg_stop_lvls, @lsb_start_lvls, @lsb_stop_lvls);
467
($lsb_start_ref, $lsb_stop_ref) = parse_def_start_stop("/etc/init.d/$name");
468
@lsb_start_lvls = @$lsb_start_ref;
469
@lsb_stop_lvls = @$lsb_stop_ref;
470
return if (!@lsb_start_lvls and !@lsb_stop_lvls);
472
if ($act eq 'defaults') {
473
@arg_start_lvls = (2, 3, 4, 5);
474
@arg_stop_lvls = (0, 1, 6);
475
} elsif ($act eq 'start' or $act eq 'stop') {
476
my $start = $act eq 'start' ? 1 : 0;
477
my $stop = $act eq 'stop' ? 1 : 0;
479
# The legacy part of this program passes arguments starting with
480
# "start|stop NN x y z ." but the insserv part gives argument list
481
# starting with sequence number (ie. strips off leading "start|stop")
482
# Start processing arguments immediately after the first seq number.
483
my $argi = $_[0] eq $act ? 2 : 1;
485
while (defined $_[$argi]) {
488
# Runlevels 0 and 6 are always stop runlevels
489
if ($arg eq 0 or $arg eq 6) {
490
$start = 0; $stop = 1;
491
} elsif ($arg eq 'start') {
492
$start = 1; $stop = 0; $argi++; next;
493
} elsif ($arg eq 'stop') {
494
$start = 0; $stop = 1; $argi++; next;
495
} elsif ($arg eq '.') {
498
push(@arg_start_lvls, $arg) if $start;
499
push(@arg_stop_lvls, $arg) if $stop;
505
if ($#arg_start_lvls != $#lsb_start_lvls or
506
join("\0", sort @arg_start_lvls) ne join("\0", sort @lsb_start_lvls)) {
507
$arg_str = @arg_start_lvls ? "@arg_start_lvls" : "none";
508
$lsb_str = @lsb_start_lvls ? "@lsb_start_lvls" : "none";
509
warning "$name start runlevel arguments ($arg_str) do not match",
510
"LSB Default-Start values ($lsb_str)";
512
if ($#arg_stop_lvls != $#lsb_stop_lvls or
513
join("\0", sort @arg_stop_lvls) ne join("\0", sort @lsb_stop_lvls)) {
514
$arg_str = @arg_stop_lvls ? "@arg_stop_lvls" : "none";
515
$lsb_str = @lsb_stop_lvls ? "@lsb_stop_lvls" : "none";
516
warning "$name stop runlevel arguments ($arg_str) do not match",
517
"LSB Default-Stop values ($lsb_str)";
522
my ($dryrun, $act, $name) = (shift, shift, shift);
523
my (@toggle_lvls, $start_lvls, $stop_lvls, @symlinks);
524
my $lsb_header = lsb_header_for_script($name);
526
# Extra arguments to disable|enable action are runlevels. If none
527
# given parse LSB info for Default-Start value.
531
($start_lvls, $stop_lvls) = parse_def_start_stop($lsb_header);
532
@toggle_lvls = @$start_lvls;
533
if ($#toggle_lvls < 0) {
534
error("$name Default-Start contains no runlevels, aborting.");
538
# Find symlinks in rc.d directories. Refuse to modify links in runlevels
539
# not used for normal system start sequence.
540
for my $lvl (@toggle_lvls) {
541
if ($lvl !~ /^[S2345]$/) {
542
warning("$act action will have no effect on runlevel $lvl");
545
push(@symlinks, $_) for glob("/etc/rc$lvl.d/[SK][0-9][0-9]$name");
549
error("no runlevel symlinks to modify, aborting!");
552
# Toggle S/K bit of script symlink.
553
for my $cur_lnk (@symlinks) {
555
my @new_lnk = split(//, $cur_lnk);
557
if ("disable" eq $act) {
558
$sk = rindex($cur_lnk, '/S') + 1;
562
$sk = rindex($cur_lnk, '/K') + 1;
568
printf("rename(%s, %s)\n", $cur_lnk, join('', @new_lnk));
572
rename($cur_lnk, join('', @new_lnk)) or error($!);