views:

112

answers:

3

THE NEW QUERY: I am trying to make a unified script that initializes a new Ubuntu install to my liking, it must be run under sudo to install packages, but using gconftool-2 to affect gconf setting relies on the dbus session which is not handled properly by the method of simply changing UID in the script alone. Does someone know how to manage to do this?

OLD QUERY: I am writing a Perl script to be executed on first boot of a new Ubuntu install. This is to ease adding repositories, installing packages, and setting gconf settings. My problem is permissions. To install packages I need the script to be executed as sudo, but then the gconftool-2 call act on the root user and not on my personal user.

A: 

You can use sudo again to drop your root privileges like:

sudo -u 'your_username' gfconftool-2
Lekensteyn
I've done some testing and I'm not sure that that works, though it certainly seems that it should!
Joel
+4  A: 

You can change uids in the middle of the script by altering the uid with POSIX::setuid() (see perldoc POSIX):

use POSIX 'setuid';

# call cpan to install modules...

POSIX::setuid($newuid);

# ... continue with script
Ether
This looks promising. Combined with getlogin() to get the login name, and getpwnam(name) to get my uid at the start, it should work, I hope.
Joel
Sadly, this isn't sufficient. After reading some more, gconftool-2 checks with dbus somehow to do its magic. This is well above my head. I will edit my question, but if this doesn't progress well I will have to content myself with two scripts one to run under sudo and one to run as user.
Joel
I did need the POSIX::setuid command but I needed the environment variable more so I voted you up but not correct. No hard feelings!
Joel
A: 

After much reading and trial and error it seems that what is missing when you run a script as root is that the DBUS_SESSION_BUS_ADDRESS environment variable is not set. This must be set AND the uid changed to that of the user before the gconf settings can be set. This is my test script that I used to try it out. Run one or the other of the system calls at the end to switch the window button order. Try the script as the user or as root (sudo) to see that it works.

#!/usr/bin/perl

use strict;
use warnings;

use POSIX;

# get the user's name (as opposed to root)
my $user_name = getlogin();
# get the uid of the user by name
my $user_uid = getpwnam($user_name);
print $user_name . ": " . $user_uid . "\n";

my %dbus;
# get the DBUS machine ID
$dbus{'machine_id'} = qx{cat /var/lib/dbus/machine-id};
chomp( $dbus{'machine_id'} );
# read the user's DBUS session file to get variable DBUS_SESSION_BUS_ADDRESS
$dbus{'file'} = "/home/" . $user_name . "/.dbus/session-bus/" . $dbus{'machine_id'} . "-0";
print "checking DBUS file: " . $dbus{'file'} . "\n";
if (-e $dbus{'file'}) { 
  open(FILE, '<', $dbus{'file'});
  while(<FILE>) {
    if ($_ =~ /^DBUS_SESSION_BUS_ADDRESS=(.*)$/) {
      $dbus{'address'} = $1;
      print "Found DBUS address: " . $dbus{'address'} . "\n";
    }
  }
  close(FILE);
} else {
  print "cannot find DBUS file";
}

# set the uid to the user's uid not root's
POSIX::setuid($user_uid);
# set the DBUS_SESSION_BUS_ADDRESS environment variable
$ENV{'DBUS_SESSION_BUS_ADDRESS'} = $dbus{'address'};

my $command1 = 'gconftool-2 --set "/apps/metacity/general/button_layout" --type string "menu:maximize,minimize,close"';
my $command2 = 'gconftool-2 --set "/apps/metacity/general/button_layout" --type string "menu:minimize,maximize,close"';
system($command1);
## or
#system($command2);

Note: Got some good info here.

Joel