This is getpwwho.c in view mode; [Download] [Up]
/*
* Copyright (c) 1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
* SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Users of this software agree to return to Carnegie Mellon any
* improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* Export of this software is permitted only after complying with the
* regulations of the U.S. Deptartment of Commerce relating to the
* Export of Technical Data.
*/
/*
**********************************************************************
* HISTORY
* $Log: getpwwho.c,v $
* Revision 1.3 90/12/11 17:55:13 mja
* Add copyright/disclaimer for distribution.
*
* 11-Aug-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Mapped ulstr to strcase compare.
*
* 05-Mar-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Removed all special gecos code for 4.2 version.
*
* 03-Jan-86 Rudy Nedved (ern) at Carnegie-Mellon University
* Basically the entire module was re-written. Parts of the getpwambig
* routine are from the old package but that is it. The new code was
* written using the CMU TOPS-10 SAIL library algorithm for parsing
* account file names. The original motivation for this routine was
* based on the visible actions of that algorithm, it might as well
* used the actually algorithm.
*
* Hopefully all the compatibility issues have been handled. The
* getpwwho(NULL) behavior is handled and the special loading of
* middle names into the first name is handled.
*
* I would have coded the routine to really handle things in a mail
* context but that is suppose to be handled by the network name
* database.
*
* 06-Jan-84 Eric Patterson (egp) at Carnegie-Mellon University
* Fixed bug: if a string exactly matches some name, but is also a
* substring of some other name, no ambiguity is observed.
*
* 18-Dec-81 Mike Accetta (mja) at Carnegie-Mellon University
* Fixed two bugs:
* 1) adjusted length passed to FoldEQ() to a maximum so that login name
* comparison never succeeds on a partial match.
* 2) added check for exact match after IsName() succeeds in case the
* full name is a substring of some other full name with which it
* would otherwise be ambiguous.
*
* 07-Dec-81 James Gosling (jag) at Carnegie-Mellon University
* Now does case-folded compares on login ID's. eg. "ern" and "ERN"
* match.
*
* 11-Dec-80 Mike Accetta(mja) at Carnegie-Mellon University
* Changed to convert all separator characters to spaces when
* copying name into internal buffer so that dots in names with
* more than two parts will match password file entries.
*
* 03-Dec-80 Mike Accetta (mja) at Carnegie-Mellon University
* Changed to treat everything before last blank in name as first
* name and modified to close password file when called with null
* pointer.
*
* 29-Nov-80 Mike Accetta (mja) at Carnegie-Mellon University
* Changed to allow '.' as separator in names.
*
* 07-Nov-80 Mike Accetta (mja) at Carnegie-Mellon University
* Removed reference to (extinct) alias name.
*
**********************************************************************
*/
#include <stdio.h>
#include <ctype.h>
#include <pwd.h>
extern struct passwd *getpwent();
#define MAXNAME 100
static char FirstPart[MAXNAME],LastPart[MAXNAME];
static char ThisFirst[MAXNAME],ThisLast[MAXNAME];
static int ExactFirst,ExactLast;
static int MatchLevel,Matches,ambigstate;
/*
* break the supplied name down in to last name and first name(s).
* Translate dots into spaces. Note: middle names are part of the
* first name.
*/
static BreakDown(name,firsts,last)
char *name,*firsts,*last;
{
register char *p,*lp;
strncpy(firsts,name,MAXNAME);
lp = (char *)0;
p = firsts;
while (*p) {
if (*p == '.' || *p == ' ') {
*(lp = p++) = ' ';
}
else
p++;
}
if (lp != (char *)0) {
strncpy(last,lp+1,MAXNAME);
*lp = '\0';
}
else {
strncpy(last,firsts,MAXNAME);
*firsts = '\0';
}
}
/*
* We could just do a getpwuid() at the end of the name search
* but this causes alot of extra time spent and for mail and finger
* clients this is highly irritating especially on a loaded machine
* with many entries in the /etc/passwd file. On of these days, an
* additional binary index will be available making lookups on uid
* and login names fast.
*/
static pw_entry_save(bufp,valp)
char **bufp;
register char *valp;
{
register char *p;
p = *bufp;
while ((*p++ = *valp++) != '\0');
*bufp = p;
}
static struct passwd *copypw(pw)
struct passwd *pw;
{
static struct passwd mypw;
static char mybuf[BUFSIZ+1];
char *p;
mypw = *pw; /* copy things like pw_uid, pw_gid, etc. */
p = mybuf;
mypw.pw_name = p; pw_entry_save(&p,pw->pw_name);
mypw.pw_passwd = p; pw_entry_save(&p,pw->pw_passwd);
mypw.pw_comment = p; pw_entry_save(&p,pw->pw_comment);
mypw.pw_gecos = p; pw_entry_save(&p,pw->pw_gecos);
mypw.pw_dir = p; pw_entry_save(&p,pw->pw_dir);
mypw.pw_shell = p; pw_entry_save(&p,pw->pw_shell);
return &mypw;
}
static struct passwd *scanpw(stop)
int stop;
{
struct passwd *bestpw,*pw;
bestpw = (struct passwd *) 0;
while (pw = getpwent()) {
/* handle login ids, exact Matches win always */
if (*FirstPart == '\0' && strcasecmp(LastPart,pw->pw_name) == 0) {
Matches = 1;
MatchLevel = 7777777; /* large number */
return copypw(pw);
}
/* check out names */
BreakDown(pw->pw_gecos,ThisFirst,ThisLast);
if (namecheck(ThisLast,LastPart,ExactLast)) {
/* last match */
if (namecheck(ThisFirst,FirstPart,ExactFirst)) {
/* both match */
if (!ExactLast)
if (strcasecmp(ThisLast,LastPart) == 0)
ExactLast = 1;
if (ExactLast && !ExactFirst)
if (strcasecmp(ThisFirst,FirstPart) == 0)
ExactFirst = 1;
/* see if we got something better */
if (MatchLevel < (ExactFirst + ExactLast)) {
MatchLevel = ExactFirst + ExactLast;
bestpw = copypw(pw);
Matches = 1;
if (stop)
return bestpw;
}
else if (MatchLevel == (ExactFirst + ExactLast)) {
Matches++;
bestpw = copypw(pw);
if (stop)
return bestpw;
}
}
}
}
return bestpw;
}
struct passwd *getpwwho (name)
char *name;
{
struct passwd *pw;
/* initialize a few things */
MatchLevel = -1;
Matches = 0;
ExactFirst = ExactLast = 0;
ambigstate = -1;
/* NULL for a name is a no-op...used to clear some internal state */
if (name == NULL)
return (struct passwd *) 0;
/* break down the probe name for comparisons */
BreakDown(name,FirstPart,LastPart);
/* now search thru the password file for Matches */
setpwent();
pw = scanpw(0);
endpwent();
/* see what we got */
if (Matches == 0)
return (struct passwd *)0;
else if (Matches == 1)
return pw;
ambigstate = 0;
return (struct passwd *)-1;
}
struct passwd *getpwambig ()
{
struct passwd *pw;
if (ambigstate < 0)
return 0;
if (ambigstate++ == 0) {
Matches = 0;
setpwent();
}
pw = scanpw(1);
if (pw == 0) {
ambigstate = -1;
endpwent();
}
return pw;
}
static namecheck(a,b,exact)
char *a, *b;
int exact;
{
if (exact) return(strcasecmp(a,b) == 0);
if (*b == 0) return 1;
return(strncasecmp(a,b,strlen(b)) == 0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.