The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#! perl

use common::sense;
use Data::Dumper;
use Config;

my $PAPPRC = "$ENV{HOME}/.papp_config";
my $ETCDIR = "/etc/papp";

my %CFG;
my %secure;

if (-t STDIN) {
   # flush input
   use POSIX ();
   POSIX::tcflush 0, POSIX::TCIFLUSH;
}

$|=1;

if (-e "config") {
   eval {
      local $PApp::Config::NO_AUTOCONNECT = 1;
      local @INC = (".", @INC);
      require PApp::Config;
      %CFG = %PApp::Config;
      1;
   } or
      print "[notice] unable to read new configuration\n";
} else {
   eval {
      $ENV{PAPP_ETCDIR} = ".";
      local $PApp::Config::NO_AUTOCONNECT = 1;
      require PApp::Config;
      %CFG = %PApp::Config;
      1;
   } or
      print "[notice] unable to read old configuration\n";
}

delete $CFG{SECURE};
delete $CFG{ETCDIR};

if (-e $PAPPRC) {
   print "using values from $PAPPRC\n";
   do $PAPPRC;
}

sub get_value($$$$) {
   my ($sec, $var, $desc, $default) = @_;
   $secure{$var} = $sec;
   $CFG{$var} = $default unless defined $CFG{$var};
   #unless (defined $CFG{$var}) {
      print "$desc [$CFG{$var}]? ";
      chomp (my $res = <STDIN>);
      $res =~ s/^\"(.*)\"$/$1/s;
      $CFG{$var} = $res if $res =~ /\S/;
   #}
}

print <<EOF;

Welcome to the PApp configuration ;)

Please read the INSTALL file for instructions on what the various
questions mean.

EOF

get_value 0, "LIBDIR" , "papp library directory"      , "$Config{installprefixexp}/lib/papp";
get_value 0, "I18NDIR", "directory for i18n tables"   , "$CFG{LIBDIR}/i18n";

print <<EOF;

Please enter a system ID. A system ID is a number that uniquely identifies
your PApp installation (one papp database - one papp sysid). Please
don't make up system id's, either ask for a system ID by writing to
sysid\@nethype.de, stating something that we can use to uniquely identify
you (we keep a database of sysids, anonymized if you want), or use an
official(!) IPv4 address assigned to you.

See the FAQ entry "Why do I need a sysid?"

EOF

get_value 0, "SYSID", "unique system id", "0";

use Socket;
$CFG{SYSID} = unpack "N", Socket::inet_aton $CFG{SYSID};

print <<EOF;

PApp will usually run as a specific user/group (e.g. www/www). All files
installed will be chown'ed to that uid/gid, including the file that
contains "secret" information.

EOF

do {
   if (defined getpwuid $CFG{PAPP_UID}) {
      $CFG{PAPP_UID} = getpwuid ($CFG{PAPP_UID});
   } 
   get_value 0, "PAPP_UID", "papp user id", "0";
} until (($CFG{PAPP_UID} ne ((getpwnam $CFG{PAPP_UID})[2])
          && defined ((getpwnam $CFG{PAPP_UID})[2]))
         || ($CFG{PAPP_UID} =~ /^\d+$/));

do {
   if (defined getgrgid $CFG{PAPP_GID}) {
      $CFG{PAPP_GID} = getgrgid ($CFG{PAPP_GID});
   }
   get_value 0, "PAPP_GID", "papp group id", "0";
} until (($CFG{PAPP_GID} ne ((getgrnam $CFG{PAPP_GID})[2])
          && defined ((getgrnam $CFG{PAPP_GID})[2]))
         || ($CFG{PAPP_GID} =~ /^\d+$/));

$CFG{PAPP_UID} &&= (getpwnam $CFG{PAPP_UID})[2] || $CFG{PAPP_UID};
$CFG{PAPP_GID} &&= (getgrnam $CFG{PAPP_GID})[2] || $CFG{PAPP_GID};

print <<EOF;

PApp requires a database for it to function properly. The default should
probably be a MySQL database (which will be created if necessary),
for other databases you must modify the CREATE statements in the
"papp-install" script (or create the database manually).

EOF

get_value 0, "STATEDB", "papp database", "DBI:mysql:papp";

get_value 0, "STATEDB_USER", "papp database user", "";

print <<EOF;

The following values will be stored in the file $ETCDIR/secure and are
security-sensitive. Secure this file with appropriate permissions after
running "make install".

If you do not want to specify them here just leave them empty (you can
override them for each program/server).

EOF

get_value 1, "STATEDB_PASS", "papp database password", "";
srand;
get_value 1, "CIPHERKEY", "the serverwide cipherkey", join "", map sprintf("%02x", rand 256), 0..31;

print <<EOF;

Congratulations! Interactive configuration is complete!

EOF

sub wr {
   my ($sec, $path) = @_;

   print "writing $path\n";
   open my $fh, ">$path~"
      or die "$path: $!";
   
   my %cfg;

   while (my ($k, $v) = each %CFG) {
      $cfg{$k} = $v if $sec == $secure{$k};
   }

   local $Data::Dumper::Useqq     = 1;
   local $Data::Dumper::Terse     = 1;
   local $Data::Dumper::Quotekeys = 0;
   local $Data::Dumper::Sortkeys  = 1;

   syswrite $fh, Data::Dumper::Dumper \%cfg;
   close $fh;

   rename "$path~", $path
      or die "$path: $!";
}

wr 0, "config";
umask 077;
wr 1, "secure";