For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > November 2007 > system sudo and backslashing #









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author system sudo and backslashing #
R Chandrasekhar

2007-11-17, 7:59 am

Folks,

This is a Linux-oriented question.

I am writing a script that may be executed by a user with admin privileges, if
required, on a root-userless K/Ubuntu system. I want to make sub-directories
under a parent using sudo with the same UID as the parent directory. I am also
trying to copy files from one directory to another in this case using the UID of
the target directory.

In the scripts, the relevant lines are:

-------
system "sudo -u \#$uid mkdir -m 755 $rootdir"; # (A)

and

system "sudo -u \\#$uid cp $fontdir/*.$fontdoc $paths{doc}"; # (B)
-------

where

$uid is a UID obtained using File::stat or supplied as an argumnent;
$rootdir is a fully qualified path to a directory being crated;
$fontdir/*.$fontdoc is a set of globbed source files being copied;
$paths{doc} is that target directory to which these files are being copied.

The values of these variables are not relevant to this question.

I have found that in bash or dash as the shell in Linux, I need to backslash the
hash character # to give a numeric UID to sudo because the shell (like Perl)
interprets # as a comment character.

Strangely, I have found by trial and error that a single backslash-hash (\#) is
needed for statement (A) to work but a double backslash-hash (\\#) is needed for
statement (B) to work. Changing both to single or double backslashes results in
error messages from the shell.

Can someone please explain why this is so and what is going on?

Kindly copy replies to my email address as I am not always able to access this
newsgroup.

Thanks.

Chandra
17 Nov 07
P.S. I have not used existing modules for creating directories or copying files
because they do not allow UID-specific directory and file ownership.
Rob Dixon

2007-11-17, 7:00 pm

R (Chandra) Chandrasekhar wrote:
>
> This is a Linux-oriented question.


[snip]

I'm sorry, we answer only Perl-orientated questions on this list :)

Rob
Tom Phoenix

2007-11-17, 7:00 pm

On 11/16/07, R (Chandra) Chandrasekhar <chandra@ee.uwa.edu.au> wrote:

> This is a Linux-oriented question.


Then why would you ask it in a Perl-oriented forum? It would seem,
from your opening, that you should be asking in a Linux-oriented
forum. (But you do have a Perl question, after all.)

> system "sudo -u \#$uid mkdir -m 755 $rootdir"; # (A)


What happens if you put this line above that one?

print "About to run: sudo -u \#$uid mkdir -m 755 $rootdir\n";

> system "sudo -u \\#$uid cp $fontdir/*.$fontdoc $paths{doc}"; # (B)


And this above that one:

print "About to run: sudo -u \\#$uid cp $fontdir/*.$fontdoc $paths{doc}\n";

> I have found that in bash or dash as the shell in Linux, I need to
> backslash the hash character # to give a numeric UID to sudo
> because the shell (like Perl) interprets # as a comment character.


> Strangely, I have found by trial and error that a single backslash-hash
> (\#) is needed for statement (A) to work but a double backslash-hash
> (\\#) is needed for statement (B) to work. Changing both to single or
> double backslashes results in error messages from the shell.


I admire someone who admits publicly to playing trial-and-error with
sudo. But it's not necessary in this case. If you tried the print
statements, you should have seen that "\#" means a hash mark, but
"\\#" means a backslash and a hash mark. A single backslash is the
same as none at all, in this case. If you want to give a literal
backslash to the shell, you have to use two backslashes in your source
code to mean one real one.

Statement A seems to be correct with one backslash (meaning none in
the command) because it works fine without any backslashes at all.
Because perl doesn't see any shell metacharacters in that command
(oddly, it seems that "#" doesn't count), it runs sudo directly; so
sudo is happy to get the hash mark. In contrast, when running
statement B, perl sees a shell metacharacter, so it has to call the
shell to handle it. The shell eats the backslash in that command, then
gives the hash mark to sudo.

But you don't really need the shell, do you? Since you're running
sudo, avoiding the shell is probably a good idea for security reasons,
too. You could give system() a list of arguments, and then there's no
shell involved; a simple hash mark will stay a hash mark:

system "sudo", "-u", "#$uid", "mkdir", "-m", "755", $rootdir;

This has the additional advantage that the shell won't become
by any shell metacharacters in $rootdir, should they creep in.

Hope this helps!

--Tom Phoenix
Stonehenge Perl Training
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com