openfoam-selector.in 27.3 KB
Newer Older
1
#!/usr/bin/perl
2 3
#
# Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.
4
# Copyright (C) 2018 OpenCFD Ltd.
5 6
#
# Simple perl script to effect system-wide and per-user default
7
# selections of which OPENFOAM to use.
8 9 10 11 12 13 14 15 16 17
#

use strict;
use Getopt::Long;
use Text::Wrap;

#===========================================================================

=head1 NAME

18
openfoam-selector - A simple site-wide/per-user OPENFOAM versions selection tool
19 20 21 22 23

=head1 SYNOPSIS

=head2 Commands for end users

24
openfoam-selector [options] --list
25

26
openfoam-selector [options] --set <name>
27

28
openfoam-selector [options] --unset
29

30
openfoam-selector [options] --query
31

32
openfoam-selector [options] --version
33

34
=head2 Commands for OPENFOAM versions
35

36
openfoam-selector [options] --register <name> --source-dir <dir>
37

38
openfoam-selector [options] --unregister <name>
39 40 41

=head1 DESCRIPTION

42 43 44 45
The openfoam-selector command is a simplistic tool to select one of
multiple OPENFOAM versions.  openfoam-selector allows system
administrators to set a site-wide default OPENFOAM version while
also allowing users to set their own default OPENFOAM version
46 47 48 49 50 51 52 53
(thereby overriding the system-wide default).

Note that both the site-wide and per-user defaults are independent
from each other; a system administrator may choose not to have a
site-wide default while a user may choose to have a personal default
-- and vice versa.

The system is effected by having system-wide shell startup files that
54 55
looks first at the user's OPENFOAM preferences.  If found, the OPENFOAM
version indicated by the user's preferences is setup in the
56
current environment.  If not found, look for a site-wide default.  If
57
found, the OPENFOAM version indicated in by the site-wide default is
58 59 60 61
setup in the current environment.  If not found, exit silently.

=head2 End Users / System Administrators

62
The openfoam-selector command provides four main actions:
63 64 65

=over

66
=item * List which OPENFOAM versions are available
67 68 69 70 71 72 73 74 75 76

=item * Set a default (either on a per-user or site-wide basis)

=item * Unset a default (either on a per-user or site-wide basis)

=item * Query what the current default is

=back

A common scenario is that a system administrator sets a site-wide
77 78 79
default for a supported OPENFOAM version that most users will use.
Power users then change their per-user defaults to use a different OPENFOAM
version.
80 81

Another common scenario is for power users to frequently use
82 83
openfoam-selector to swap back and forth between multiple different OPENFOAM
version.
84

85 86 87
B<NOTE:> The openfoam-selector command only changes the defaults for I<new>
shells.  Specifically, after you invoke the openfoam-selector command to
change the default OPENFOAM version, this change does not take
88 89 90
effect until you start a new shell.  This is intentional.  See the
"KNOWN LIMITATIONS" section, below.

91
=head2 OPENFOAM Versions
92

93
OPENFOAM versions register themselves with openfoam-selector when they
94
are installed and unregister themselves when they are uninstalled.
95
Each OPENFOAM installation provides two files that setup the environment
96 97 98 99
for itself:

=over

100
=item * etc/bashrc: File sourceable by Bourne-like shells (sh, bash,
101 102
etc.)

103
=item * etc/cshrc: File sourceable by C-like shells (csh, tcsh,
104 105 106 107 108
etc.)

=back

These files are expected to be in a single directory and "registered"
109 110 111
with openfoam-selector using the I<--register> and I<--source-dir> options.
openfoam-selector will copy these files to its own internal store; it is
safe to remove the originals after the openfoam-selector registration
112 113 114 115 116 117 118
completes successfully.

The <name> argument to I<--register> must be simplistic -- it cannot
contain any shell special characters (not even if they are escaped),
nor can it contain spaces.  The intent is to provide simple names that
users can type without escaping or quoting.  Names not conforming to
these rules will be rejected and the registration will fail.
119 120
Additionally, names with a leading prefix I<__internal> are reserved
for internal use.
121

