Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env perl
- # File: systemd-control.pl
- # SPDX-License-Identifier: Unlicense
- # This is free and unencumbered software released into the public domain.
- #
- # Anyone is free to copy, modify, publish, use, compile, sell, or
- # distribute this software, either in source code form or as a compiled
- # binary, for any purpose, commercial or non-commercial, and by any
- # means.
- # Tectonics:
- # perltidy -b -pbp -nst -xci systemd-control.pl
- # perlcritic -p perlcriticrc systemd-control.pl
- # podchecker systemd-control.pl
- package SystemdController;
- use 5.040;
- use strict;
- use warnings;
- use strictures 2;
- use autodie qw( :all );
- use version; our $VERSION = version->declare('0.1.0');
- use File::Path qw( make_path );
- use IPC::System::Simple qw( capture capturex system systemx );
- use English qw( -no_match_vars );
- use Getopt::Euclid qw( :vars );
- use IO::Prompt::Tiny qw( prompt );
- use Term::ANSIColor;
- use Class::Std;
- use Readonly;
- use Carp;
- use Data::Dumper;
- # use Smart::Comments; # comment out to disable smart comments
- # error codes
- Readonly my $GENERAL_ERR => 1;
- Readonly my $INVALID_ARG_ERR => 3;
- Readonly my $READ_WRITE_ERR => 5;
- Readonly my $CMDLINE_ERR => 64;
- Readonly my $OPEN_INPUT_ERR => 66;
- Readonly my $INTERNAL_SW_ERR => 70;
- Readonly my $OS_ERR => 71;
- Readonly my $FILE_MISSING_ERR => 72;
- Readonly my $CANT_CREATE_ERR => 73;
- Readonly my $IO_ERR => 74;
- Readonly my $PERMISSION_ERR => 77;
- Readonly my $CONFIG_ERR => 78;
- Readonly my $CMD_CANNOT_EXEC_ERR => 126;
- Readonly my $CMD_NOT_FOUND_ERR => 127;
- {
- ### program started...
- ### Euclid has already parsed \$ARGV into \%ARGV...
- ### %ARGV
- ### @ARGV has been consumed by Euclid: @ARGV
- Readonly my $UNITS_DIR => '/etc/systemd/system';
- Readonly my $EXECUTABLES_DIR => '/usr/local/bin';
- Readonly my $ERROR_COLOR => 'bright_red';
- Readonly my $INFO_COLOR => 'white';
- Readonly my $STATUS_COLOR => 'bright_cyan';
- Readonly my $WARNING_COLOR => 'bright_yellow';
- ### systemd unit file links stored in: $UNITS_DIR
- ### executable file links stored in: $EXECUTABLES_DIR
- ### error colour name : $ERROR_COLOR
- ### info colour name : $INFO_COLOR
- ### status colour name : $STATUS_COLOR
- ### warning colour name : $WARNING_COLOR
- # class attributes
- my %argv_ref_of : ATTR( :init_arg => 'argv_ref', :get => 'argv_ref' );
- my %filenames_ref_of :
- ATTR( :get => 'filenames_ref', :set => 'filenames_ref' );
- my %options_ref_of : ATTR( :get => 'options_ref', :set => 'options_ref' );
- my %is_confirm_of : ATTR( :get => 'is_confirm', :set => 'is_confirm' );
- my %is_interactive_of :
- ATTR( :get => 'is_interactive', :set => 'is_interactive' );
- my %is_verbose_of : ATTR( :get => 'is_verbose', :set => 'is_verbose' );
- my $controller = SystemdController->new( { argv_ref => \@ARGV } );
- exit $controller->run();
- ### assert: !'execution should have ended'
- # ----------------------------------------------------------------------
- # Name : START
- # Purpose : Sets object attributes to default values
- # Returns : n/a
- # Parameters : $self - reference to this class instance
- # $id - instance identifier
- # $args_ref - reference to arguments new() was called with
- # Throws : no exceptions
- sub START( $self, $id, $args_ref ) {
- ### START() started...
- ### assert: $self
- ### assert: $id
- ### filenames defaults to empty list...
- $self->set_filenames_ref( [] )
- if ( !$filenames_ref_of{$id} );
- ### $filenames_ref_of{$id}: $filenames_ref_of{$id}
- ### assert: @{$filenames_ref_of{$id}} == 0
- ### confirm defaults to 0...
- $self->set_is_confirm(0) if ( !$is_confirm_of{$id} );
- ### $is_confirm_of{$id}: $is_confirm_of{$id}
- ### assert: ref($is_confirm_of{$id}) == 0
- ### interactive defaults to 0...
- $self->set_is_interactive(0)
- if ( !$is_interactive_of{$id} );
- ### $is_interactive_of{$id}: $is_interactive_of{$id}
- ### assert: ref($is_interactive_of{$id}) == 0
- ### is_verbose defaults to 0...
- $self->set_is_verbose(0)
- if ( !$is_verbose_of{$id} );
- ### $is_verbose_of{$id}: $is_verbose_of{$id}
- ### assert: ref($is_verbose_of{$id}) == 0
- ### options defaults to empty hash...
- $self->set_options_ref( {} )
- if ( !$options_ref_of{$id} );
- ### $options_ref_of{$id}: $options_ref_of{$id}
- ### assert: keys %{$options_ref_of{$id}} == 0
- return $self;
- } # START
- # ----------------------------------------------------------------------
- # Usage : $controller->run()
- # Purpose : Runs the systemd controller. Operates on personal systemd
- # services, timers, and executables
- # Returns : Program status code
- # Parameters : $self - reference to this class instance
- # Throws : no exceptions
- # Comments : If an error occurs, then writes the error message
- # to the error output.
- # In this case the program exits with the status code
- # returned by the code that experienced an error
- sub run($self) {
- ### run() started...
- ### assert: $self
- my $opt_ref_of = $self->parse_cmdline();
- ### parse_cmdline returned: $opt_ref_of
- ### ensure that UNITS_DIR and EXECUTABLES_DIR exist...
- make_path( $UNITS_DIR, { mode => 0o775 } );
- make_path( $EXECUTABLES_DIR, { mode => 0o775 } );
- ### add symbolic links to files...
- if ( $self->get_options_ref()->{add} ) {
- $self->print_status_if_verbose(
- "\nAdding symbolic links to files...\n");
- $self->add_executable_links();
- $self->add_systemd_links();
- }
- ### remove symbolic links to files...
- if ( $self->get_options_ref()->{remove} ) {
- $self->print_status_if_verbose(
- "\nRemoving symbolic links to files...\n");
- $self->remove_executable_links();
- $self->remove_systemd_links();
- }
- ### enable systemd units and executables...
- if ( $self->get_options_ref()->{enable} ) {
- $self->print_status_if_verbose(
- "\nEnabling systemd units and executables...\n");
- $self->enable_systemd_services();
- $self->enable_systemd_timers();
- $self->enable_executables();
- }
- ### list systemd services, timers, and executables...
- if ( $self->get_options_ref()->{list_services} ) {
- $self->print_status_if_verbose("\nListing services...\n");
- $self->list_services();
- }
- if ( $self->get_options_ref()->{list_timers} ) {
- $self->print_status_if_verbose("\nListing timers...\n");
- $self->list_timers();
- }
- if ( $self->get_options_ref()->{list_executables} ) {
- $self->print_status_if_verbose("\nListing executables...\n");
- $self->list_executables();
- }
- return 0;
- } # run
- # ----------------------------------------------------------------------
- # Usage : %options = $controller->parse_cmdline()
- # Purpose : Parses any and all command line arguments and/or options
- # Returns : A hash of the found arguments/options
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- # CAVEAT: does not throw errors for unknown options
- # Comments : If the help, usage, man, or version option are given then
- # they write their message and exit the program with status
- # code 0.
- # If the command line could not be parsed then an error is
- # written to the error output stream and the program exits
- # with status code 2.
- sub parse_cmdline($self) {
- ### parse_cmdline() started...
- ### assert: $self
- ### parsing by Euclid has already occurred at this point...
- ### transfer the parsed values to a new, normalized, hash...
- my $result_ref = {};
- $result_ref->{add} = $ARGV_add ? 1 : 0;
- $result_ref->{confirm} = $ARGV_confirm ? 1 : 0;
- $result_ref->{enable} = $ARGV_enable ? 1 : 0;
- $result_ref->{interactive} = $ARGV_interactive ? 1 : 0;
- $result_ref->{list_services} = $ARGV_list_services ? 1 : 0;
- $result_ref->{list_timers} = $ARGV_list_timers ? 1 : 0;
- $result_ref->{list_executables} = $ARGV_list_executables ? 1 : 0;
- $result_ref->{verbose} = $ARGV_verbose ? 1 : 0;
- $result_ref->{filenames} = \@ARGV_filename;
- ### update instance attributes based on
- ### parsed command line filenames and options...
- $self->set_filenames_ref( $result_ref->{filenames} );
- # filenames_ref updated to: $self->get_filenames_ref();
- $self->set_is_confirm( ( $result_ref->{confirm} ) ? 1 : 0 );
- ### is_confirm updated to: $self->get_is_confirm()
- $self->set_is_interactive( ( $result_ref->{interactive} ) ? 1 : 0 );
- ### is_interactive updated to: $self->get_is_interactive()
- $self->set_is_verbose( ( $result_ref->{verbose} ) ? 1 : 0 );
- ### is_verbose updated to: $self->get_is_verbose()
- $self->set_options_ref($result_ref);
- ### options_ref updated to: $self->get_options_ref()
- return $result_ref;
- } # parse_cmdline
- # --------------------------------------------------------------------------
- # Usage : $controller->add_executable_links()
- # Purpose : Adds links from EXECUTABLES_DIR to executable files included
- # in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub add_executable_links($self) {
- ### add_executable_links() started...
- ### assert: $self
- my @filenames = $self->executable_filenames();
- if (@filenames) {
- ### executables to link to: @filenames
- }
- else {
- ### no executable files to add...
- $self->print_warning_if_verbose("No executable files to add.\n");
- return;
- }
- ### ensure script is being executed as root...
- if ($EFFECTIVE_USER_ID) {
- $self->print_error(
- "\nCannot add symbolic links to executable "
- . "files if not the root user.\n" );
- $self->confirm_quit(
- 'Executable files cannot be added "
- . "unless you are the root user.',
- $PERMISSION_ERR
- );
- }
- ### TODO add symbolic links to executable files...
- return;
- } # add_executable_links
- # ----------------------------------------------------------------------
- # Usage : $controller->add_systemd_links()
- # Purpose : Adds links from UNITS_DIR to systemd files included
- # in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub add_systemd_links($self) {
- ### add_systemd_links() started...
- ### assert: $self
- my @filenames = $self->systemd_filenames();
- if (@filenames) {
- ### systemd files to link to: @filenames
- }
- else {
- ### no systemd files to add...
- $self->print_warning_if_verbose("No systemd files to add.\n");
- return;
- }
- ### ensure script is being executed as root...
- if ($EFFECTIVE_USER_ID) {
- $self->print_error( "\nCannot add symbolic links to systemd "
- . "files if not the root user.\n" );
- $self->confirm_quit(
- 'Systemd files cannot be linked to "
- . "unless you are the root user.',
- $PERMISSION_ERR
- );
- }
- ### TODO add symbolic links to systemd files...
- return;
- } # add_systemd_links
- # ----------------------------------------------------------------------
- # Usage : $controller->enable_executables()
- # Purpose : Enables executable files included in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- # Comments : Executables are not enabled, so this sub prints a
- # notification if given executables that this step is ignored
- sub enable_executables($self) {
- ### enable_executables() started...
- ### assert: $self
- my @filenames = $self->executable_filenames();
- if (@filenames) {
- ### exectable files to enable: @filenames
- }
- else {
- ### no executable files to enable...
- $self->print_warning_if_verbose("No executable files to add.\n");
- return;
- }
- ### ignore enabling executables...
- $self->print_info_if_verbose(
- "Executable files are not enabled. Ignoring this step.\n");
- return;
- } # enable_executables
- # ----------------------------------------------------------------------
- # Usage : $controller->enable_systemd_services()
- # Purpose : Enables systemd services included in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub enable_systemd_services($self) {
- ### enable_systemd_services() started...
- ### assert: $self
- my @filenames = $self->systemd_filenames();
- if (@filenames) {
- ### systemd files to enable: @filenames
- }
- else {
- ### no systemd services to enable...
- $self->print_warning_if_verbose(
- "No systemd services to enable.\n");
- return;
- }
- ### ensure script is being executed as root...
- if ($EFFECTIVE_USER_ID) {
- $self->print_error(
- "\nCannot enable systemd services if not the root user.\n");
- $self->confirm_quit(
- 'Cannot enable systemd services unless you are the root user.',
- $PERMISSION_ERR
- );
- return $PERMISSION_ERR;
- }
- ### TODO enable systemd services...
- return;
- } # enable_systemd_services
- # ----------------------------------------------------------------------
- # Usage : $controller->enable_systemd_timers()
- # Purpose : Enables systemd timers included in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub enable_systemd_timers($self) {
- ### enable_systemd_timers() started...
- ### assert: $self
- my @filenames = $self->timer_filenames();
- if (@filenames) {
- ### systemd timers to enable: @filenames
- }
- else {
- ### no systemd timers to enable...
- $self->print_warning_if_verbose("No systemd timers to enable.\n");
- return;
- }
- ### ensure script is being executed as root...
- if ($EFFECTIVE_USER_ID) {
- $self->print_error(
- "\nCannot enable systemd timers if not the root user.\n");
- $self->confirm_quit(
- 'Cannot enable systemd timers unless you are the root user.',
- $PERMISSION_ERR
- );
- return $PERMISSION_ERR;
- }
- ### TODO enable systemd timers...
- return;
- } # enable_systemd_timers
- # ----------------------------------------------------------------------
- # Usage : $controller->list_executables()
- # Purpose : Lists executables included in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub list_executables($self) {
- ### list_executables() started...
- ### assert: $self
- my @filenames = $self->executable_filenames();
- if (@filenames) {
- ### executable files to list: @filenames
- }
- else {
- ### no executable files to list...
- $self->print_warning_if_verbose("No executable files to list.\n");
- return;
- }
- ### TODO list executables...
- return;
- } # list_executables
- # ----------------------------------------------------------------------
- # Usage : $controller->list_services()
- # Purpose : Lists systemd services included in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub list_services($self) {
- ### list_services() started...
- ### assert: $self
- my @filenames = $self->service_filenames();
- if (@filenames) {
- ### systemd services to list: @filenames
- }
- else {
- ### no systemd services to list...
- $self->print_warning_if_verbose("No systemd services to list.\n");
- return;
- }
- ### TODO list systemd services...
- return;
- } # list_services
- # ----------------------------------------------------------------------
- # Usage : $controller->list_timers()
- # Purpose : Lists systemd timers included in provided filenames
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub list_timers($self) {
- ### list_timers() started...
- ### assert: $self
- my @filenames = $self->timer_filenames();
- if (@filenames) {
- ### systemd timers to list: @filenames
- }
- else {
- ### no systemd timers to list...
- $self->print_warning_if_verbose("No systemd timers to list.\n");
- return;
- }
- ### TODO list systemd timers...
- return;
- } # list_timers
- # ----------------------------------------------------------------------
- # Usage : $controller->remove_executable_links()
- # Purpose : Removes links to executables files
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub remove_executable_links($self) {
- ### remove_executable_links() started...
- ### assert: $self
- my @filenames = $self->executable_filenames();
- if (@filenames) {
- ### executable files to remove: : @filenames
- }
- else {
- ### no executable files to remove...
- $self->print_warning_if_verbose(
- "No executable files to remove.\n");
- return;
- }
- ### ensure script is being executed as root...
- if ($EFFECTIVE_USER_ID) {
- $self->print_error( "\nCannot remove links to executable "
- . "files if not the root user.\n" );
- $self->confirm_quit(
- 'Cannot remove links to executable files "
- . "unless you are the root user.',
- $PERMISSION_ERR
- );
- return $PERMISSION_ERR;
- }
- ### TODO remove links to executable files...
- return;
- } # remove_executable_links
- # ----------------------------------------------------------------------
- # Usage : $controller->remove_systemd_links()
- # Purpose : Removes links to systemd files
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated error is returned to the caller
- sub remove_systemd_links($self) {
- ### remove_systemd_links() started...
- ### assert: $self
- my @filenames = $self->systemd_filenames();
- if (@filenames) {
- ### systemd files to remove: @filenames
- }
- else {
- ### no systemd files to remove...
- $self->print_warning_if_verbose("No systemd files to remove.\n");
- return;
- }
- ### ensure script is being executed as root...
- if ($EFFECTIVE_USER_ID) {
- $self->print_error(
- "\nCannot remove links to systemd files if not the root user.\n"
- );
- $self->confirm_quit(
- 'Cannot remove links to systemd files "
- . "unless you are the root user.',
- $PERMISSION_ERR
- );
- return $PERMISSION_ERR;
- }
- ### TODO remove links to systemd files...
- return;
- } # remove_systemd_links
- # ------------------------------------------------------------------
- # Usage : @filenames = $controller->executable_filenames()
- # Purpose : Filters instance filenames for executable files
- # Returns : List of files that are executable
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated errors are returned to the caller
- sub executable_filenames($self) {
- ### executable_filenames() started...
- ### assert: $self
- my @filenames = @{ $self->get_filenames_ref() };
- ### command line filenames: @filenames
- my @executables = grep { !-d && -x } @filenames;
- ### @executables
- return @executables;
- } # executable_filenames
- # ------------------------------------------------------------------
- # Usage : @filenames = $controller->systemd_filenames()
- # Purpose : Filters instance filenames for systemd unit files
- # Returns : List of files that are systemd units
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated errors are returned to the caller
- sub systemd_filenames($self) {
- ### systemd_filenames() started...
- ### assert: $self
- my @filenames = @{ $self->get_filenames_ref() };
- ### command line filenames: @filenames
- my @systemd_units = grep {
- $ARG =~ qr{
- [.] # literal dot
- (?: # one of these extensions
- automount
- | device
- | mount
- | path
- | scope
- | service
- | slice
- | socket
- | swap
- | target
- | timer
- )
- \z # end of string
- }xms
- } @filenames;
- ### @systemd_units
- return @systemd_units;
- } # systemd_filenames
- # ------------------------------------------------------------------
- # Usage : @filenames = $controller->service_filenames()
- # Purpose : Filters instance filenames for systemd service files
- # Returns : List of files that are systemd services
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated errors are returned to the caller
- sub service_filenames($self) {
- ### service_filenames() started...
- ### assert: $self
- my @filenames = @{ $self->get_filenames_ref() };
- ### command line filenames: @filenames
- my @services = grep {
- $ARG =~ qr{
- [.] # literal dot
- service # service extension
- \z # end of string
- }xms
- } @filenames;
- ### @services
- return @services;
- } # service_filenames
- # ------------------------------------------------------------------
- # Usage : @filenames = $controller->timer_filenames()
- # Purpose : Filters instance filenames for systemd timer files
- # Returns : List of files that are systemd services
- # Parameters : $self - reference to this class instance
- # Throws : Any unanticipated errors are returned to the caller
- sub timer_filenames($self) {
- ### remove_systemd_links() started...
- ### assert: $self
- my @filenames = @{ $self->get_filenames_ref() };
- ### command line filenames: @filenames
- my @timers = grep {
- $ARG =~ qr{
- [.] # literal dot
- timer # timer extension
- \z # end of string
- }xms
- } @filenames;
- ### @timers
- return @timers;
- } # timer_filenames
- # ------------------------------------------------------------------
- # Usage : @filenames = $obj->confirm_quit($self, $msg, $code)
- # Purpose : Confirms that the program should exit.
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # $msg - message shown to the user, followed by
- # " Quit? (y/n) "
- # $code - status/result code returned to the system
- # Throws : Any unanticipated errors are returned to the caller
- # Comments : If the program should exit then returns program status
- # $code to the operating system.
- # If not running interactively, or if the user enters an
- # empty string, then defaults to exiting the program
- sub confirm_quit( $self, $msg, $code ) {
- ### confirm_quit() started
- ### assert: $self
- ### if not confirmation is not enabled then simply exit with $code
- exit $code if ( !$self->is_confirm() );
- $msg = "\n$msg" . ' Quit? (y/n) ';
- my $answer = '';
- while ( $answer ne 'n' ) {
- $answer = prompt( $msg, 'y' );
- $answer = lc substr( $answer, 0, 1 );
- exit $code if ( $answer eq 'y' );
- }
- return;
- } # confirm_quit
- # ------------------------------------------------------------------
- # Usage : $controller->print_info_if_verbose(@msg)
- # Purpose : Prints message and newline if the verbose option was
- # was given on the command line
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_info_if_verbose( $self, @msg ) {
- ### assert: $self
- $self->print_if_verbose( colored( @msg, $INFO_COLOR ) );
- return;
- } # print_info_if_verbose
- # ------------------------------------------------------------------
- # Usage : $controller->print_status_if_verbose(@msg)
- # Purpose : Prints message and newline if the verbose option was
- # was given on the command line
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_status_if_verbose( $self, @msg ) {
- ### assert: $self
- $self->print_if_verbose( colored( @msg, $STATUS_COLOR ) );
- return;
- } # print_status_if_verbose
- # ------------------------------------------------------------------
- # Usage : $controller->print_warning_if_verbose(@msg)
- # Purpose : Prints message and newline if the verbose option was
- # was given on the command line
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_warning_if_verbose( $self, @msg ) {
- ### assert: $self
- $self->print_if_verbose( $self->print_warning(@msg) );
- return;
- } # print_warning_if_verbose
- # ------------------------------------------------------------------
- # Usage : $controller->print_if_verbose(@msg)
- # Purpose : Prints message and newline if the verbose option
- # was given on the command line
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_if_verbose( $self, @msg ) {
- ### assert: $self
- ### print_if_verbose() started...
- ### assert: $self
- if ( $self->get_is_verbose() ) {
- print @msg;
- }
- return;
- } # print_if_verbose
- # ------------------------------------------------------------------
- # Usage : $controller->print_error(@msg)
- # Purpose : Prints message to standard error using error colors
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_error( $self, @msg ) {
- ### assert: $self
- print_stderr( colored( @msg, $ERROR_COLOR ) );
- return;
- } # print_error
- # ------------------------------------------------------------------
- # Usage : $controller->print_warning(@msg)
- # Purpose : Prints message using warning colors
- # Returns : nothing
- # Parameters : $self - reference to this class instance
- # @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_warning( $self, @msg ) {
- ### assert: $self
- print colored( @msg, $WARNING_COLOR );
- return;
- } # print_warning
- # ------------------------------------------------------------------
- # Usage : $controller->error_exit($code, @msg)
- # Purpose : Prints message to standard error and then exits the
- # program with code
- # Returns : Does not return
- # Parameters : $self - reference to this class instance
- # $code - exit status code (default: GENERAL_ERR)
- # : @msg - message printed to stderr
- # (default: 'Something went wrong.')
- # Throws : Any unanticipated error is returned to the caller
- sub error_exit( $self, $code, @msg ) {
- ### error_exit() started...
- ### assert: $self
- $code = $GENERAL_ERR if ( !defined $code );
- ### $code
- @msg = ('Something went wrong.') if ( !keys @msg );
- ### @msg
- $self->print_error(@msg);
- exit $code;
- } # error_exit
- # ------------------------------------------------------------------
- # Usage : print_stderr(@msg)
- # Purpose : Prints message to error output
- # Returns : nothing
- # Parameters : @msg - message printed to stderr
- # Throws : Any unanticipated error is returned to the caller
- sub print_stderr(@msg) {
- ### print_stderr() started...
- @msg = ('Something went wrong.') if ( !keys @msg );
- ### @msg
- return print STDERR join( $LIST_SEPARATOR, @msg );
- } # print_stderr
- } # SystemdController
- # my $cron_list = capturex( 'crontab', '-l' );
- # print {$out} $cron_list;
- __END__
- =pod
- =head1 NAME
- systemd-control.pl - maintains personal systemd services, timers,
- and executables.
- =head1 VERSION
- This document describes B<systemd-control.pl> version B<0.1.0>
- =head1 USAGE
- B<systemd-control.pl> [I<option>]... [I<filename>]...
- B<systemd-control.pl> --help
- B<systemd-control.pl> --usage
- B<systemd-control.pl> --man
- B<systemd-control.pl> --version
- B<systemd-control.pl> --add --enable -v *.timer
- B<systemd-control.pl> --remove --confirm *.service myexe
- B<systemd-control.pl> -x --list-services --list-timers
- =head1 DESCRIPTION
- B<systemd-control.pl> maintains personal L<systemd(1)> services, timers,
- and executables.
- This program is used to integrate local systemd units and executables into the
- Unix/Linux environment, and to maintain the same.
- =head1 REQUIRED ARGUMENTS
- There are no required arguments.
- =head1 OPTIONS
- =over
- =item <filename>...
- Names of the files on which to perform the requested options (e.g., C<--add>).
- =item -a | --add
- Creates symbolic links to the given local files to integrate them into the
- Unix/Linux system.
- Symbolic links to systemd units are written to the C</etc/systemd/system>
- directory, and symbolic links to executables are written to the
- C</usr/local/bin> directory.
- =item -r | --remove
- Removes symbolic links to the given local files.
- Symbolic links to systemd units are deleted from anywhere they occur under the
- C</etc> or C</usr> directories.
- Symbolic links to executables are deleted from the C</usr/local/bin> directory.
- =item -e | --enable
- Enables the given systemd services and timers.
- Timers are automatically started when enabled.
- Executables do not need to be enabled, and are ignored.
- =item -c | --confirm
- Prints whether or not the given systemd services, systemd timers, and
- executables have been added (i.e., linked) to.
- Prints the L<systemctl(1)> status of services/timers.
- =item -s | --[list-]services
- Lists the local services that have been added to the system.
- =item -t | --[list-]timers
- Lists the local timers that have been added to the system.
- =item -x | --[list-]executables
- Lists the local executables that have been added to the system.
- =item -i | --interactive
- Asks whether or not to create missing directories, create symbolic links, or
- remove obsolete symbolic links.
- =item -v | --verbose
- Prints messages of what is being done.
- =item -h | -? | --help
- Prints help for this program and exits.
- =item --usage
- Prints the usage summary for this program and exits.
- =item --man
- Prints the POD manual for this program and exits.
- =item --version
- Prints the program version and exits.
- =back
- =head1 CONFIGURATION
- This program is configured entirely by command line options and arguments.
- =head1 DEPENDENCIES
- B<Perl> version B<5.40.0> or later.
- =head2 In The Standard Distribution
- =over
- =item B<Carp>
- An alternative warn and die.
- =item B<Data::Dumper>
- Stringifies Perl data structures.
- =item B<English>
- Nice English (or awk) names for ugly punctuation variables.
- =item B<File::Find>
- Traverses a directory tree.
- =item B<Getopt::Long>
- Extended processing of command line options.
- =item B<Pod::Usage>
- Extracts POD documentation and shows usage information. This is used for the
- I<help>, I<usage>, and I<man> command line options.
- =item B<autodie>
- Replaces functions with ones that succeed or die with lexical scope.
- =item B<strict>
- Restricts unsafe constructs.
- =item B<version>
- Declares version numbers.
- =item B<warnings>
- Controls optional warnings.
- =back
- =head2 Must Be Installed Separately
- =over
- =item B<Class::Std>
- Supports creating standard inside-out classes
- =item B<IPC::System::Simple>
- Runs commands simply, with detailed diagnostics.
- =item B<Readonly>
- Facilitates creating read-only scalars, arrays, and hashes.
- =item B<Smart::Comments>
- Provides an easy way to insert debugging and tracking code into the program.
- =item B<Term::ANSIColor>
- Colors screen output using ANSI escape sequences.
- =item B<strictures>
- Turns on strict and makes most warnings fatal.
- =back
- =head1 EXIT STATUS
- On successful completion this program returns status code B<0>, otherwise
- please see the B<Diagnostics> section for an explanation of the error message
- and the returned status code.
- =head1 DIAGNOSTICS
- TODO update Diagnostics section
- =head2 Status Code 0
- If the I<help>, I<usage>, I<man>, or I<version> option is given on the command
- line, then its contents will be written and the program will exit.
- =head2 Status Code 2
- =over
- =item B<Undefined subroutine <subroutine name> called at ...>
- This will be printed if L<cron(8)> is not available on your system. Please
- ensure your system has L<cron(8)>.
- =item B<Can't locate <package> in @INC ...>
- This will be printed if any of the required Perl package dependencies is not
- installed. Please install any necessary packages to proceed.
- =item B<### ...>
- This means that the C<Smart::Comments> package is enabled. If you want to turn
- these off then locate B<systemd-control.pl> (this file) and
- disable the line "use Smart::Comments ...", either by starting the line with a
- "#", or by deleting the line.
- If the C<Smart::Comments> package is enabled then please report it as a bug.
- =back
- =head2 Status Code 77
- This means that a permission error has occurred. This program needs to be run
- as/by the root user.
- =over
- =item B<Various Error Messages>
- This means that an error occurred while trying to execute a system command.
- Ensure that the named command is available and can be found by
- B<systemd-control.pl>. You can try to run the system command from
- the directory B<systemd-control.pl> is in to ensure that the
- system command can be executed by B<systemd-control.pl>.
- =back
- =head1 INCOMPATIBILITIES
- This program has no known incompatibilities.
- Please report incompatibilities to Justin Hanekom ([email protected]).
- =head1 BUGS AND LIMITATIONS
- This program has no known bugs or limitations.
- Please report problems to Justin Hanekom ([email protected]).
- =head1 AUTHOR
- This program was initially written by Justin Hanekom ([email protected]).
- =head1 LICENSE AND COPYRIGHT
- This is free and unencumbered software released into the public domain.
- Anyone is free to copy, modify, publish, use, compile, sell, or
- distribute this software, either in source code form or as a compiled
- binary, for any purpose, commercial or non-commercial, and by any
- means.
- In jurisdictions that recognize copyright laws, the author or authors
- of this software dedicate any and all copyright interest in the
- software to the public domain. We make this dedication for the benefit
- of the public at large and to the detriment of our heirs and
- successors. We intend this dedication to be an overt act of
- relinquishment in perpetuity of all present and future rights to this
- software under copyright law.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- For more information, please refer to <https://unlicense.org/>
- =cut
Advertisement
Add Comment
Please, Sign In to add comment