Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem setting SHELL ENV variable to bash 1

Status
Not open for further replies.

mantab888

MIS
Nov 26, 2001
69
US
I'm using an Adduser perl script that came from a FreeBSD system on a Solaris 8 system and have tweeked most everything except that a couple of commands only work in a bash shell but the script tries (and fails) to run them in a Bourne (sh) shell.

I've set root' default shell to bash and tried a couple of ways in the script to set the shell:

$ENV{SHELL} = "/usr/local/bin/bash";
$shell = $ENV{'SHELL'};

Neither work. Can anyone assist in what I thought was a simple problem?
 
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';


Kind Regards
Duncan
 
This is what I set that to:

$ENV{PATH} = "/bin:/usr/bin:/usr/sbin:/usr/local/bin";

Also I've tried the SHELL variable with the quotes ('SHELL') and it still failed . The original version did not have the "''".

 
do you not need it exactly like you posted?

$ENV{PATH} = "/usr/local/bin/bash";


Kind Regards
Duncan
 
Does the script explicitly call /bin/sh anywhere? If it doesn't, you've got the option of specifying it yourself
Code:
system qw{ /bin/bash -c adduser } @adduser_args;

f

"As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs."
--Maurice Wilkes
 
Here is the script:

#!/usr/bin/perl

#Adduser - add a user to the xxxdomain NIS domain
# also, creates a home directory and establishes an alias

# emails notification to <username>@xxx.com automatically, so

# usage: Adduser <username> <homedir node> <uid> "<User Full Name">

#Valid nodes
undef %is_node;
grep($is_node{$_}++, ('filer','topone','aixserver'));

#Main program

#Untaint the variables
$ENV{PATH} = "/bin:/usr/bin:/usr/sbin:/usr/local/bin";

I've tried this several ways:
$ENV{SHELL} = "/usr/local/bin/bash";
$shell = $ENV{'SHELL'};
($ARGV[0]) || die 'Account name not specified (Adduser user node uid "User Name")';
($ARGV[1]) || die 'Node name not specified (Adduser user node uid "User Name")';
($ARGV[2]) || die 'Employee ID / User ID not specified (Adduser user node uid "User Name")';
($ARGV[3]) || die 'User name not specified (Adduser user node uid "User name")';
$ARGV[0] =~ /(\w+)/;
$ARGV[0] = $1;
$ARGV[1] =~ /(\w+)/;
$ARGV[1] = $1;
$ARGV[2] =~ /(\w+)/;
$ARGV[2] = $1;
$ARGV[3] =~ /(.+)/;
$ARGV[3] = $1;

#Check arguments
if (`/usr/bin/grep ^$ARGV[0]: /var/yp/etc/passwd`) {die "User $ARGV[0] already exists"};
if (`/usr/bin/grep ^.*:$ARGV[2]: /var/yp/etc/passwd`) {die "UID $ARGV[2] already exists"};
$is_node{$ARGV[1]} || die "$ARGV[1] -- Invalid node name";
if($ARGV[0] =~ /[A-Z]/) {die "$ARGV[0] -- Caps not allowed in usernames"};

#Create the user
print "\n\nMaking the user ...\n\n";
$homed = "/usr1"; # aixserver
if ($ARGV[1] eq "topone") { $homed = "/home3"};
if ($ARGV[1] eq "filer") { $homed = "/vol/vol0/home"};
#
print `echo "$ARGV[0]:*:$ARGV[2]:1::0:0:$ARGV[3],,,,$ARGV[2]:/net/$ARGV[1]$homed/$ARGV[0]:/bin/ksh" | cat >> /var/yp/etc/passwd`;
print "\n";

# Add an alias..
print "\n\nMaking the alias ...\n\n";
print `echo "$ARGV[0]: $ARGV[0]\@xxx.com" >> /var/yp/etc/aliases`;

# Push NIS maps
print `cd /var/yp ; /usr/ccs/bin/make`;
print "\n";

# Give the user a random password, with a safety backup
# -x = length, -x = alt. right and left hand when typing
# uppercase converted to lowercase, and print it out
$ipassword=`/usr/local/bin/mkpasswd -x x -x x -x x -x -x /usr/bin/passwd $ARGV[0]`;
if ( ! $ipassword ) { print ">>> mkpasswd failed! fix me! <<<...\n"; }

# Notify
chomp($ipassword);
print "$ARGV[0]'s initial password = \"$ipassword\" --- user should change it immediately!!!...\n";

#Make home & populate
print "\n\nMaking the home directory on $ARGV[1]...\n";
#must change uid to do remsh saving the original name
$logname = (getpwuid($<))[0];
if($ENV{REMOTE_USER}) {$logname = $ENV{REMOTE_USER};} #Running from Web
$< = $>;

print `mkdir -m 755 /net/$ARGV[1]/$homed/$ARGV[0]`;
print `cd /usr/local/share/skel ; cp * .[^.]* /net/$ARGV[1]/$homed/$ARGV[0]`;
print `chown -R $ARGV[0] /net/$ARGV[1]/$homed/$ARGV[0]`;

#Send a message to admins
print `echo $ARGV[0], uid $ARGV[2], added on $ARGV[1] | mail -s "New user added by $logname" admin\@xxx.com`;

