Imported Upstream version 3.3.3
[debian/amanda] / common-src / amgetconf.pl
1 #! @PERL@
2 # Copyright (c) 2008-2012 Zmanda, Inc.  All Rights Reserved.
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 # for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc.,
16 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
20
21 use lib '@amperldir@';
22 use strict;
23 use warnings;
24 use Amanda::Config qw( :getconf :init );
25 use Amanda::Debug qw( :logging );
26 use Amanda::Util qw( :constants );
27 use Amanda::Paths;
28 use Amanda::Constants;
29 eval 'use Amanda::Disklist;';  # can fail if compiled for client only
30 use Getopt::Long;
31
32 # Implementation note: this application is a bit funny, because it does not
33 # set up Amanda fully until some time into processing.  This lets it respond
34 # with build configuration information without a config file, and lets it set
35 # up debugging for the caller.  
36 #
37 # The most obvious consequence is that, rather than calling die (which interfaces
38 # with Amanda::Debug), this file uses a locally defined 'fail' to print error 
39 # messages.
40
41 sub usage {
42     print <<EOF;
43 Usage: amgetconf [--client] [--execute-where client|server] [-l|--list] [-o configoption]* <config> <paramname>
44   (any ordering of options and arguments is acceptable)
45
46 --client is equivalent to --execute-where client
47
48 --execute-where tells amgetconf whether to operate on the client or the 
49 server; the server is the default.
50
51 paramname can be one of
52   dbopen.APPNAME -- open a debug file
53   dbclose.APPNAME:FILENAME -- close debug file FILENAME
54   build.PARAM -- get a build parameter
55   PARAM -- get an Amanda configuration parameter
56
57 For all but Amanda configuration parameters, the <config> option is
58 ignored, but must be present.  For Amanda configuration parameters,
59 values in subsections are specified in the form TYPE:NAME:PARAMETER.
60
61 With --list, PARAM can be one of
62 EOF
63     for my $name (keys %Amanda::Config::subsection_names) {
64         print "    $name\n"
65             if $Amanda::Config::subsection_names{$name};
66     }
67     exit(1);
68 }
69
70 sub fail {
71     print STDERR @_, "\n";
72     exit(1);
73 }
74
75 sub no_such_param {
76     my ($parameter) = @_;
77     fail("amgetconf: no such parameter \"$parameter\"");
78 }
79
80 ## build parameters
81
82 my %build_info = (
83     # NOTE TO MAINTAINERS:
84     #   If you add to this list, be sure to also add the new parameter 
85     #   amgetconf(8) manual page.  Note that all keys are lower-case.
86
87     ## directories from Amanda::Paths
88
89     'bindir' => $bindir,
90     'sbindir' => $sbindir,
91     'libexecdir' => $libexecdir,
92     'amlibexecdir' => $amlibexecdir,
93     'mandir' => $mandir,
94     'amanda_tmpdir' => $AMANDA_TMPDIR,
95     'config_dir' => $CONFIG_DIR,
96     'amanda_dbgdir' => $AMANDA_DBGDIR,
97     'application_dir' => $APPLICATION_DIR,
98     'gnutar_listed_incremental_dir' => $GNUTAR_LISTED_INCREMENTAL_DIR,
99     'listed_inc_dir' => $GNUTAR_LISTED_INCREMENTAL_DIR, # (historical alias)
100
101     ## constants from Amanda::Constants
102
103     # build environment info
104
105     'cc' => $Amanda::Constants::CC,
106     'version' => $Amanda::Constants::VERSION,
107     'assertions' => $Amanda::Constants::ASSERTIONS,
108     'use_version_suffixes' => 'no', # for backward compatibility
109     'locking' => $Amanda::Constants::LOCKING,
110
111     # executable paths
112
113     'dump' => $Amanda::Constants::DUMP,
114     'restore' => $Amanda::Constants::RESTORE,
115     'vdump' => $Amanda::Constants::VDUMP,
116     'vrestore' => $Amanda::Constants::VRESTORE,
117     'xfsdump' => $Amanda::Constants::XFSDUMP,
118     'xfsrestore' => $Amanda::Constants::XFSRESTORE,
119     'vxdump' => $Amanda::Constants::VXDUMP,
120     'vxrestore' => $Amanda::Constants::VXRESTORE,
121     'samba_client' => $Amanda::Constants::SAMBA_CLIENT,
122     'gnutar' => $Amanda::Constants::GNUTAR,
123     'star' => $Amanda::Constants::STAR,
124     'compress_path' => $Amanda::Constants::COMPRESS_PATH,
125     'uncompress_path' => $Amanda::Constants::UNCOMPRESS_PATH,
126     'aix_backup' => $Amanda::Constants::AIX_BACKUP,
127     'dump_returns_1' => $Amanda::Constants::DUMP_RETURNS_1,
128
129     # amanda modules
130
131     'bsd_security' => $Amanda::Constants::BSD_SECURITY,
132     'bsdudp_security' => $Amanda::Constants::BSDUDP_SECURITY,
133     'bsdtcp_security' => $Amanda::Constants::BSDTCP_SECURITY,
134     'krb5_security' => $Amanda::Constants::KRB5_SECURITY,
135     'ssh_security' => $Amanda::Constants::SSH_SECURITY,
136     'rsh_security' => $Amanda::Constants::RSH_SECURITY,
137     'use_amandahosts' => $Amanda::Constants::USE_AMANDAHOSTS,
138
139     # build-time constants
140     
141     'amanda_debug_days' => $Amanda::Constants::AMANDA_DEBUG_DAYS,
142     'default_server' => $Amanda::Constants::DEFAULT_SERVER,
143     'default_amandates_file' => $Amanda::Constants::DEFAULT_AMANDATES_FILE,
144     'default_config' => $Amanda::Constants::DEFAULT_CONFIG,
145     'default_tape_server' => $Amanda::Constants::DEFAULT_TAPE_SERVER,
146     'default_tape_device' => $Amanda::Constants::DEFAULT_TAPE_DEVICE,
147     'client_login' => $Amanda::Constants::CLIENT_LOGIN,
148     'use_rundump' => $Amanda::Constants::USE_RUNDUMP,
149     'check_userid' => $Amanda::Constants::CHECK_USERID,
150
151     # compression information
152
153     'compress_suffix' => $Amanda::Constants::COMPRESS_SUFFIX,
154     'compress_fast_opt' => $Amanda::Constants::COMPRESS_FAST_OPT,
155     'compress_best_opt' => $Amanda::Constants::COMPRESS_BEST_OPT,
156     'uncompress_opt' => $Amanda::Constants::UNCOMPRESS_OPT,
157
158     # kerberos information
159
160     'ticket_lifetime' => $Amanda::Constants::TICKET_LIFETIME,
161     'server_host_principal' => $Amanda::Constants::SERVER_HOST_PRINCIPAL,
162     'server_host_instance' => $Amanda::Constants::SERVER_HOST_INSTANCE,
163     'server_host_key_file' => $Amanda::Constants::SERVER_HOST_KEY_FILE,
164     'client_host_principal' => $Amanda::Constants::CLIENT_HOST_PRINCIPAL,
165     'client_host_instance' => $Amanda::Constants::CLIENT_HOST_INSTANCE,
166     'client_host_key_file' => $Amanda::Constants::CLIENT_HOST_KEY_FILE,
167     # (historical typos:)
168     'server_host_principle' => $Amanda::Constants::SERVER_HOST_PRINCIPAL,
169     'client_host_principle' => $Amanda::Constants::CLIENT_HOST_PRINCIPAL,
170     # (for testing purposes)
171     '__empty' => '',
172
173 );
174
175 sub build_param {
176     my ($parameter, $opt_list) = @_;
177
178     if ($opt_list) {
179         usage() unless ($parameter eq "build");
180
181         for my $pname (sort keys %build_info) {
182             print "$pname\n";
183         }
184     } else {
185         my ($pname) = $parameter =~ /^build\.(.*)/;
186
187         my $val = $build_info{lc $pname};
188         no_such_param($parameter) unless (defined($val));
189
190         print "$val\n";
191     }
192 }
193
194 ## dbopen or dbclose
195
196 sub db_param {
197     my ($parameter, $opt_list) = @_;
198     my ($appname, $filename);
199
200     # copy amgetconf pname and pcontext
201     my $pname = Amanda::Util::get_pname();
202     my $pcontext = Amanda::Util::get_pcontext();
203
204     if (($appname) = $parameter =~ /^dbopen\.(.*)/) {
205         $appname =~ s/[^[:alnum:]]/_/g;
206         # set pname and pcontext for the application
207         Amanda::Util::set_pname($appname);
208         Amanda::Util::set_pcontext($CONTEXT_CMDLINE);
209         Amanda::Debug::dbopen("server");
210         print Amanda::Debug::dbfn(), "\n";
211     } elsif (($appname, $filename) = $parameter =~ /^dbclose\.([^:]*):(.*)/) {
212         fail("debug file $filename does not exist") unless (-f $filename);
213         # set pname and pcontext for the application
214         Amanda::Util::set_pname($appname);
215         Amanda::Util::set_pcontext($CONTEXT_CMDLINE);
216         Amanda::Debug::dbreopen($filename, '');
217         Amanda::Debug::dbclose();
218         print "$filename\n";
219     } else {
220         fail("cannot parse $parameter");
221     }
222     # reset pname and pcontext for amgetconf
223     Amanda::Util::set_pcontext($pcontext);
224     Amanda::Util::set_pname($pname);
225 }
226
227 ## regular configuration parameters
228
229 sub conf_param {
230     my ($parameter, $opt_list) = @_;
231
232     if ($opt_list) {
233         # getconf_list will return an empty list for any unrecognized name,
234         # so first check that the user has supplied a real subsection
235         no_such_param($parameter)
236             unless defined($Amanda::Config::subsection_names{$parameter});
237         my @list = getconf_list($parameter);
238
239         for my $subsec (@list) {
240             print "$subsec\n";
241         }
242     } elsif ($parameter =~ /^property:/i) {
243         my %properties = %{ getconf($CNF_PROPERTY)};
244         my $propname = $parameter;
245         $propname =~ s/^property://i;
246         $propname = lc($propname);
247         if (exists $properties{$propname}) {
248             print $properties{$propname}->{'values'}[0], "\n";
249         }
250     } elsif ($parameter =~ /^device-property:/i ||
251              $parameter =~ /^device_property:/i) {
252         my %properties = %{ getconf($CNF_DEVICE_PROPERTY) };
253         my $propname = $parameter;
254         $propname =~ s/^device-property://i;
255         $propname =~ s/^device_property://i;
256         $propname = lc($propname);
257         if (exists $properties{$propname}) {
258             print $properties{$propname}->{'values'}[0], "\n";
259         }
260     } else {
261         no_such_param($parameter)
262             unless defined(getconf_byname($parameter));
263         my @strs = getconf_byname_strs($parameter, 0);
264         
265         for my $str (@strs) {
266             print "$str\n";
267         }
268     }
269 }
270
271 Amanda::Util::setup_application("amgetconf", "server", $CONTEXT_SCRIPTUTIL);
272
273 ## Command-line parsing
274
275 my $opt_list = '';
276 my $config_overrides = new_config_overrides($#ARGV+1);
277 my $execute_where = undef;
278
279 debug("Arguments: " . join(' ', @ARGV));
280 Getopt::Long::Configure(qw{bundling});
281 GetOptions(
282     'version' => \&Amanda::Util::version_opt,
283     'list|l' => \$opt_list,
284     'o=s' => sub { add_config_override_opt($config_overrides, $_[1]); },
285     'execute-where=s' => sub {
286         my $where = lc($_[1]);
287         fail("Invalid value ($_[1]) for --execute-where. Must be client or server.") 
288             unless $where eq 'client' or $where eq 'server';
289         fail("--execute-where=server conflicts with --execute-where=client or --client.")
290             unless !defined($execute_where) || (
291                 ($where eq 'client' && $execute_where) ||
292                 ($where eq 'server' && !$execute_where));
293         $execute_where = ($where eq 'client')? $CONFIG_INIT_CLIENT : 0;
294     },
295     'client' => sub {
296         fail("--execute-where=server conflicts with --execute-where=client or --client.")
297             unless !defined($execute_where) || $execute_where;
298         $execute_where = $CONFIG_INIT_CLIENT;
299     }
300 ) or usage();
301
302 my $config_name;
303 my $parameter;
304
305 if (@ARGV == 1) {
306     $parameter = $ARGV[0];
307 } elsif (@ARGV >= 2) {
308     # note that we ignore any arguments past these two.  Amdump lazily passes 
309     # such arguments on to us, so we have no choice.
310     $config_name = $ARGV[0];
311     $parameter = $ARGV[1];
312 } else {
313     usage();
314 }
315
316 ## Now start looking at the parameter.
317
318 if ($parameter =~ /^build(?:\..*)?/) {
319     config_init(0|$execute_where, undef);
320     build_param($parameter, $opt_list);
321     Amanda::Util::finish_application();
322     exit(0);
323
324
325 if ($parameter =~ /^db(open|close)\./) {
326     config_init(0|$execute_where, undef);
327     db_param($parameter, $opt_list);
328     Amanda::Util::finish_application();
329     exit(0);
330 }
331
332 # finally, finish up the application startup procedure
333 set_config_overrides($config_overrides);
334 if ($execute_where == $CONFIG_INIT_CLIENT &&
335     defined($config_name) && $config_name eq '.') {
336     config_init($CONFIG_INIT_USE_CWD | $execute_where, undef);
337 } elsif ($execute_where == $CONFIG_INIT_CLIENT &&
338     defined($config_name) && $config_name ne '.') {
339     config_init($CONFIG_INIT_EXPLICIT_NAME | $execute_where, $config_name);
340 } elsif ($execute_where == $CONFIG_INIT_CLIENT) {
341     config_init($execute_where, undef);
342 } else {
343     config_init($CONFIG_INIT_EXPLICIT_NAME | $CONFIG_INIT_USE_CWD | $execute_where, $config_name);
344 }
345 my ($cfgerr_level, @cfgerr_errors) = config_errors();
346 if ($cfgerr_level >= $CFGERR_WARNINGS) {
347     config_print_errors();
348     if ($cfgerr_level >= $CFGERR_ERRORS) {
349         die("errors processing config file");
350     }
351 }
352
353 Amanda::Util::finish_setup($RUNNING_AS_ANY);
354
355 if ($execute_where != $CONFIG_INIT_CLIENT) {
356     my $diskfile = Amanda::Config::config_dir_relative(getconf($CNF_DISKFILE));
357     $cfgerr_level = Amanda::Disklist::read_disklist('filename' => $diskfile);
358 #    if ($cfgerr_level >= $CFGERR_ERRORS) {
359 #       die "Errors processing disklist";
360 #    }
361 }
362
363 conf_param($parameter, $opt_list);
364
365 Amanda::Util::finish_application();