122 123
When an OPENFOAM version is uninstalled, it should unregister with
openfoam-selector via the I<--unregister> option.
124 125 126

=head1 OPTIONS

127
--list: List which OPENFOAM versions are available
128 129 130 131 132 133 134 135 136

--no: Assume "no" to any interactive questions asked.

--query: See what the current default is.  If specified with no
options, whichevery default has precedence -- if any -- will be
shown.  If specified with I<--user>, only show the per-user default
(if there is one).  If specified with I<--system>, only show the
site-wide default (if there is one).

137
--register: Register a new OPENFOAM version.  Must be
138 139
combined with the I<--source-dir> option.

140
--set <name>: Set the default OPENFOAM version.  May be combined
141 142 143
with I<--system> or I<--user> (I<--user> is the default and does not
need to be specified).

144 145
--source-dir: Specify the location where F<etc/bashrc, etc/cshrc> files
can be found.  Only meaningful when used with the
146 147 148 149 150 151
I<--register> option.

--system: When used with I<--set> or I<--unset>, specifies to work
with the site-wide default (vs. the per-user default).  When used with
I<--query>, it specifies to specifically query the site-wide default.

152
--unregister: Unregister an OPENFOAM version.
153 154 155 156 157

--user: When used with I<--set> or I<--unset>, specifies to work with
the per-user default (vs. the site-wide default).  When used with
I<--query>, it specifies to specifically query the per-user default.

158
--unset: Unset the default OPENFOAM version.  May be combined with
159 160 161 162 163
I<--system> or I<--user> (I<--user> is the default and does not need
to be explicitly specified).

--verbose: Be verbose.

164
--version: Return the version of openfoam-selector.
165 166 167 168 169 170 171 172

--yes: Assume "yes" to any interactive questions asked.

=head1 EXAMPLES

=head2 Examples for End Users / System Administrators

The four main actions that system administrators and end users invoke
173
are: listing which OPENFOAM versions are available, setting a
174 175 176
default, unsetting a default, and querying what the current default
is.

177
=head3 Listing which OPENFOAM versions are available
178

179 180
The I<--list> option to the openfoam-selector command shows a simple list
of which OPENFOAM versions are available:
181

182 183 184 185 186
  shell$ openfoam-selector --list
  openfoam-1.5
  openfoam-2.2
  openfoam-1712
  openfoam-1806
187 188 189 190
  shell$

=head3 Setting a default

191 192 193
By default, OPENFOAM selections are performed on a per-user basis with the
I<--set> option, using a name from the list of available OPENFOAM
versions (which can be obtained via the I<--list> command):
194

195
  shell$ openfoam-selector --set openfoam-1712
196 197 198 199 200
  shell$

Note that the default takes effect in the I<next> shell that is
started; it does B<NOT> take effect in the current shell!

201
If a default OPENFOAM is already set, setting a new default will cause an
202 203 204 205
interactive confirmation prompt.  This interactive prompt can be
avoided by using the I<--yes> option, which assumes a "yes" answer to
all questions:

206 207
  shell$ openfoam-selector --set openfoam-1806
  shell$ openfoam-selector --set openfoam-1806 --yes
208 209 210 211 212 213
  shell$

If the I<--system> option is used, the site-wide default is modified
instead of the per-user default.  Since this option typically reqires
writing files into protected areas, root access may be required.

214
  shell# openfoam-selector --set openfoam-1806 --system
215 216 217 218 219 220
  shell#

=head3 Unsetting a default

Unset the current default with the I<--unset> option:

221
  shell$ openfoam-selector --unset
222 223 224 225 226
  shell$

Similar to I<--set>, the I<--system> option can be used to unset the
site-wide default

227
  shell# openfoam-selector --unset --system
228 229 230 231
  shell#

=head3 Querying what the current default is

232 233
The I<--query> option can be used to see what the current OPENFOAM
version is (more specifically, what the OPENFOAM version
234
I<will be> for the next shell that is started).  It indicates both
235
which OPENFOAM is the default and at what level the default was set
236 237
(per-user vs. site-wide):

