Writers Block

D

dale

Here's what I'm trying to do in this block of code - I'm trying to get
the UIDs from /etc/passwd and present them to the user. Then, the
user can pick a UID not in the list. If the user picks a UID in the
list, user should have his hand slapped and be prompted to enter a new
value.

The "Get UID from user" and "Check to make sure it's a new UID" parts
are what I am having trouble with.


Here is the code:

############################################## GET UID #########
#
### Get /etc/passwd names and UIDs
my $toBe = "/etc/passwd";
my $copy = "/root/bin/temp";
copy($toBe, $copy) or die "\n Cannot open file \n";
`awk -F : '{print \$1"," \$3}' /root/bin/temp > tempUID`;
`rm -f /root/bin/temp`;

### Read login names and UIDs into hash
my $tempUID = "/root/bin/tempUID";
open(FILE,"<$tempUID") || die "\nCan't read: $tempUID$!\n";
my $uid;
my $login;
while(<FILE>){
($login,$uid)=split(/,/,$_);
chomp $uid;
$hashUID->{$uid} = $login;}

### Print UIDs
$counter = 0; # reset counter
while (($uid, $login) = each(%$hashUID))
{
if ( ($uid >500)&&($uid < 5000) ){
print "\n\t$uid \t$login";}
}

### Get UID from user
sub get_UID{
print "\n\n These are the non-system logins on this system.
\n Please input a new UID to start your users with: ";
$uidInput=<>;
chomp $uidInput;}

get_UID();

### Check to make sure it's a new UID
foreach (keys (%$hashUID)) {
print "\nchecking UID"; ##for debugging
if ($uidInput == $uid) {
print "\n That UID exists already. Try another: ";
goto &get_UID;}
}

#
################################################################
 
J

Joost Diepenmaat

dale said:
Here's what I'm trying to do in this block of code - I'm trying to get
the UIDs from /etc/passwd and present them to the user. Then, the
user can pick a UID not in the list. If the user picks a UID in the
list, user should have his hand slapped and be prompted to enter a new
value.

The "Get UID from user" and "Check to make sure it's a new UID" parts
are what I am having trouble with.

Without any other info on what the trouble is:

http://perl.plover.com/FAQs/Buffering.html
 
D

dale

Without any other info on what the trouble is:

http://perl.plover.com/FAQs/Buffering.html


I should note that this is my first attempt at a PERL script. I have
hit writer's block due to my lack of PERL knowledge and I am not sure
if I am checking the user's input correctly.

I skimmed over the page you referenced, but I do not understand how it
applies in this situation.

thanks,
-dale-
 
R

Randal L. Schwartz

dale> I should note that this is my first attempt at a PERL script.

Unless you're talking about shooting a commercial for the
non-profit "Protecting Escarpment Rural Lands" (perlofburlington.org),
you are probably working on a Perl script, and not a "PERL script".
 
J

John W. Krahn

dale said:
Here's what I'm trying to do in this block of code - I'm trying to get
the UIDs from /etc/passwd and present them to the user. Then, the
user can pick a UID not in the list. If the user picks a UID in the
list, user should have his hand slapped and be prompted to enter a new
value.

The "Get UID from user" and "Check to make sure it's a new UID" parts
are what I am having trouble with.


Here is the code:

[ SNIP ]

Try something like this:

#!/usr/bin/perl
use warnings;
use strict;

my %hashUID;
while ( my ( $name, $uid ) = ( getpwent )[ 0, 2 ] ) {
$hashUID{ $uid } = $name;
}

### Print UIDs
while ( my ( $uid, $login ) = each %hashUID ) {
if ( $uid > 500 && $uid < 5000 ) {
print "\t$uid \t$login\n";
}
}

print "\nThese are the non-system logins on this system.\nPlease input a
new UID to start your users with: ";
{
( my $uidInput = <STDIN> ) =~ tr/0-9//cd;
if ( $uidInput <= 500 || $uidInput >= 5000 || exists $hashUID{
$uidInput } ) {
print "\nThat UID exists already. Try another: ";
redo;
}
}

__END__




John
 
J

Joost Diepenmaat

dale said:
I skimmed over the page you referenced, but I do not understand how it
applies in this situation.

