/* @(#)names.c 1.23 07/04/20 Copyright 1993, 1995-2007 J. Schilling */
#ifndef lint
static char sccsid[] =
"@(#)names.c 1.23 07/04/20 Copyright 1993, 1995-2007 J. Schilling";
#endif
/*
* Handle user/group names for archive header
*
* Copyright (c) 1993, 1995-2007 J. Schilling
*/
/*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* See the file CDDL.Schily.txt in this distribution for details.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file CDDL.Schily.txt from this distribution.
*/
#include <schily/mconfig.h>
#include <stdio.h>
#include <schily/standard.h>
#include <schily/utypes.h>
#include <pwd.h>
#include <grp.h>
#include <schily/string.h>
#ifdef __STAR__
#include "star.h"
#include "starsubs.h"
#else
#define TUNMLEN 32
#define TGNMLEN 32
#endif
#include <schily/schily.h>
#define C_SIZE 16
typedef struct u_id {
uid_t uid;
char name[TUNMLEN+1];
char valid;
} uidc_t;
typedef struct g_id {
gid_t gid;
char name[TGNMLEN+1];
char valid;
} gidc_t;
LOCAL uidc_t uidcache[C_SIZE];
LOCAL int lastuidx; /* Last index for new entry */
LOCAL gidc_t gidcache[C_SIZE];
LOCAL int lastgidx; /* Last index for new entry */
LOCAL uid_t _uid_nobody; /* Uid for user "nobody" */
LOCAL gid_t _gid_nobody; /* Gid for user "nobody" */
LOCAL BOOL name_init = FALSE;
EXPORT BOOL nameuid __PR((char *name, int namelen, uid_t uid));
EXPORT BOOL uidname __PR((char *name, int namelen, uid_t *uidp));
EXPORT BOOL namegid __PR((char *name, int namelen, gid_t gid));
EXPORT BOOL gidname __PR((char *name, int namelen, gid_t *gidp));
LOCAL void nameinit __PR((void));
EXPORT uid_t uid_nobody __PR((void));
EXPORT gid_t gid_nobody __PR((void));
/*
* Get name from uid
*/
#ifdef PROTOTYPES
EXPORT BOOL
nameuid(char *name, int namelen, uid_t uid)
#else
EXPORT BOOL
nameuid(name, namelen, uid)
char *name;
int namelen;
uid_t uid;
#endif
{
struct passwd *pw;
register int i;
register uidc_t *idp;
for (i = 0, idp = uidcache; i < C_SIZE; i++, idp++) {
if (idp->valid == 0) /* Entry not yet filled */
break;
if (idp->uid == uid)
goto out;
}
idp = &uidcache[lastuidx++]; /* Round robin fill next ent */
if (lastuidx >= C_SIZE)
lastuidx = 0;
idp->uid = uid;
idp->name[0] = '\0';
idp->valid = 1;
if ((pw = getpwuid(uid)) != NULL) {
strncpy(idp->name, pw->pw_name, TUNMLEN);
idp->name[TUNMLEN] = '\0';
/*
* XXX We should find a better method than shortening the cache
*/
if (namelen <= (TUNMLEN+1))
idp->name[namelen-1] = 0;
}
out:
strcpy(name, idp->name);
return (name[0] != '\0');
}
/*
* Get uid from name
*/
EXPORT BOOL
uidname(name, namelen, uidp)
char *name;
int namelen;
uid_t *uidp;
{
struct passwd *pw;
register int len = namelen > TUNMLEN?TUNMLEN:namelen;
register int i;
register uidc_t *idp;
if (name[0] == '\0') {
*uidp = uid_nobody(); /* Return UID_NOBODY */
return (FALSE);
}
for (i = 0, idp = uidcache; i < C_SIZE; i++, idp++) {
if (idp->valid == 0) /* Entry not yet filled */
break;
if (name[0] == idp->name[0] &&
strncmp(name, idp->name, len) == 0) {
*uidp = idp->uid;
if (idp->valid == 2) { /* Name not found */
*uidp = uid_nobody(); /* Return UID_NOBODY */
return (FALSE);
}
return (TRUE);
}
}
idp = &uidcache[lastuidx++]; /* Round robin fill next ent */
if (lastuidx >= C_SIZE)
lastuidx = 0;
idp->uid = 0;
idp->name[0] = '\0';
strncpy(idp->name, name, len);
idp->name[len] = '\0';
idp->valid = 1;
if ((pw = getpwnam(idp->name)) != NULL) {
idp->uid = pw->pw_uid;
*uidp = idp->uid;
return (TRUE);
} else {
idp->valid = 2; /* Mark name as not found */
*uidp = uid_nobody(); /* Return UID_NOBODY */
return (FALSE);
}
}
/*
* Get name from gid
*/
#ifdef PROTOTYPES
EXPORT BOOL
namegid(char *name, int namelen, gid_t gid)
#else
EXPORT BOOL
namegid(name, namelen, gid)
char *name;
int namelen;
gid_t gid;
#endif
{
struct group *gr;
register int i;
register gidc_t *idp;
for (i = 0, idp = gidcache; i < C_SIZE; i++, idp++) {
if (idp->valid == 0) /* Entry not yet filled */
break;
if (idp->gid == gid)
goto out;
}
idp = &gidcache[lastgidx++]; /* Round robin fill next ent */
if (lastgidx >= C_SIZE)
lastgidx = 0;
idp->gid = gid;
idp->name[0] = '\0';
idp->valid = 1;
if ((gr = getgrgid(gid)) != NULL) {
strncpy(idp->name, gr->gr_name, TGNMLEN);
idp->name[TGNMLEN] = '\0';
/*
* XXX We should find a better method than shortening the cache
*/
if (namelen <= (TGNMLEN+1))
idp->name[namelen-1] = 0;
}
out:
strcpy(name, idp->name);
return (name[0] != '\0');
}
/*
* Get gid from name
*/
EXPORT BOOL
gidname(name, namelen, gidp)
char *name;
int namelen;
gid_t *gidp;
{
struct group *gr;
register int len = namelen > TGNMLEN?TGNMLEN:namelen;
register int i;
register gidc_t *idp;
if (name[0] == '\0') {
*gidp = gid_nobody(); /* Return GID_NOBODY */
return (FALSE);
}
for (i = 0, idp = gidcache; i < C_SIZE; i++, idp++) {
if (idp->valid == 0) /* Entry not yet filled */
break;
if (name[0] == idp->name[0] &&
strncmp(name, idp->name, len) == 0) {
*gidp = idp->gid;
if (idp->valid == 2) { /* Name not found */
*gidp = gid_nobody(); /* Return GID_NOBODY */
return (FALSE);
}
return (TRUE);
}
}
idp = &gidcache[lastgidx++]; /* Round robin fill next ent */
if (lastgidx >= C_SIZE)
lastgidx = 0;
idp->gid = 0;
idp->name[0] = '\0';
strncpy(idp->name, name, len);
idp->name[len] = '\0';
idp->valid = 1;
if ((gr = getgrnam(idp->name)) != NULL) {
idp->gid = gr->gr_gid;
*gidp = idp->gid;
return (TRUE);
} else {
idp->valid = 2; /* Mark name as not found */
*gidp = gid_nobody(); /* Return GID_NOBODY */
return (FALSE);
}
}
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifndef UID_NOBODY
#define UID_NOBODY 65534 /* The old SunOS-4.x and *BSD value */
#endif
#ifndef GID_NOBODY
#define GID_NOBODY 65534 /* The old SunOS-4.x and *BSD value */
#endif
LOCAL void
nameinit()
{
char *name;
int namelen;
uid_t uid;
gid_t gid;
/*
* Make sure that uidname()/gidname() do not call nameinit().
*/
name_init = TRUE;
name = "nobody";
namelen = strlen(name);
if (!uidname(name, namelen, &uid))
uid = UID_NOBODY;
_uid_nobody = uid;
if (!gidname(name, namelen, &gid))
gid = GID_NOBODY;
_gid_nobody = gid;
}
EXPORT uid_t
uid_nobody()
{
if (!name_init)
nameinit();
return (_uid_nobody);
}
EXPORT uid_t
gid_nobody()
{
if (!name_init)
nameinit();
return (_gid_nobody);
}
syntax highlighted by Code2HTML, v. 0.9.1