Writers Block

Discussion in 'Perl Misc' started by dale, Feb 15, 2008.

  1. dale

    dale Guest

    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;}
    }

    #
    ################################################################
    dale, Feb 15, 2008
    #1
    1. Advertising

  2. dale <> writes:

    > 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


    --
    Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/
    Joost Diepenmaat, Feb 15, 2008
    #2
    1. Advertising

  3. dale

    dale Guest

    On Feb 15, 2:45 pm, Joost Diepenmaat <> wrote:
    > dale <> writes:
    > > 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



    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-
    dale, Feb 15, 2008
    #3
  4. >>>>> "dale" == dale <> writes:

    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".

    --
    Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
    <> <URL:http://www.stonehenge.com/merlyn/>
    Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
    See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
    Randal L. Schwartz, Feb 15, 2008
    #4
  5. dale wrote:
    > 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
    --
    Perl isn't a toolbox, but a small machine shop where you
    can special-order certain sorts of tools at low cost and
    in short order. -- Larry Wall
    John W. Krahn, Feb 15, 2008
    #5
  6. dale <> writes:
    > 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).

    --
    Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/
    Joost Diepenmaat, Feb 15, 2008
    #6
  7. dale

    dale Guest

    On Feb 15, 3:47 pm, Joost Diepenmaat <> wrote:
    > dale <> writes:
    > > 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.
    >

    [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`;
    ###########################################################
    dale, Feb 15, 2008
    #7
  8. dale

    J. Gleixner Guest

    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.
    J. Gleixner, Feb 15, 2008
    #8
  9. Joost Diepenmaat <> wrote:


    > 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.


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad J McClellan, Feb 16, 2008
    #9
  10. On Fri, 15 Feb 2008 12:58:00 -0800 (PST), dale
    <> wrote:

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

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


    I skimmed the rest of this thread, but try $|++;


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Feb 16, 2008
    #10
  11. dale

    Dave Weaver Guest

    dale <> wrote:

    > ############################################# 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".
    Dave Weaver, Feb 18, 2008
    #11
  12. dale

    dale Guest

    On Feb 18, 4:02 am, Dave Weaver <> wrote:
    > dale <> wrote:
    > > ############################################# 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".


    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.)
    dale, Feb 19, 2008
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy Fish

    closing writers and outputstreams

    Andy Fish, Nov 13, 2003, in forum: Java
    Replies:
    1
    Views:
    487
    Thomas Weidenfeller
    Nov 13, 2003
  2. Duke Hamacher

    APIs for SAX writers

    Duke Hamacher, Oct 12, 2004, in forum: XML
    Replies:
    3
    Views:
    372
    Donald Roby
    Oct 14, 2004
  3. M.Kumar

    Advanced C++ writers

    M.Kumar, Aug 1, 2004, in forum: C++
    Replies:
    3
    Views:
    390
    Julie
    Aug 2, 2004
  4. morrell
    Replies:
    1
    Views:
    925
    roy axenov
    Oct 10, 2006
  5. Phy6
    Replies:
    2
    Views:
    290
Loading...

Share This Page