2 # Copyright (c) 1996, Carnegie Mellon University
5 # See CMUCS/CMU_copyright.ph for use and distribution information
11 OpenAFS::util - General AFS utilities
18 AFS_Trace($subject, $level);
19 AFS_SetParm($parm, $value);
21 use OpenAFS::util qw(GetOpts_AFS);
22 %options = GetOpts_AFS(\@argv, \@optlist);
26 This module defines a variety of AFS-related utility functions. Virtually
27 every application that uses AFStools will need to use some of the utilities
28 defined in this module. In addition, a variety of global variables are
29 defined here for use by all the AFStools modules. Most of these are
30 private, but a few are semi-public.
34 use OpenAFS::CMU_copyright;
36 require OpenAFS::afsconf; ## Avoid circular 'use' dependencies
42 @EXPORT = qw(&AFS_Init
45 @EXPORT_OK = qw(%AFS_Parms
51 %EXPORT_TAGS = (afs_internal => [qw(%AFS_Parms %AFS_Trace %AFScmd %AFS_Help)],
52 afs_getopts => [qw(&GetOpts_AFS &GetOpts_AFS_Help)] );
57 This function does basic initialization of AFStools. It must be called before
58 any other AFStools function.
64 my(@dirs, $c, $i, $x);
66 $AFS_Parms{'authlvl'} = 1;
67 $AFS_Parms{'confdir'} = $def_ConfDir;
68 $AFS_Parms{'cell'} = OpenAFS::afsconf::AFS_conf_localcell();
70 # Search for AFS commands
75 foreach $i ($[ .. $#dirs)
78 if (-x "$x/$c" && ! -d "$x/$c")
80 $AFScmd{$c} = "$x/$c";
81 splice(@dirs, $i, 1); # Move this item to the start of the array
86 return "Unable to locate $c!" if (!$AFScmd{$c});
92 =head2 AFS_Trace($subject, $level)
94 Sets the tracing level for a particular "subject" to the specified level.
95 All tracing levels start at 0, and can be set to higher values to get debugging
96 information from different parts of AFStools. This function is generally
97 only of use to people debugging or extending AFStools.
101 $AFS_Help{Trace} = '$subject, $level => void';
103 my($subject, $level) = @_;
105 $AFS_Trace{$subject} = $level;
109 =head2 AFS_SetParm($parm, $value)
111 Sets the AFStools parameter I<$parm> to I<$value>. AFStools parameters are
112 used to alter the behaviour of various parts of the system. The following
113 parameters are currently defined:
119 The authentication level to use for commands that talk directly to AFS
120 servers (bos, vos, pts, etc.). Set to 0 for unauthenticated access (-noauth),
121 1 to use the user's existing tokens, or 2 to use the AFS service key
126 The default AFS cell in which to work. This is initially the workstation's
131 The AFS configuration directory to use. If none is specified, the default
132 (as defined in OpenAFS::config) will be used.
136 Set the tracing level used by various B<vos> utilities. The default is 0,
137 which disables any tracing of activity of B<vos> commands. A setting of 1
138 copies output from all commands except those which are invoked solely to
139 get information; a setting of 2 additionally uses the "-verbose" command
140 on any command whose output is copied. If a setting of 3 is used, all
141 B<vos> commands will be invoked with "-verbose", and have their output
148 $AFS_Help{SetParm} = '$parm, $value => void';
150 my($parm, $value) = @_;
152 $AFS_Parms{$parm} = $value;
156 #: GetOpts_AFS(\@argv, \@optlist)
157 #: Parse AFS-style options.
158 #: \@argv is a hard reference to the list of arguments to be parsed.
159 #: \@optlist is a hard reference to the list of option specifications for valid
160 #: options; in their default order. Each option specification, in turn, is a
161 #: hard reference to an associative array containing some of the following
163 #: name => The name of the argument
164 #: numargs => Number of arguments (0, 1, or -1 for multiple)
165 #: required => If nonzero, this argument is required
166 #: default => Value to give this option if not specified
167 #: noauto => Don't use this option for unadorned arguments
169 #: Results are returned in the form of an associative array of options and
171 #: - Boolean (0-argument) options have a value of 1 if specified. This type
172 #: of option may not be marked 'required'.
173 #: - Simple (1-argument) options have a value which is the string given by the
175 #: - Multiple-argument options have a value which is a hard reference to an
176 #: array of values given by the user.
178 #: Argument parsing is done in a similar manner to the argument parser used by
179 #: various AFS utilities. Options have multi-character names, and may not be
180 #: combined with their arguments or other options. Those options which take
181 #: arguments use up at least the next argument, regardless of whether it begins
182 #: with a dash. Options which can take multiple arguments will eat at least
183 #: one argument, as well as any following argument up to the next option (i.e.,
184 #: the next argument beginning with a dash). An "unadorned" argument will be
185 #: used by the next argument-taking option. If there are multiple unadorned
186 #: arguments, they will be used up by successive arguments much in the same
187 #: way Perl handles list assignment - each one-argument (scalar) option will
188 #: use one argument; the first multi-argument (list) option will use up any
189 #: remaining unadorned arguments.
191 #: On completion, @argv will be left with any unparsed arguments (this can
192 #: happen if the last option specified is _not_ a multi-argument option, and
193 #: there are no "defaulted" options). This is considered to be an error
196 sub GetOpts_AFS_Help {
197 my($cmd, $optlist) = @_;
198 my($option, $optname, $desc);
200 foreach $option (@$optlist) {
201 $optname = '-' . $$option{name};
202 if ($$option{numargs}) {
203 $desc = $$option{desc} ? $$option{desc} : $$option{name};
205 $desc .= '+' if ($$option{numargs} < 0);
208 $optname = "[$optname]" if (!$$option{required});
215 my($optname, @options) = @_;
218 foreach $o (@options) {
219 next unless ($o =~ /^$optname/);
223 ($n == 1) ? $which : $optname;
227 my($argv, $optlist) = @_;
228 my(@autolist, %opttbl, %result);
229 my($stop, $key, $value, $diemsg);
233 if ($_->{numargs} && !$_->{noauto} && !$stop) {
234 $stop = 1 if ($_->{numargs} < 0);
239 } (@$optlist, { name=>'-help', numargs=>0, required=>0 } );
240 %opttbl = map { $_->{name} => $_ } @$optlist;
243 my($optname, $optkind);
245 # Parse the next argument. It can either be an option, or an
246 # unadorned argument. If the former, shift it off and process it.
247 # Otherwise, grab the next "automatic" option. If there are no
248 # more automatic options, we have extra arguments and should return.
249 if ($argv->[0] =~ /^-(.+)/) { # Got an option!
252 } else { # An unadorned argument
254 $optname = shift(@autolist);
256 $diemsg = join(' ', "Extra arguments:", @$argv) unless ($diemsg);
261 $optname = &_which_opt($optname, keys %opttbl);
263 # Find out how many arguments this thing wants, then remove it from
264 # the option table and automatic option list.
265 $optkind = $opttbl{$optname}->{numargs};
266 delete $opttbl{$optname};
267 @autolist = grep($_ ne $optname, @autolist);
269 # Parse arguments (if any), and set the result value
270 if (!$optkind) { # Boolean!
271 $result{$optname} = 1;
272 } elsif ($optkind == 1) { # Single argument
273 # Shift off a single argument, or signal an error
275 $diemsg = "No argument for -$optname" unless ($diemsg);
278 $result{$optname} = shift(@$argv);
279 } elsif ($optkind < 0) { # Multiple arguments
280 # Shift off at least one argument, and any additional
281 # ones that are present. EXCEPT, if there are no more
282 # explicitly-specified options but there ARE automatic
283 # options left in our list, then only eat up one.
286 $diemsg = "No argument for -$optname" unless ($diemsg);
289 $val = shift(@$argv);
290 push(@val, shift @$argv) while (@$argv && $argv->[0] !~ /^-/);
291 if (@autolist && !@$argv) {
292 unshift(@$argv, @val);
297 $result{$optname} = [@val];
299 die "Invalid argument spec for -$optname ($optkind)\n";
303 # Now for a little clean-up
304 # Set default values for any unspecified option that has them.
305 # Set an error condition if there are any required options that
306 # were not specified.
307 while (($key, $value) = each %opttbl) {
308 if ($value->{required}) {
309 $diemsg = "Required option -$key not specified" unless($diemsg);
311 $result{$key} = $value->{default};
313 if ($diemsg && !$result{help}) { die $diemsg . "\n" }
322 The following global variables are defined by B<OpenAFS::util>. None of these
323 are exported by default. Those marked "Private" should not be used outside
324 AFStools; their names, meaning, and even existence may change at any time.
328 =item %AFS_Help - Help info
330 This array contains argument lists for all publicly-exported AFStools
331 functions with names of the form AFS_*. It is intended for programs like
332 B<testbed>, which provide a direct interactive interface to AFStools.
334 =item %AFS_Parms - Parameter settings [Private]
336 This array contains the settings of AFStools parameters set with
337 B<OpenAFS::util::AFS_SetParm>.
339 =item %AFS_Trace - Tracing levels [Private]
341 This array contains the tracing levels set with B<OpenAFS::util::AFS_Trace>.
343 =item %AFScmd - AFS command locations [Private]
345 This array contains paths to the various AFS command binaries, for use
346 by B<OpenAFS::wrapper::wrapper> and possibly other AFStools functions.
352 The CMUCS AFStools, including this module are
353 Copyright (c) 1996, Carnegie Mellon University. All rights reserved.
354 For use and redistribution information, see CMUCS/CMU_copyright.pm