#!/usr/bin/perl -l

our (%setup, %startup, %config);
my ($gdm_conf, $wdm_conf, $xdm_conf) =
  qw(/etc/X11/gdm/gdm.conf /etc/X11/wdm/wdm-config /etc/X11/xdm/xdm-config);
my $config = sub {};

my $dm = shift
  if $ARGV[0] =~ /^[gwx]dm$/;

unless (defined &{$ARGV[0]}) {
    print STDERR <<EOF;
usage: xbannerconfig [gdm | wdm | xdm] install | remove | force
  install: add entries to gdm, wdm or xdm cofiguration to start xbanner
      automatically if they do not already exist
  remove: remove entries from gdm, wdm or xdm configuration to start
      xbanner automatically
  force: remove then re-add entries to gdm, wdm or xdm configuration to
      start xbanner automatically

If you do not explicitly choose a display manager, xbannerconfig will
attempt to determine which display manager you are using and configure
it for you.

EOF
    exit 1;
}

unless ($dm) {
  die "Cant' select a display manager.  Are you sure you have one installed?\n"
    unless (open FH, "/etc/X11/default-display-manager");

  ($dm) = <FH> =~ m!([^/\n]+)$!;

  close FH;

  die "Unknown display manager: $dm\n"
    unless $dm =~ /^[gwx]dm$/;
}

&{$dm}();
&{$ARGV[0]}();

foreach (%setup, %startup, %config) {
    if (! ref) {
	close FH;
	die "Couldn't create updated configuration files. Are you running as root?\n"
	  unless open FH, "> $_.$$"
    }
    else {
	print FH join "\n", @$_;
    }
} 
close FH;

foreach (keys %stat) {
    rename "$_.$$", $_ or next;
    chmod ${$stat{$_}}[2], $_;
    chown @{$stat{$_}}[4,5], $_;
    utime @{$stat{$_}}[8,9], $_;
}

print "WARNING: Modification of $dm files incomplete! Please check."
    if grep {-f "$_.$$" and unlink "$_.$$"} keys %stat;

print "$dm files modified ",
    ($ARGV[0] eq 'remove' && 'not '),'to run xbanner.';

exit 0;

