diff --git a/init/config.info b/init/config.info
index 9ed4b0d3b..7f778fa2e 100644
--- a/init/config.info
+++ b/init/config.info
@@ -1,11 +1,12 @@
line1=Configurable options,11
expert=Allow selection of individual runlevels?,1,1-Yes,0-No
desc=Display actions with descriptions,1,2-Yes, and show all runlevels,1-Yes,0-No
+systemd_dedicated=Hide systemd services table?,1,-No,1-Yes
order=Show boot order of actions?,1,1-Yes,0-No
status_check=Show current status of actions,1,2-On index and action pages,1-On action page only,0-No
sort_mode=Sort actions by,1,1-Boot order,0-Name
line2=System configuration,11
-init_mode=Boot system,4,-Detect automatically,init-SysV init,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-FreeBSD RC scripts,win32-Windows services,local-Single boot script
+init_mode=Boot system,4,-Detect automatically,systemd-Systemd,init-SysV init,openrc-OpenRC,upstart-Upstart,local-Single boot script,rc-FreeBSD RC scripts,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Windows services
init_base=Directory in which runlevel directories are located,0
init_dir=Directory containing master init scripts,0
order_digits=Number of digits in action order,0
@@ -17,8 +18,8 @@ shutdown_command=Command to shutdown the system,0
inittab_id=inittab ID for bootup runlevel,0
rc_dir=FreeBSD rc scripts directories,3,None
rc_conf=FreeBSD configuration files,3,None
-line3=OSX system configuration,11
-startup_dirs=Darwin StartupItems directories,0
+line3=macOS StartupItems configuration,11
+startup_dirs=macOS StartupItems directories,0
darwin_setup=Directory for custom StartupItems,0
-hostconfig=Darwin hostconfig file,0
+hostconfig=Legacy hostconfig file,0
plist=Name of plist in a StartupItems directory,0
diff --git a/init/config.info.ca b/init/config.info.ca
index 02d2e5360..2388274e4 100644
--- a/init/config.info.ca
+++ b/init/config.info.ca
@@ -5,7 +5,7 @@ order=Mostra l'ordre d'engegada de les accions,1,1-Sí,0-No
status_check=Mostra l'estat actual de les accions,1,2-A les pàgines d'índex i de l'acció,1-Només a la pàgina de l'acció,0-No
sort_mode=Ordena les accions per,1,1-Ordre d'engegada,0-Nom
line2=Configuració del sistema,11
-init_mode=Engegada del sistema,4,-Detecta-ho automàticament,init-Init de SysV,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-Scripts RC de FreeBSD,win32-Serveis Windows,local-Script únic d'engegada
+init_mode=Engegada del sistema,4,-Detecta-ho automàticament,systemd-Systemd,init-Init de SysV,openrc-OpenRC,upstart-Upstart,local-Script únic d'engegada,rc-Scripts RC de FreeBSD,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Serveis Windows
init_base=Directori on s'allotgen els directoris de nivells d'execució,0
init_dir=Directori que conté els scripts init mestres,0
order_digits=Nombre de dígits de l'ordre de l'acció,0
diff --git a/init/config.info.de b/init/config.info.de
index 4a0b7ffef..a54c5687d 100644
--- a/init/config.info.de
+++ b/init/config.info.de
@@ -5,7 +5,7 @@ order=Zeige die Aktionen in Reihenfolge des Starts an?,1,1-Ja,0-Nein
status_check=Zeige aktuellen Status der Aktionen,1,2-Auf Index- und Aktionen-Seite,1-Nur auf der Aktionen-Seite,0-Nein
sort_mode=Sortiere Aktionen nach,1,1-Boot-Reihenfolge,0-Name
line2=Systemkonfiguration,11
-init_mode=Boot-System,4,-automatisch erkennen,init-SysV init,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-FreeBSD RC Script,win32-Windows-Dienste,local-Single Bootskript
+init_mode=Boot-System,4,-automatisch erkennen,systemd-Systemd,init-SysV init,openrc-OpenRC,upstart-Upstart,local-Single Bootskript,rc-FreeBSD RC Script,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Windows-Dienste
init_base=Verzeichnis, in dem die Runlevel-Verzeichnisse liegen,0
init_dir=Verzeichnis, in dem das Haupt-Skript liegt,0
order_digits=Anzahl Ziffern in Aktionsreihenfolge,0
diff --git a/init/config.info.no b/init/config.info.no
index 227712c50..c75fcf84e 100644
--- a/init/config.info.no
+++ b/init/config.info.no
@@ -5,7 +5,7 @@ order=Vis handlingenes oppstartsrekkefølge?1,1-Ja,0-Nei
status_check=Vis handlingenes gjeldende status,1,2-På indeks- og handlingssider,1-Bare på handlingssider,0-Nei
sort_mode=Sorter handlinger etter,1,1-Oppstartrekkefølge,0-Navn
line2=System konfigurasjon,11
-init_mode=Oppstartssystem,4,-Oppdag automatisk,init-SysV init,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-FreeBSD RC scripts,win32-Windows tjenester,local-Enkelt oppstartsscript
+init_mode=Oppstartssystem,4,-Oppdag automatisk,systemd-Systemd,init-SysV init,openrc-OpenRC,upstart-Upstart,local-Enkelt oppstartsscript,rc-FreeBSD RC scripts,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Windows tjenester
init_base=Katalog hvor kjøretids-kataloger finnes,0
init_dir=Katalog som inneholder master init scripts,0
order_digits=Antall sifre i handlingssortering,0
diff --git a/init/index.cgi b/init/index.cgi
index c87868ae9..31cb73e1b 100755
--- a/init/index.cgi
+++ b/init/index.cgi
@@ -329,70 +329,74 @@ elsif ($init_mode eq "upstart" && $access{'bootup'}) {
}
elsif ($init_mode eq "systemd" && $access{'bootup'}) {
- # Show systemd actions
- print &ui_form_start("mass_systemd.cgi", "post");
- @links = ( &select_all_link("d"),
- &select_invert_link("d"),
- &ui_link("edit_systemd.cgi?new=1", $text{'index_sadd'}) );
- print &ui_links_row(\@links);
- print &ui_columns_start([ "", $text{'systemd_name'},
- $config{'desc'} ? $text{'systemd_desc'} : (),
- $text{'systemd_type'},
- $text{'systemd_status'},
- $text{'systemd_boot'},
- $text{'index_ustatus'} ]);
- my $units_piped = join('|', map { quotemeta } &get_systemd_unit_types());
- foreach $u (&list_systemd_services()) {
- if ($u->{'legacy'}) {
- $l = "edit_action.cgi?0+".&urlize($u->{'name'});
- }
- else {
- $l = "edit_systemd.cgi?name=".&urlize($u->{'name'});
- }
- my $sname = $u->{'name'};
- my ($type) = $sname =~ /\.([^.]+)$/;
- if (defined($type) && $type =~ /^(?:$units_piped)$/) {
- $sname =~ s/\.$type$//;
- }
- else {
- $type = '';
- }
- my $title = ($u->{'boot'} == -1 ?
- &html_escape($sname) :
- &ui_link($l, &html_escape($sname)));
- my $desc = $config{'desc'} ? &html_escape($u->{'desc'}) : undef;
- print &ui_columns_row([
- &ui_checkbox("d", $u->{'name'}, undef),
- $title,
- $desc // (),
- $type,
- $u->{'fullstatus'} || "$text{'index_unknown'}",
- $u->{'boot'} == 1 ?
- &ui_text_color("$text{'yes'}", 'success') :
- $u->{'boot'} == 2 ?
- &ui_text_color("$text{'index_sboot6'}", 'success') :
- $u->{'boot'} == -1 ?
- &ui_text_color("$text{'index_sboot5'}", 'warn') :
- &ui_text_color("$text{'no'}", 'warn'),
- $u->{'status'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
- $u->{'status'} == 0 ?
- &ui_text_color("$text{'no'}", 'warn') :
- "$text{'index_unknown'}",
- ]);
+ if (!&init_show_systemd_services()) {
+ my $systemd_link = &ui_tag('a',
+ $text{'index_systemd_module'},
+ { 'href' => '../systemd/' });
+ print &ui_alert_box(
+ &text('index_systemd_dedicated', $systemd_link),
+ 'info', undef, undef, ""),"\n";
}
- print &ui_columns_end();
- print &ui_links_row(\@links);
- print &ui_form_end([ [ "start", $text{'index_start'} ],
- [ "stop", $text{'index_stop'} ],
- [ "restart", $text{'index_restart'} ],
- undef,
- [ "addboot", $text{'index_addboot'} ],
- [ "delboot", $text{'index_delboot'} ],
- undef,
- [ "addboot_start", $text{'index_addboot_start'} ],
- [ "delboot_stop", $text{'index_delboot_stop'} ],
- ]);
+ else {
+ # Show systemd actions
+ print &ui_form_start("mass_systemd.cgi", "post");
+ @links = ( &select_all_link("d"),
+ &select_invert_link("d"),
+ &ui_link("edit_systemd.cgi?new=1",
+ $text{'index_sadd'}) );
+ print &ui_links_row(\@links);
+ print &ui_columns_start([ "", $text{'systemd_name'},
+ $config{'desc'} ?
+ $text{'systemd_desc'} : (),
+ $text{'systemd_status'},
+ $text{'systemd_boot'},
+ $text{'index_ustatus'} ]);
+ foreach $u (&list_systemd_services()) {
+ if ($u->{'legacy'}) {
+ $l = "edit_action.cgi?0+".&urlize($u->{'name'});
+ }
+ else {
+ $l = "edit_systemd.cgi?name=".&urlize($u->{'name'});
+ }
+ my $sname = $u->{'name'};
+ $sname =~ s/\.service$//;
+ my $title = ($u->{'boot'} == -1 ?
+ &html_escape($sname) :
+ &ui_link($l, &html_escape($sname)));
+ my $desc = $config{'desc'} ?
+ &html_escape($u->{'desc'}) : undef;
+ print &ui_columns_row([
+ &ui_checkbox("d", $u->{'name'}, undef),
+ $title,
+ $desc // (),
+ $u->{'fullstatus'} || "$text{'index_unknown'}",
+ $u->{'boot'} == 1 ?
+ &ui_text_color("$text{'yes'}", 'success') :
+ $u->{'boot'} == 2 ?
+ &ui_text_color("$text{'index_sboot6'}", 'success') :
+ $u->{'boot'} == -1 ?
+ &ui_text_color("$text{'index_sboot5'}", 'warn') :
+ &ui_text_color("$text{'no'}", 'warn'),
+ $u->{'status'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
+ $u->{'status'} == 0 ?
+ &ui_text_color("$text{'no'}", 'warn') :
+ "$text{'index_unknown'}",
+ ]);
+ }
+ print &ui_columns_end();
+ print &ui_links_row(\@links);
+ print &ui_form_end([ [ "start", $text{'index_start'} ],
+ [ "stop", $text{'index_stop'} ],
+ [ "restart", $text{'index_restart'} ],
+ undef,
+ [ "addboot", $text{'index_addboot'} ],
+ [ "delboot", $text{'index_delboot'} ],
+ undef,
+ [ "addboot_start", $text{'index_addboot_start'} ],
+ [ "delboot_stop", $text{'index_delboot_stop'} ],
+ ]);
+ }
}
elsif ($init_mode eq "launchd" && $access{'bootup'}) {
# Show launchd agents
@@ -449,4 +453,3 @@ if ($access{'shutdown'}) {
print &ui_buttons_end();
&ui_print_footer("/", $text{'index'});
-
diff --git a/init/init-lib.pl b/init/init-lib.pl
index 620f8351d..451047399 100644
--- a/init/init-lib.pl
+++ b/init/init-lib.pl
@@ -28,9 +28,9 @@ use WebminCore;
This variable is set based on the bootup system in use. Possible values are :
-=item osx - MacOSX hostconfig files, for older versions
+=item osx - Legacy macOS StartupItems and hostconfig files
-=item launchd - MacOS Launchd, for newer versions
+=item launchd - macOS launchd, for newer versions
=item rc - FreeBSD 6+ RC files
@@ -2311,16 +2311,15 @@ if (@list_systemd_services_cache && !$noinit) {
return @list_systemd_services_cache;
}
-my $units_piped = join('|', &get_systemd_unit_types());
-
# Get all systemd unit names
my $out = &backquote_command("systemctl list-units --full --all -t service --no-legend");
my $ex = $?;
foreach my $l (split(/\r?\n/, $out)) {
$l =~ s/^[^a-z0-9\-\_\.]+//i;
my ($unit, $loaded, $active, $sub, $desc) = split(/\s+/, $l, 5);
+ next if ($unit !~ /\.service$/);
my $a = $unit;
- $a =~ s/\.($units_piped)$//;
+ $a =~ s/\.service$//;
my $f = &action_filename($a);
if ($unit ne "UNIT" && $loaded eq "loaded" && !-r $f) {
push(@units, $unit);
@@ -2332,29 +2331,26 @@ foreach my $l (split(/\r?\n/, $out)) {
# and so don't show up in systemctl list-units
my $root = &get_systemd_root(undef, 1);
opendir(UNITS, $root);
-push(@units, grep { !/\.wants$/ && !/^\./ && !-d "$root/$_" } readdir(UNITS));
+push(@units, grep { /\.service$/ && !-d "$root/$_" } readdir(UNITS));
closedir(UNITS);
# Also add units from list-unit-files that also don't show up
$out = &backquote_command("systemctl list-unit-files -t service --no-legend");
foreach my $l (split(/\r?\n/, $out)) {
- if ($l =~ /^(\S+\.($units_piped))\s+disabled/ ||
- $l =~ /^(\S+)\s+disabled/) {
+ if ($l =~ /^(\S+\.service)\s+disabled/) {
push(@units, $1);
}
}
# Skip useless units
@units = grep { !/^sys-devices-/ &&
- !/^\-\.mount/ &&
- !/^\-\.slice/ &&
!/^dev-/ &&
!/^systemd-/ } @units;
@units = &unique(@units);
# Filter out templates
-my @templates = grep { /\@$/ || /\@\.($units_piped)$/ } @units;
-@units = grep { !/\@$/ && !/\@\.($units_piped)$/ } @units;
+my @templates = grep { /\@$/ || /\@\.service$/ } @units;
+@units = grep { !/\@$/ && !/\@\.service$/ } @units;
# Dump state of all of them, 100 at a time
my %info;
@@ -3142,11 +3138,90 @@ return $name =~ /\./ ? $name : "com.webmin.".$name;
}
# config_pre_load(mod-info, [mod-order])
-# Check if some config options are conditional
+# Hides config options that do not apply to the detected boot system.
sub config_pre_load
{
my ($modconf_info, $modconf_order) = @_;
-$modconf_info->{'desc'} =~ s/2-[^,]+,// if ($init_mode eq "systemd");
+return if (ref($modconf_info) ne 'HASH');
+
+if ($init_mode eq "systemd" && $modconf_info->{'desc'}) {
+ # Systemd has no runlevels, so keep only the plain yes/no choices.
+ $modconf_info->{'desc'} =~ s/2-[^,]+,//;
+ }
+
+my %keep = map { $_, 1 } &init_config_options_for_mode($init_mode);
+foreach my $key (keys %$modconf_info) {
+ delete($modconf_info->{$key}) if (!$keep{$key});
+ }
+if (ref($modconf_order) eq 'ARRAY') {
+ @$modconf_order = grep { $keep{$_} } @$modconf_order;
+ }
+&hide_single_init_config_section($modconf_info, $modconf_order);
+}
+
+# init_config_options_for_mode(mode)
+# Returns config.info keys that should be visible for a boot system.
+sub init_config_options_for_mode
+{
+my ($mode) = @_;
+my @display = ( 'expert', 'desc', 'order', 'status_check', 'sort_mode' );
+my @common = ( 'init_mode', 'reboot_command', 'shutdown_command' );
+my @sysv = ( @common, 'init_base', 'init_dir', 'order_digits',
+ 'boot_levels', 'local_script', 'local_down', 'inittab_id' );
+my @systemd_display = ( 'desc' );
+push(@systemd_display, 'systemd_dedicated')
+ if (&init_dedicated_systemd_module_available());
+
+return ( 'line1', @systemd_display, 'line2', @common )
+ if ($mode eq 'systemd');
+return ( 'line1', @display, 'line2', @sysv )
+ if ($mode eq 'init' || $mode eq 'upstart' || $mode eq 'openrc');
+return ( 'line2', @common, 'local_script', 'local_down',
+ 'rc_dir', 'rc_conf' )
+ if ($mode eq 'rc');
+return ( 'line2', @common, 'local_script', 'local_down' )
+ if ($mode eq 'local');
+return ( 'line2', @common, 'line3', 'startup_dirs', 'darwin_setup',
+ 'hostconfig', 'plist' )
+ if ($mode eq 'osx');
+return ( 'line2', @common )
+ if ($mode eq 'launchd' || $mode eq 'win32');
+return ( 'line1', @display, 'line2', @sysv, 'rc_dir', 'rc_conf',
+ 'line3', 'startup_dirs', 'darwin_setup', 'hostconfig', 'plist' );
+}
+
+# hide_single_init_config_section(&config-info, [&config-order])
+# Removes the lone section header when filtering leaves only one group.
+sub hide_single_init_config_section
+{
+my ($modconf_info, $modconf_order) = @_;
+my @sections = grep {
+ exists($modconf_info->{$_}) &&
+ (split(/,/, $modconf_info->{$_}))[1] == 11
+ } keys %$modconf_info;
+return if (@sections != 1);
+
+delete($modconf_info->{$sections[0]});
+if (ref($modconf_order) eq 'ARRAY') {
+ @$modconf_order = grep { $_ ne $sections[0] } @$modconf_order;
+ }
+}
+
+# init_dedicated_systemd_module_available()
+# Returns 1 if the standalone Systemd module can be used by this Webmin user.
+sub init_dedicated_systemd_module_available
+{
+return &foreign_available("systemd") && &foreign_installed("systemd");
+}
+
+# init_show_systemd_services()
+# Returns 1 if this module should show its legacy systemd service table.
+sub init_show_systemd_services
+{
+return 1 if (!&init_dedicated_systemd_module_available());
+return 0 if ($config{'systemd_dedicated'} &&
+ $config{'systemd_dedicated'} eq '1');
+return 1;
}
1;
diff --git a/init/lang/en b/init/lang/en
index 7844f1c36..1dbd92582 100644
--- a/init/lang/en
+++ b/init/lang/en
@@ -188,13 +188,14 @@ change_title=Switch Runlevel
change_cmd=Switching to runlevel $1 with command $2. This may take some time, and Webmin might not be available anymore after switching.
mode_init=SysV init
-mode_osx=MacOS
+mode_osx=Legacy macOS StartupItems
mode_local=Single boot script
mode_win32=Windows services
mode_rc=FreeBSD RC scripts
mode_upstart=Upstart
mode_systemd=Systemd
-mode_launchd=LaunchD
+mode_launchd=macOS launchd
+mode_openrc=OpenRC
upstart_title1=Create Upstart Service
upstart_title2=Edit Upstart Service
@@ -246,6 +247,8 @@ systemd_edesc=Missing unit description
systemd_return=systemd unit
systemd_econf=No systemd unit configuration entered
systemd_estart=Missing commands to run on startup
+index_systemd_module=Systemd Services and Units
+index_systemd_dedicated=Use the dedicated $1 module to manage systemd services and units. This page now shows only system reboot and shutdown controls.
launchd_title1=Create Launchd Agent
launchd_title2=Edit Launchd Agent