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