bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(no subject)


From: Bruce Korb
Subject: (no subject)
Date: Tue, 16 Dec 2003 11:50:18 -0800 (PST)

>From - Tue Dec 16 11:48:45 2003
X-Mozilla-Status: 8001
X-Mozilla-Status2: 00000000
Message-ID: <address@hidden>
Date: Tue, 16 Dec 2003 11:47:21 -0800
From: Bruce Korb <address@hidden>
Reply-To: address@hidden
Sender: address@hidden
X-Mailer: Mozilla 4.8 [en] (X11; U; SunOS 5.8 sun4u)
X-Accept-Language: en
MIME-Version: 1.0
To: address@hidden
Subject: getpwnam(1) ?
Content-Type: multipart/mixed;
 boundary="------------136311A7BB107C214BB1D637"

This is a multi-part message in MIME format.
--------------136311A7BB107C214BB1D637
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi all,

I was writing another shell script and needed a full user name
(i.e., the "comment" entry from /etc/passwd).  Grepping and sedding
is such a nuisance, especially since there is a POSIX lib call to
do the job:  getwpnam(3).  Why not just expose this (and other?)
lib/sys calls with a wrapper program?  Attached is something I threw
together that has the following usage:

$ getpwnam -?
getpwnam - Get password entries - Ver. 1.2
USAGE:  getpwnam [ -<flag> | --<name> ]... [ user-name-or-id ]

   -n, --name                 Print the user name
   -p, --passwd               Print the (encrypted) password
   -u, --uid                  Print the user id
   -g, --gname                Print the group name
   -G, --gid                  Print the group id
   -N, --gecos                Print the real user name (comment string)
   -d, --dir                  Print the home directory
   -s, --shell                Print the login shell
   -A, --all                  Print everything
                                - prohibits these options:
                                name
                                passwd
                                uid
                                gname
                                gid
                                gecos
                                dir
                                shell
   -V, --verbose              Verbose output
   -v, --version[=arg]        Output version information and exit
   -?, --help                 Display usage information and exit
   -!, --more-help            Extended usage information passed thru pager

Options are specified by doubled hyphens and their name
or by a single hyphen and the flag character.

This command uses getpwnam(3) or getpwuid(3) to obtain the requested
information from the passwd database.  If a user name or user id is
not provided, the information for the current user is obtained.
The results are printed in the order selected.  If you select no options,
nothing is printed on success, but the user name/user id will have been
validated.

please send bug reports to:  address@hidden
$ getpwnam -A
bkorb x 4438 fcf 119 Bruce Korb /u/bkorb /bin/ksh
$ getpwnam -A -V
user name:    bkorb
password:     'x' (encrypted)
user id:      4438
group name:   fcf
group id:     119
full name:    Bruce Korb
directory:    /u/bkorb
login shell:  /bin/ksh
--------------136311A7BB107C214BB1D637
Content-Type: text/plain; charset=us-ascii;
 name="getpwnam.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="getpwnam.c"


#include <sys/types.h>

#include <stdlib.h>

#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#ifdef __sun
# include <inttypes.h>
#else
# include <stdint.h>
#endif

#include "opts.h"

void
printInfo( struct passwd* pw );

void
printInfoVerbosely( struct passwd* pw );

int
main( int argc, char** argv )
{
    static const char zBadUser[] =
        "%s error:  '%s' is not a valid user name or id\n";

    uid_t uid = getuid();
    struct passwd*  pw;
    char*  pzUser;

    {
        int ct = optionProcess( &getpwnamOptions, argc, argv );
        argc  -= ct;
        pzUser = argv[ ct ];
    }

    switch (argc) {
    default:
        fputs( "Error:  Too many command line arguments\n", stderr );
        USAGE( EXIT_FAILURE );
        /* NOTREACHED */

    case 1:
        pw = getpwnam( pzUser );
        if (pw != NULL)
            break;
        errno = 0;
        {
            char* pz;
            long  l = strtol( pzUser, &pz, 0 );
            switch (l) {
            case LONG_MIN:
            case LONG_MAX:
            case 0:
                if (errno != 0) {
                    fprintf( stderr, zBadUser, getpwnamOptions.pzProgName,
                             pzUser );
                    USAGE( EXIT_FAILURE );
                }
            }
            uid = (uid_t)l;
        }
        /* FALLTHROUGH */

    case 0:
        pw = getpwuid( uid );

        if (pw != NULL)
            break;

        if (argc == 0) {
            fprintf( stderr, "%s error:  uid %d has no password entry\n",
                     getpwnamOptions.pzProgName, uid );
        } else {
            fprintf( stderr, zBadUser, getpwnamOptions.pzProgName, pzUser );
        }
        return EXIT_FAILURE;
    }

    if (selectCt > 0) {
        if (HAVE_OPT( VERBOSE ))
            printInfoVerbosely( pw );
        else
            printInfo( pw );
    }

    return EXIT_SUCCESS;
}