I'm assuming (since you didn't make it clear) that the "print prompt,
read input" parts is where the problem is, and that the problem is that
you don't actually see the prompt.

Please correct me if that's not the case.

From that assumption, the problem is that perl is buffering your
script's output and you should switch off output buffering. Put

$|=1;

At the top of the code (or at least, before the prompting code).
 
D

dale

I'm assuming (since you didn't make it clear) that the "print prompt,
read input" parts is where the problem is, and that the problem is that
you don't actually see the prompt.

Please correct me if that's not the case.
[SNIP]

The code I was using and the code posted by John Krahn both work
(Thanks John). In other words, they both will accept numerical input
from the user and store the inputted value in $uidInput.

The problem is that I want the user to be prompted to enter a
different UID if the UID already exists in %hashUID (which is just a
copy of username and uid values from /etc/passwd). I am having
problem with this error checking portion.

Overall, what I would like this script to do is allow a user to create
users on a Linux server in batch from a CSV file (to save me time).
Obviously, a UID that is already in use cannot be used by a newly
created user. On the other hand, the user is encouraged to reuse a
GID (which is what I will probably do 9/10 of the time). In the
future, I would like to also allow the user to create a new group with
this script, but that is outside of the scope of what I am currently
trying to accomplish.

Perhaps knowing my overall goal and seeing my code in it's entirety
would allow anyone to assist me further. I realize there may be some
better way to do things in this script, such as how I awk files with
Perl instead of issuing Bash commands. Hopefully, I will be able to
streamline those things as my Perl skills get better. I just started
learning Perl on Monday. Any suggestions for optimization are
certainly welcome.

Anyway, here is the code:

#!/usr/bin/perl
# Author: Dale Stubblefield
# Purpose: To add multiple users from an input file.
# input file syntax: "login,user name"
#
use warnings;
use strict;
use File::Copy;

# Declare Variables
my $hash;
my $hashGID;
my %hashUID;
my $uid;
my $uidInput;
my $counter = 0;

# Clear the screen
system("clear");

############################# Get input file from user #########
#
print "\n\n Please provide a file with logins and names.";
print "\n\n (File syntax: ag03555,Jack ) ";
print "\n\n (FILE Input example: /root/fake.list ) ";
print "\n\n FILE: ";
my $FILE=<>;

open(FILE,"<$FILE") || die "\nCan't read: $FILE$!\n";
while(<FILE>){
my($login,$name)=split(/,/,$_);
chomp $name;
$hash->{$login} = $name;
}
close(FILE);
#
###########################################################


############################################## GET GID #########
#
### Get /etc/group names and GIDs
my $toBe = "/etc/group";
my $copy = "/root/bin/temp";
copy($toBe, $copy) or die "\n Cannot open file \n";
`awk -F : '{print \$1"," \$3}' /root/bin/temp > /root/bin/tempGID`;
`rm -f /root/bin/temp`;
### FOR DEBUGGING ###
# print $tempGID;
#####################

### Read group names and GIDs into hash
my $tempGID = "/root/bin/tempGID";
open(FILE,"<$tempGID") || die "\nCan't read: $tempGID$!\n";
my $gid;
my $group;
while(<FILE>){
($group,$gid)=split(/,/,$_);
chomp $gid;
$hashGID->{$gid} = $group;
}
close(FILE);

### Print GIDs
print "\n These are the non-system groups on this system.";
print "\n\tGID\tGroupname";
while (($gid, $group) = each(%$hashGID)){
if ( ($gid >500)&&($gid < 5000) ){
print "\n\t$gid \t$group";}
}

### Get GID from user
print "\n\n Please select a GID to add your users to: ";
my $gidInput=<>;
chomp $gidInput;
#
###########################################################


############################################## GET UID #########
#
### Get /etc/passwd names and UIDs
my $toBe = "/etc/passwd";
my $copy = "/root/bin/temp";
copy($toBe, $copy) or die "\n Cannot open file \n";
`awk -F : '{print \$1"," \$3}' /root/bin/temp > /root/bin/tempUID`;
`rm -f /root/bin/temp`;

### Read login names and UIDs into hash
my $tempUID = "/root/bin/tempUID";
open(FILE,"<$tempUID") || die "\nCan't read: $tempUID$!\n";
my $uid;
my $login;
while(<FILE>){
($login,$uid)=split(/,/,$_);
chomp $uid;
%hashUID->{$uid} = $login;}