238 239 240
  shell$ openfoam-selector --set openfoam-1.2.3
  shell$ openfoam-selector --query
  default:openfoam-1.2.3
241 242 243 244 245 246
  level:user
  shell$

Note that if there is no per-user default, the system default will be
shown:

247
  shell# openfoam-selector --set openfoam-1.2.3 --system
248

249 250 251
  shell$ openfoam-selector --unset
  shell$ openfoam-selector --query
  default:otherfoam-4.5.6
252
  level:system
253 254 255
  shell$ openfoam-selector --set openfoam-1.2.3
  shell$ openfoam-selector --query
  default:openfoam-1.2.3
256 257 258 259 260 261
  level:user
  shell$

If there is no per-user default and no site-wide default, I<--query>
will return silently:

262
  shell$ openfoam-selector --query
263 264
  shell$

265
=head2 Examples for OPENFOAM versions
266 267 268 269

Registering and unregistering typically writes files into protected
areas, and therefore usually requires root access.

270
If there are no OPENFOAM versions registered, I<--list> will return
271 272
silently:

273
  shell# openfoam-selector --list
274 275
  shell#

276
An OPENFOAM with etc/bashrc in /opt/somefoam can be
277 278
registered as follows:

279 280 281 282
  shell# openfoam-selector --register myfavourite \
         --source-dir /opt/somefoam
  shell# openfoam-selector --list
  myfavourite
283 284 285 286 287 288
  shell#

Note that re-registering the same <name> will cause an interactive
confirmation prompt; the I<--yes> option can be supplied to assume
"yes" to all questions asked:

289 290 291 292 293
  shell# openfoam-selector --list
  openfoam-1806
  shell# openfoam-selector --register myfavourite \
         --source-dir /usr/local/openfoam-1806 --yes
  myfavourite is already registered.
294
  Overwriting previously registered files.
295 296
  shell# openfoam-selector --list
  myfavourite
297 298 299 300
  shell#

Unregistering is also simple:

301 302 303 304
  shell# openfoam-selector --list
  myfavourite
  shell# openfoam-selector --unregister myfavourite
  shell# openfoam-selector --list
305 306 307 308 309 310 311 312 313
  shell#

=head2 Registering and Unregistering in RPMs

Registering and unregistering via RPM is unfortunately more
complicated than it needs to be because of the following issues:

1. Although RPM obeys dependency ordering of "rpm -i a b c".  That is,
   F<c> will be installed before F<a> if F<a> requires F<c>.
314
   Regardless, RPM's must know a) that the openfoam-selector command is
315 316 317 318
   installed, and b) be able to find it in its path.

2. RPM does not obey dependency ordering of "rpm -e a b c".  That is,
   F<c> may be uninstalled before F<a>, even if F<a> requires F<c>.
319 320
   Hence, the openfoam-selector command may disappear before an RPM using the
   openfoam-selector command in a scriptlet is uninstalled.
321 322 323 324 325

3. "Updating" RPMs will first uninstall the old RPM and then
   re-install the new one.

Additionally, the staged installations (such as the OFED installer)
326
require telling the openfoam-selector command additional information so
327 328
that various internal data files can be found.

329
In general, OPENFOAM installations via RPMs should register during the
330 331 332
%post scriptlet and unregister during the %preun scriptlet (I<not>
during the %postun scriptlet!).

333 334 335 336
If RPMs "require" the openfoam-selector RPM, they can be assured that the
openfoam-selector command will exist and be installed properly, but they
still need to be able to find openfoam-selector in their PATH.  Hence, if
openfoam-selector is not installed into a default PATH location, the %post
337 338
scriptlet won't be able to find it, and the registration call will
fail.  The simplest workaround (at least for the moment) is to set the
339
PATH to where openfoam-selector is installed before installing any RPMs
340 341 342 343 344
that use it.

With that in mind, here is a possible %post scriptlet for
OFED-installed RPMS:

345
  openfoam-selector --register <name> --source-dir <source_dir> \
