1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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 
35 NoN(eaccess)
36 
37 #else
38 
39 #if defined(__EXPORT__)
40 #define extern	__EXPORT__
41 #endif
42 
43 extern int
44 eaccess(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