1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#pragma prototyped
23/*
24 * access() euid/egid implementation
25 */
26
27#include <ast.h>
28#include <errno.h>
29#include <ls.h>
30
31#include "FEATURE/eaccess"
32
33#if _lib_eaccess
34
35NoN(eaccess)
36
37#else
38
39#if defined(__EXPORT__)
40#define extern	__EXPORT__
41#endif
42
43extern int
44eaccess(const char* path, register int flags)
45{
46#ifdef EFF_ONLY_OK
47	return access(path, flags|EFF_ONLY_OK);
48#else
49#if _lib_euidaccess
50	return euidaccess(path, flags);
51#else
52	register int	mode;
53	struct stat	st;
54
55	static int	init;
56	static uid_t	ruid;
57	static uid_t	euid;
58	static gid_t	rgid;
59	static gid_t	egid;
60
61	if (!init)
62	{
63		ruid = getuid();
64		euid = geteuid();
65		rgid = getgid();
66		egid = getegid();
67		init = (ruid == euid && rgid == egid) ? 1 : -1;
68	}
69	if (init > 0 || flags == F_OK)
70		return access(path, flags);
71	if (stat(path, &st))
72		return -1;
73	mode = 0;
74	if (euid == 0)
75	{
76		if (!S_ISREG(st.st_mode) || !(flags & X_OK) || (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
77			return 0;
78		goto nope;
79	}
80	else if (euid == st.st_uid)
81	{
82		if (flags & R_OK)
83			mode |= S_IRUSR;
84		if (flags & W_OK)
85			mode |= S_IWUSR;
86		if (flags & X_OK)
87			mode |= S_IXUSR;
88	}
89	else if (egid == st.st_gid)
90	{
91#if _lib_getgroups
92	setgroup:
93#endif
94		if (flags & R_OK)
95			mode |= S_IRGRP;
96		if (flags & W_OK)
97			mode |= S_IWGRP;
98		if (flags & X_OK)
99			mode |= S_IXGRP;
100	}
101	else
102	{
103#if _lib_getgroups
104		register int	n;
105
106		static int	ngroups = -2;
107		static gid_t*	groups;
108
109		if (ngroups == -2)
110		{
111			if ((ngroups = getgroups(0, (gid_t*)0)) <= 0)
112				ngroups = NGROUPS_MAX;
113			if (!(groups = newof(0, gid_t, ngroups + 1, 0)))
114				ngroups = -1;
115			else
116				ngroups = getgroups(ngroups, groups);
117		}
118		n = ngroups;
119		while (--n >= 0)
120			if (groups[n] == st.st_gid)
121				goto setgroup;
122#endif
123		if (flags & R_OK)
124			mode |= S_IROTH;
125		if (flags & W_OK)
126			mode |= S_IWOTH;
127		if (flags & X_OK)
128			mode |= S_IXOTH;
129	}
130	if ((st.st_mode & mode) == mode)
131		return 0;
132 nope:
133	errno = EACCES;
134	return -1;
135#endif
136#endif
137}
138
139#endif
140