void
printInfoVerbosely( struct passwd* pw )
{
    static const char zBadGrp[] =
        "%s error: the primary group for %s is invalid\n";
    int ix = 0;
    do  {
        switch (selections[ix]) {
        case INDEX_OPT_NAME:
            printf( "user name:    %s\n", pw->pw_name );
            break;

        case INDEX_OPT_PASSWD:
            printf( "password:     '%s' (encrypted)\n", pw->pw_passwd );
            break;

        case INDEX_OPT_UID:
            printf( "user id:      %d\n", pw->pw_uid );
            break;

        case INDEX_OPT_GNAME:  {
            struct group* pg = getgrgid( pw->pw_gid );
            if (pg == NULL) {
                fprintf( stderr, zBadGrp, getpwnamOptions.pzProgName,
                         pw->pw_name );
                exit( EXIT_FAILURE );
            }
            printf( "group name:   %s\n", pg->gr_name );
            break;
        }

        case INDEX_OPT_GID:
            printf( "group id:     %d\n", pw->pw_gid );
            break;

        case INDEX_OPT_GECOS:
            printf( "full name:    %s\n", pw->pw_gecos );
            break;

        case INDEX_OPT_DIR:
            printf( "directory:    %s\n", pw->pw_dir );
            break;

        case INDEX_OPT_SHELL:
            printf( "login shell:  %s\n", pw->pw_shell );
            break;

        default:
            fprintf( stderr, "%s error: unknown selection:  %d\n",
                     getpwnamOptions.pzProgName, selections[ix] );
            exit( EXIT_FAILURE );
        }
    } while (++ix < selectCt);
}

void
printInfo( struct passwd* pw )
{
    static const char zBadGrp[] =
        "%s error: the primary group for %s is invalid\n";
    int ix = 0;

    for (;;) {
        switch (selections[ix]) {
        case INDEX_OPT_NAME:   fputs( pw->pw_name,   stdout ); break;
        case INDEX_OPT_PASSWD: fputs( pw->pw_passwd, stdout ); break;
        case INDEX_OPT_UID:    printf( "%d", pw->pw_uid );     break;
        case INDEX_OPT_GNAME:  {
            struct group* pg = getgrgid( pw->pw_gid );
            if (pg == NULL) {
                fprintf( stderr, zBadGrp, getpwnamOptions.pzProgName,
                         pw->pw_name );
                exit( EXIT_FAILURE );
            }
            fputs( pg->gr_name, stdout );
            break;
        }

        case INDEX_OPT_GID:    printf( "%d", pw->pw_gid );     break;
        case INDEX_OPT_GECOS:  fputs( pw->pw_gecos,  stdout ); break;
        case INDEX_OPT_DIR:    fputs( pw->pw_dir,    stdout ); break;
        case INDEX_OPT_SHELL:  fputs( pw->pw_shell,  stdout ); break;
        default:
            fprintf( stderr, "%s error: unknown selection:  %d\n",
                     getpwnamOptions.pzProgName, selections[ix] );
            exit( EXIT_FAILURE );
        }

        if (++ix >= selectCt)
            break;

        fputc( ' ', stdout );
    }
    fputc( '\n', stdout );
}

/*
 * Local Variables:
 * mode: C
 * c-file-style: "stroustrup"
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 * end of getpwnam.c */

--------------136311A7BB107C214BB1D637
Content-Type: text/plain; charset=us-ascii;
 name="opts.def"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="opts.def"


autogen definitions options;

copyright = {
    date  = "2003";
    owner = "Bruce Korb";
    eaddr = "address@hidden";
    type  = gpl;
};

/*
 *  $Id: opts.def,v 1.2 2003/05/25 22:51:14 bkorb Exp $
 */

prog-name      = "getpwnam";
prog-title     = "Get password entries";
argument       = "[ user-name-or-id ]";
gnu-usage;
long-opts;

version        = `echo "$Revision: 1.2 $" | sed 's/^.*: *//;s/ .*//'`;

