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