346 347 348 349 350
      --yes --silent

Note the following:

1. The I<--yes> option forces an overwrite if, for some reason, a
351
   previous OPENFOAM of the name is already registered.
352

353
2. The I<--silent> option makes openfoam-selector run silently, since RPMs
354 355 356 357
   are supposed to install with no output.

Here is a possible %preun scriptlet for OFED-installed RPMs:

358
  openfoam-selector --unregister <name> --yes || \
359 360 361 362 363 364 365
      /bin/true > /dev/null 2> /dev/null

Note the following:

1. We use %preun instead of %postun because of RPM's upgrade behavior.

2. Since RPM does not honor dependencies when uninstalling, it is
366 367
   possible that openfoam-selector is no longer installed, and therefore
   the command may fail.  However, since openfoam-selector is no longer
368 369 370 371 372 373 374
   installed, we don't care that it failed (i.e., there's nothing to
   unregister from), so just redirect all output to F</dev/null> and
   ensure that the return code from the overall command is "true" (RPM
   will abort if any individual scriptlet command fails).

=head1 KNOWN LIMITATIONS

375
The main known limitation of openfoam-selector is that it only affects
376
I<future> shells -- running it does not affect the I<current> shell.
377
After you run openfoam-selector to set a new default OPENFOAM (regardless of
378 379 380 381
whether it is a system-level or user-specific default), that default
will not take effect until you start a new shell -- even though
I<--query> will report the new default.

382 383
This behavior is because openfoam-selector defaults are I<only> read during
shell startup.  It was an intentional design decision -- openfoam-selector
384 385 386 387 388 389
is intended to be a simplistic tool, and an all-encompassing solution.

