=head1 NAME

CFX5::System - Miscellaneous system-dependent routines

=head1 SYNOPSIS

Various miscellaneous system interactions which are not covered by any
of the other modules available in CFX-5.

=cut

package CFX5::System;

use strict;

use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS);
use Exporter;
@ISA=qw(Exporter);
@EXPORT_OK=qw(allow_coredumps assert_can_window set_x_resource);
%EXPORT_TAGS=(
	      core => [qw(allow_coredumps)],
	     );

use CFX5::Config qw(%Config);
use CFX5::Output qw(:all);
use CFX5::Commands qw(handle_rv parse_rv);

=head1 CORE DUMPS

=head2 allow_coredumps

  allow_coredumps(1);

Takes one parameter. If it is true, or not passed, the function allows
programs to dump core on error; if false, it prevents this by means
fair or foul.

This function is a NOP on Windows NT.

Core dumps are disabled by default if you use the standard CFX-5
initialisation routines.

=cut

sub allow_coredumps {
  my $arg=shift;
  $arg=(defined $arg ? $arg : 1);

  # don't use do_cmd, we don't really need this logged
  if ($arg) {
    if (handle_rv(system("ulimit", "-c", "unlimited"))) {
      # if it fails, there's not really a lot we can do
      _warn("Unable to increase core file size limit");
    }
  } else {
    if (handle_rv(system("ulimit", "-c", "0"))) {
      # if it fails, there's not really a lot we can do. Note that in
      # the script version, on HP-UX, ulimit -c is assumed not to
      # work; my experiments indicate that it now does.
      _warn("Unable to set core file size limit to zero");
    }
  }
}

=head1 WINDOWING SYSTEMS

These functions deal with tests for individual windowing systems, IOW 
X-Windows or MS Windows.

=head2 assert_can_window

This function does some quick checks, to check that there is somewhere
to display any windows programs might want to bring up. If this turns
out not to be the case it displays an error using _error and returns
false; otherwise, it does nothing and returns true.

On X, this checks for a C<DISPLAY> variable; on NT it currently does
nothing.

=cut

sub assert_can_window {
  if (!$Config{windows_nt}) {
    unless (exists $ENV{DISPLAY}) {
      _error("Cannot open X display: DISPLAY variable unset");
      return 0;
    }
  }
  return 1;
}

=head2 set_x_resource

  set_x_resource('Express*background' => 'black',
                 'Express*foreground' => 'white');

For systems running X Windows, set each argument pair as an X resource on the
default display, by opening a pipe to "xrdb -merge". This will not work on systems
not running X windows.

The return value is an empty string on success, or an error message on failure.

=cut

sub set_x_resource {
  return "No windowing system is available. Do you need to set DISPLAY?"
    unless assert_can_window();

  my %res=@_;

  local $SIG{PIPE} = 'IGNORE';
  local $SIG{CHLD} = 'DEFAULT';

  local *XRDB;

  _debug "...";
  my $openrv;
  {
    # supress warnings with -w
    local $^W;
    $^W=0;
    # -nocpp means that "linux" and "hpux" (at least) in the path
    # don't get turned into something unhelpful like "1".
    $openrv=open(XRDB, "|xrdb -merge -nocpp");
  }

  return "Error opening pipe to xrdb: $!"
    unless (defined $openrv);

  _debug "... $openrv";

  for my $r (keys %res) {
    print XRDB "$r: $res{$r}\n";
  }
  _debug "Written";
  unless (close XRDB) {
    if ($!) {
      return "Error closing pipe: $!";
    } else {
      my $hrv=parse_rv($?);
      if ($hrv->{signal}) {
        return "xrdb was interrupted by signal $hrv->{sig_name} ($hrv->{signal})".($hrv->{core} ? 'and dumped core' : '');
      } else {
        return "xrdb exited with return code $hrv->{rv}";
      }
    }
  }
  _debug "Closed";

  return '';
}

=head2 lang_fixup

This applies a workaround for some programs on HP-UX, where an
incorrect setting of the LANG environment variable causes them to
hang.  On all other platforms, it does nothing.

Viral writes:

> > It would appear that it will work with the Locale set to 'C' but HP-UX
> > has a querk that it's LANG string has to be defined as the
> > <locale>.<charset> or things don't work as expected there are numerous
> > articles on this "Feature !!!"
> > i.e.
> >     'C' has to be defined as 'C.iso88591'
> >
> >     this can be set up in the users startup files
> >
> >     setenv LANG C.iso88591
> >
> >     or
> >
> >     export LANG=C.iso88591
> >
> > you could always set this before solverManager executable is started for
> > HP systems.
> >
> > There is a posibility that having a locale.alias file on the HP systems
> > which map between locales could be a more permanent solution, but don't
> > quote me. Our HP's don't seem to have this anywhere.
> >
> > from what i understand that if LANG is not set then 'C' is used as a
> > fall back but for Hp's this is not good.

and then

I have realised that it's not all locale setttings that are causing
this, it is only the LC_CTYPE setting. Setting LANG or LC_ALL actually
causes all other locale settings to be altered accordingly & this may
have other side effects. Also altering the locale on all platforms
causes some other problems with other platforms mainly in the way of
warning messages hence LC_CTYPE should only be set for HP-UX.

=cut '

sub lang_fixup {
  return unless $Config{CFX5OS} eq 'hpux';

  unless (exists $ENV{LC_CTYPE} and $ENV{LC_CTYPE} =~ m!\.!) {
    $ENV{LC_CTYPE}='C.iso88591';
  }

  1;
}

1;
