#!/usr/bin/perl
#  Copyright (C)1996 Austin Donnelly <and1000@cam.ac.uk>.
#  This is free software; you may modify and distribute it under the
#  terms of the GNU General Public Licence as published by the Free
#  Software Foundation, version 2 or at your option any later version.
#  There is NO WARRANTY.

$CONVPROG="./fvwmrc_convert";

# Syscall number for setgroups(), from /usr/include/sys/syscall.h
$SYS_SETGROUPS=81; # valid for linux, fill in for your flavour of unix
die "I need configuring" if (!defined($SYS_SETGROUPS));

print "Checking which users have untranslated ~/.fvwmrc files...\n";

# Read password file & build list of affected users
@todo=();
setpwent();
($name,$passwd,$uid,$gid,
 $quota,$comment,$gcos,$dir,$shell) = getpwent();
while(defined($uid))
{
    push(@todo, "$uid:$gid:$name:$dir")
	if (-f "$dir/.fvwmrc" && ! -f "$dir/.fvwm2rc");
    ($name,$passwd,$uid,$gid,
     $quota,$comment,$gcos,$dir,$shell) = getpwent();
}
endpwent();

if ($#todo == -1)
{
    print "No user has an untranslated ~/.fvwmrc - no conversion necessary.\n";
    exit 0;
}

print ($#todo + 1);
print " users need conversion, shall I convert them all now?\n";
if ($#todo < 10)
{
    printf("The user%s: ", ($#todo == 1)? " is" : "s are");
    foreach $i (@todo)
    {
	$i =~ /^[^:]+:[^:]+:([^:]+):.+$/;
	print "$1 ";
    }
    print "\n";
}
$resp="<invalid>";
while(! (($resp eq "") || ($resp =~ /^y/io) || ($resp =~ /^n/io)))
{
    print "Type Y to convert, N to skip [Y]: ";
    $resp=<STDIN>;
    chop($resp);
}

if ($resp =~ /^n/io)
{
    print "Ok, not converting\n";
    exit 0;
}

print <<EOT ;

Warnings during the conversion process will be written to
/home/<username>/.fvwm2rc.conversion
for each user.

EOT

# Do all the files
$unum=1;
printf(STDERR "Processing user: %3d/%3d", 0, $#todo+1);
foreach $line (@todo)
{
    printf(STDERR "\b\b\b\b\b\b\b"); # 7 backspaces
    printf(STDERR "%3d/%3d", $unum, $#todo+1);
    # XXX: assumes all directories in /home have corresponding uids.
    &translate($line);
    $unum++;
}
print STDERR "\n";

print "All done!\n";
exit 0;

###########################

# run $CONVPROG
sub translate
{
    local ($line) = @_;
    local ($uid, $gid, $name, $dir);

    $line =~ m/^([^:]+):([^:]+):([^:]+):(.+)$/o;
    $uid=$1;
    $gid=$2;
    $name=$3;
    $dir=$4;

    # fork, child drops privs & does work, while parent waits for child
    $pid=fork();
    die "fork() failed: $!\n" if ($pid==-1);
    if ($pid==0) # child
    {
	syscall($SYS_SETGROUPS, 0, 0); # SYS_setgroups(0, NULL); /* nasty! */
	$( = $) = $gid;  # real, eff gid
	$< = $> = $uid;  # real, eff uid
	# ok, now plain mortal, so run conversion
	open(STDOUT, ">$dir/.fvwm2rc.conversion") ||
	    die "cannot open $dir/.fvwm2rc.conversion for write: $!\n";
	open(STDERR, ">&STDOUT") || die "Can't dup stdout";
	exec($CONVPROG, "$dir/.fvwmrc", "$dir/.fvwm2rc",
	     ">$dir/.fvwm2rc.conversion 2>&1");
	die "exec() of $CONVPROG failed: $!\n";
    } else {
	# parent
	waitpid($pid, 0);
	$ret=$?>>8;
	die "Child returned with non-zero exit status($ret)\n" if ($ret);
    }
}