sub gdm {
  die "Can't find gdm config files. Won't try to add xbanner to gdm.\n"
    unless (open FH, $gdm_conf);

  my @gdm = <FH>;
  close FH;
  chomp @gdm;

  my ($presession, $init);
  foreach (@gdm) {
    next unless m{^\s*
		  (?:(PreSession)ScriptDir|Display(Init)Dir)
		  \s*=\s*
		  (\S+)/?}x;

    $presession = $3
      if $1 and -d $3;

    $init = $3
      if $2 and -d $3;
  }
  close FH;
  $init ||= "/etc/gdb/Init";
  $presession ||= "/etc/gdb/PreSession";


  for (<$init/*>) {
    die "Can't find gdm config files. Won't try to add xbanner to gdm.\n"
      unless (-f $_  and open IN, $_);
    $stat{$_} = [stat (_)];

    my $file = $setup{$_} = [];
    push @$file, <IN>;
    chomp @$file;
    close IN;
  }

  for (<$presession/*>) {
    die "Can't find gdm config files. Won't try to add xbanner to gdm.\n"
      unless (-f $_  and open IN, $_);
    $stat{$_} = [stat (_)];

    my $file = $startup{$_} = [];
    push @$file, <IN>;
    chomp @$file;
    close IN;
  }

  $stat{$gdm_conf} = [stat ($gdm_conf)];
  $config{$gdm_conf} = \@gdm;
  $config = \&gdm_config;
}

sub gdm_config {
  my $cmd = shift;
  my $re = qr'\s*# changed from (\d+) by xbannerconfig';

  for (@{$config{$gdm_conf}}) {
    next unless m!^\s*BackgroundType\s*=!;

    s!^(\s*BackgroundType\s*)=0$re!$1=$2!, next
      if $cmd eq "remove";

    s/^(\s*BackgroundType\s*)=\s*(\d+)/$1=0 # changed from $2 by xbannerconfig/, next
      if $cmd eq "install";

    warn "Unrecognised BackgroundType= entry in gdm configuration. Leaving it alone.\n"
  }
}

sub wdm {
  die "Can't find wdm config files. Won't try to add xbanner to wdm.\n"
    unless (open FH, $wdm_conf);

  my @wdm = <FH>;
  close FH;
  chomp @wdm;

  foreach (@wdm) {
    next unless m{^\s*
		  DisplayManager
		  (?:\._\d+\.|\*)
		  (setup|startup)
		  \s*:\s*(?:\\\n)?\s*
		  (\S+)}x;

    die "Can't find wdm config files. Won't try to add xbanner to wdm: $2\n"
      unless (-f $2  and open IN, $2);

    $stat{$2} = [stat (_)];

    my $file = $$1{$2} = [];
    push @$file, <IN>;
    chomp @$file;
    close IN;
  }

  $stat{$wdm_conf} = [stat ($wdm_conf)];
  $config{$wdm_conf} = \@wdm;
  $config = \&wdm_config;
}

sub wdm_config {
  my $cmd = shift;
  my $re = qr'\s*DisplayManager\*wdmBg\s*:';

  for (@{$config{$wdm_conf}}) {
    next unless m!$re!;

    s/^! commented out by xbannerconfig ($re)/$1/, next
      if $cmd eq "remove";

    s/^($re)/! commented out by xbannerconfig $1/, next
      if $cmd eq "install";
  }
}

sub xdm {
  die "Can't find xdm config files. Won't try to add xbanner to xdm.\n"
    unless (open FH, $xdm_conf);

  foreach (<FH>) {
    next unless m{^\s*
		  DisplayManager
		  (?:\._\d+\.|\*)
		  (setup|startup)
		  \s*:\s*(?:\\\n)?\s*
		  (\S+)}x;

    die "Can't find xdm config files. Won't try to add xbanner to xdm.\n"
      unless (-f $2  and open IN, $2);

    $stat{$2} = [stat (_)];

    my $file = $$1{$2} = [];
    push @$file, <IN>;
    chomp @$file;
    close IN;
  }
}

sub force {
  remove();
  install();
}

sub remove {
  foreach (values %setup, values %startup) {
    @$_ = grep !(m!^#\s*XBanner -! ||
		     m!^\s*/usr/X11R6/bin/(?:xbanner|freetemp)!), @$_;
  }

  &$config("remove");
}

sub install {
    foreach (values %setup) {
      die "xbanner already in use in $dm.  You may want the force option.\n"
	if grep m!^\s*/usr/X11R6/bin/xbanner!, @$_;
    }

    print <<EOF;

Xbanner configuration
---------------------

A popular use of xbanner is to make it run when $dm is run, to beautify
the $dm login screen. I can modify some files to make this work, if you
want.
EOF

    {
      local $\ = undef;
      print "Should I modify $dm files to make xbanner be launched on $dm startup? [Y/n] ";
    }
    if (<STDIN> =~ m!^\s*[nN]!) {
      print "All right, I won't do that.";
      exit 0;
    }

    my @setup = split "\n", q{
# XBanner - begin
/usr/X11R6/bin/freetemp
/usr/X11R6/bin/xbanner -file /etc/X11/XBanner.ad
# XBanner - end
}, -1;
    pop @setup;
    shift @setup;

    foreach (values %setup) {
      my $i = @$_;
      while ($i--) {
	next if $_->[$i] =~ /^\s*(?:$|#)/ && $i;
	$_->[$i] !~ m!^\s*(?:exit(?:\s+0)?\s*)?$! and ++$i;
	splice @$_, $i, 0, @setup;
	last;
      }
    }

    my @startup = split "\n", q{
# XBanner - begin
/usr/X11R6/bin/freetemp
# XBanner - end
}, -1;
    pop @startup;
    shift @startup;

    foreach (values %startup) {
      my $i = @$_;
      while ($i--) {
	next if $_->[$i] =~ /^\s*(?:$|#)/ && $i;
	$_->[$i] !~ m!^\s*(?:exit(?:\s+0)?\s*)?$! and ++$i;
	splice @$_, $i, 0, @startup;
	last;
      }
    }

  &$config("install");
}