explain = <<- _EndExplanation_
        This command uses getpwnam(3) or getpwuid(3) to obtain the requested
        information from the passwd database.  If a user name or user id is
        not provided, the information for the current user is obtained.
        The results are printed in the order selected.  If you select no 
options,
        nothing is printed on success, but the user name/user id will have been
        validated.
        _EndExplanation_;

export = <<- _EndExport_
        #include <stdio.h>

        extern int selectCt;
        int selections[INDEX_OPT_ALL];
        _EndExport_;

include = <<- _EndInclude_
        int selectCt = 0;
        int selections[INDEX_OPT_ALL] = { 0 };
        _EndInclude_;

flag = {
    name      = name;
    value     = n;
    descrip   = "Print the user name";
    doc       = "The user login name will be printed.";
    flag-code = <<- _EndCode_
                    int ix = selectCt++;
                    if (selectCt > INDEX_OPT_ALL) {
                        fprintf( stderr, "%s PROGRAM BUG: too many 
selections\n",
                                 pOptions->pzProgName );
                        exit( 1 );
                    }
                    selections[ ix ] = pOptDesc->optIndex;
                _EndCode_;
};

flag = {
    name      = passwd;
    value     = p;
    descrip   = "Print the (encrypted) password";
    doc       = "The encrypted password will be printed.";
    flag-proc = name;
};

flag = {
    name      = uid;
    value     = u;
    descrip   = "Print the user id";
    doc       = "The numeric user id will be printed.";
    flag-proc = name;
};

flag = {
    name      = gname;
    value     = g;
    descrip   = "Print the group name";
    doc       = "The name of the user's primary group will be printed.";
    flag-proc = name;
};

flag = {
    name      = gid;
    value     = G;
    descrip   = "Print the group id";
    doc       = "The numeric primary group id will be printed.";
    flag-proc = name;
};

flag = {
    name      = gecos;
    value     = N;
    descrip   = "Print the real user name (comment string)";
    doc       = "The real user name will be printed, usually.\n"
                "It is designated as the account \"comment string\".";
    flag-proc = name;
};

flag = {
    name      = dir;
    value     = d;
    descrip   = "Print the home directory";
    doc       = "The user's home directory will be printed.";
    flag-proc = name;
};

flag = {
    name      = shell;
    value     = s;
    descrip   = "Print the login shell";
    doc       = "The name of the program that is run when the user logs in "
                "will be printed.";
    flag-proc = name;
};

flag = {
    name      = all;
    value     = A;
    descrip   = "Print everything";
    doc       = "Print all of the available fields, including the name of\n"
                "the primary group.";
    flags-cant = name, passwd, uid, gname, gid, gecos, dir, shell;
    flag-code = <<- _EndCode_
                    int sel = INDEX_OPT_NAME;
                    int ix  = 0;
                    do {
                        selections[ ix++ ] = sel++;
                    } while ( sel < INDEX_OPT_ALL );
                    selectCt = ix;
                _EndCode_;
};

flag = {
    name      = verbose;
    value     = V;
    descrip   = "Verbose output";
    doc       = "Print each item of information on a separate line, with\n"
                "a short description of each.";
};

--------------136311A7BB107C214BB1D637
Content-Type: text/plain; charset=us-ascii;
 name="getpwnam.mk"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="getpwnam.mk"


SRC      = getpwnam.c opts.c
OBJ      = $(SRC:.c=.o)
MOD      = getpwnam
CFLAGS   = `autoopts-config cflags`

# remove ``-lgen'' when not needed:
#
LDFLAGS  = `autoopts-config static-libs` -lgen
TARGETS  = $(MOD) $(MOD).1 $(MOD).texi

default  : $(MOD)
all      : $(TARGETS)
man      : $(MOD).1
texi     : $(MOD).texi

$(MOD)   : $(OBJ)
        $(CC) -o $@ $(OBJ) $(LDFLAGS)

$(SRC)   : opts.h
opts.h   : opts.def
        autogen opts.def

$(MOD).1 : opts.def
        autogen -b$(MOD) -T agman1.tpl opts.def

$(MOD).texi : $(MOD)
        autogen -b$(MOD) -T aginfo.tpl opts.def

.c.o :
        $(CC) -o $@ $(CFLAGS) -c $<

clean :
        rm -f $(OBJ) *~

clobber : clean
        rm -f $(TARGETS) $(MOD).menu opts.[ch]

--------------136311A7BB107C214BB1D637--




reply via email to

[Prev in Thread] Current Thread [Next in Thread]