### Print UIDs
print "\n\n These are the non-system logins on this system.\n";

while (($uid, $login) = each(%hashUID)){
if ( ($uid >500)&&($uid < 5000) ){
print "\n\t$uid \t$login";}
}

### Get UID from user
print "\n\n Please input a new UID to start your users with: ";
my $uidInput;
#chomp $uidInput;
{
( $uidInput = <STDIN> ) =~ tr/0-9//cd;
if ( ($uidInput <= 500 || $uidInput >= 5000 ) ||exists
$hashUID{uidInput} ) {
print "\n That UID already exists or is out of range. Try another:
";
redo;
}
}
#
###########################################################


######################################### Create Users #########
#
$counter = 0; # reset counter
foreach (keys (%$hash)){
# -u = UID
# -g = GID
# -c = comments/user real name
print "\n useradd $_ -u $uidInput -g $gidInput -c \"$hash->{$_}
\" ";
print "\n echo changeme | passwd --stdin $_ ";
print "\n chage -d 2007-10-10 -W 14 -M 90 $_ \n";
print "\n";
##### Left commented out for debugging
##### so users aren't actually created
# `useradd $_ -u $uid -g $gidInput -c \"$hash->{$_}\"`;
# `echo changeme | passwd --stdin $_`;
# `chage -d 2007-10-10 -W 14 -M 90 $_`;
######################################
$uid ++;
$counter ++;
}
print " $counter users were added.\n";
print "\n";
#
###########################################################


############################################# Clean up #########
`rm -f /root/bin/temp`;
`rm -f /root/bin/tempGID`;
`rm -f /root/bin/tempUID`;
###########################################################
 
J

J. Gleixner

dale wrote:
[...]
The problem is that I want the user to be prompted to enter a
different UID if the UID already exists in %hashUID (which is just a
copy of username and uid values from /etc/passwd). I am having
problem with this error checking portion.

Overall, what I would like this script to do is allow a user to create
users on a Linux server in batch from a CSV file (to save me time).

There are better ways to push accounts around.
Obviously, a UID that is already in use cannot be used by a newly
created user. [...]
if ( ($uidInput <= 500 || $uidInput >= 5000 ) ||exists
$hashUID{uidInput} ) {

Missing a '$' there..

if ( ($uidInput <= 500 || $uidInput >= 5000 ) ||exists
$hashUID{$uidInput} ) {


However, why do you care about the UID? Just let adduser, or
whatever you're going to use to actually add the account, create it.
A unique username is what you should care about, possibly they
could select their group, but the UID isn't something you generally
care about.

There are plenty of adduser types of scripts available. Search
the Internet and you'll find many solutions.
 
T

Tad J McClellan

perl is buffering your
script's output and you should switch off output buffering. Put

$|=1;


That is not switching off output buffering, that is switching on autoflush.

IO is still buffered, it just gets flushed more often than when
autoflush is left off.
 
D

Dave Weaver

dale said:
############################################# Clean up #########
`rm -f /root/bin/temp`;
`rm -f /root/bin/tempGID`;
`rm -f /root/bin/tempUID`;
###########################################################


Ick!

The `` backticks operator runs a shell command and returns its standard
output. If you don't want that output, use system() instead.

But there's no need to do that just to delete some files. Perl has its own
built-in "rm", spelled "unlink".
 
D

dale

Ick!

The `` backticks operator runs a shell command and returns its standard
output. If you don't want that output, use system() instead.

But there's no need to do that just to delete some files. Perl has its own
built-in "rm", spelled "unlink".

Dave - thanks man. That is exactly the kind of advice I was looking
for. I will work on implementing this. I come from a bash scripting
background so I am using those crutches until I learn replacement Perl
commands.

J.G. - THANKS!!! I had spent so much time going over this that I
didn't notice the $. Adding that made the script starting error
checking the UID properly.

You are right - normally, a person would not care about the UID.
However, in this case, it is necessary for the UIDs of the accounts to
be in a particular range in the environments I work in. (Fake
Example: UIDs starting with 500 would be for admin accounts and UIDs
starting with 1000 would be user accounts.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top