Other solutions for modifying the current environment exist, such as
the Environment Modules package (L<http://modules.sourceforge.net/>)
and SoftEnv from Argonne National Laboratory (and probably others).
Using these tools, you can immediately change the environment of the
390 391 392
current shell (to include switching to use a different OPENFOAM
version).  As such, these already-existing, mature tools are
better suited for such usage patterns; openfoam-selector is not intended to
393 394 395 396 397
replace them.

For rsh/ssh-based parallel environments, switching defaults frequently
should be done with care.  Specifically, rsh/ssh-based launchers may
depends on a common environment across all nodes (e.g., to find helper
398
executables and/or libraries for a specific OPENFOAM).  Consider the
399 400
following example:

401 402
  shell$ openfoam-selector --set openfoam-1.2.3
  shell$ mpirun -np 32 --hostfile myhosts openfoam_app -parallel
403

404 405
While F<openfoam_app> is starting, it may be dangerous to switch the
openfoam-selector default (perhaps in a different window) because the rsh
406
and/or ssh commands currently executing may be relying on finding the
407 408
same OPENFOAM version on all nodes.  Changing the default I<while>
the application is launching may cause a different OPENFOAM version
409 410 411 412
to be found on some nodes, thereby causing undefined behavior.

=head1 FILES

413
$HOME/@OPENFOAM_SELECTOR_HOME_FILE@ Location of per-user default selection
414

415
@OPENFOAM_SELECTOR_SYSCONFDIR@/@OPENFOAM_SELECTOR_SYSCONFIG_FILE@ Location of
416 417
site-wide default selection.

418
@OPENFOAM_SELECTOR_DATADIR@/data Directory containing registered OPENFOAM
419 420 421 422 423 424 425 426 427 428
shell startup files.

=head1 AUTHOR

Written by Jeff Squyres.

=head1 REPORTING BUGS

Send bug reports to the OpenFabrics general mailing list (see
L<http://www.openfabrics.org/>).  This is a high-volume mailing list,
429
so be sure to put "openfoam-selector" in the subject to ensure that it is
430 431 432 433 434 435 436 437 438 439
not missed.

=head1 COPYRIGHT

Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.

This is free software; see the source for copying conditions.  There
is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

440
Copyright (C) 2018 OpenCFD Ltd.
441

442 443 444 445 446 447
=cut

#===========================================================================

# Global variables

448 449
my $data_dir = "@OPENFOAM_SELECTOR_DATADIR@";
my $sysconfig_dir = "@OPENFOAM_SELECTOR_SYSCONFDIR@";
450

451 452
my $sysconfig_file = "@OPENFOAM_SELECTOR_SYSCONFIG_FILE@";
my $home_file = "@OPENFOAM_SELECTOR_HOME_FILE@";
453 454 455 456 457 458 459 460 461

#===========================================================================

sub show_help {
    our $silent;
    my $ret = shift;

    print "$0 options:

462
Options for OPENFOAM versions:
463

464 465
--register <name>     Register an OPENFOAM version with the central
                      openfoam-selector database.  Requires use of the
466 467
                      --source-dir option.
--source-dir <dir>    Used with --register, indicating that <dir> is
468 469 470
                      where the etc/bashrc file can be found.
--unregister <name>   Remove an OPENFOAM version list from the
                      central openfoam-selector database.
471 472 473 474 475

Options for system administrators:

--system              When used with the --set and --unset options,
                      act on the system-wide defaults (vs. the
476
                      per-user defaults).  When used with --query, only
477 478 479
                      show the site-wide default (if there is one).
--user                When used with the --set and --unset options,
                      act on the per-user defaults (vs. the
480
                      site-wide defaults).  When used with --query, only
481 482 483 484
                      show the per-user default (if there is one).

Options for users:

485 486 487 488 489
--list                Show a list of the currently registered OPENFOAM
                      versions.
--set <name>          Set <name> to be the default OPENFOAM selection.
--unset               Remove the default OPENFOAM selection.
--query               Shows the current default OPENFOAM selection.
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
--yes                 Assume the answer is \"yes\" to any question.
--no                  Assume the answer is \"no\" to any question.
--verbose             Be verbose about actions.
--silent              Print nothing (not even warnings or errors;
                      overrides --verbose)
--version             Display the version of $0.
"
      if (!$silent);
    exit($ret);
}

#===========================================================================

sub make_safe_filename {
    my $name = shift;
    $name =~ s/[ :\/\\\*\&\$\#\@\!\t\n\[\]\{\}\(\)]/_/g;
506
    $name =~ s/^__internal//;  # Disallow reserved names
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
    return $name;
}

#===========================================================================

sub error {
    our $silent;
    print STDERR wrap("ERROR: ", "       ", @_) . "\n"
      if (!$silent);
    exit(1);
}


sub warning {
    our $silent;
    print STDERR wrap("WARNING: ", "         ", @_) . "\n"
      if (!$silent);
}


sub verbose {
    our $silent;
    our $verbose_flag;
    print wrap("", "", @_) . "\n"
      if ($verbose_flag && !$silent);
}

#===========================================================================

sub get_yn {
    my $prompt = shift;
    my $default = shift;

    if (defined($default)) {
        if ($default) {
            $default = 1;
            $prompt .= " (Y/n) ";
        } else {
            $default = 0;
            $prompt .= " (y/N) ";
        }
    } else {
        $prompt .= " (y/n/) ";
    }

    while (1) {
        print $prompt;
        my $ans = <STDIN>;
        chomp($ans);
        if ($ans =~ /y/i) {
            return 1;
        } elsif ($ans =~ /n/i) {
            return 0;
        } elsif ("" eq $ans) {
561
            return $default
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
              if (defined($default));
        }
        print "\nPlease choose Y or N\n";
    }
}

#===========================================================================

sub do_query {
    my $file = shift;
    my $level = shift;

    if (-f $file) {
        open(FILE, $file);
        my $name = <FILE>;
        close(FILE);
578

579 580 581 582 583 584 585 586 587 588 589 590 591 592
        chomp($name);
        print "default:$name\nlevel:$level\n";
        exit(0);
    }
}

#===========================================================================

# Set autoflush
select STDOUT;
$| = 1;

# Module options
$Text::Wrap::columns = 76;
593
# No option bundling
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639

my $help = 0;
my $register;
my $source_dir;
my $unregister;
my $system = 0;
my $user = 0;
my $list = 0;
my $set;
my $unset;
my $yes;
my $query = 0;
our $verbose_flag = 0;
my $version = 0;
my $no;
our $silent = 0;

my $ok = Getopt::Long::GetOptions("help|h" => \$help,
                                  "register=s" => \$register,
                                  "source-dir=s" => \$source_dir,
                                  "unregister=s" => \$unregister,
                                  "system" => \$system,
                                  "user" => \$user,
                                  "list" => \$list,
                                  "set=s" => \$set,
                                  "unset" => \$unset,
                                  "query" => \$query,
                                  "yes|y" => \$yes,
                                  "verbose" => \$verbose_flag,
                                  "version" => \$version,
                                  "no" => \$no,
                                  "silent" => \$silent,
                                  );

show_help(1) if (!$ok);
show_help(0) if ($help);
$yes = 0
  if (defined($no));
error("Can only specify one of --user or --system; not both")
    if ($user + $system > 1);

#---------------------------------------------------------------------------

# Check for bozo case -- this is a simple script, so let's limit to
# one action at a time

640
my $val = defined($register) + defined($unregister) + $list +
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
  defined($set) + defined($unset) + $query + $version;
if (0 == $val) {
    print("Nothing to do!\n")
      if (!$silent);
    show_help(0);
}
if (1 != $val) {
    print("ERROR: Please only specify one action\n")
      if (!$silent);
    show_help(1);
}

#---------------------------------------------------------------------------

# Version informtion

if ($version) {
    print "$0 version @PACKAGE_VERSION@

Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

664 665 666
Written by Jeff Squyres.

Changes Copyright (C) 2018 OpenCFD Ltd.\n"
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
      if (!$silent);
    exit(0);
}

#---------------------------------------------------------------------------

# Registration

elsif ($register) {
    # Check to be sure that they also specified a --source-dir
    error("--register must be used in conjunction with --source-dir")
      if (!defined($source_dir));

    # Make sure that the source dir exists
    error("Cannot read from source directory ($source_dir)")
      if (! -d $source_dir);

    # Look for the target files in the source dir
685 686
    error("Cannot find both etc/bashrc in source directory ($source_dir)")
      if (! (-f "$source_dir/etc/bashrc"));
687 688

    # Only allow simple names, just for simplicity
689
    my $foam_name = make_safe_filename($register);
690
    error("Please use a simple registration name that is also valid as a filename; avoid shell meta characters that would need to be escaped (\"$register\" is not suitable)")
691
      if ($foam_name ne $register);
692 693 694 695

    # Ensure data directory exists
    if (! -d $data_dir) {
        system("mkdir -p $data_dir");
696
        error("Cannot make openfoam-selector data directory ($data_dir)")
697 698 699
          if (! -d $data_dir);
    }

700 701 702
    # See if there's already registered files for this OPENFOAM version
    if (-f "$data_dir/$foam_name") {
        verbose("$foam_name is already registered.");
703 704 705 706 707
        if (defined($yes)) {
            if (!$yes) {
                verbose("NOT overwriting previously registered files");
                exit(0);
            }
708
        } else {
709 710 711 712 713 714 715 716 717 718
            my $ans = get_yn("Overwrite the previously registered files?", 0);
            if (!$ans) {
                verbose("Did NOT overwrite previous files");
                exit(0);
            }
            verbose("Overwriting previously registered files");
        }
    }

    # Copy the files over
719 720 721 722 723 724 725 726 727 728
    verbose("Registering $source_dir");

    if (open my $fh, '>', "$data_dir/$foam_name")
    {
        print $fh "$source_dir\n";
    }
    else
    {
        error("Unable to register $source_dir to $data_dir -- aborting");
    }
729 730 731 732 733 734 735 736
}

#---------------------------------------------------------------------------

# Unregistration

elsif ($unregister) {
    # Only allow simple names, just for simplicity
737 738
    my $foam_name = make_safe_filename($unregister);
    if ($foam_name ne $unregister) {
739 740 741 742
        error("Please use a simple registration name that is also valid as a filename; avoid shell meta characters that would need to be escaped (\"$register\" is not suitable)");
    }

    # If the data directory does not exist, there's nothing to do
743
    error("Could not find $foam_name files registered")
744 745 746
      if (! -d $data_dir);

    # Look for the files in the data directory
747 748 749
    if (-f "$data_dir/$foam_name") {
        verbose("Unregistering $foam_name");
        unlink("$data_dir/$foam_name");
750

751 752
        warning("Unable to unregister $foam_name -- file not removed!")
          if (-f "$data_dir/$foam_name");
753
    } else {
754
        warning("No files found to unregister for $foam_name -- aborting");
755 756 757 758 759 760 761 762 763 764 765 766 767
    }
}

#---------------------------------------------------------------------------

# Listing

elsif ($list) {
    exit(0)
      if ($silent);

    if (-d $data_dir) {
        opendir(DIR, "$data_dir") ||
768
          error("Cannot open openfoam-selector data directory ($data_dir)");
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
        my @names = grep { -f "$data_dir/$_" } readdir(DIR);
        closedir(DIR);

        # Strip off the .sh/.csh endings
        my $index;
        foreach my $n (@names) {
            $n =~ s/\.sh$//;
            $n =~ s/\.csh$//;
            $index->{$n} = 1;
        }
        # Sort and print out what's left
        foreach my $n (sort(keys(%$index))) {
            print "$n\n";
        }
    }
}

#---------------------------------------------------------------------------

# Setting

elsif ($set) {
    my $file;

    # Check to see if the specified files exist
794 795
    error("OPENFOAM \"$set\" does not seem to be registered -- aborting")
      if (! -f "$data_dir/$set");
796 797 798 799 800 801 802 803

    # Which default are we changing?
    if ($system) {
        verbose("Setting system-wide default: $set");
        $file = "$sysconfig_dir/$sysconfig_file";
        # Ensure that the directory exists
        system("mkdir -p $sysconfig_dir")
          if (! -d $sysconfig_dir);
804
        error("Could not make openfoam-selector defaults directory ($sysconfig_dir)")
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
          if (! -d $sysconfig_dir);
    } else {
        verbose("Setting user-specific default: $set");
        $file = "$ENV{HOME}/$home_file";
    }

    # If the file already exist, prompt if they want to overwrite it
    if (-f $file) {
        if (defined($yes)) {
            if (!$yes) {
                verbose("NOT overwriting pre-existing default");
                exit(0);
            }
        } else {
            my $ans = get_yn("Defaults already exist; overwrite them?", 0);
            if (!$ans) {
                verbose("Defaults NOT overwritten");
                exit(0);
            }
        }
        verbose("Overwriting pre-existing default");
    }

    # Write it
    open(FILE, ">$file") ||
      error("Could not write to defaults file ($file) -- aborting");
    print FILE "$set\n";
    close(FILE);
}

#---------------------------------------------------------------------------

# Unsetting

elsif ($unset) {
    # If system, unlink the sysconfig file
    if ($system) {
        verbose("Removing system-wide default");
        unlink("$sysconfig_dir/$sysconfig_file") ||
844
          error("Unable to remove the openfoam-selector defaults file! ($sysconfig_dir/$sysconfig_file)");
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
        exit(0);
    }

    # Otherwise, we're unsetting user-level defaults.  So unlink the
    # file under $HOME
    my $file;
    $file = "$ENV{HOME}/$home_file";
    if (-f $file) {
        verbose("Removing user-specific default");
        unlink($file) ||
          error("Unable to remove user-level default file! ($file)");
    }
}

#---------------------------------------------------------------------------

# Querying

elsif ($query) {
    exit(0)
      if ($silent);

    my $files = {
        user => "$ENV{HOME}/$home_file",
        system => "$sysconfig_dir/$sysconfig_file",
    };

    do_query($files->{user}, "user")
        if ($user || !$system);
    do_query($files->{system}, "system")
        if ($system || !$user);
}

# Should never get here
exit(0);