#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include <pwd.h>
#include <errno.h>
#if HAVE_GETGRENT
#include <grp.h>
#if GETGRENT_DECLARATION_OK
#ifndef getgrent
extern struct group *getgrent ();
#endif
#endif
#endif
#if GETPWNAM_DECLARATION_OK
#ifndef getpwnam
extern struct passwd *getpwnam ();
#endif
#endif
boolean
fsuser_access (q, imode, zuser)
const struct stat *q;
int imode;
const char *zuser;
{
static char *zuser_hold;
static uid_t iuid_hold;
static gid_t igid_hold;
static int cgroups_hold;
static gid_t *paigroups_hold;
unsigned int ir, iw, ix, iand;
if (imode == F_OK)
return TRUE;
if (zuser != NULL)
{
if (zuser_hold == NULL || strcmp (zuser_hold, zuser) != 0)
{
struct passwd *qpwd;
if (zuser_hold != NULL)
{
ubuffree (zuser_hold);
zuser_hold = NULL;
cgroups_hold = 0;
xfree ((pointer) paigroups_hold);
paigroups_hold = NULL;
}
qpwd = getpwnam ((char *) zuser);
if (qpwd == NULL)
{
zuser = NULL;
}
else
{
#if HAVE_GETGRENT
struct group *qg;
#endif
zuser_hold = zbufcpy (zuser);
iuid_hold = qpwd->pw_uid;
igid_hold = qpwd->pw_gid;
#if HAVE_GETGRENT
setgrent ();
while ((qg = getgrent ()) != NULL)
{
const char **pz;
if (qg->gr_gid == igid_hold)
continue;
for (pz = (const char **) qg->gr_mem; *pz != NULL; pz++)
{
if ((*pz)[0] == *zuser
&& strcmp (*pz, zuser) == 0)
{
paigroups_hold = ((gid_t *)
(xrealloc
((pointer) paigroups_hold,
((cgroups_hold + 1)
* sizeof (gid_t)))));
paigroups_hold[cgroups_hold] = qg->gr_gid;
++cgroups_hold;
break;
}
}
}
endgrent ();
#endif
}
}
}
if (zuser != NULL)
{
if (iuid_hold == 0)
return TRUE;
if (iuid_hold == geteuid ())
return TRUE;
}
ir = S_IROTH;
iw = S_IWOTH;
ix = S_IXOTH;
if (zuser != NULL)
{
if (iuid_hold == q->st_uid)
{
ir = S_IRUSR;
iw = S_IWUSR;
ix = S_IXUSR;
}
else
{
boolean fgroup;
fgroup = FALSE;
if (igid_hold == q->st_gid)
fgroup = TRUE;
else
{
int i;
for (i = 0; i < cgroups_hold; i++)
{
if (paigroups_hold[i] == q->st_gid)
{
fgroup = TRUE;
break;
}
}
}
if (fgroup)
{
ir = S_IRGRP;
iw = S_IWGRP;
ix = S_IXGRP;
}
}
}
iand = 0;
if ((imode & R_OK) != 0)
iand |= ir;
if ((imode & W_OK) != 0)
iand |= iw;
if ((imode & X_OK) != 0)
iand |= ix;
return (q->st_mode & iand) == iand;
}