1#
2# (c) Jan Gehring <jan.gehring@gmail.com>
3#
4# vim: set ts=2 sw=2 tw=0:
5# vim: set expandtab:
6
7=head1 NAME
8
9Rex::Config - Handles Rex configuration
10
11=head1 SYNOPSIS
12
13 use Rex::Config;
14
15 # set a config option
16 Rex::Config->set_exec_autodie(TRUE);
17
18 # get value of a config option
19 my $user = Rex::Config->get_user();
20
21=head1 DESCRIPTION
22
23This module holds all configuration options for Rex, and also allows you to specify your own ones for your modules.
24
25Please take a look at L<Rex::Commands> first, which provides convenience wrappers for many of these options.
26
27While it's possible to use the methods below to set a configuration option directly, their main intended purpose is to be used as internal plumbing, and to provide an escape hatch in case there are no better alternatives.
28
29=head1 EXPORTED METHODS
30
31=cut
32
33package Rex::Config;
34
35use 5.010001;
36use strict;
37use warnings;
38
39our $VERSION = '1.13.4'; # VERSION
40
41use Rex::Helper::File::Spec;
42use Rex::Logger;
43use YAML;
44use Data::Dumper;
45use Rex::Require;
46use Symbol;
47
48our (
49  $user,                        $password,
50  $port,                        $timeout,
51  $max_connect_fails,           $password_auth,
52  $key_auth,                    $krb5_auth,
53  $public_key,                  $private_key,
54  $parallelism,                 $log_filename,
55  $log_facility,                $sudo_password,
56  $ca_file,                     $ca_cert,
57  $ca_key,                      $path,
58  $no_path_cleanup,             $set_param,
59  $environment,                 $connection_type,
60  $distributor,                 $template_function,
61  $SET_HANDLER,                 $HOME_CONFIG,
62  $HOME_CONFIG_YAML,            %SSH_CONFIG_FOR,
63  $sudo_without_locales,        $sudo_without_sh,
64  $no_tty,                      $source_global_profile,
65  $source_profile,              %executor_for,
66  $allow_empty_groups,          $use_server_auth,
67  $tmp_dir,                     %openssh_opt,
68  $use_cache,                   $cache_type,
69  $use_sleep_hack,              $report_type,
70  $do_reporting,                $say_format,
71  $exec_autodie,                $verbose_run,
72  $disable_taskname_warning,    $proxy_command,
73  $task_call_by_method,         $fallback_auth,
74  $register_cmdb_template,      $check_service_exists,
75  $set_no_append,               $use_net_openssh_if_present,
76  $use_template_ng,             $use_rex_kvm_agent,
77  $autodie,                     $task_chaining_cmdline_args,
78  $waitpid_blocking_sleep_time, $write_utf8_files,
79  $default_auth,
80);
81
82# some defaults
83%executor_for = (
84  perl   => "perl",
85  python => "python",
86  ruby   => "ruby",
87  bash   => "bash",
88);
89
90=head2 set_autodie
91
92=head2 get_autodie
93
94Sets and gets the value of the C<$autodie> configuration variable.
95
96This controls whether Rex should C<die()> if there's an error while executing L<file system commands that are supposed to change the contents|Rex::Commands::Fs#Changing-content>.
97
98Default is C<undef>.
99
100=cut
101
102sub set_autodie {
103  my $class = shift;
104  $autodie = shift;
105}
106
107sub get_autodie {
108  return $autodie;
109}
110
111=head2 set_use_net_openssh_if_present
112
113=head2 get_use_net_openssh_if_present
114
115Sets and gets the value of the C<$use_net_openssh_if_present> configuration variable.
116
117This controls whether Rex should use L<Net::OpenSSH> for connections if that is available.
118
119Default is C<undef>.
120
121=cut
122
123sub set_use_net_openssh_if_present {
124  my $class = shift;
125  $use_net_openssh_if_present = shift;
126}
127
128sub get_use_net_openssh_if_present {
129  return $use_net_openssh_if_present;
130}
131
132=head2 set_use_rex_kvm_agent
133
134=head2 get_use_rex_kvm_agent
135
136Sets and gets the value of the C<$use_rex_kvm_agent> configuration variable.
137
138This controls whether Rex should setup and use a serial device for the experimental L<Rex KVM agent|https://github.com/RexOps/rex-kvm-agent> for managed VMs.
139
140Default is C<undef>.
141
142=cut
143
144sub set_use_rex_kvm_agent {
145  my $class = shift;
146  $use_rex_kvm_agent = shift;
147}
148
149sub get_use_rex_kvm_agent {
150  return $use_rex_kvm_agent;
151}
152
153=head2 set_use_template_ng
154
155=head2 get_use_template_ng
156
157Sets and gets the value of the C<$use_template_ng> configuration variable.
158
159This controls whether Rex should use L<Rex::Template::NG> to render templates.
160
161Default is C<undef>.
162
163=cut
164
165sub set_use_template_ng {
166  my $class = shift;
167  $use_template_ng = shift;
168}
169
170sub get_use_template_ng {
171  return $use_template_ng;
172}
173
174=head2 set_set_no_append
175
176=head2 get_set_no_append
177
178Sets and gets the value of the C<$set_no_append> configuration variable.
179
180This controls whether Rex should overwrite or append values of configuration options when using the L<set|Rex::Commands#set> command.
181
182Default is C<undef>.
183
184=cut
185
186sub set_set_no_append {
187  my $class = shift;
188  $set_no_append = shift;
189}
190
191sub get_set_no_append {
192  return $set_no_append;
193}
194
195=head2 set_check_service_exists
196
197=head2 get_check_service_exists
198
199Sets and gets the value of the C<$check_service_exists> configuration variable.
200
201This controls whether Rex should C<die()> early if it is asked to manage a service that doesn't exist.
202
203Default is C<undef>.
204
205=cut
206
207sub set_check_service_exists {
208  my $class = shift;
209  $check_service_exists = shift;
210}
211
212sub get_check_service_exists {
213  return $check_service_exists;
214}
215
216=head2 set_register_cmdb_template
217
218=head2 get_register_cmdb_template
219
220Sets and gets the value of the C<$register_cmdb_template> configuration variable.
221
222This controls whether Rex should make L<CMDB|Rex::CMDB> data available to be used in templates as variables.
223
224Default is C<undef>.
225
226=cut
227
228sub set_register_cmdb_template {
229  my $class = shift;
230  $register_cmdb_template = shift;
231}
232
233sub get_register_cmdb_template {
234  return $register_cmdb_template;
235}
236
237=head2 set_fallback_auth
238
239=head2 get_fallback_auth
240
241Sets and gets the value of the C<$fallback_auth> configuration variable.
242
243This can be used to define an array of hash references, each of them containing L<authentication details|Rex::Commands#auth> to be tried during connection attempts when the directly specified ones fail.
244
245Default is C<undef>.
246
247=cut
248
249sub set_fallback_auth {
250  my $class = shift;
251  $fallback_auth = [@_];
252}
253
254sub get_fallback_auth {
255  return $fallback_auth;
256}
257
258=head2 set_task_call_by_method
259
260=head2 get_task_call_by_method
261
262Sets and gets the value of the C<$task_call_by_method> configuration variable.
263
264This controls whether calling tasks as a method is allowed or not.
265
266Default is C<undef>.
267
268=cut
269
270sub set_task_call_by_method {
271  my $class = shift;
272  $task_call_by_method = shift;
273}
274
275sub get_task_call_by_method {
276  return $task_call_by_method;
277}
278
279=head2 set_disable_taskname_warning
280
281=head2 get_disable_taskname_warning
282
283Sets and gets the value of the C<$disable_taskname_warning> configuration variable.
284
285This controls whether Rex should show or suppress the warning message about task names that can not be used as Perl identifiers.
286
287Default is C<undef>.
288
289=cut
290
291sub set_disable_taskname_warning {
292  my $class = shift;
293  $disable_taskname_warning = shift;
294}
295
296sub get_disable_taskname_warning {
297  return $disable_taskname_warning;
298}
299
300=head2 set_task_chaining_cmdline_args
301
302=head2 get_task_chaining_cmdline_args
303
304Sets and gets the value of the C<$task_chaining_cmdline_args> configuration variable.
305
306This controls whether Rex should parse task arguments on the command line per task, or should pass all arguments to all tasks.
307
308Default is C<undef>.
309
310=cut
311
312sub set_task_chaining_cmdline_args {
313  my $class = shift;
314  $task_chaining_cmdline_args = shift;
315}
316
317sub get_task_chaining_cmdline_args {
318  return $task_chaining_cmdline_args;
319}
320
321=head2 set_verbose_run
322
323=head2 get_verbose_run
324
325Sets and gets the value of the C<$verbose_run> configuration variable.
326
327This controls whether Rex should show verbose output about executed L<run|Rex::Commands::Run#run> commands. This means an error message if the command is not found, a warning message if the exit code indicates an error, and an informational message upon success.
328
329Default is C<undef>.
330
331=cut
332
333sub set_verbose_run {
334  my $class = shift;
335  $verbose_run = shift;
336}
337
338sub get_verbose_run {
339  return $verbose_run;
340}
341
342=head2 set_exec_autodie
343
344=head2 get_exec_autodie
345
346Sets and gets the value of the C<$exec_autodie> configuration variable.
347
348This controls whether Rex should C<die()> or not when the exit code of executed L<run|Rex::Commands::Run#run> command indicate an error.
349
350Default is C<undef>.
351
352=cut
353
354sub set_exec_autodie {
355  my $class = shift;
356  $exec_autodie = shift;
357}
358
359sub get_exec_autodie {
360  return $exec_autodie;
361}
362
363=head2 set_no_path_cleanup
364
365=head2 get_no_path_cleanup
366
367Sets and gets the value of the C<$no_path_cleanup> configuration variable.
368
369This controls whether Rex should clean up the C<$PATH> before executing a L<run|Rex::Commands::Run#run> command.
370
371Default is C<undef>.
372
373=cut
374
375sub set_no_path_cleanup {
376  my $class = shift;
377  $no_path_cleanup = shift;
378}
379
380sub get_no_path_cleanup {
381  return $no_path_cleanup;
382}
383
384=head2 set_source_profile
385
386=head2 get_source_profile
387
388Sets and gets the value of the C<$source_profile> configuration variable.
389
390This controls whether Rex should source shell-specific profile files before executing commands.
391
392Default is C<undef>.
393
394=cut
395
396sub set_source_profile {
397  my $class = shift;
398  $source_profile = shift;
399}
400
401sub get_source_profile {
402  return $source_profile;
403}
404
405=head2 set_say_format
406
407=head2 get_say_format
408
409Sets and gets the value of the C<$say_format> configuration variable.
410
411This controls the output format of the built-in C<say> command (see also L<sayformat|Rex::Commands#sayformat>).
412
413Default is C<undef>.
414
415=cut
416
417sub set_say_format {
418  my $class = shift;
419  $say_format = shift;
420}
421
422sub get_say_format {
423  return $say_format;
424}
425
426=head2 set_do_reporting
427
428=head2 get_do_reporting
429
430Sets and gets the value of the C<$do_reporting> configuration variable.
431
432This controls whether Rex should do reporting on executed resources where it is supported. This only affects the data structures returned internally.
433
434Default is C<undef>.
435
436=cut
437
438sub set_do_reporting {
439  my $class = shift;
440  $do_reporting = shift;
441}
442
443sub get_do_reporting {
444  return $do_reporting;
445}
446
447=head2 set_report_type
448
449=head2 get_report_type
450
451Sets and gets the value of the C<$report_type> configuration variable, which can also be controlled via the C<REX_REPORT_TYPE> environment variable.
452
453This selects the reporting type (format) Rex should use, e.g. C<'YAML'>.
454
455Default is C<undef>.
456
457=cut
458
459sub set_report_type {
460  my $class = shift;
461  $report_type = shift;
462}
463
464sub get_report_type {
465  if ( exists $ENV{REX_REPORT_TYPE} ) {
466    return $ENV{REX_REPORT_TYPE};
467  }
468
469  return $report_type;
470}
471
472=head2 set_sleep_hack
473
474=head2 get_sleep_hack
475
476Sets and gets the value of the C<$sleep_hack> configuration variable.
477
478This controls whether Rex should use or not an extra 10 ns long sleep after executed commands.
479
480This might help working around an issue when Rex runs inside a KVM virtualized host and L<Net::SSH2>/L<libssh2|https://www.libssh2.org> is used to connect to another VM on the same hardware.
481
482Default is C<undef>.
483
484=cut
485
486sub set_sleep_hack {
487  my $class = shift;
488  $use_sleep_hack = shift;
489}
490
491sub get_sleep_hack {
492  return $use_sleep_hack;
493}
494
495=head2 set_cache_type
496
497=head2 get_cache_type
498
499Sets and gets the value of the C<$cache_type> configuration variable, which can also be controlled via the C<REX_CACHE_TYPE> environment variable.
500
501This selects the cache type Rex should use, e.g. C<'YAML'>.
502
503Default is C<'Base'>.
504
505=cut
506
507sub set_cache_type {
508  my $class = shift;
509  $cache_type = shift;
510}
511
512sub get_cache_type {
513  if ( exists $ENV{REX_CACHE_TYPE} ) {
514    return $ENV{REX_CACHE_TYPE};
515  }
516
517  return $cache_type || "Base";
518}
519
520=head2 set_use_cache
521
522=head2 get_use_cache
523
524Sets and gets the value of the C<$use_cache> configuration variable.
525
526This controls whether Rex should use caching or not for runtime information like CMDB contents, hardware and operating system information, or the shell type that is being used to execute commands on the managed endpoint.
527
528Default is C<undef>.
529
530=cut
531
532sub set_use_cache {
533  my $class = shift;
534  $use_cache = shift;
535}
536
537sub get_use_cache {
538  return $use_cache;
539}
540
541=head2 set_openssh_opt
542
543=head2 get_openssh_opt
544
545Sets and gets the value of the C<$openssh_opt> configuration variable, which holds a hash of the SSH configuration options used for the connection. See the L<ssh_config(5) man page|http://man.openbsd.org/OpenBSD-current/man5/ssh_config.5> for the available options.
546
547  Rex::Config->set_openssh_opt( $option => $value, );
548
549There is a custom option named C<initialize_options> specific to Rex, which can be used to pass a hash reference describing the L<constructor parameters|https://metacpan.org/pod/Net::OpenSSH#Net::OpenSSH-E<gt>new($host,-%opts)> for the underlying L<Net::OpenSSH> object:
550
551 Rex::Config->set_openssh_opt( initialize_options => { $parameter => $value, } );
552
553Default is C<undef>.
554
555=cut
556
557sub set_openssh_opt {
558  my ( $class, %opt ) = @_;
559
560  for my $key ( keys %opt ) {
561    if ( !defined $opt{$key} ) {
562      $openssh_opt{$key} = undef;
563      delete $openssh_opt{$key};
564      next;
565    }
566
567    $openssh_opt{$key} = $opt{$key};
568  }
569}
570
571sub get_openssh_opt {
572  return %openssh_opt;
573}
574
575=head2 set_sudo_without_locales
576
577=head2 get_sudo_without_locales
578
579Sets and gets the value of the C<$sudo_without_locales> configuration variable.
580
581This controls whether Rex should execute L<sudo|Rex::Commands::Run#sudo> commands without setting any locales via the C<LC_ALL> environment variable.
582
583B<Warning:> if the locale is something else than C<C> or C<en_US>, then things will break!
584
585Default is C<undef>.
586
587=cut
588
589sub set_sudo_without_locales {
590  my $class = shift;
591  $sudo_without_locales = shift;
592}
593
594sub get_sudo_without_locales {
595  return $sudo_without_locales;
596}
597
598=head2 set_sudo_without_sh
599
600=head2 get_sudo_without_sh
601
602Sets and gets the value of the C<$sudo_without_sh> configuration variable.
603
604This controls whether Rex should run L<sudo|Rex::Commands::Run#sudo> commands without C<sh>. This might break things.
605
606Default is C<undef>.
607
608=cut
609
610sub set_sudo_without_sh {
611  my $class = shift;
612  $sudo_without_sh = shift;
613}
614
615sub get_sudo_without_sh {
616  return $sudo_without_sh;
617}
618
619=head2 set_executor_for
620
621=head2 get_executor_for
622
623Sets and gets the keys and values of the C<%executor_for> configuration variable.
624
625This sets the executor for a given file type when using the C<upload_and_run()> function of L<Rex::Helper::Run> module.
626
627Default is:
628
629 (
630   perl   => 'perl',
631   python => 'python',
632   ruby   => 'ruby',
633   bash   => 'bash',
634 )
635
636=cut
637
638sub set_executor_for {
639  my $class = shift;
640  my $for   = shift;
641  my $e     = shift;
642
643  $executor_for{$for} = $e;
644}
645
646sub get_executor_for {
647  my $class = shift;
648  my $e     = shift;
649
650  return $executor_for{$e};
651}
652
653=head2 set_tmp_dir
654
655=head2 get_tmp_dir
656
657Sets and gets the value of the C<$tmp_dir> configuration variable.
658
659This controls which directory Rex should use for temporary files.
660
661Default is determined by the following logic:
662
663=over 4
664
665=item * try to use what C<< File::Spec->tmpdir >> would return on the managed endpoint
666
667=item * fall back to C<'/tmp'>
668
669=back
670
671=cut
672
673sub set_tmp_dir {
674  my ( $class, $dir ) = @_;
675  if ( $class eq "Rex::Config" ) {
676    $tmp_dir = $dir;
677  }
678  else {
679    $tmp_dir = $class;
680  }
681}
682
683sub get_tmp_dir {
684  my $cache = Rex::get_cache();
685  if ( my $cached_tmp = $cache->get("tmpdir") ) {
686    return $cached_tmp;
687  }
688
689  if ( !$tmp_dir ) {
690    if ( my $ssh = Rex::is_ssh() ) {
691      my $exec;
692      if ( Rex::is_sudo() ) {
693        if ( ref $ssh eq "Net::OpenSSH" ) {
694          $exec = Rex::Interface::Exec->create("OpenSSH");
695        }
696        else {
697          $exec = Rex::Interface::Exec->create("SSH");
698        }
699      }
700      else {
701        $exec = Rex::Interface::Exec->create;
702      }
703      my ($out) =
704        $exec->exec("perl -MFile::Spec -le 'print File::Spec->tmpdir'");
705
706      if ( $? == 0 && $out ) {
707        $out =~ s/[\r\n]//gms;
708
709        $cache->set( "tmpdir", $out );
710        return $out;
711      }
712      $cache->set( "tmpdir", "/tmp" );
713      return "/tmp";
714    }
715    else {
716      $cache->set( "tmpdir", Rex::Helper::File::Spec->tmpdir );
717      return Rex::Helper::File::Spec->tmpdir;
718    }
719  }
720  return $tmp_dir;
721}
722
723=head2 set_path
724
725=head2 get_path
726
727Sets and gets the value of the C<$path> configuration variable.
728
729This controls which C<PATH> Rex should use when executing L<run|Rex::Commands::Run#run> commands. The value should be set as an array reference, and will be dereferenced as such before returned by C<get_path>.
730
731Default is
732
733 qw(
734   /bin
735   /sbin
736   /usr/bin
737   /usr/sbin
738   /usr/local/bin
739   /usr/local/sbin
740   /usr/pkg/bin
741   /usr/pkg/sbin
742 )
743
744=cut
745
746sub set_path {
747  my $class = shift;
748  $path = shift;
749}
750
751sub get_path {
752  if ( !$path ) {
753    return (
754      "/bin",         "/sbin",          "/usr/bin",
755      "/usr/sbin",    "/usr/local/bin", "/usr/local/sbin",
756      "/usr/pkg/bin", "/usr/pkg/sbin"
757    );
758  }
759  return @{$path};
760}
761
762=head2 set_user
763
764=head2 get_user
765
766Sets and gets the value of the C<$user> configuration variable, which also can be set via the C<REX_USER> environment variable.
767
768This controls which L<user|Rex::Commands#user> Rex should use for authentication.
769
770Default is determined by the following logic:
771
772=over 4
773
774=item * value of C<REX_USER> environment variable
775
776=item * user set by L<user|Rex::Commands#user> command
777
778=item * user running Rex
779
780=back
781
782=cut
783
784sub set_user {
785  my $class = shift;
786  $user = shift;
787}
788
789sub has_user {
790  my $class = shift;
791  return $user;
792}
793
794sub get_user {
795  my $class = shift;
796
797  if ( exists $ENV{REX_USER} ) {
798    return $ENV{REX_USER};
799  }
800
801  if ($user) {
802    return $user;
803  }
804
805  if ( $^O =~ m/^MSWin/ ) {
806    return getlogin;
807  }
808  else {
809    return scalar getpwuid($<);
810  }
811}
812
813=head2 set_password
814
815=head2 get_password
816
817Sets and gets the value of the C<$password> configuration variable, which also can be set via the C<REX_PASSWORD> environment variable.
818
819This controls what L<password|Rex::Commands#password> Rex should use for authentication or as passphrase when using private keys.
820
821Default is C<undef>.
822
823=cut
824
825sub set_password {
826  my $class = shift;
827  $password = shift;
828}
829
830sub get_password {
831  my $class = shift;
832
833  if ( exists $ENV{REX_PASSWORD} ) {
834    return $ENV{REX_PASSWORD};
835  }
836
837  return $password;
838}
839
840=head2 set_port
841
842=head2 get_port
843
844Sets and gets the value of the C<$port> configuration variable.
845
846This controls which L<port|Rex::Commands#port> Rex should connect to.
847
848C<get_port> accepts an optional C<< server => $server >> argument to return the C<port> setting for the given C<$server> as optionally set in group files.
849
850Default is C<undef>.
851
852=cut
853
854sub set_port {
855  my $class = shift;
856  $port = shift;
857}
858
859sub get_port {
860  my $class = shift;
861  my $param = {@_};
862
863  if ( exists $param->{server}
864    && exists $SSH_CONFIG_FOR{ $param->{server} }
865    && exists $SSH_CONFIG_FOR{ $param->{server} }->{port} )
866  {
867    return $SSH_CONFIG_FOR{ $param->{server} }->{port};
868  }
869
870  return $port;
871}
872
873=head2 set_sudo_password
874
875=head2 get_sudo_password
876
877Sets and gets the value of the C<$sudo_password> configuration variable, which can also be controlled via the C<REX_SUDO_PASSWORD> environment variable.
878
879This controls what L<sudo password|Rex::Commands#sudo_password> Rex should use.
880
881Default is determined by the following logic:
882
883=over 4
884
885=item * value of C<REX_SUDO_PASSWORD> environment variable
886
887=item * sudo password set by the L<sudo_password|Rex::Command#sudo_password> command
888
889=item * password set by the L<password|Rex::Command#password> command
890
891=item * empty string (C<''>)
892
893=back
894
895=cut
896
897sub set_sudo_password {
898  my $class = shift;
899  $sudo_password = shift;
900}
901
902sub get_sudo_password {
903  my $class = shift;
904
905  if ( exists $ENV{REX_SUDO_PASSWORD} ) {
906    return $ENV{REX_SUDO_PASSWORD};
907  }
908
909  if ($sudo_password) {
910    return $sudo_password;
911  }
912  elsif ( !defined $sudo_password ) {
913    return "";
914  }
915  else {
916    return $password;
917  }
918
919  return "";
920}
921
922=head2 set_source_global_profile
923
924=head2 get_source_global_profile
925
926Sets and gets the value of the C<$source_global_profile> configuration variable.
927
928This controls whether Rex should source C</etc/profile> before executing commands.
929
930Default is C<undef>.
931
932=cut
933
934sub set_source_global_profile {
935  my $class = shift;
936  $source_global_profile = shift;
937}
938
939sub get_source_global_profile {
940  return $source_global_profile;
941}
942
943=head2 set_max_connect_fails
944
945=head2 get_max_connect_fails
946
947Sets and gets the value of the C<$max_connect_fails> configuration variable.
948
949This controls how many times Rex should retry to connect before giving up.
950
951C<get_max_connect_fails> accepts an optional C<< server => $server >> argument to C<connectionattempts> setting for the given C<$server> as optionally set in group files.
952
953Default is C<undef>.
954
955=cut
956
957sub set_max_connect_fails {
958  my $class = shift;
959  $max_connect_fails = shift;
960}
961
962sub get_max_connect_fails {
963  my $class = shift;
964  my $param = {@_};
965
966  if ( exists $param->{server}
967    && exists $SSH_CONFIG_FOR{ $param->{server} }
968    && exists $SSH_CONFIG_FOR{ $param->{server} }->{connectionattempts} )
969  {
970    return $SSH_CONFIG_FOR{ $param->{server} }->{connectionattempts};
971  }
972
973  return $max_connect_fails || 3;
974}
975
976=head2 set_proxy_command
977
978=head2 get_proxy_command
979
980Sets and gets the value of the C<$proxy_command> configuration variable.
981
982This controls the SSH ProxyCommand Rex should set for connections when L<Net::OpenSSH> is used.
983
984C<get_proxy_command> accepts an optional C<< server => $server >> argument to return the C<proxycommand> setting for the given C<$server> as optionally set in group files.
985
986Default is C<undef>.
987
988=cut
989
990sub set_proxy_command {
991  my $class = shift;
992  $proxy_command = shift;
993}
994
995sub get_proxy_command {
996  my $class = shift;
997  my $param = {@_};
998
999  if ( exists $param->{server}
1000    && exists $SSH_CONFIG_FOR{ $param->{server} }
1001    && exists $SSH_CONFIG_FOR{ $param->{server} }->{proxycommand} )
1002  {
1003    return $SSH_CONFIG_FOR{ $param->{server} }->{proxycommand};
1004  }
1005
1006  return $proxy_command;
1007}
1008
1009=head2 set_timeout
1010
1011=head2 get_timeout
1012
1013Sets and gets the value of the C<$timeout> configuration variable.
1014
1015This controls how many seconds Rex should wait for connections to succeed when using SSH or L<Rex::Commands::Rsync>.
1016
1017C<get_timeout> accepts an optional C<< server => $server >> argument to return the C<connecttimeout> setting for the given C<$server> as optionally set in group files.
1018
1019Default is C<undef>.
1020
1021=cut
1022
1023sub set_timeout {
1024  my $class = shift;
1025  $timeout = shift;
1026}
1027
1028sub get_timeout {
1029  my $class = shift;
1030  my $param = {@_};
1031
1032  if ( exists $param->{server}
1033    && exists $SSH_CONFIG_FOR{ $param->{server} }
1034    && exists $SSH_CONFIG_FOR{ $param->{server} }->{connecttimeout} )
1035  {
1036    return $SSH_CONFIG_FOR{ $param->{server} }->{connecttimeout};
1037  }
1038
1039  return $timeout || 2;
1040}
1041
1042=head2 set_password_auth
1043
1044=head2 get_password_auth
1045
1046Sets and gets the value of the C<$password_auth> configuration variable, which can also be set by setting the C<REX_AUTH_TYPE> environment variable to C<pass>.
1047
1048This controls whether Rex should use the L<password authentication|Rex::Commands#pass_auth> method.
1049
1050Default is C<undef>.
1051
1052=cut
1053
1054sub set_password_auth {
1055  my $class = shift;
1056  $key_auth      = 0;
1057  $krb5_auth     = 0;
1058  $password_auth = shift || 1;
1059}
1060
1061sub get_password_auth {
1062  if ( exists $ENV{REX_AUTH_TYPE} && $ENV{REX_AUTH_TYPE} eq "pass" ) {
1063    return 1;
1064  }
1065  return $password_auth;
1066}
1067
1068=head2 set_key_auth
1069
1070=head2 get_key_auth
1071
1072Sets and gets the value of the C<$key_auth> configuration variable, which can also be set by setting the C<REX_AUTH_TYPE> environment variable to C<key>.
1073
1074This controls whether Rex should use the L<key authentication|Rex::Commands#key_auth> method.
1075
1076Default is C<undef>.
1077
1078=cut
1079
1080sub set_key_auth {
1081  my $class = shift;
1082  $password_auth = 0;
1083  $krb5_auth     = 0;
1084  $key_auth      = shift || 1;
1085}
1086
1087sub get_key_auth {
1088  if ( exists $ENV{REX_AUTH_TYPE} && $ENV{REX_AUTH_TYPE} eq "key" ) {
1089    return 1;
1090  }
1091  return $key_auth;
1092}
1093
1094=head2 set_krb5_auth
1095
1096=head2 get_krb5_auth
1097
1098Sets and gets the value of the C<$krb5_auth> configuration variable, which can also be set by setting the C<REX_AUTH_TYPE> environment variable to C<krb5>.
1099
1100This controls whether Rex should use the L<Kerberos 5|Rex::Commands#krb5_auth> authentication method.
1101
1102Default is C<undef>.
1103
1104=cut
1105
1106sub set_krb5_auth {
1107  my $class = shift;
1108  $password_auth = 0;
1109  $key_auth      = 0;
1110  $krb5_auth     = shift || 1;
1111}
1112
1113sub get_krb5_auth {
1114  if ( exists $ENV{REX_AUTH_TYPE} && $ENV{REX_AUTH_TYPE} eq "krb5" ) {
1115    return 1;
1116  }
1117  return $krb5_auth;
1118}
1119
1120=head2 set_public_key
1121
1122=head2 get_public_key
1123
1124Sets and gets the value of the C<$public_key> configuration variable.
1125
1126This controls which L<public key|Rex::Commands#public_key> Rex should use when using L<Net::SSH2> for connections.
1127
1128Default is C<undef>.
1129
1130=cut
1131
1132sub set_public_key {
1133  my $class = shift;
1134  $public_key = shift;
1135}
1136
1137sub has_public_key {
1138  return get_public_key();
1139}
1140
1141sub get_public_key {
1142  if ( exists $ENV{REX_PUBLIC_KEY} ) { return $ENV{REX_PUBLIC_KEY}; }
1143  if ($public_key) {
1144    return $public_key;
1145  }
1146
1147  return;
1148}
1149
1150=head2 set_private_key
1151
1152=head2 get_private_key
1153
1154Sets and gets the value of the C<$private_key> configuration variable.
1155
1156This controls which L<private key|Rex::Commands#private_key> Rex should use with L<Rex::Commands::Rsync> or when using L<Net::SSH2> for connections.
1157
1158Default is C<undef>.
1159
1160=cut
1161
1162sub set_private_key {
1163  my $class = shift;
1164  $private_key = shift;
1165}
1166
1167sub has_private_key {
1168  return get_private_key();
1169}
1170
1171sub get_private_key {
1172  if ( exists $ENV{REX_PRIVATE_KEY} ) { return $ENV{REX_PRIVATE_KEY}; }
1173  if ($private_key) {
1174    return $private_key;
1175  }
1176
1177  return;
1178}
1179
1180=head2 set_parallelism
1181
1182=head2 get_parallelism
1183
1184Sets and gets the value of the C<$parallelism> configuration variable.
1185
1186This controls how many hosts Rex should connect to in L<parallel|Rex::Commands#parallelism>.
1187
1188Default is C<1>.
1189
1190=cut
1191
1192sub set_parallelism {
1193  my $class = shift;
1194  $parallelism = $_[0];
1195}
1196
1197sub get_parallelism {
1198  my $class = shift;
1199  return $parallelism || 1;
1200}
1201
1202=head2 set_log_filename
1203
1204=head2 get_log_filename
1205
1206Sets and gets the value of the C<$log_filename> configuration variable.
1207
1208This controls which file Rex should use for L<logging|Rex::Commands#logging>.
1209
1210Default is C<undef>.
1211
1212=cut
1213
1214sub set_log_filename {
1215  my $class = shift;
1216  $log_filename = shift;
1217}
1218
1219sub get_log_filename {
1220  my $class = shift;
1221  return $log_filename;
1222}
1223
1224=head2 set_log_facility
1225
1226=head2 get_log_facility
1227
1228Sets and gets the value of the C<$log_facility> configuration variable.
1229
1230This controls which log facility Rex should use when L<logging|Rex::Commands#logging> to syslog.
1231
1232Default is C<'local0'>.
1233
1234=cut
1235
1236sub set_log_facility {
1237  my $class = shift;
1238  $log_facility = shift;
1239}
1240
1241sub get_log_facility {
1242  my $class = shift;
1243  return $log_facility || "local0";
1244}
1245
1246=head2 set_environment
1247
1248=head2 get_environment
1249
1250Sets and gets the value of the C<$environment> configuration variable.
1251
1252This controls which L<environment|Rex::Commands#environment> Rex should use.
1253
1254Default is C<''>.
1255
1256=cut
1257
1258sub set_environment {
1259  my ( $class, $env ) = @_;
1260  $environment = $env;
1261}
1262
1263sub get_environment {
1264  return $environment || "";
1265}
1266
1267sub get_ssh_config_username {
1268  my $class = shift;
1269  my $param = {@_};
1270
1271  if ( exists $param->{server}
1272    && exists $SSH_CONFIG_FOR{ $param->{server} }
1273    && exists $SSH_CONFIG_FOR{ $param->{server} }->{user} )
1274  {
1275    return $SSH_CONFIG_FOR{ $param->{server} }->{user};
1276  }
1277
1278  return 0;
1279}
1280
1281sub get_ssh_config_hostname {
1282  my $class = shift;
1283  my $param = {@_};
1284
1285  if ( exists $param->{server}
1286    && exists $SSH_CONFIG_FOR{ $param->{server} }
1287    && exists $SSH_CONFIG_FOR{ $param->{server} }->{hostname} )
1288  {
1289    if ( $SSH_CONFIG_FOR{ $param->{server} }->{hostname} =~ m/^\%h(\.(.*))?/ ) {
1290      return $param->{server} . $1;
1291    }
1292    else {
1293      return $SSH_CONFIG_FOR{ $param->{server} }->{hostname};
1294    }
1295  }
1296
1297  return 0;
1298}
1299
1300sub get_ssh_config_private_key {
1301  my $class = shift;
1302  my $param = {@_};
1303
1304  if ( exists $param->{server}
1305    && exists $SSH_CONFIG_FOR{ $param->{server} }
1306    && exists $SSH_CONFIG_FOR{ $param->{server} }->{identityfile} )
1307  {
1308
1309    my $file     = $SSH_CONFIG_FOR{ $param->{server} }->{identityfile};
1310    my $home_dir = _home_dir();
1311    $file =~ s/^~/$home_dir/;
1312
1313    return $file;
1314  }
1315
1316  return 0;
1317}
1318
1319sub get_ssh_config_public_key {
1320  my $class = shift;
1321  my $param = {@_};
1322
1323  if ( exists $param->{server}
1324    && exists $SSH_CONFIG_FOR{ $param->{server} }
1325    && exists $SSH_CONFIG_FOR{ $param->{server} }->{identityfile} )
1326  {
1327    my $file     = $SSH_CONFIG_FOR{ $param->{server} }->{identityfile} . ".pub";
1328    my $home_dir = _home_dir();
1329    $file =~ s/^~/$home_dir/;
1330    return $file;
1331  }
1332
1333  return 0;
1334}
1335
1336sub get_connection_type {
1337  my $class = shift;
1338
1339  if ( $^O !~ m/^MSWin/ && !$connection_type && $use_net_openssh_if_present ) {
1340    my $has_net_openssh = 0;
1341    eval {
1342      Net::OpenSSH->require;
1343      Net::SFTP::Foreign->require;
1344      $has_net_openssh = 1;
1345      1;
1346    };
1347
1348    if ($has_net_openssh) {
1349      Rex::Logger::debug(
1350        "Found Net::OpenSSH and Net::SFTP::Foreign - using it as default");
1351      $connection_type = "OpenSSH";
1352      return "OpenSSH";
1353    }
1354  }
1355
1356  if ( !$connection_type ) {
1357    my $has_net_ssh2 = 0;
1358    eval {
1359      Net::SSH2->require;
1360      $has_net_ssh2 = 1;
1361      1;
1362    };
1363
1364    if ($has_net_ssh2) {
1365      $connection_type = "SSH";
1366      return "SSH";
1367    }
1368  }
1369
1370  return $connection_type || "SSH";
1371}
1372
1373sub get_ca {
1374  my $class = shift;
1375  return $ca_file || "";
1376}
1377
1378sub get_ca_cert {
1379  my $class = shift;
1380  return $ca_cert || "";
1381}
1382
1383sub get_ca_key {
1384  my $class = shift;
1385  return $ca_key || "";
1386}
1387
1388=head2 set_distributor
1389
1390=head2 get_distributor
1391
1392Sets and gets the value of the C<$distributor> configuration variable.
1393
1394This controls which method Rex should use for distributing tasks for parallel execution.
1395
1396Default is C<'Base'>.
1397
1398=cut
1399
1400sub set_distributor {
1401  my $class = shift;
1402  $distributor = shift;
1403}
1404
1405sub get_distributor {
1406  my $class = shift;
1407  return $distributor || "Base";
1408}
1409
1410=head2 set_template_function
1411
1412=head2 get_template_function
1413
1414Sets and gets the value of the C<$template_function> configuration variable.
1415
1416This controls the function to be used for rendering L<templates|Rex::Commands::File#template>. The value should be a subroutine reference that will be called with passing two scalar references as positional arguments: first is template content, second is template variables.
1417
1418Default is determined by the following logic:
1419
1420=over 4
1421
1422=item * if L<Rex::Template::NG> is loadable and L<use_template_ng|Rex::Config#get_use_template_ng> is true, use that
1423
1424=item * fall back to L<Rex::Template> otherwise
1425
1426=back
1427
1428=cut
1429
1430sub set_template_function {
1431  my $class = shift;
1432  ($template_function) = @_;
1433}
1434
1435sub get_template_function {
1436  if ( ref($template_function) eq "CODE" ) {
1437    return sub {
1438      my ( $content, $template_vars ) = @_;
1439      $template_vars = {
1440        Rex::Commands::task()->get_opts,
1441        (
1442          Rex::Resource->is_inside_resource
1443          ? %{ Rex::Resource->get_current_resource()->get_all_parameters }
1444          : ()
1445        ),
1446        %{ $template_vars || {} }
1447        }
1448        if ( Rex::Commands::task() );
1449      return $template_function->( $content, $template_vars );
1450    };
1451  }
1452
1453  if ( Rex::Template::NG->is_loadable && get_use_template_ng() ) {
1454
1455    # new template engine
1456    return sub {
1457      my ( $content, $template_vars ) = @_;
1458      $template_vars = {
1459        Rex::Commands::task()->get_opts,
1460        (
1461          Rex::Resource->is_inside_resource
1462          ? %{ Rex::Resource->get_current_resource()->get_all_parameters }
1463          : ()
1464        ),
1465        %{ $template_vars || {} }
1466        }
1467        if ( Rex::Commands::task() );
1468      Rex::Template::NG->require;
1469      my $t = Rex::Template::NG->new;
1470      return $t->parse( $content, %{$template_vars} );
1471    };
1472  }
1473
1474  return sub {
1475    my ( $content, $template_vars ) = @_;
1476    $template_vars = {
1477      Rex::Commands::task()->get_opts,
1478      (
1479        Rex::Resource->is_inside_resource
1480        ? %{ Rex::Resource->get_current_resource()->get_all_parameters }
1481        : ()
1482      ),
1483      %{ $template_vars || {} }
1484      }
1485      if ( Rex::Commands::task() );
1486    use Rex::Template;
1487    my $template = Rex::Template->new;
1488    return $template->parse( $content, $template_vars );
1489  };
1490}
1491
1492=head2 set_no_tty
1493
1494=head2 get_no_tty
1495
1496Sets and gets the value of the C<$no_tty> configuration variable.
1497
1498This controls whether Rex should request a terminal when using L<Net::SSH2> or allocate a pseudo-tty for the remote process when using L<Net::OpenSSH>.
1499
1500Default is C<undef>.
1501
1502=cut
1503
1504sub set_no_tty {
1505  shift;
1506  $no_tty = shift;
1507}
1508
1509sub get_no_tty {
1510  return $no_tty;
1511}
1512
1513=head2 set_allow_empty_groups
1514
1515=head2 get_allow_empty_groups
1516
1517Sets and gets the value of the C<$allow_empty_groups> configuration variable.
1518
1519This controls whether Rex should allow empty L<groups of hosts|Rex::Commands#group> or not.
1520
1521Default is C<0>.
1522
1523=cut
1524
1525sub set_allow_empty_groups {
1526  my ( $class, $set ) = @_;
1527  if ($set) {
1528    $allow_empty_groups = 1;
1529  }
1530  else {
1531    $allow_empty_groups = 0;
1532  }
1533}
1534
1535sub get_allow_empty_groups {
1536  if ($allow_empty_groups) {
1537    return 1;
1538  }
1539
1540  return 0;
1541}
1542
1543=head2 set_use_server_auth
1544
1545=head2 get_use_server_auth
1546
1547Sets and gets the value of the C<$use_server_auth> configuration variable.
1548
1549This controls whether Rex should use server-specific authentication information from group files.
1550
1551Default is C<0>.
1552
1553=cut
1554
1555sub set_use_server_auth {
1556  my ( $class, $set ) = @_;
1557  if ($set) {
1558    $use_server_auth = 1;
1559  }
1560  else {
1561    $use_server_auth = 0;
1562  }
1563}
1564
1565sub get_use_server_auth {
1566  if ($use_server_auth) {
1567    return 1;
1568  }
1569
1570  return 0;
1571}
1572
1573=head2 set_waitpid_blocking_sleep_time
1574
1575=head2 get_waitpid_blocking_sleep_time
1576
1577Sets and gets the value of the C<$waitpid_blocking_sleep_time> configuration variable.
1578
1579This controls how many seconds Rex should sleep between checking forks.
1580
1581Default is C<0.1>.
1582
1583=cut
1584
1585sub set_waitpid_blocking_sleep_time {
1586  my $self = shift;
1587  $waitpid_blocking_sleep_time = shift;
1588}
1589
1590sub get_waitpid_blocking_sleep_time {
1591  return $waitpid_blocking_sleep_time // 0.1;
1592}
1593
1594=head2 set_write_utf8_files
1595
1596=head2 get_write_utf8_files
1597
1598Sets and gets the value of the C<$write_utf8_files> configuration variable.
1599
1600This controls whether Rex should force C<UTF-8> encoding when writing files.
1601
1602Default is C<undef>.
1603
1604=cut
1605
1606sub set_write_utf8_files {
1607  my $self = shift;
1608  $write_utf8_files = shift;
1609}
1610
1611sub get_write_utf8_files {
1612  return $write_utf8_files;
1613}
1614
1615=head2 set_default_auth
1616
1617=head2 get_default_auth
1618
1619Sets and gets the value of the C<$default_auth> configuration variable.
1620
1621This controls whether Rex should attach default authentication info to tasks.
1622
1623Default is C<1>.
1624
1625=cut
1626
1627sub set_default_auth {
1628  my $self = shift;
1629  $default_auth = shift;
1630}
1631
1632sub get_default_auth {
1633  return $default_auth // 1;
1634}
1635
1636=head2 register_set_handler($handler_name, $code)
1637
1638Register a handler that gets called by I<set>.
1639
1640 Rex::Config->register_set_handler("foo", sub {
1641   my ($value) = @_;
1642   print "The user set foo -> $value\n";
1643 });
1644
1645And now you can use this handler in your I<Rexfile> like this:
1646
1647 set foo => "bar";
1648
1649=cut
1650
1651sub register_set_handler {
1652  my ( $class, $handler_name, $code ) = @_;
1653  $SET_HANDLER->{$handler_name} = $code;
1654}
1655
1656sub set {
1657  my ( $class, $var, $data ) = @_;
1658
1659  if ( exists( $SET_HANDLER->{$var} ) ) {
1660    shift;
1661    shift;
1662    return &{ $SET_HANDLER->{$var} }(@_);
1663  }
1664
1665  if ($set_no_append) {
1666    $set_param->{$var} = $data;
1667  }
1668  else {
1669    if ( ref($data) eq "HASH" ) {
1670      if ( !ref( $set_param->{$var} ) ) {
1671        $set_param->{$var} = {};
1672      }
1673      for my $key ( keys %{$data} ) {
1674        $set_param->{$var}->{$key} = $data->{$key};
1675      }
1676    }
1677    elsif ( ref($data) eq "ARRAY" ) {
1678      push( @{ $set_param->{$var} }, @{$data} );
1679    }
1680    else {
1681      $set_param->{$var} = $data;
1682    }
1683  }
1684}
1685
1686sub unset {
1687  my ( $class, $var ) = @_;
1688  $set_param->{$var} = undef;
1689  delete $set_param->{$var};
1690}
1691
1692sub get {
1693  my ( $class, $var ) = @_;
1694  $var or return;
1695  if ( exists $set_param->{$var} ) {
1696    return $set_param->{$var};
1697  }
1698}
1699
1700sub get_all {
1701  my ($class) = @_;
1702  return $set_param;
1703}
1704
1705=head2 register_config_handler($topic, $code)
1706
1707With this function it is possible to register own sections in the users config file (C<$HOME/.rex/config.yml>).
1708
1709Example:
1710
1711 Rex::Config->register_config_handler("foo", sub {
1712  my ($param) = @_;
1713  print "bar is: " . $param->{bar} . "\n";
1714 });
1715
1716And now the user can set this in his configuration file:
1717
1718 base:
1719   user: theuser
1720   password: thepassw0rd
1721 foo:
1722   bar: baz
1723
1724=cut
1725
1726sub register_config_handler {
1727  my ( $class, $topic, $code ) = @_;
1728
1729  if ( !ref($HOME_CONFIG) ) { $HOME_CONFIG = {}; }
1730  $HOME_CONFIG->{$topic} = $code;
1731
1732  if ( ref($HOME_CONFIG_YAML) && exists $HOME_CONFIG_YAML->{$topic} ) {
1733    &$code( $HOME_CONFIG_YAML->{$topic} );
1734  }
1735}
1736
1737sub read_config_file {
1738  my ($config_file) = @_;
1739  $config_file ||= _home_dir() . "/.rex/config.yml";
1740
1741  if ( -f $config_file ) {
1742    my $yaml = eval { local ( @ARGV, $/ ) = ($config_file); <>; };
1743    eval { $HOME_CONFIG_YAML = Load($yaml); };
1744
1745    if ($@) {
1746      print STDERR "Error loading $config_file\n";
1747      print STDERR "$@\n";
1748      exit 2;
1749    }
1750
1751    for my $key ( keys %{$HOME_CONFIG} ) {
1752      if ( exists $HOME_CONFIG_YAML->{$key} ) {
1753        my $code = $HOME_CONFIG->{$key};
1754        &$code( $HOME_CONFIG_YAML->{$key} );
1755      }
1756    }
1757  }
1758}
1759
1760sub read_ssh_config_file {
1761  my ($config_file) = @_;
1762  $config_file ||= _home_dir() . '/.ssh/config';
1763
1764  if ( -f $config_file ) {
1765    my @lines = eval { local (@ARGV) = ($config_file); <>; };
1766    %SSH_CONFIG_FOR = _parse_ssh_config(@lines);
1767  }
1768}
1769
1770sub _parse_ssh_config {
1771  my (@lines) = @_;
1772
1773  my %ret = ();
1774
1775  my ( @host, $in_host );
1776  for my $line (@lines) {
1777    chomp $line;
1778    next if ( $line =~ m/^\s*#/ );
1779    next if ( $line =~ m/^\s*$/ );
1780
1781    if ( $line =~ m/^Host(?:\s*=\s*|\s+)(.*)$/i ) {
1782      my $host_tmp = $1;
1783      @host    = split( /\s+/, $host_tmp );
1784      $in_host = 1;
1785      for my $h (@host) {
1786        $ret{$h} = {};
1787      }
1788      next;
1789    }
1790    elsif ($in_host) {
1791
1792      #my ($key, $val) = ($line =~ m/^\s*([^\s]+)\s+=?\s*(.*)$/);
1793      $line =~ s/^\s*//g;
1794      my ( $key, $val_tmp ) = split( /[\s=]/, $line, 2 );
1795      $val_tmp =~ s/^[\s=]+//g;
1796      my $val = $val_tmp;
1797
1798      $val =~ s/^\s+//;
1799      $val =~ s/\s+$//;
1800      for my $h (@host) {
1801        $ret{$h}->{ lc($key) } = $val;
1802      }
1803    }
1804  }
1805
1806  return %ret;
1807}
1808
1809sub import {
1810  read_ssh_config_file();
1811  read_config_file();
1812}
1813
1814_register_config_handlers();
1815
1816sub _register_config_handlers {
1817  __PACKAGE__->register_config_handler(
1818    base => sub {
1819      my ($param) = @_;
1820
1821      for my $key ( keys %{$param} ) {
1822
1823        if ( $key eq "keyauth" ) {
1824          $key_auth = $param->{keyauth};
1825          next;
1826        }
1827
1828        if ( $key eq "passwordauth" ) {
1829          $password_auth = $param->{passwordauth};
1830          next;
1831        }
1832
1833        if ( $key eq "passauth" ) {
1834          $password_auth = $param->{passauth};
1835          next;
1836        }
1837
1838        my $ref_to_key        = qualify_to_ref( $key, __PACKAGE__ );
1839        my $ref_to_key_scalar = *{$ref_to_key}{SCALAR};
1840
1841        ${$ref_to_key_scalar} = $param->{$key};
1842      }
1843    }
1844  );
1845}
1846
1847_register_set_handlers();
1848
1849sub _register_set_handlers {
1850  my @set_handler =
1851    qw/user password private_key public_key -keyauth -passwordauth -passauth
1852    parallelism sudo_password connection ca cert key distributor
1853    template_function port waitpid_blocking_sleep_time/;
1854  for my $hndl (@set_handler) {
1855    __PACKAGE__->register_set_handler(
1856      $hndl => sub {
1857        my ($val) = @_;
1858        if ( $hndl =~ m/^\-/ ) {
1859          $hndl = substr( $hndl, 1 );
1860        }
1861        if ( $hndl eq "keyauth" ) { $hndl = "key_auth"; $val = 1; }
1862        if ( $hndl eq "passwordauth" || $hndl eq "passauth" ) {
1863          $hndl = "password_auth";
1864          $val  = 1;
1865        }
1866        if ( $hndl eq "connection" ) { $hndl = "connection_type"; }
1867        if ( $hndl eq "ca" )         { $hndl = "ca_file"; }
1868        if ( $hndl eq "cert" )       { $hndl = "ca_cert"; }
1869        if ( $hndl eq "key" )        { $hndl = "ca_key"; }
1870
1871        my $ref_to_hndl        = qualify_to_ref( $hndl, __PACKAGE__ );
1872        my $ref_to_hndl_scalar = *{$ref_to_hndl}{SCALAR};
1873
1874        ${$ref_to_hndl_scalar} = $val;
1875      }
1876    );
1877  }
1878}
1879
1880sub _home_dir {
1881  if ( $^O =~ m/^MSWin/ ) {
1882    return $ENV{'USERPROFILE'};
1883  }
1884
1885  return $ENV{'HOME'} || "";
1886}
1887
18881;
1889