diff --git a/svc b/svc index f2810af..967856b 100644 --- a/svc +++ b/svc @@ -3,9 +3,6 @@ # runit sv utility ignores evironment variable SVDIR # and unable to list services, fully relying to user this knowlege -# TODO handle root user case as system mode! -# TODO handle system mode correctly - use strict; use warnings "all"; use JSON::PP; @@ -14,29 +11,45 @@ sub help; sub ctrl ($); sub status; -my $sep = $/; -$/ = ''; +my $c; -open (CONF, "$ENV{HOME}/.local/etc/svc.json") or die "No config at $ENV{HOME}/.local/etc/svc.json\n"; +if ($>) { +# looks like we run in user-mode, so manage user services + die "\$HOME is not set\n" unless (defined($ENV{HOME})); + die "$ENV{HOME} does not exist\n" unless (-d $ENV{HOME}); -my $c = ; -close CONF; -$/ = $sep; + my $sep = $/; + $/ = ''; -$c = decode_json($c); +# TODO: actually, to be the most XDG-compatible, we should put config to $ENV{HOME}/.config/svc/svc.json + open (CONF, "$ENV{HOME}/.local/etc/svc.json") or die "No config at $ENV{HOME}/.local/etc/svc.json\n"; + $c = ; + close CONF; + $/ = $sep; -if ($c->{mode} eq 'user') { - die "\$HOME is no set\n" unless (defined($ENV{HOME})); - die "$ENV{HOME} does not exist" unless (-d $ENV{HOME}); - chdir $ENV{HOME}; - die "No such directory $ENV{HOME}$c->{dir}\n" unless(-d "$ENV{HOME}$c->{dir}"); - chdir "$ENV{HOME}$c->{dir}"; + $c = decode_json($c); + $c->{dir} = sprintf("%s%s", $ENV{HOME}, $c->{dir}); + $c->{servicedir} = sprintf("%s%s", $ENV{HOME}, $c->{servicedir}); } else { - die "No such directory $c->{dir}" unless(-d $c->{dir}); - chdir $c->{dir}; +# looks like we run with root privileges, manage system services + $c->{mode} = "system"; + $c->{dir} = "/etc/service"; + + if (-d "/etc/service.d") { + $c->{servicedir} = "/etc/service.d"; + } else { + +# guideline of runit suggest to use /service directory, also sv utility expects services placed there by default + $c->{servicedir} = "/service"; + } + + $c->{timeout} = 3; } -unless(defined($ARGV[0])) { +die "No such directory $c->{dir}\n" unless (-d $c->{dir}); +chdir $c->{dir}; + +unless (defined($ARGV[0])) { help; } else { if ($ARGV[0] ne 'list') { @@ -48,32 +61,32 @@ if ($ARGV[0] eq 'list') { my $d; if (defined($ARGV[1]) && $ARGV[1] eq '--all') { - $d = "$ENV{HOME}$c->{servicedir}"; + $d = $c->{servicedir}; } else { - $d = "$ENV{HOME}$c->{dir}"; + $d = $c->{dir}; } - opendir(D, $d) or die "Unable to list services\n"; - print join("\n", sort(grep {!/^\.{1,2}$/} readdir(D))) . "\n"; + opendir(D, $d) or die "Unable to list services, no such directory $d\n"; + print join("\n", sort (grep {!/^\.{1,2}$/} readdir(D))) . "\n"; closedir D; } elsif ($ARGV[1] eq 'disable') { - my $d = "$ENV{HOME}$c->{dir}/$ARGV[0]"; + my $d = "$c->{dir}/$ARGV[0]"; if (-l $d) { - unlink("$d") or die "Unable to disable $ARGV[0]\n"; + unlink ("$d") or die "Unable to disable $ARGV[0]\n"; } else { die "No such service $ARGV[0]\n"; } } elsif ($ARGV[1] eq 'enable') { - my $d = "$ENV{HOME}$c->{dir}/$ARGV[0]"; + my $d = "$c->{dir}/$ARGV[0]"; if (-l $d) { die "Service $ARGV[0] already enabled\n"; } else { - my $svcdir = "$ENV{HOME}$c->{servicedir}/$ARGV[0]"; + my $svcdir = "$c->{servicedir}/$ARGV[0]"; if (-d $svcdir) { - symlink($svcdir, $d) or die "Unable to enable service $ARGV[0]\n"; + symlink ($svcdir, $d) or die "Unable to enable service $ARGV[0]\n"; } else { die "No such service $ARGV[0]\n"; } @@ -132,16 +145,17 @@ sub help { sub ctrl ($) { my $command = shift; - open (C, ">", "control") or die; + open (C, ">", "control") or die "Unable to write to control socket\n"; print C $command; close C; } sub status { - open (S, "stat") or die; + open (S, "stat") or die "Unable to read status.\n"; my $status = ; - chomp($status); + chomp $status; close S; return $status; } -# vim: set ft=perl noet ai : + +# vim: set ft=perl noet ai ts=4 sw=4 sts=4: diff --git a/svc.json b/svc.json index 9535917..fc37f3b 100644 --- a/svc.json +++ b/svc.json @@ -1,5 +1,6 @@ { "mode": "user", "dir": "/.local/etc/services", + "servicedir": "/.local/etc/service.d", "timeout": 3 }