#Send a message to user
I cut out a long section that notifies me of the account creation as well as a welcome email to the user.
#End of program
 
There doesn't seem much wrong with that. Which commands are failing? Any error messages?

f

&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
Here is the first error:

Usage: grep -hblcnsviw pattern file . . .
sh: .*:1114:: not found


After creating the homedirectory, then the script goes to cp skel files, the cp command only works in bash, thus the error:

sh: .]*: not found

Thanks!
 
I'm not sure why you indict the cp. Both the errors you show come from this line
Code:
if (`/usr/bin/grep ^.*:$ARGV[2]: /var/yp/etc/passwd`)  {die "UID $ARGV[2] already exists"};

The argument to grep contains shell meta-characters but you are not quoting them. The obvious fix is
Code:
(`/usr/bin/grep '^.*:$ARGV[2]:' /var/yp/etc/passwd`)  ...
or why not just
Code:
(`/usr/bin/grep :$ARGV[2]: /var/yp/etc/passwd`)  ...

However,I'd seriously suggest something much more like this
Code:
die "Name $ARGV[0] already exists" if getpwnam($ARGV[0]);
die "UID $ARGV[2] already exists" if getpwuid($ARGV[2]);
It's clearer, faster, shell-independent, saves two processes, and is proof from input argument typos causing random shell commands.


&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
The reason that I'm sure that the cp command is failing is from the messages that progress thru the script and when I manually tried this command from either the sh or ksh shells it fails. The cp command does work manually from the command line in a bash shell.
 
OK - but of the error message you posted, the first line is a usage message from grep and the second is from the shell trying to expand it's unescaped argument.

Please try one of the suggestions above and see if the error changes.

f

&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
I tried the last suggestion first and did not receive the sh error but when I tested running the creation of the same user and UID the script did not tell me that it already existed but failed during the makes and directory creation.

I will try the earlioer suggestions and let you know how they do.

Thanks
 
Progress!

Your 1st suggestion of quoting the meta characters worked. I also tested that it died when trying to create a duplicate entry.

Now the cp command is the last hurdle, for now.

Thanks for your help.
 
2nd suggestion probably failed becase of name service switching (/etc/nsswithc.conf) not telling the getpwent routines about NIS.

This code
Code:
print `mkdir -m 755 /net/$ARGV[1]/$homed/$ARGV[0]`;
print `cd /usr/local/share/skel ; cp * .[^.]* /net/$ARGV[1]/$homed/$ARGV[0]`;
print `chown -R $ARGV[0] /net/$ARGV[1]/$homed/$ARGV[0]`;
looks like debugging. Have you added the "print" to see what should be happening?

Assuming it is, and that what you wanted was
Code:
`mkdir -m 755 /net/$ARGV[1]/$homed/$ARGV[0]`;
`cd /usr/local/share/skel ; cp * .[^.]* /net/$ARGV[1]/$homed/$ARGV[0]`;
`chown -R $ARGV[0] /net/$ARGV[1]/$homed/$ARGV[0]`;
then your best bet would be to use the equivalent perl forms of these commands rather than invoking various utility programs via the shell. Backticks capture output but your calling them in void context anyway so that's not a problem. Try
Code:
use File::Copy;
use File::Find;
my $target = "/net/$ARGV[1]/$homed/$ARGV[0]";
mkdir( $target );
chmod( 0775, $target );
sub copy_and_chown {
  copy($_[0],$target)
  chown($ARGV[0],$_[0]);
}
find( \&copy_and_chown, '/usr/local/share/skel' );

I've omitted the error checking for clarity (I've not tested this so your mileage may vary).

see how you go,

f

&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
Does the $_[0] represent everything including files that start with a period?

sub copy_and_chown {
copy($_[0],$target)
chown($ARGV[0],$_[0]);
}
find( \&copy_and_chown, '/usr/local/share/skel' );
 
It's anything passed to it - in this case by find(). I think that hiding files beginning with a period is a shell convention, mimiced by glob or <*> in perl but not implemented in find.

I've checked the docs but to be sure, you should try it.

Yours,

f

&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
I got some compilation errors stating that there were not enough arguments for the mkdir command.

bash-3.00# ./Adduser.mod austin69 wnis 1169 "test5 July29 by MG"
Not enough arguments for mkdir at ./Adduser.mod line 99, near "$target )"
syntax error at ./Adduser.mod line 103, near ")
chown"
Execution of ./Adduser.mod aborted due to compilation errors.
 
sorry: missing semi-colon after copy.
Code:
sub copy_and_chown {
  copy($_[0],$target)
  chown($ARGV[0],$_[0]);
}
should be
Code:
sub copy_and_chown {
  copy($_[0],$target);
  chown($ARGV[0],$_[0]);
}

f

&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
One more thing:

bash-3.00# ./Adduser.mod austin70 wnis 1140 "test6 July29 by MG"
Not enough arguments for mkdir at ./Adduser.mod line 99, near "$target )"
Execution of ./Adduser.mod aborted due to compilation errors.
 
mkdir takes one or two args and neither File:Find or File::Copy overrde mkdir so I suspect you've got a typo. Can you post us the whole sub?

f

&quot;As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.&quot;
--Maurice Wilkes
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top