xref: /netbsd/external/gpl2/xcvs/dist/src/acl.c (revision cc7958a0)
1b22328f9Schristos /*
2b22328f9Schristos  * Copyright (C) 2006 The Free Software Foundation, Inc.
3b22328f9Schristos  *
4b22328f9Schristos  * Portions Copyright (C) 2006, Baris Sahin <sbaris at users.sourceforge.net>
5b22328f9Schristos  *                                          <http://cvsacl.sourceforge.net>
6b22328f9Schristos  *
7b22328f9Schristos  *
8b22328f9Schristos  * You may distribute under the terms of the GNU General Public License as
9b22328f9Schristos  * specified in the README file that comes with the CVS source distribution.
10b22328f9Schristos  *
11b22328f9Schristos  *
12b22328f9Schristos  *
13b22328f9Schristos  * CVS ACCESS CONTROL LIST EXTENSION
14b22328f9Schristos  *
15b22328f9Schristos  * It provides advanced access control definitions per modules,
16b22328f9Schristos  * directories, and files on branch/tag for remote cvs repository
17b22328f9Schristos  * connections.Execution of all CVS subcommands can be controlled
18b22328f9Schristos  * with eight different permissions.
19b22328f9Schristos  *
20b22328f9Schristos  * Permission Types:
21b22328f9Schristos  * - no permission      (n) (1)
22b22328f9Schristos  * - all permissions    (a) (2)
23b22328f9Schristos  * - write permission   (w) (3)
24b22328f9Schristos  * - tag permission     (t) (4)
25b22328f9Schristos  * - read permission    (r) (5)
26b22328f9Schristos  * - add permission     (c) (6)
27b22328f9Schristos  * - remove permission  (d) (7)
28b22328f9Schristos  * - permission	change  (p) (8)
29b22328f9Schristos  *
30b22328f9Schristos  */
31b22328f9Schristos #include "cvs.h"
32b22328f9Schristos #include "getline.h"
33b22328f9Schristos #include <grp.h>
34b22328f9Schristos 
35b22328f9Schristos static int acl_fileproc (void *callerdat, struct file_info *finfo);
36b22328f9Schristos 
37b22328f9Schristos static Dtype acl_dirproc (void *callerdat, const char *dir, const char *repos,
38b22328f9Schristos 			  const char *update_dir, List *entries);
39b22328f9Schristos 
40b22328f9Schristos static int acllist_fileproc (void *callerdat, struct file_info *finfo);
41b22328f9Schristos static Dtype acllist_dirproc (void *callerdat, const char *dir,
42b22328f9Schristos 			      const char *repos, const char *update_dir,
43b22328f9Schristos 			      List *entries);
44b22328f9Schristos 
45b22328f9Schristos static void acllist_print (char *line, const char *obj);
46b22328f9Schristos 
47b22328f9Schristos static int racl_proc (int argc, char **argv, char *xwhere,
48b22328f9Schristos 		      char *mwhere, char *mfile, int shorten,
49b22328f9Schristos 		      int local_specified, char *mname, char *msg);
50b22328f9Schristos 
51b22328f9Schristos static FILE *open_accessfile (char *xmode, const char *repos, char **fname);
52b22328f9Schristos static FILE *open_groupfile (char *xmode);
53b22328f9Schristos 
54b22328f9Schristos static char *get_perms (const char *xperms);
55b22328f9Schristos static char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
56b22328f9Schristos 
57b22328f9Schristos static char *findusername (const char *string1, const char *string2);
58b22328f9Schristos static char *findgroupname (const char *string1, const char *string2);
59b22328f9Schristos static int valid_tag (const char *part_tag, const char *tag);
60b22328f9Schristos static int valid_perm (const char *part_perms, int perm);
61b22328f9Schristos static int write_perms (const char *user, const char *perms,
62b22328f9Schristos 			const char *founduserpart, int foundline,
63b22328f9Schristos 			char *otheruserparts, const char *part_type,
64b22328f9Schristos 			const char *part_object, const char *part_tag, int pos,
65b22328f9Schristos 			const char *arepos);
66b22328f9Schristos 
67b22328f9Schristos static char *cache_repository;
68b22328f9Schristos static int cache_retval;
69b22328f9Schristos static int founddeniedfile;
70b22328f9Schristos static int cache_perm;
71b22328f9Schristos 
72b22328f9Schristos static int is_racl;
73b22328f9Schristos static int debug = 0;
74b22328f9Schristos 
75b22328f9Schristos int use_cvs_acl = 0;
76b22328f9Schristos char *cvs_acl_default_permissions;
77b22328f9Schristos int use_cvs_groups = 0;
78b22328f9Schristos int use_system_groups = 0;
79b22328f9Schristos int use_separate_acl_file_for_each_dir = 0;
80b22328f9Schristos char *cvs_acl_file_location = NULL;
81b22328f9Schristos char *cvs_groups_file_location = NULL;
82b22328f9Schristos char *cvs_server_run_as = NULL;
83b22328f9Schristos int stop_at_first_permission_denied = 0;
84b22328f9Schristos 
85b22328f9Schristos char *tag = NULL;
86b22328f9Schristos 
87b22328f9Schristos char *muser;
88b22328f9Schristos char *mperms;
89b22328f9Schristos static int defaultperms;
90b22328f9Schristos 
91b22328f9Schristos static char *default_perms_object;
92b22328f9Schristos char *default_part_perms_accessfile;
93b22328f9Schristos int aclconfig_default_used;
94b22328f9Schristos 
95b22328f9Schristos int acldir = 0;
96b22328f9Schristos int aclfile = 0;
97b22328f9Schristos int listacl = 0;
98b22328f9Schristos 
99b22328f9Schristos int userfound = 0;
100b22328f9Schristos int groupfound = 0;
101b22328f9Schristos 
102b22328f9Schristos /* directory depth ... */
103b22328f9Schristos char *dirs[255];
104b22328f9Schristos 
105b22328f9Schristos static const char *const acl_usage[] =
106b22328f9Schristos         {
107b22328f9Schristos                 "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...] [files...]\n",
108b22328f9Schristos                 "\t-R\tProcess directories recursively.\n",
109b22328f9Schristos                 "\t-r rev\tExisting revision/tag.\n",
110b22328f9Schristos                 "\t-l\tList defined ACLs.\n",
111b22328f9Schristos                 "(Specify the --help global option for a list of other help options)\n",
112b22328f9Schristos                 NULL
113b22328f9Schristos         };
114b22328f9Schristos 
115b22328f9Schristos static const char *const racl_usage[] =
116b22328f9Schristos {
117b22328f9Schristos     "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...]"
118b22328f9Schristos     " [files...]\n",
119b22328f9Schristos     "\t-R\tProcess directories recursively.\n",
120b22328f9Schristos     "\t-r rev\tExisting revision/tag.\n",
121b22328f9Schristos     "\t-l\tList defined ACLs.\n",
122b22328f9Schristos     "(Specify the --help global option for a list of other help options)\n",
123b22328f9Schristos     NULL
124b22328f9Schristos };
125b22328f9Schristos 
126b22328f9Schristos 
127b22328f9Schristos int
128b22328f9Schristos access_allowed (const char *file, const char *repos, const char *tag,
129b22328f9Schristos 		int perm, char **mline, int *mpos, int usecache)
130b22328f9Schristos {
131b22328f9Schristos     int retval = 0;
132b22328f9Schristos     int foundline = 0;
133b22328f9Schristos     FILE *accessfp;
134b22328f9Schristos 
135b22328f9Schristos     int flag = 1;
136b22328f9Schristos 
137b22328f9Schristos     char *iline;
138b22328f9Schristos     char *tempv;
139b22328f9Schristos     char *tempc;
140b22328f9Schristos     size_t tempsize;
141b22328f9Schristos 
142b22328f9Schristos     int intcount;
143b22328f9Schristos     int accessfilecount;
144b22328f9Schristos     int signlevel = -1;
145b22328f9Schristos     int dadmin = 0;
146b22328f9Schristos 
147b22328f9Schristos     const char *repository;
148b22328f9Schristos     char *filefullname = NULL;
149b22328f9Schristos     userfound = 0;
150b22328f9Schristos     groupfound = 0;
151b22328f9Schristos 
152b22328f9Schristos     if (defaultperms)
153b22328f9Schristos     {
154b22328f9Schristos 	repository = xstrdup ("ALL");
155b22328f9Schristos     }
156b22328f9Schristos     else {
157b22328f9Schristos 	if (strlen(repository = Short_Repository (repos)) == 0)
158b22328f9Schristos 	{
159b22328f9Schristos 	    repository = xstrdup (".");
160b22328f9Schristos 	}
161b22328f9Schristos     }
162b22328f9Schristos 
163b22328f9Schristos     /* cache */
164b22328f9Schristos     if (usecache && cache_repository != NULL &&
165b22328f9Schristos 	strcmp (cache_repository, repository) == 0 && !founddeniedfile
166b22328f9Schristos 	&& perm == cache_perm)
167b22328f9Schristos 	return (cache_retval);
168b22328f9Schristos     else
169b22328f9Schristos     {
170b22328f9Schristos 	free (cache_repository);
171b22328f9Schristos 	cache_repository = xstrdup (repository);
172b22328f9Schristos 	cache_perm = perm;
173b22328f9Schristos     }
174b22328f9Schristos 
175b22328f9Schristos     iline = xstrdup(repository);
176b22328f9Schristos 
177b22328f9Schristos     tempv = strtok(iline, "/\t");
178b22328f9Schristos     tempc = xstrdup(tempv);
179b22328f9Schristos     tempsize = ( tempc != NULL ) ? strlen(tempc) : 0;
180b22328f9Schristos 
181b22328f9Schristos     intcount = 0;
182b22328f9Schristos     /* store paths from object to cvsroot */
183b22328f9Schristos     dirs[intcount] = xstrdup(tempc);
184b22328f9Schristos     while ((tempv = strtok(NULL, "/\t")) != NULL)
185b22328f9Schristos     {
186b22328f9Schristos 	intcount++;
187b22328f9Schristos 
188b22328f9Schristos 	xrealloc_and_strcat(&tempc, &tempsize, "/");
189b22328f9Schristos 	xrealloc_and_strcat(&tempc, &tempsize, tempv);
190b22328f9Schristos 
191b22328f9Schristos 	dirs[intcount] = xstrdup(tempc);
192b22328f9Schristos     }
193b22328f9Schristos 
194b22328f9Schristos     /* free not needed variables here */
195b22328f9Schristos     free (tempv);
196b22328f9Schristos     free (tempc);
197b22328f9Schristos     free (iline);
198b22328f9Schristos 
199b22328f9Schristos     /* accessfilecount will used
200b22328f9Schristos      * if UseSeparateACLFile keyword is set to yes*/
201b22328f9Schristos     accessfilecount = intcount;
202b22328f9Schristos 
203b22328f9Schristos     /* if file is not null add it to dirs array */
204b22328f9Schristos     if (file != NULL)
205b22328f9Schristos     {
206b22328f9Schristos 	filefullname = Xasprintf("%s/%s", repository, file);
207b22328f9Schristos 	intcount++;
208b22328f9Schristos 	dirs[intcount] = xstrdup(filefullname);
209b22328f9Schristos     }
210b22328f9Schristos 
211b22328f9Schristos     for (accessfilecount; accessfilecount >= 0 && flag; accessfilecount--)
212b22328f9Schristos     {
213b22328f9Schristos 	if (!use_separate_acl_file_for_each_dir) {
214b22328f9Schristos 	    flag = 0;
215b22328f9Schristos 	    accessfp = open_accessfile ("r", repository, NULL);
216b22328f9Schristos 	}
217b22328f9Schristos 	else
218b22328f9Schristos 	{
219b22328f9Schristos 	    flag = 1;
220b22328f9Schristos 	    accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
221b22328f9Schristos 	}
222b22328f9Schristos 
223b22328f9Schristos 	if (accessfp != NULL)
224b22328f9Schristos 	{
225b22328f9Schristos 	    char *line = NULL;
226b22328f9Schristos 	    size_t line_allocated = 0;
227b22328f9Schristos 
228b22328f9Schristos 	    char *xline;
229b22328f9Schristos 	    char *part_type = NULL;
230b22328f9Schristos 	    char *part_object = NULL;
231b22328f9Schristos 	    char *part_tag = NULL;
232b22328f9Schristos 	    char *part_perms = NULL;
233b22328f9Schristos 
234b22328f9Schristos 	    int x;
235b22328f9Schristos 
236b22328f9Schristos 	    while (getline (&line, &line_allocated, accessfp) >= 0)
237b22328f9Schristos 	    {
238b22328f9Schristos 
239b22328f9Schristos 		if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
240b22328f9Schristos 			continue;
241b22328f9Schristos 
242b22328f9Schristos 		xline = xstrdup (line);
243b22328f9Schristos 		part_type = strtok (line, ":\t");
244b22328f9Schristos 		part_object = strtok (NULL, ":\t");
245b22328f9Schristos 		part_tag = strtok (NULL, ":\t");
246b22328f9Schristos 		part_perms = strtok (NULL, ":\t");
247b22328f9Schristos 
248b22328f9Schristos 		if (part_type == NULL || part_object == NULL ||
249b22328f9Schristos 		    part_tag == NULL || part_perms == NULL)
250b22328f9Schristos 		{
251b22328f9Schristos 		    free (line);
252b22328f9Schristos 		    error(1, 0, "access file is corrupted or has invalid"
253b22328f9Schristos 				" format");
254b22328f9Schristos 		}
255b22328f9Schristos 
256b22328f9Schristos 		if (debug) fprintf (stderr, "type %s object %s tag %s perms"
257b22328f9Schristos 				    "%s\n", part_type, part_object, part_tag,
258b22328f9Schristos 				    part_perms);
259b22328f9Schristos 		for (x = intcount; x >= signlevel && x != -1; x--)
260b22328f9Schristos 		{
261b22328f9Schristos 		    if (debug) fprintf (stderr, "dirs[%d] = %s, part_object="
262b22328f9Schristos 					"%s\n", x, dirs[x], part_object);
263b22328f9Schristos 		    if (strcmp (dirs[x], part_object) == 0)
264b22328f9Schristos 		    {
265b22328f9Schristos 			if (debug) fprintf(stderr, "tag %s \n", tag);
266b22328f9Schristos 			if (valid_tag (part_tag, tag))
267b22328f9Schristos 			{
268b22328f9Schristos 			    foundline  = 1;
269b22328f9Schristos 			    if (debug) fprintf(stderr, "foundline\n");
270b22328f9Schristos 
271b22328f9Schristos 			    if (listacl || ((acldir || aclfile) &&
272b22328f9Schristos 					    x == intcount) &&
273b22328f9Schristos 				strcmp(part_tag, tag) == 0)
274b22328f9Schristos 			    {
275b22328f9Schristos 				*mline = xstrdup (xline);
276b22328f9Schristos 				*mpos = ftell (accessfp);
277b22328f9Schristos 			    }
278b22328f9Schristos 
279b22328f9Schristos 			    if (debug) fprintf(stderr, "perm %d\n", perm);
280b22328f9Schristos 			    if (valid_perm (part_perms, perm))
281b22328f9Schristos 			    {
282b22328f9Schristos 				if (signlevel == x)
283b22328f9Schristos 				{
284b22328f9Schristos 				    if (strcmp(part_tag, "ALL") != 0 &&
285b22328f9Schristos 					!aclconfig_default_used)
286b22328f9Schristos 					retval = 1;
287b22328f9Schristos 				}
288b22328f9Schristos 				else if (!aclconfig_default_used)
289b22328f9Schristos 				{
290b22328f9Schristos 				    signlevel = x;
291b22328f9Schristos 				    retval = 1;
292b22328f9Schristos 				}
293b22328f9Schristos 				else {
294b22328f9Schristos 				    /* nothing... */
295b22328f9Schristos 				}
296b22328f9Schristos 			    }
297b22328f9Schristos 			    else
298b22328f9Schristos 			    {
299b22328f9Schristos 				if (signlevel == x)
300b22328f9Schristos 				{
301b22328f9Schristos 				    if (strcmp(part_tag, "ALL") != 0 &&
302b22328f9Schristos 					!aclconfig_default_used)
303b22328f9Schristos 					retval = 0;
304b22328f9Schristos 				}
305b22328f9Schristos 				else if (!aclconfig_default_used)
306b22328f9Schristos 				{
307b22328f9Schristos 				    signlevel = x;
308b22328f9Schristos 				    retval = 0;
309b22328f9Schristos 
310b22328f9Schristos 				    if (strncmp (part_type, "f", 1) == 0)
311b22328f9Schristos 					founddeniedfile = 1;
312b22328f9Schristos 				}
313b22328f9Schristos 				else {
314b22328f9Schristos 				}
315b22328f9Schristos 			    }
316b22328f9Schristos 			}
317b22328f9Schristos 		    }
318b22328f9Schristos 		}
319b22328f9Schristos 
320b22328f9Schristos 		if (debug) fprintf (stderr, "xline tag = %s %d %d\n", xline,
321b22328f9Schristos 				    groupfound, userfound);
322b22328f9Schristos 		if (strncmp (xline, "d:ALL:", 6) == 0 &&
323b22328f9Schristos 		    ((!groupfound && !userfound) || listacl))
324b22328f9Schristos 		{
325b22328f9Schristos 		    if (debug) fprintf (stderr, "ALL tag = %s\n", tag);
326b22328f9Schristos 		    /* a default found */
327b22328f9Schristos 		    if (valid_tag (part_tag, tag) > 0)
328b22328f9Schristos 		    {
329b22328f9Schristos 			foundline = 1;
330b22328f9Schristos 
331b22328f9Schristos 			default_part_perms_accessfile = xstrdup (part_perms);
332b22328f9Schristos 
333b22328f9Schristos 			if (debug) fprintf (stderr, "valid perm = %d\n", perm);
334b22328f9Schristos 			if (valid_perm (part_perms, perm))
335b22328f9Schristos 			{
336b22328f9Schristos 			    retval = 1;
337b22328f9Schristos 			    if (perm == 8)
338b22328f9Schristos 				dadmin = 1;
339b22328f9Schristos 			}
340b22328f9Schristos 			else
341b22328f9Schristos 			    retval = 0;
342b22328f9Schristos 		    }
343b22328f9Schristos 		}
344b22328f9Schristos 
345b22328f9Schristos 	    }
346b22328f9Schristos 
347b22328f9Schristos 	    if (fclose (accessfp) == EOF)
348b22328f9Schristos 		error (1, errno, "cannot close 'access' file");
349b22328f9Schristos 	}
350b22328f9Schristos     }
351b22328f9Schristos 
352b22328f9Schristos     if (!foundline)
353b22328f9Schristos     {
354b22328f9Schristos 	if (debug) fprintf(stderr, "not found line\n");
355b22328f9Schristos 	/* DEFAULT */
356b22328f9Schristos 	if (valid_perm (NULL, perm))
357b22328f9Schristos 	    retval = 1;
358b22328f9Schristos 	else
359b22328f9Schristos 	    retval = 0;
360b22328f9Schristos     }
361b22328f9Schristos 
362b22328f9Schristos     /* acl admin rigths 'p' */
363b22328f9Schristos     if (dadmin)
364b22328f9Schristos     {
365b22328f9Schristos 	retval = dadmin;
366b22328f9Schristos     }
367b22328f9Schristos 
368b22328f9Schristos     cache_retval = retval;
369b22328f9Schristos 
370b22328f9Schristos     free (filefullname);
371b22328f9Schristos     /* free directories array */
372b22328f9Schristos     while (intcount >= 0)
373b22328f9Schristos     {
374b22328f9Schristos 	free (dirs[intcount]);
375b22328f9Schristos 	intcount--;
376b22328f9Schristos     }
377b22328f9Schristos 
378b22328f9Schristos     return retval;
379b22328f9Schristos }
380b22328f9Schristos 
381b22328f9Schristos /* Returns 1 if tag is valid, 0 if not */
382b22328f9Schristos static int
383b22328f9Schristos valid_tag (const char *part_tag, const char *tag)
384b22328f9Schristos {
385b22328f9Schristos     int retval;
386b22328f9Schristos 
387b22328f9Schristos     if (tag == NULL)
388b22328f9Schristos 	tag = "HEAD";
389b22328f9Schristos 
390b22328f9Schristos     if (strcmp (tag, part_tag) == 0 || strcmp (part_tag, "ALL") == 0)
391b22328f9Schristos 	retval = 1;
392b22328f9Schristos     else
393b22328f9Schristos 	retval = 0;
394b22328f9Schristos 
395b22328f9Schristos     return retval;
396b22328f9Schristos }
397b22328f9Schristos 
398b22328f9Schristos /* Returns 1 if successful, 0 if not. */
399b22328f9Schristos static int
400b22328f9Schristos valid_perm (const char *part_perms, int perm)
401b22328f9Schristos {
402b22328f9Schristos     char *perms;
403b22328f9Schristos     int retval = 0;
404b22328f9Schristos 
405b22328f9Schristos     perms = get_perms (part_perms);
406b22328f9Schristos 
407b22328f9Schristos     /* Allow, if nothing found. */
408b22328f9Schristos     if (perms[0] == '\0')
409b22328f9Schristos 	return (1);
410b22328f9Schristos 
411b22328f9Schristos     /* no access allowed, exit */
412b22328f9Schristos     if (strstr (perms, "n"))
413b22328f9Schristos 	retval = 0;
414b22328f9Schristos 
415b22328f9Schristos     if (strstr (perms, "p"))
416b22328f9Schristos 	/* admin rights */
417b22328f9Schristos 	retval = 1;
418b22328f9Schristos     else if (strstr (perms, "a") && perm != 8)
419b22328f9Schristos 	/* all access allowed, exit */
420b22328f9Schristos 	retval = 1;
421b22328f9Schristos     else
422b22328f9Schristos 	switch (perm)
423b22328f9Schristos 	{
424b22328f9Schristos 	case 3:/* write permission */
425b22328f9Schristos 	    if (strstr (perms, "w"))
426b22328f9Schristos 		retval = 1;
427b22328f9Schristos 	    break;
428b22328f9Schristos 	case 4:/* tag permission */
429b22328f9Schristos 	    if (strstr (perms, "t"))
430b22328f9Schristos 		retval = 1;
431b22328f9Schristos 	    break;
432b22328f9Schristos 	case 5:/* read permission */
433b22328f9Schristos 	    if (strstr (perms, "w") || strstr (perms, "t") ||
434b22328f9Schristos 		strstr (perms, "c") || strstr (perms, "d") ||
435b22328f9Schristos 		strstr (perms, "r"))
436b22328f9Schristos 		retval = 1;
437b22328f9Schristos 	    break;
438b22328f9Schristos 	case 6:/* create permission */
439b22328f9Schristos 	    if (strstr (perms, "c"))
440b22328f9Schristos 		retval = 1;
441b22328f9Schristos 	    break;
442b22328f9Schristos 	case 7:/* delete permission */
443b22328f9Schristos 	    if (strstr (perms, "d"))
444b22328f9Schristos 		retval = 1;
445b22328f9Schristos 	    break;
446b22328f9Schristos 	case 8:/* permission change */
447b22328f9Schristos 	    if (strstr (perms, "p"))
448b22328f9Schristos 		retval = 1;
449b22328f9Schristos 	    break;
450b22328f9Schristos 	default:/* never reached */
451b22328f9Schristos 	    retval = 0;
452b22328f9Schristos 	    break;
453b22328f9Schristos 	}
454b22328f9Schristos 
455b22328f9Schristos     free (perms);
456b22328f9Schristos 
457b22328f9Schristos     return (retval);
458b22328f9Schristos }
459b22328f9Schristos 
460b22328f9Schristos /* returns permissions found */
461b22328f9Schristos char *
462b22328f9Schristos get_perms (const char *part_perms)
463b22328f9Schristos {
464b22328f9Schristos     char *username;
465b22328f9Schristos     char *xperms;
466b22328f9Schristos     size_t xperms_len = 1;
467b22328f9Schristos 
468b22328f9Schristos     FILE *groupfp;
469b22328f9Schristos 
470b22328f9Schristos     char *founduser = NULL;
471b22328f9Schristos     char *foundall = NULL;
472b22328f9Schristos     int default_checked = 0;
473b22328f9Schristos 
474b22328f9Schristos     if (debug) fprintf (stderr, "get_perms %s...", part_perms);
475b22328f9Schristos     aclconfig_default_used = 0;
476b22328f9Schristos 
477b22328f9Schristos     xperms = xmalloc (xperms_len);
478b22328f9Schristos     xperms[0] = '\0';
479b22328f9Schristos 
480b22328f9Schristos     /* use CVS_Username if set */
481b22328f9Schristos     if (CVS_Username == NULL)
482b22328f9Schristos 	username = getcaller ();
483b22328f9Schristos     else
484b22328f9Schristos 	username = CVS_Username;
485b22328f9Schristos 
486b22328f9Schristos     /* no defined acl, no default acl in access file,
487b22328f9Schristos      * or no access file at all */
488b22328f9Schristos     if (part_perms == NULL) {
489b22328f9Schristos 	if (cvs_acl_default_permissions)
490b22328f9Schristos 	{
491b22328f9Schristos 	    aclconfig_default_used = 1;
492b22328f9Schristos 	    if (debug) fprintf (stderr, "default %s\n",
493b22328f9Schristos 			        cvs_acl_default_permissions);
494b22328f9Schristos 	    return (cvs_acl_default_permissions);
495b22328f9Schristos 	}
496b22328f9Schristos 	else {
497b22328f9Schristos 	    if (debug) fprintf (stderr, "early %s\n", xperms);
498b22328f9Schristos 	    return xperms;
499b22328f9Schristos 	}
500b22328f9Schristos     }
501b22328f9Schristos 
502b22328f9Schristos check_default:
503b22328f9Schristos     founduser = findusername (part_perms, username);
504b22328f9Schristos     foundall = strstr (part_perms, "ALL!");
505b22328f9Schristos 
506b22328f9Schristos     if (debug) fprintf (stderr, "founduser=%s foundALL=%s\n",
507b22328f9Schristos 		        founduser, foundall);
508b22328f9Schristos     if (founduser)
509b22328f9Schristos     {
510b22328f9Schristos 	char *usr;
511b22328f9Schristos 	char *per;
512b22328f9Schristos 
513b22328f9Schristos 	usr = strtok (founduser, "!\t");
514b22328f9Schristos 	per = strtok (NULL, ",\t");
515b22328f9Schristos 
516*cc7958a0Schristos 	free(xperms);
517b22328f9Schristos 	xperms = xstrdup (per);
518b22328f9Schristos 	xperms_len = strlen (xperms);
519b22328f9Schristos 
520b22328f9Schristos 	userfound = 1;
521*cc7958a0Schristos 	free (founduser);
522b22328f9Schristos     }
523b22328f9Schristos     else
524b22328f9Schristos     {
525b22328f9Schristos 	if (debug) fprintf (stderr, "usesystemgroups=%d\n", use_system_groups);
526b22328f9Schristos 	if (use_system_groups) {
527b22328f9Schristos 	    struct group *griter;
528b22328f9Schristos 	    setgrent ();
529b22328f9Schristos 	    while (griter = getgrent ())
530b22328f9Schristos 	    {
531b22328f9Schristos 		char **users=griter->gr_mem;
532b22328f9Schristos 		int index = 0;
533b22328f9Schristos 		char *userchk = users [index++];
534b22328f9Schristos 		while(userchk != NULL) {
535b22328f9Schristos 		    if(strcmp (userchk, username) == 0)
536b22328f9Schristos 			break;
537b22328f9Schristos 		    userchk = users[index++];
538b22328f9Schristos 		}
539b22328f9Schristos 		if (debug) fprintf (stderr, "usercheck=%s\n", userchk);
540b22328f9Schristos 		if (userchk != NULL) {
541b22328f9Schristos 		    char *grp;
542b22328f9Schristos 		    if ((grp = findusername (part_perms, griter->gr_name)))
543b22328f9Schristos 		    {
544b22328f9Schristos 			char *gperm = strtok (grp, "!\t");
545b22328f9Schristos 			if (debug) fprintf (stderr, "usercheck=%s, grp=%s\n",
546b22328f9Schristos 					    userchk, grp);
547b22328f9Schristos 			gperm = strtok (NULL, ",\t");
548b22328f9Schristos 			xrealloc_and_strcat (&xperms, &xperms_len, gperm);
549b22328f9Schristos 
550b22328f9Schristos 			groupfound = 1;
551*cc7958a0Schristos 			free (grp);
552b22328f9Schristos 		    }
553b22328f9Schristos 		}
554b22328f9Schristos 	    }
555b22328f9Schristos 	    endgrent ();
556b22328f9Schristos 	}
557b22328f9Schristos 	else if (use_cvs_groups) {
558b22328f9Schristos 	    groupfp = open_groupfile ("r");
559b22328f9Schristos 	    if (groupfp != NULL)
560b22328f9Schristos 	    {
561b22328f9Schristos 		char *line = NULL;
562b22328f9Schristos 		char *grp;
563b22328f9Schristos 		char *gperm;
564b22328f9Schristos 		int read;
565b22328f9Schristos 
566b22328f9Schristos 		size_t line_allocated = 0;
567b22328f9Schristos 
568b22328f9Schristos 		while ((read = getline (&line, &line_allocated, groupfp)) >= 0)
569b22328f9Schristos 		{
570*cc7958a0Schristos 		    char *user;
571b22328f9Schristos 		    if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
572b22328f9Schristos 			continue;
573b22328f9Schristos 
574b22328f9Schristos 		    if (line[read - 1] == '\n')
575b22328f9Schristos 			line[--read] = '\0';
576b22328f9Schristos 
577*cc7958a0Schristos 		    if ((grp = findgroupname (line, username)) &&
578*cc7958a0Schristos 			(user = findusername (part_perms, grp)))
579*cc7958a0Schristos 
580b22328f9Schristos 		    {
581*cc7958a0Schristos 			gperm = strtok (user, "!\t");
582b22328f9Schristos 			gperm = strtok (NULL, ",\t");
583b22328f9Schristos 			xrealloc_and_strcat (&xperms, &xperms_len, gperm);
584b22328f9Schristos 			groupfound = 1;
585*cc7958a0Schristos 			free (grp);
586*cc7958a0Schristos 			free (user);
587b22328f9Schristos 		    }
588b22328f9Schristos 		}
589b22328f9Schristos 
590b22328f9Schristos 		free (line);
591b22328f9Schristos 
592b22328f9Schristos 		if (fclose (groupfp) == EOF)
593b22328f9Schristos 		    error (1, errno, "cannot close 'group' file");
594b22328f9Schristos 	    }
595b22328f9Schristos 	}
596b22328f9Schristos     }
597b22328f9Schristos 
598b22328f9Schristos     if (foundall)
599b22328f9Schristos     {
600b22328f9Schristos 	char *usr;
601b22328f9Schristos 	char *per;
602b22328f9Schristos 
603b22328f9Schristos 	usr = strtok (strstr (part_perms, "ALL!"), "!\t");
604b22328f9Schristos 	per = strtok (NULL, ",\t");
605b22328f9Schristos 
606b22328f9Schristos 	if (!default_checked)
607b22328f9Schristos 	    default_perms_object = xstrdup (per);
608b22328f9Schristos 
609b22328f9Schristos 	if (xperms[0] == '\0')
610b22328f9Schristos 	{
611b22328f9Schristos 	    xperms = xstrdup (per);
612b22328f9Schristos 	    xperms_len = strlen (xperms);
613b22328f9Schristos 	}
614b22328f9Schristos 
615b22328f9Schristos 	/* You don't free pointers from strtok()! */
616b22328f9Schristos 	//free(usr);
617b22328f9Schristos 	//free(per);
618b22328f9Schristos     }
619b22328f9Schristos 
620b22328f9Schristos     if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
621b22328f9Schristos     {
622b22328f9Schristos 	part_perms = xstrdup (default_part_perms_accessfile);
623b22328f9Schristos 	default_checked = 1;
624b22328f9Schristos 
625b22328f9Schristos 	goto check_default;
626b22328f9Schristos     }
627b22328f9Schristos 
628b22328f9Schristos     if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
629b22328f9Schristos     {
630b22328f9Schristos 	if (default_perms_object)
631b22328f9Schristos 	    xperms = xstrdup (default_perms_object);
632b22328f9Schristos 	else if (default_part_perms_accessfile)
633b22328f9Schristos 	{
634b22328f9Schristos 	    part_perms = default_part_perms_accessfile;
635b22328f9Schristos 	    default_checked = 1;
636b22328f9Schristos 	    goto check_default;
637b22328f9Schristos 	}
638b22328f9Schristos 	else if (cvs_acl_default_permissions)
639b22328f9Schristos 	{
640b22328f9Schristos 	    aclconfig_default_used = 1;
641b22328f9Schristos 	    xperms = xstrdup (cvs_acl_default_permissions);
642b22328f9Schristos 	}
643b22328f9Schristos     }
644b22328f9Schristos 
645b22328f9Schristos     if (xperms[0] == '\0' && cvs_acl_default_permissions)
646b22328f9Schristos     {
647b22328f9Schristos 	aclconfig_default_used = 1;
648b22328f9Schristos 	xperms = xstrdup (cvs_acl_default_permissions);
649b22328f9Schristos     }
650b22328f9Schristos 
651b22328f9Schristos     if (debug) fprintf (stderr, "late %s\n", xperms);
652b22328f9Schristos     return xperms;
653b22328f9Schristos }
654b22328f9Schristos 
655b22328f9Schristos 
656b22328f9Schristos int
657b22328f9Schristos cvsacl (int argc, char **argv)
658b22328f9Schristos {
659b22328f9Schristos     char *chdirrepository;
660b22328f9Schristos     int c;
661b22328f9Schristos     int err = 0;
662b22328f9Schristos     int usetag = 0;
663b22328f9Schristos     int recursive = 0;
664b22328f9Schristos 
665b22328f9Schristos     int which;
666b22328f9Schristos     char *where;
667b22328f9Schristos 
668b22328f9Schristos     is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
669b22328f9Schristos 
670b22328f9Schristos     if (argc == -1)
671b22328f9Schristos 	usage (is_racl ? racl_usage : acl_usage);
672b22328f9Schristos 
673b22328f9Schristos     /* parse the args */
674b22328f9Schristos     optind = 0;
675b22328f9Schristos 
676b22328f9Schristos     while ((c = getopt (argc, argv, "dRr:l")) != -1)
677b22328f9Schristos     {
678b22328f9Schristos 	switch (c)
679b22328f9Schristos 	{
680b22328f9Schristos 	case 'd':
681b22328f9Schristos 	    debug++;
682b22328f9Schristos 	    break;
683b22328f9Schristos 	case 'R':
684b22328f9Schristos 	    recursive = 1;
685b22328f9Schristos 	    break;
686b22328f9Schristos 	case 'r': // baris
687b22328f9Schristos 	    tag = xstrdup (optarg);
688b22328f9Schristos 	    break;
689b22328f9Schristos 	case 'l':
690b22328f9Schristos 	    listacl = 1;
691b22328f9Schristos 	    break;
692b22328f9Schristos 	case '?':
693b22328f9Schristos 	default:
694b22328f9Schristos 	    usage (is_racl ? racl_usage : acl_usage);
695b22328f9Schristos 	    break;
696b22328f9Schristos 	}
697b22328f9Schristos     }
698b22328f9Schristos 
699b22328f9Schristos     argc -= optind;
700b22328f9Schristos     argv += optind;
701b22328f9Schristos 
702b22328f9Schristos     if (argc < (is_racl ? 1 : 1))
703b22328f9Schristos 	usage (is_racl ? racl_usage : acl_usage);
704b22328f9Schristos     if (listacl) {
705b22328f9Schristos 	if (strstr (argv[0], ":"))
706b22328f9Schristos 	    usage (is_racl ? racl_usage : acl_usage);
707b22328f9Schristos     } else {
708b22328f9Schristos 	if (!strstr (argv[0], ":"))
709b22328f9Schristos 	    usage (is_racl ? racl_usage : acl_usage);
710b22328f9Schristos     }
711b22328f9Schristos 
712b22328f9Schristos 
713b22328f9Schristos #ifdef CLIENT_SUPPORT
714b22328f9Schristos 
715b22328f9Schristos     if (current_parsed_root->isremote)
716b22328f9Schristos     {
717b22328f9Schristos 	start_server ();
718b22328f9Schristos 	ign_setup ();
719b22328f9Schristos 
720b22328f9Schristos 	if(recursive)
721b22328f9Schristos 	    send_arg ("-R");
722b22328f9Schristos 
723b22328f9Schristos 	if (listacl)
724b22328f9Schristos 	    send_arg ("-l");
725b22328f9Schristos 
726b22328f9Schristos 	if(tag)
727b22328f9Schristos 	{
728b22328f9Schristos 	    option_with_arg ("-r", tag);
729b22328f9Schristos 	}
730b22328f9Schristos 
731b22328f9Schristos 	send_arg ("--");
732b22328f9Schristos 
733b22328f9Schristos 	if (!listacl)
734b22328f9Schristos 	{
735b22328f9Schristos 	    send_arg (argv[0]);
736b22328f9Schristos 
737b22328f9Schristos 	    argc--;
738b22328f9Schristos 	    argv++;
739b22328f9Schristos 	}
740b22328f9Schristos 
741b22328f9Schristos 	if (is_racl)
742b22328f9Schristos 	{
743b22328f9Schristos 	    int i;
744b22328f9Schristos 	    for (i = 0; i < argc; ++i)
745b22328f9Schristos 		send_arg (argv[i]);
746b22328f9Schristos 
747b22328f9Schristos 	    send_to_server ("racl\012",0);
748b22328f9Schristos 	}
749b22328f9Schristos 	else
750b22328f9Schristos 	{
751b22328f9Schristos 	    send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
752b22328f9Schristos 	    send_file_names (argc, argv, SEND_EXPAND_WILD);
753b22328f9Schristos 	    send_to_server ("acl\012", 0);
754b22328f9Schristos 	}
755b22328f9Schristos 
756b22328f9Schristos 	return get_responses_and_close ();
757b22328f9Schristos     }
758b22328f9Schristos #endif
759b22328f9Schristos 
760b22328f9Schristos #ifdef SERVER_SUPPORT
761b22328f9Schristos 
762b22328f9Schristos     if (!listacl)
763b22328f9Schristos     {
764b22328f9Schristos 	muser = strtok (argv[0], ":\t");
765b22328f9Schristos 	mperms = strtok (NULL, ":\t");
766b22328f9Schristos 
767b22328f9Schristos 	/* if set to 'default' */
768b22328f9Schristos 	if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
769b22328f9Schristos 	    mperms = xstrdup ("x");
770b22328f9Schristos 
771b22328f9Schristos 	/* Check that the given permissions are valid. */
772b22328f9Schristos 	if (!given_perms_valid (mperms))
773b22328f9Schristos 	    error (1,0,"Invalid permissions: `%s'", mperms);
774b22328f9Schristos 
775b22328f9Schristos 	argc--;
776b22328f9Schristos 	argv++;
777b22328f9Schristos     }
778b22328f9Schristos 
779b22328f9Schristos 
780b22328f9Schristos     if (!tag)
781b22328f9Schristos 	tag = xstrdup ("HEAD");
782b22328f9Schristos 
783b22328f9Schristos     if (!strcasecmp (argv[0], "ALL"))
784b22328f9Schristos     {
785b22328f9Schristos 	argv[0] = xstrdup (".");
786b22328f9Schristos 	defaultperms = 1;
787b22328f9Schristos 	if (!use_separate_acl_file_for_each_dir)
788b22328f9Schristos 	{
789b22328f9Schristos 	    recursive = 0;
790b22328f9Schristos 	}
791b22328f9Schristos 
792b22328f9Schristos     }
793b22328f9Schristos 
794b22328f9Schristos     if (is_racl)
795b22328f9Schristos     {
796b22328f9Schristos 	DBM *db;
797b22328f9Schristos 	int i;
798b22328f9Schristos 	db = open_module ();
799b22328f9Schristos 	for (i = 0; i < argc; i++)
800b22328f9Schristos 	{
801b22328f9Schristos 	    err += do_module (db, argv[i], MISC, "ACL ing: ",
802b22328f9Schristos 			      racl_proc, NULL, 0, !recursive, 0,
803b22328f9Schristos 			      0, NULL);
804b22328f9Schristos 	}
805b22328f9Schristos 	close_module (db);
806b22328f9Schristos     }
807b22328f9Schristos     else
808b22328f9Schristos     {
809b22328f9Schristos 	err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive,
810b22328f9Schristos 			 NULL, NULL);
811b22328f9Schristos     }
812b22328f9Schristos 
813b22328f9Schristos     return err;
814b22328f9Schristos 
815b22328f9Schristos #endif
816b22328f9Schristos }
817b22328f9Schristos 
818b22328f9Schristos static int
819b22328f9Schristos racl_proc (int argc, char **argv, char *xwhere, char *mwhere,
820b22328f9Schristos 	   char *mfile, int shorten, int local, char *mname, char *msg)
821b22328f9Schristos {
822b22328f9Schristos     char *myargv[2];
823b22328f9Schristos     int err = 0;
824b22328f9Schristos     int which;
825*cc7958a0Schristos     char *repository;
826b22328f9Schristos     char *where;
827b22328f9Schristos     char *obj;
828b22328f9Schristos     size_t objlen = 0;
829b22328f9Schristos 
830b22328f9Schristos     if (!use_cvs_acl)
831b22328f9Schristos     {
832b22328f9Schristos 	error(1, 0, "CVSACL extension is not enabled, set `UseCVSACL=yes'"
833b22328f9Schristos 	      " in aclconfig file");
834b22328f9Schristos     }
835b22328f9Schristos 
836b22328f9Schristos     if (is_racl)
837b22328f9Schristos     {
838*cc7958a0Schristos 	char *v;
839b22328f9Schristos 	repository = Xasprintf ("%s/%s", current_parsed_root->directory,
840b22328f9Schristos 				argv[0]);
841*cc7958a0Schristos 	where = xstrdup (argv[0]);
842b22328f9Schristos 
843b22328f9Schristos 	/* if mfile isn't null, we need to set up to do only part of the
844b22328f9Schristos 	 * module */
845b22328f9Schristos 	if (mfile != NULL)
846b22328f9Schristos 	{
847b22328f9Schristos 	    char *cp;
848b22328f9Schristos 	    char *path;
849b22328f9Schristos 
850b22328f9Schristos 	    /* if the portion of the module is a path, put the dir part on
851b22328f9Schristos 	     * repos */
852b22328f9Schristos 	    if ((cp = strrchr (mfile, '/')) != NULL)
853b22328f9Schristos 	    {
854b22328f9Schristos 		*cp = '\0';
855*cc7958a0Schristos 		v = Xasprintf ("%s/%s", repository, mfile);
856*cc7958a0Schristos 		free (repository);
857*cc7958a0Schristos 		repository = v;
858*cc7958a0Schristos 		v = Xasprintf ("%s/%s", where, mfile);
859*cc7958a0Schristos 		free(where);
860*cc7958a0Schristos 		where = v;
861b22328f9Schristos 		mfile = cp + 1;
862b22328f9Schristos 	    }
863b22328f9Schristos 
864b22328f9Schristos 	    /* take care of the rest */
865b22328f9Schristos 	    path = Xasprintf ("%s/%s", repository, mfile);
866b22328f9Schristos 	    if (isdir (path))
867b22328f9Schristos 	    {
868b22328f9Schristos 		/* directory means repository gets the dir tacked on */
869*cc7958a0Schristos 		free(repository);
870*cc7958a0Schristos 		repository = path;
871*cc7958a0Schristos 		v = Xasprintf ("%s/%s", where, mfile);
872*cc7958a0Schristos 		free(where);
873*cc7958a0Schristos 		where = v;
874b22328f9Schristos 	    }
875b22328f9Schristos 	    else
876b22328f9Schristos 	    {
877*cc7958a0Schristos 		free (path);
878b22328f9Schristos 		myargv[0] = argv[0];
879b22328f9Schristos 		myargv[1] = mfile;
880b22328f9Schristos 		argc = 2;
881b22328f9Schristos 		argv = myargv;
882b22328f9Schristos 	    }
883b22328f9Schristos 	}
884b22328f9Schristos 
885b22328f9Schristos 	/* cd to the starting repository */
886b22328f9Schristos 	if ( CVS_CHDIR (repository) < 0)
887b22328f9Schristos 	{
888b22328f9Schristos 	    error (0, errno, "cannot chdir to %s", repository);
889b22328f9Schristos 	    free (repository);
890b22328f9Schristos 	    free (where);
891b22328f9Schristos 	    return 1;
892b22328f9Schristos 	}
893b22328f9Schristos 
894b22328f9Schristos 	/* End section which is identical to patch_proc.  */
895b22328f9Schristos 
896b22328f9Schristos 	which = W_REPOS | W_ATTIC;
897b22328f9Schristos 
898b22328f9Schristos 	if (argc > 1)
899b22328f9Schristos 	{
900b22328f9Schristos 		obj = Xasprintf ("%s/%s", repository, argv[1]);
901b22328f9Schristos 	}
902b22328f9Schristos 	else
903b22328f9Schristos 	{
904b22328f9Schristos 		obj = xstrdup(repository);
905b22328f9Schristos 	}
906b22328f9Schristos     }
907b22328f9Schristos     else
908b22328f9Schristos     {
909b22328f9Schristos 	where = NULL;
910*cc7958a0Schristos 	repository = NULL;
911b22328f9Schristos 	which = W_LOCAL | W_REPOS | W_ATTIC;
912b22328f9Schristos 
913b22328f9Schristos 	obj = xstrdup (argv[1]);
914b22328f9Schristos     }
915b22328f9Schristos 
916b22328f9Schristos     if (isdir (obj))
917b22328f9Schristos 	acldir = 1;
918b22328f9Schristos     else if (isfile (obj))
919b22328f9Schristos 	aclfile = 1;
920b22328f9Schristos     else
921b22328f9Schristos 	error(1, 0, "no such file or directory");
922b22328f9Schristos 
923b22328f9Schristos     free (obj);
924b22328f9Schristos 
925b22328f9Schristos     if (listacl)
926b22328f9Schristos 	err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL,
927b22328f9Schristos 			       NULL, argc - 1, argv + 1, local, which, 0, 0,
928*cc7958a0Schristos 			       where, 1, repository);
929b22328f9Schristos     else
930b22328f9Schristos 	err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
931b22328f9Schristos 			       argc - 1, argv + 1, local, which, 0, 0,
932*cc7958a0Schristos 			       where, 1, repository);
933b22328f9Schristos 
934b22328f9Schristos     if (repository != NULL)
935b22328f9Schristos 	free (repository);
936*cc7958a0Schristos     if (where != NULL)
937*cc7958a0Schristos 	free (where);
938b22328f9Schristos 
939b22328f9Schristos     return err;
940b22328f9Schristos }
941b22328f9Schristos 
942b22328f9Schristos 
943b22328f9Schristos static int
944b22328f9Schristos acl_fileproc (void *callerdat, struct file_info *finfo)
945b22328f9Schristos {
946b22328f9Schristos     char *filefullname;
947b22328f9Schristos     char *founduserpart = NULL;
948b22328f9Schristos     char *otheruserparts = NULL;
949b22328f9Schristos     size_t otherslen = 0;
950b22328f9Schristos 
951b22328f9Schristos     const char *frepository;
952b22328f9Schristos     int foundline = 0;
953b22328f9Schristos 
954b22328f9Schristos     char *line = NULL;
955b22328f9Schristos     size_t line_allocated = 0;
956b22328f9Schristos     int linelen;
957b22328f9Schristos 
958b22328f9Schristos     char *wperms;
959b22328f9Schristos     char *errmsg;
960b22328f9Schristos 
961b22328f9Schristos     int pos;
962b22328f9Schristos 
963b22328f9Schristos     if (!aclfile)
964b22328f9Schristos 	return 0;
965b22328f9Schristos 
966b22328f9Schristos     frepository = Short_Repository (finfo->repository);
967b22328f9Schristos 
968b22328f9Schristos     filefullname = Xasprintf("%s/%s", frepository, finfo->file);
969b22328f9Schristos 
970b22328f9Schristos 
971b22328f9Schristos     if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos,
972b22328f9Schristos 			 0))
973b22328f9Schristos 	error (1, 0, "You do not have acl admin rights on '%s'", frepository);
974b22328f9Schristos 
975b22328f9Schristos     if (line != NULL)
976b22328f9Schristos     {
977b22328f9Schristos 	char *part_type = NULL;
978b22328f9Schristos 	char *part_object = NULL;
979b22328f9Schristos 	char *part_tag = NULL;
980b22328f9Schristos 	char *part_perms = NULL;
981b22328f9Schristos 	char *userpart;
982b22328f9Schristos 
983b22328f9Schristos 	part_type = strtok (line, ":\t");
984b22328f9Schristos 	part_object = strtok (NULL, ":\t");
985b22328f9Schristos 	part_tag = strtok (NULL, ":\t");
986b22328f9Schristos 	part_perms = strtok (NULL, ":\t");
987b22328f9Schristos 
988b22328f9Schristos 	foundline = 1;
989b22328f9Schristos 	userpart = strtok (part_perms, ",\t");
990b22328f9Schristos 
991b22328f9Schristos 	do
992b22328f9Schristos 	{
993b22328f9Schristos 	    if (strncmp (userpart, muser, strlen (muser)) == 0)
994b22328f9Schristos 		founduserpart = xstrdup (userpart);
995b22328f9Schristos 	    else
996b22328f9Schristos 	    {
997b22328f9Schristos 		if (otheruserparts != NULL)
998b22328f9Schristos 		{
999b22328f9Schristos 		    xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1000b22328f9Schristos 		    xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1001b22328f9Schristos 		}
1002b22328f9Schristos 		else
1003b22328f9Schristos 		{
1004b22328f9Schristos 		    otheruserparts = xstrdup (userpart);
1005b22328f9Schristos 		    otherslen = strlen (otheruserparts);
1006b22328f9Schristos 		}
1007b22328f9Schristos 	    }
1008b22328f9Schristos 	} while ((userpart = strtok (NULL, ",\t")) != NULL);
1009b22328f9Schristos 
1010b22328f9Schristos 	free (userpart);
1011b22328f9Schristos     }
1012b22328f9Schristos 
1013b22328f9Schristos     wperms = make_perms (mperms, founduserpart, &errmsg);
1014b22328f9Schristos     if (wperms == NULL)
1015b22328f9Schristos     {
1016b22328f9Schristos 	if (errmsg)
1017b22328f9Schristos 	    error (0, 0, "`%s' %s", filefullname, errmsg);
1018b22328f9Schristos     }
1019b22328f9Schristos     else
1020b22328f9Schristos     {
1021b22328f9Schristos 	cvs_output ("X ", 0);
1022b22328f9Schristos 	cvs_output (filefullname, 0);
1023b22328f9Schristos 	cvs_output ("\n", 0);
1024b22328f9Schristos 
1025b22328f9Schristos 	write_perms (muser, wperms, founduserpart, foundline,
1026b22328f9Schristos 		     otheruserparts, "f", filefullname, tag, pos,
1027b22328f9Schristos 		     Short_Repository(finfo->repository));
1028b22328f9Schristos     }
1029b22328f9Schristos 
1030b22328f9Schristos     free (line);
1031b22328f9Schristos     free (founduserpart);
1032b22328f9Schristos     free (otheruserparts);
1033b22328f9Schristos     free (wperms);
1034b22328f9Schristos     free (filefullname);
1035b22328f9Schristos 
1036b22328f9Schristos     return 0;
1037b22328f9Schristos }
1038b22328f9Schristos 
1039b22328f9Schristos static Dtype
1040b22328f9Schristos acl_dirproc (void *callerdat, const char *dir, const char *repos,
1041b22328f9Schristos 	     const char *update_dir, List *entries)
1042b22328f9Schristos {
1043b22328f9Schristos     const char *drepository;
1044b22328f9Schristos     char *founduserpart = NULL;
1045b22328f9Schristos     char *otheruserparts = NULL;
1046b22328f9Schristos     size_t otherslen = 0;
1047b22328f9Schristos     int foundline = 0;
1048b22328f9Schristos 
1049b22328f9Schristos     char *line = NULL;
1050b22328f9Schristos     size_t line_allocated = 0;
1051b22328f9Schristos     int linelen;
1052b22328f9Schristos 
1053b22328f9Schristos     int pos;
1054b22328f9Schristos 
1055b22328f9Schristos     char *wperms;
1056b22328f9Schristos     char *errmsg;
1057b22328f9Schristos 
1058b22328f9Schristos     if (!acldir)
1059b22328f9Schristos 	return 0;
1060b22328f9Schristos 
1061b22328f9Schristos     if (repos[0] == '\0')
1062b22328f9Schristos 	repos = Name_Repository (dir, NULL);
1063b22328f9Schristos 
1064b22328f9Schristos     if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
1065b22328f9Schristos 	error (1, 0, "You do not have admin rights on '%s'",
1066b22328f9Schristos 	       Short_Repository (repos));
1067b22328f9Schristos 
1068b22328f9Schristos     drepository = Short_Repository (repos);
1069b22328f9Schristos 
1070b22328f9Schristos     if (line != NULL)
1071b22328f9Schristos     {
1072b22328f9Schristos 	char *part_type = NULL;
1073b22328f9Schristos 	char *part_object = NULL;
1074b22328f9Schristos 	char *part_tag = NULL;
1075b22328f9Schristos 	char *part_perms = NULL;
1076b22328f9Schristos 	char *userpart;
1077b22328f9Schristos 
1078b22328f9Schristos 	part_type = strtok (line, ":\t");
1079b22328f9Schristos 	part_object = strtok (NULL, ":\t");
1080b22328f9Schristos 	part_tag = strtok (NULL, ":\t");
1081b22328f9Schristos 	part_perms = strtok (NULL, ":\t");
1082b22328f9Schristos 
1083b22328f9Schristos 	foundline = 1;
1084b22328f9Schristos 	userpart = strtok (part_perms, ",\t");
1085b22328f9Schristos 
1086b22328f9Schristos 	do
1087b22328f9Schristos 	{
1088b22328f9Schristos 	    if (strncmp (userpart, muser, strlen (muser)) == 0)
1089b22328f9Schristos 		founduserpart = xstrdup (userpart);
1090b22328f9Schristos 	    else
1091b22328f9Schristos 	    {
1092b22328f9Schristos 		if (otheruserparts != NULL)
1093b22328f9Schristos 		{
1094b22328f9Schristos 		    xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1095b22328f9Schristos 		    xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1096b22328f9Schristos 		}
1097b22328f9Schristos 		else
1098b22328f9Schristos 		{
1099b22328f9Schristos 		    otheruserparts = xstrdup (userpart);
1100b22328f9Schristos 		    otherslen = strlen (otheruserparts);
1101b22328f9Schristos 		}
1102b22328f9Schristos 	    }
1103b22328f9Schristos 	} while ((userpart = strtok (NULL, ",\t")) != NULL);
1104b22328f9Schristos     }
1105b22328f9Schristos 
1106b22328f9Schristos     wperms = make_perms (mperms, founduserpart, &errmsg);
1107b22328f9Schristos     if (wperms == NULL)
1108b22328f9Schristos     {
1109b22328f9Schristos 	if (errmsg)
1110b22328f9Schristos 	    error (0, 0, "`%s' %s", drepository, errmsg);
1111b22328f9Schristos     }
1112b22328f9Schristos     else
1113b22328f9Schristos     {
1114b22328f9Schristos 	if (defaultperms)
1115b22328f9Schristos 	{
1116b22328f9Schristos 	    cvs_output ("X ", 0);
1117b22328f9Schristos 	    cvs_output ("ALL", 0);
1118b22328f9Schristos 	    cvs_output ("\n", 0);
1119b22328f9Schristos 	    write_perms (muser, wperms, founduserpart, foundline,
1120b22328f9Schristos 			 otheruserparts, "d", "ALL", tag, pos, drepository);
1121b22328f9Schristos 
1122b22328f9Schristos 	}
1123b22328f9Schristos 	else
1124b22328f9Schristos 	{
1125b22328f9Schristos 	    cvs_output ("X ", 0);
1126b22328f9Schristos 	    cvs_output (drepository, 0);
1127b22328f9Schristos 	    cvs_output ("\n", 0);
1128b22328f9Schristos 	    write_perms (muser, wperms, founduserpart, foundline,
1129b22328f9Schristos 			 otheruserparts, "d", drepository, tag, pos,
1130b22328f9Schristos 			 drepository);
1131b22328f9Schristos 	}
1132b22328f9Schristos     }
1133b22328f9Schristos 
1134b22328f9Schristos     free (line);
1135b22328f9Schristos     free (founduserpart);
1136b22328f9Schristos     free (otheruserparts);
1137b22328f9Schristos     free (wperms);
1138b22328f9Schristos 
1139b22328f9Schristos     return 0;
1140b22328f9Schristos }
1141b22328f9Schristos 
1142b22328f9Schristos /* Open CVSROOT/access or defined CVSACLFileLocation file
1143b22328f9Schristos  * Open access file In each directory if UseSeparateACLFileForEachDir=yes
1144b22328f9Schristos  * returns file pointer to access file or NULL if access file not found */
1145b22328f9Schristos FILE *
1146b22328f9Schristos open_accessfile (char *fmode, const char *adir, char **fname)
1147b22328f9Schristos {
1148b22328f9Schristos     char *accessfile = NULL;
1149b22328f9Schristos     FILE *accessfp;
1150b22328f9Schristos 
1151b22328f9Schristos     if (!use_separate_acl_file_for_each_dir)
1152b22328f9Schristos     {
1153b22328f9Schristos 	if (cvs_acl_file_location == NULL)
1154b22328f9Schristos 	{
1155b22328f9Schristos 	    accessfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
1156b22328f9Schristos 				   CVSROOTADM, CVSROOTADM_ACCESS);
1157b22328f9Schristos 	}
1158b22328f9Schristos 	else
1159b22328f9Schristos 	{
1160b22328f9Schristos 	    accessfile = xstrdup(cvs_acl_file_location);
1161b22328f9Schristos 	}
1162b22328f9Schristos     }
1163b22328f9Schristos     else
1164b22328f9Schristos     {
1165b22328f9Schristos 	size_t accessfilelen = 0;
1166b22328f9Schristos 	xrealloc_and_strcat (&accessfile, &accessfilelen,
1167b22328f9Schristos 			     current_parsed_root->directory);
1168b22328f9Schristos 	xrealloc_and_strcat (&accessfile, &accessfilelen, "/");
1169b22328f9Schristos 	xrealloc_and_strcat (&accessfile, &accessfilelen, adir);
1170b22328f9Schristos 	xrealloc_and_strcat (&accessfile, &accessfilelen, "/access");
1171b22328f9Schristos     }
1172b22328f9Schristos 
1173b22328f9Schristos     accessfp = CVS_FOPEN (accessfile, fmode);
1174b22328f9Schristos 
1175b22328f9Schristos     if (fname != NULL)
1176b22328f9Schristos 	*fname = xstrdup (accessfile);
1177b22328f9Schristos 
1178b22328f9Schristos     free (accessfile);
1179b22328f9Schristos 
1180b22328f9Schristos     return accessfp;
1181b22328f9Schristos }
1182b22328f9Schristos 
1183b22328f9Schristos /* Open /etc/group file if UseSystemGroups=yes in config file
1184b22328f9Schristos  * Open CVSROOT/group file if UseCVSGroups=yes in config file
1185b22328f9Schristos  * Open group file if specified in CVSGroupsFileLocation
1186b22328f9Schristos  * returns group file pointer if UseSystemGroups=yes
1187b22328f9Schristos  * returns NULL if UseSystemGroups=no or group file not found */
1188b22328f9Schristos FILE *
1189b22328f9Schristos open_groupfile (char *fmode)
1190b22328f9Schristos {
1191b22328f9Schristos     char *groupfile;
1192b22328f9Schristos     FILE *groupfp;
1193b22328f9Schristos 
1194b22328f9Schristos     if (use_cvs_groups)
1195b22328f9Schristos     {
1196b22328f9Schristos 	if (cvs_groups_file_location != NULL)
1197b22328f9Schristos 	{
1198b22328f9Schristos 	    groupfile = xstrdup (cvs_groups_file_location);
1199b22328f9Schristos 	}
1200b22328f9Schristos 	else
1201b22328f9Schristos 	{
1202b22328f9Schristos 	    groupfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
1203b22328f9Schristos 				  CVSROOTADM, CVSROOTADM_GROUP);
1204b22328f9Schristos 	}
1205b22328f9Schristos     }
1206b22328f9Schristos     else
1207b22328f9Schristos     {
1208b22328f9Schristos 	    return NULL;
1209b22328f9Schristos     }
1210b22328f9Schristos 
1211b22328f9Schristos     groupfp = CVS_FOPEN (groupfile, "r");
1212b22328f9Schristos 
1213b22328f9Schristos     if (groupfp == NULL)
1214b22328f9Schristos 	error (0, 0, "cannot open file: %s", groupfile);
1215b22328f9Schristos 
1216b22328f9Schristos     free (groupfile);
1217b22328f9Schristos 
1218b22328f9Schristos     return groupfp;
1219b22328f9Schristos }
1220b22328f9Schristos 
1221b22328f9Schristos 
1222b22328f9Schristos /* Check whether given permissions are valid or not
1223b22328f9Schristos  * Returns 1 if permissions are valid
1224b22328f9Schristos  * Returns 0 if permissions are NOT valid */
1225b22328f9Schristos int
1226b22328f9Schristos given_perms_valid (const char *cperms)
1227b22328f9Schristos {
1228b22328f9Schristos     int cperms_len;
1229b22328f9Schristos     int retval;
1230b22328f9Schristos     int index, i;
1231b22328f9Schristos 
1232b22328f9Schristos     if (cperms[0] == '+' || cperms[0] == '-')
1233b22328f9Schristos 	index = 1;
1234b22328f9Schristos     else
1235b22328f9Schristos 	index = 0;
1236b22328f9Schristos 
1237b22328f9Schristos     cperms_len = strlen (cperms);
1238b22328f9Schristos 
1239b22328f9Schristos     switch (cperms[index])
1240b22328f9Schristos     {
1241b22328f9Schristos     case 'x':
1242b22328f9Schristos 	if ((cperms_len - index) == 1 && cperms_len == 1)
1243b22328f9Schristos 	    retval = 1;
1244b22328f9Schristos 	else
1245b22328f9Schristos 	    retval = 0;
1246b22328f9Schristos 	break;
1247b22328f9Schristos     case 'n':
1248b22328f9Schristos 	if ((cperms_len - index) == 1 && cperms_len == 1)
1249b22328f9Schristos 	    retval = 1;
1250b22328f9Schristos 	else
1251b22328f9Schristos 	    retval = 0;
1252b22328f9Schristos 	break;
1253b22328f9Schristos     case 'p':
1254b22328f9Schristos 	if ((cperms_len - index) == 1)
1255b22328f9Schristos 	    retval = 1;
1256b22328f9Schristos 	else
1257b22328f9Schristos 	    retval = 0;
1258b22328f9Schristos 	break;
1259b22328f9Schristos     case 'a':
1260b22328f9Schristos 	if ((cperms_len - index) == 1)
1261b22328f9Schristos 	    retval = 1;
1262b22328f9Schristos 	else
1263b22328f9Schristos 	    retval = 0;
1264b22328f9Schristos 	break;
1265b22328f9Schristos     case 'r':
1266b22328f9Schristos 	if ((cperms_len - index) == 1)
1267b22328f9Schristos 	    retval = 1;
1268b22328f9Schristos 	else
1269b22328f9Schristos 	    retval = 0;
1270b22328f9Schristos 	break;
1271b22328f9Schristos     case 'w':
1272b22328f9Schristos 	if ((cperms_len - index) == 1)
1273b22328f9Schristos 		retval = 1;
1274b22328f9Schristos 	else
1275b22328f9Schristos 	    for (i = index + 1; i < cperms_len; i++)
1276b22328f9Schristos 		if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1277b22328f9Schristos 		    retval = 1;
1278b22328f9Schristos 		else
1279b22328f9Schristos 		    retval = 0;
1280b22328f9Schristos 	break;
1281b22328f9Schristos     case 't':
1282b22328f9Schristos 	if ((cperms_len - index) == 1)
1283b22328f9Schristos 	    retval = 1;
1284b22328f9Schristos 	else
1285b22328f9Schristos 	    for (i = index + 1; i < cperms_len; i++)
1286b22328f9Schristos 		if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
1287b22328f9Schristos 		    retval = 1;
1288b22328f9Schristos 		else
1289b22328f9Schristos 		    retval = 0;
1290b22328f9Schristos 	break;
1291b22328f9Schristos     case 'c':
1292b22328f9Schristos 	if ((cperms_len - index) == 1)
1293b22328f9Schristos 	    retval = 1;
1294b22328f9Schristos 	else
1295b22328f9Schristos 	    for (i = index + 1; i < cperms_len; i++)
1296b22328f9Schristos 		if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
1297b22328f9Schristos 		    retval = 1;
1298b22328f9Schristos 		else
1299b22328f9Schristos 		    retval = 0;
1300b22328f9Schristos 	break;
1301b22328f9Schristos     case 'd':
1302b22328f9Schristos 	if ((cperms_len - index) == 1)
1303b22328f9Schristos 	    retval = 1;
1304b22328f9Schristos 	else
1305b22328f9Schristos 	    for (i = index + 1; i < cperms_len; i++)
1306b22328f9Schristos 		if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
1307b22328f9Schristos 		    retval = 1;
1308b22328f9Schristos 		else
1309b22328f9Schristos 		    retval = 0;
1310b22328f9Schristos 	break;
1311b22328f9Schristos     default:
1312b22328f9Schristos 	retval = 0;
1313b22328f9Schristos 	break;
1314b22328f9Schristos     }
1315b22328f9Schristos 
1316b22328f9Schristos     return retval;
1317b22328f9Schristos }
1318b22328f9Schristos 
1319b22328f9Schristos /* prepare permsissions string to be written to access file
1320b22328f9Schristos  * returns permissions or NULL if */
1321b22328f9Schristos char *
1322b22328f9Schristos make_perms (char *perms, char *founduserpart, char **xerrmsg)
1323b22328f9Schristos {
1324*cc7958a0Schristos     char *fperms = NULL;
1325b22328f9Schristos     size_t perms_len;
1326b22328f9Schristos     size_t fperms_len;
1327b22328f9Schristos 
1328b22328f9Schristos     int i, j;
1329b22328f9Schristos     int err = 0;
1330b22328f9Schristos     char *errmsg = NULL;
1331b22328f9Schristos 
1332b22328f9Schristos     char *retperms;
1333*cc7958a0Schristos     size_t retperms_len;
1334b22328f9Schristos 
1335b22328f9Schristos     perms_len = strlen (perms);
1336b22328f9Schristos     if (perms[0] == '+' || perms[0] == '-')
1337b22328f9Schristos     {
1338*cc7958a0Schristos 	retperms = xmalloc (retperms_len);
1339*cc7958a0Schristos 	retperms[0] = '\0';
1340*cc7958a0Schristos 	retperms_len = 1;
1341*cc7958a0Schristos 
1342b22328f9Schristos 	if (founduserpart)
1343b22328f9Schristos 	{
1344b22328f9Schristos 	    char *tempfperms;
1345b22328f9Schristos 	    size_t tempfperms_len;
1346b22328f9Schristos 
1347b22328f9Schristos 	    char *temp;
1348b22328f9Schristos 	    int per = 0;
1349b22328f9Schristos 	    temp = strtok (founduserpart, "!\t");
1350b22328f9Schristos 	    fperms = strtok (NULL, "!\t");
1351b22328f9Schristos 	    fperms_len = strlen (fperms);
1352b22328f9Schristos 
1353b22328f9Schristos 	    if (strncmp (fperms, "x", 1) == 0)
1354b22328f9Schristos 	    {
1355b22328f9Schristos 		err = 1;
1356b22328f9Schristos 		if (perms[0] == '+')
1357b22328f9Schristos 		    *xerrmsg = xstrdup ("cannot add default permission 'x'");
1358b22328f9Schristos 		else
1359b22328f9Schristos 		    *xerrmsg = xstrdup ("cannot remove default permission 'x'");
1360b22328f9Schristos 	    }
1361b22328f9Schristos 
1362b22328f9Schristos 	    /* go through perms */
1363b22328f9Schristos 	    for (i = 1; i < perms_len && !err; i++)
1364b22328f9Schristos 	    {
1365b22328f9Schristos 		switch (perms[i])
1366b22328f9Schristos 		{
1367b22328f9Schristos 		case 'n':
1368b22328f9Schristos 		    err = 1;
1369b22328f9Schristos 		    break;
1370b22328f9Schristos 		case 'p':
1371b22328f9Schristos 		    if (perms[0] == '+')
1372b22328f9Schristos 			fperms = xstrdup ("p");
1373b22328f9Schristos 		    else if (perms[0] == '-')
1374b22328f9Schristos 		    {
1375b22328f9Schristos 			fperms_len = 1;
1376b22328f9Schristos 			fperms = xmalloc (fperms_len);
1377b22328f9Schristos 			fperms[0] = '\0';
1378b22328f9Schristos 		    }
1379b22328f9Schristos 		    break;
1380b22328f9Schristos 		case 'a':
1381b22328f9Schristos 		    for (j = 0; j < fperms_len; j++)
1382b22328f9Schristos 		    {
1383b22328f9Schristos 			if (fperms[j] == 'p')
1384b22328f9Schristos 			{
1385b22328f9Schristos 			    err = 1;
1386b22328f9Schristos 			    *xerrmsg = xstrdup ("user have admin rights,"
1387b22328f9Schristos 						" cannot use +/- permissions");
1388b22328f9Schristos 			}
1389b22328f9Schristos 			else if (fperms[j] == 'a' && perms[0] == '+')
1390b22328f9Schristos 			{
1391b22328f9Schristos 			    err = 1;
1392b22328f9Schristos 			    *xerrmsg = xstrdup ("user already has all ('a')"
1393b22328f9Schristos 						" permission");
1394b22328f9Schristos 			}
1395b22328f9Schristos 			else if (fperms[j] != 'a' && perms[0] == '-')
1396b22328f9Schristos 			{
1397b22328f9Schristos 			    err = 1;
1398b22328f9Schristos 			    *xerrmsg = xstrdup ("user does not have all "
1399b22328f9Schristos 						"('a') permission");
1400b22328f9Schristos 			}
1401b22328f9Schristos 		    }
1402b22328f9Schristos 		    if (perms[0] == '+')
1403b22328f9Schristos 		    {
1404b22328f9Schristos 			fperms = xstrdup ("a");
1405b22328f9Schristos 			fperms_len = strlen (fperms);
1406b22328f9Schristos 		    }
1407b22328f9Schristos 		    else if (perms[0] == '-')
1408b22328f9Schristos 		    {
1409b22328f9Schristos 			fperms_len = 1;
1410b22328f9Schristos 			fperms = xmalloc (fperms_len);
1411b22328f9Schristos 			fperms[0] = '\0';
1412b22328f9Schristos 		    }
1413b22328f9Schristos 		    break;
1414b22328f9Schristos 		case 'r':
1415b22328f9Schristos 		    for (i = 0; i < fperms_len; i++)
1416b22328f9Schristos 		    {
1417b22328f9Schristos 			if (fperms[i] == 'n' && perms[0] == '+')
1418b22328f9Schristos 			{
1419b22328f9Schristos 			    fperms = xstrdup ("r");
1420b22328f9Schristos 			    fperms_len = strlen (fperms);
1421b22328f9Schristos 			}
1422b22328f9Schristos 			else if (fperms[i] == 'r' && perms[0] == '-')
1423b22328f9Schristos 			{
1424b22328f9Schristos 			    fperms_len = 1;
1425b22328f9Schristos 			    fperms = xmalloc (fperms_len);
1426b22328f9Schristos 			    fperms[0] = '\0';
1427b22328f9Schristos 			}
1428b22328f9Schristos 			else if (perms[0] == '-')
1429b22328f9Schristos 			{
1430b22328f9Schristos 			    err = 1;
1431b22328f9Schristos 			    *xerrmsg = xstrdup ("user has other permissions,"
1432b22328f9Schristos 						" cannot remove read ('r')"
1433b22328f9Schristos 						" permission");
1434b22328f9Schristos 			}
1435b22328f9Schristos 			else
1436b22328f9Schristos 			{
1437b22328f9Schristos 			    err = 1;
1438b22328f9Schristos 			    *xerrmsg = xstrdup ("user has other permissions,"
1439b22328f9Schristos 						" cannot remove read ('r')"
1440b22328f9Schristos 						" permission");
1441b22328f9Schristos 			}
1442b22328f9Schristos 		    }
1443b22328f9Schristos 		    break;
1444b22328f9Schristos 		case 'w':
1445b22328f9Schristos 		    {
1446b22328f9Schristos 			tempfperms_len = 1;
1447b22328f9Schristos 
1448b22328f9Schristos 			tempfperms = xmalloc (tempfperms_len);
1449b22328f9Schristos 			tempfperms[0] = '\0';
1450b22328f9Schristos 
1451b22328f9Schristos 			for (j = 0; j < fperms_len; j++)
1452b22328f9Schristos 			{
1453b22328f9Schristos 			    if (fperms[j] == 't' || fperms[j] == 'c' ||
1454b22328f9Schristos 				fperms[j] == 'd')
1455b22328f9Schristos 			    {
1456b22328f9Schristos 				char *temp;
1457b22328f9Schristos 				temp = xmalloc (2);
1458b22328f9Schristos 				temp[0] = fperms[j];
1459b22328f9Schristos 				temp[1] = '\0';
1460b22328f9Schristos 
1461b22328f9Schristos 				xrealloc_and_strcat (&tempfperms,
1462b22328f9Schristos 						     &tempfperms_len, temp);
1463b22328f9Schristos 				free (temp);
1464b22328f9Schristos 			    }
1465b22328f9Schristos 			    else if (fperms[j] == 'a' || fperms[j] == 'p')
1466b22328f9Schristos 			    {
1467b22328f9Schristos 				err = 1;
1468b22328f9Schristos 				*xerrmsg = xstrdup ("user has higher"
1469b22328f9Schristos 						    " permissions, cannot use"
1470b22328f9Schristos 						    " +/- write permissions");
1471b22328f9Schristos 			    }
1472b22328f9Schristos 			    else if (fperms[j] == 'n' || fperms[j] == 'r')
1473b22328f9Schristos 			    {
1474b22328f9Schristos 				if (perms[0] == '-')
1475b22328f9Schristos 				{
1476b22328f9Schristos 				    err = 1;
1477b22328f9Schristos 				    *xerrmsg = xstrdup ("user does not have"
1478b22328f9Schristos 							" write ('w')"
1479b22328f9Schristos 							" permission");
1480b22328f9Schristos 				}
1481b22328f9Schristos 			    }
1482b22328f9Schristos 			    else if (fperms[j] == 'w')
1483b22328f9Schristos 			    {
1484b22328f9Schristos 				per = 1;
1485b22328f9Schristos 				if (perms[0] == '+') {
1486b22328f9Schristos 				    err = 1;
1487b22328f9Schristos 				    *xerrmsg = xstrdup ("user already have"
1488b22328f9Schristos 							" write ('w')"
1489b22328f9Schristos 							"permission");
1490b22328f9Schristos 				}
1491b22328f9Schristos 			    }
1492b22328f9Schristos 			}
1493b22328f9Schristos 
1494*cc7958a0Schristos 			fperms = tempfperms;
1495b22328f9Schristos 			fperms_len = strlen (fperms);
1496b22328f9Schristos 
1497b22328f9Schristos 			if (!per && !err && (perms[0] == '-')) {
1498b22328f9Schristos 			    err = 1;
1499b22328f9Schristos 			    *xerrmsg = xstrdup ("user does not have write"
1500b22328f9Schristos 						" ('w') permission");
1501b22328f9Schristos 			}
1502b22328f9Schristos 
1503b22328f9Schristos 			if (perms[0] == '+')
1504b22328f9Schristos 			{
1505b22328f9Schristos 			    xrealloc_and_strcat (&fperms, &fperms_len, "w");
1506b22328f9Schristos 			}
1507b22328f9Schristos 		    }
1508b22328f9Schristos 		    break;
1509b22328f9Schristos 		case 't':
1510b22328f9Schristos 		    {
1511b22328f9Schristos 			tempfperms_len = 1;
1512b22328f9Schristos 
1513b22328f9Schristos 			tempfperms = xmalloc (tempfperms_len);
1514b22328f9Schristos 			tempfperms[0] = '\0';
1515b22328f9Schristos 
1516b22328f9Schristos 			for (j = 0; j < fperms_len; j++)
1517b22328f9Schristos 			{
1518b22328f9Schristos 			    if (fperms[j] == 'w' || fperms[j] == 'c' ||
1519b22328f9Schristos 				fperms[j] == 'd')
1520b22328f9Schristos 			    {
1521b22328f9Schristos 				char *temp;
1522b22328f9Schristos 				temp = xmalloc (2);
1523b22328f9Schristos 				temp[0] = fperms[j];
1524b22328f9Schristos 				temp[1] = '\0';
1525b22328f9Schristos 
1526b22328f9Schristos 				xrealloc_and_strcat (&tempfperms,
1527b22328f9Schristos 						     &tempfperms_len, temp);
1528b22328f9Schristos 				free (temp);
1529b22328f9Schristos 			    }
1530b22328f9Schristos 			    else if (fperms[j] == 'a' || fperms[j] == 'p')
1531b22328f9Schristos 			    {
1532b22328f9Schristos 				err = 1;
1533b22328f9Schristos 				*xerrmsg = xstrdup ("user has higher"
1534b22328f9Schristos 						    " permissions, cannot use"
1535b22328f9Schristos 						    " +/- tag permissions");
1536b22328f9Schristos 			    }
1537b22328f9Schristos 			    else if (fperms[j] == 'n' || fperms[i] == 'r')
1538b22328f9Schristos 			    {
1539b22328f9Schristos 				if (perms[0] == '-')
1540b22328f9Schristos 				    *xerrmsg = xstrdup ("user does not have tag"
1541b22328f9Schristos 							" ('t') permission");
1542b22328f9Schristos 			    }
1543b22328f9Schristos 			    else if (fperms[j] == 't')
1544b22328f9Schristos 			    {
1545b22328f9Schristos 				per = 1;
1546b22328f9Schristos 				if (perms[0] == '+')
1547b22328f9Schristos 				{
1548b22328f9Schristos 				    err = 1;
1549b22328f9Schristos 				    *xerrmsg = xstrdup ("user already have tag"
1550b22328f9Schristos 							" ('t') permission");
1551b22328f9Schristos 				}
1552b22328f9Schristos 			    }
1553b22328f9Schristos 			}
1554b22328f9Schristos 
1555*cc7958a0Schristos 			fperms = tempfperms;
1556b22328f9Schristos 			fperms_len = strlen (fperms);
1557b22328f9Schristos 
1558b22328f9Schristos 			if (!per && !err && (perms[0] == '-'))
1559b22328f9Schristos 			{
1560b22328f9Schristos 			    err = 1;
1561b22328f9Schristos 			    *xerrmsg = xstrdup ("user does not have tag ('t')"
1562b22328f9Schristos 						" permission");
1563b22328f9Schristos 			}
1564b22328f9Schristos 
1565b22328f9Schristos 			if (perms[0] == '+')
1566b22328f9Schristos 			{
1567b22328f9Schristos 			    xrealloc_and_strcat (&fperms, &fperms_len, "t");
1568b22328f9Schristos 			}
1569b22328f9Schristos 		    }
1570b22328f9Schristos 		    break;
1571b22328f9Schristos 		case 'c':
1572b22328f9Schristos 		    {
1573b22328f9Schristos 			tempfperms_len = 1;
1574b22328f9Schristos 
1575b22328f9Schristos 			tempfperms = xmalloc (tempfperms_len);
1576b22328f9Schristos 			tempfperms[0] = '\0';
1577b22328f9Schristos 
1578b22328f9Schristos 			for (j = 0; j < fperms_len; j++)
1579b22328f9Schristos 			{
1580b22328f9Schristos 			    if (fperms[j] == 'w' || fperms[j] == 't' ||
1581b22328f9Schristos 				fperms[j] == 'd')
1582b22328f9Schristos 			    {
1583b22328f9Schristos 				char *temp;
1584b22328f9Schristos 				temp = xmalloc (2);
1585b22328f9Schristos 				temp[0] = fperms[j];
1586b22328f9Schristos 				temp[1] = '\0';
1587b22328f9Schristos 
1588b22328f9Schristos 				xrealloc_and_strcat (&tempfperms,
1589b22328f9Schristos 						     &tempfperms_len, temp);
1590b22328f9Schristos 				free (temp);
1591b22328f9Schristos 			    }
1592b22328f9Schristos 			    else if (fperms[j] == 'a' || fperms[j] == 'p')
1593b22328f9Schristos 			    {
1594b22328f9Schristos 				err = 1;
1595b22328f9Schristos 				*xerrmsg = xstrdup ("user has higher"
1596b22328f9Schristos 						    " permissions, cannot use"
1597b22328f9Schristos 						    " +/- create permissions");
1598b22328f9Schristos 			    }
1599b22328f9Schristos 			    else if (fperms[j] == 'n' || fperms[i] == 'r')
1600b22328f9Schristos 			    {
1601b22328f9Schristos 				if (perms[0] == '-')
1602b22328f9Schristos 				    err = 1;
1603b22328f9Schristos 				*xerrmsg = xstrdup ("user does not have create"
1604b22328f9Schristos 						    " ('c') permission");
1605b22328f9Schristos 			    }
1606b22328f9Schristos 			    else if (fperms[j] == 'c')
1607b22328f9Schristos 			    {
1608b22328f9Schristos 				per = 1;
1609b22328f9Schristos 				if (perms[0] == '+') {
1610b22328f9Schristos 				    err = 1;
1611b22328f9Schristos 				    *xerrmsg = xstrdup ("user already have"
1612b22328f9Schristos 							" create ('c')"
1613b22328f9Schristos 							" permission");
1614b22328f9Schristos 				}
1615b22328f9Schristos 			    }
1616b22328f9Schristos 			}
1617b22328f9Schristos 
1618*cc7958a0Schristos 			fperms = tempfperms;
1619b22328f9Schristos 			fperms_len = strlen (fperms);
1620b22328f9Schristos 
1621b22328f9Schristos 			if (!per && !err && (perms[0] == '-')) {
1622b22328f9Schristos 			    err = 1;
1623b22328f9Schristos 			    *xerrmsg = xstrdup ("user does not have create"
1624b22328f9Schristos 						" ('c') permission");
1625b22328f9Schristos 			}
1626b22328f9Schristos 
1627b22328f9Schristos 			if (perms[0] == '+')
1628b22328f9Schristos 			{
1629b22328f9Schristos 			    xrealloc_and_strcat (&fperms, &fperms_len, "c");
1630b22328f9Schristos 			}
1631b22328f9Schristos 		    }
1632b22328f9Schristos 		    break;
1633b22328f9Schristos 		case 'd':
1634b22328f9Schristos 		    {
1635b22328f9Schristos 			tempfperms_len = 1;
1636b22328f9Schristos 
1637b22328f9Schristos 			tempfperms = xmalloc (tempfperms_len);
1638b22328f9Schristos 			tempfperms[0] = '\0';
1639b22328f9Schristos 
1640b22328f9Schristos 			for (j = 0; j < fperms_len; j++)
1641b22328f9Schristos 			{
1642b22328f9Schristos 			    if (fperms[j] == 'w' || fperms[j] == 'c' ||
1643b22328f9Schristos 				fperms[j] == 't')
1644b22328f9Schristos 			    {
1645b22328f9Schristos 				char *temp;
1646b22328f9Schristos 				temp = xmalloc (2);
1647b22328f9Schristos 				temp[0] = fperms[j];
1648b22328f9Schristos 				temp[1] = '\0';
1649b22328f9Schristos 
1650b22328f9Schristos 				xrealloc_and_strcat (&tempfperms,
1651b22328f9Schristos 						     &tempfperms_len, temp);
1652b22328f9Schristos 				free (temp);
1653b22328f9Schristos 			    }
1654b22328f9Schristos 			    else if (fperms[j] == 'a' || fperms[j] == 'p')
1655b22328f9Schristos 			    {
1656b22328f9Schristos 				err = 1;
1657b22328f9Schristos 				*xerrmsg = xstrdup ("user has higher"
1658b22328f9Schristos 						    " permissions, cannot use"
1659b22328f9Schristos 						    " +/- delete permissions");
1660b22328f9Schristos 			    }
1661b22328f9Schristos 			    else if (fperms[j] == 'n' || fperms[i] == 'r')
1662b22328f9Schristos 			    {
1663b22328f9Schristos 				if (perms[0] == '-')
1664b22328f9Schristos 				    err = 1;
1665b22328f9Schristos 				*xerrmsg = xstrdup ("user does not have delete"
1666b22328f9Schristos 						    " ('d') permission");
1667b22328f9Schristos 			    }
1668b22328f9Schristos 			    else if (fperms[j] == 'd')
1669b22328f9Schristos 			    {
1670b22328f9Schristos 				per = 1;
1671b22328f9Schristos 				if (perms[0] == '+') {
1672b22328f9Schristos 				    err = 1;
1673b22328f9Schristos 				    *xerrmsg = xstrdup ("user already have"
1674b22328f9Schristos 							" delete ('d')"
1675b22328f9Schristos 							" permission");
1676b22328f9Schristos 				}
1677b22328f9Schristos 			    }
1678b22328f9Schristos 			}
1679b22328f9Schristos 
1680*cc7958a0Schristos 			fperms = tempfperms;
1681b22328f9Schristos 			fperms_len = strlen (fperms);
1682b22328f9Schristos 
1683b22328f9Schristos 			if (!per && !err && (perms[0] == '-')) {
1684b22328f9Schristos 				err = 1;
1685b22328f9Schristos 				*xerrmsg = xstrdup ("user does not have delete"
1686b22328f9Schristos 						    " ('d') permission");
1687b22328f9Schristos 			}
1688b22328f9Schristos 
1689b22328f9Schristos 			if (perms[0] == '+')
1690b22328f9Schristos 			{
1691b22328f9Schristos 				xrealloc_and_strcat (&fperms, &fperms_len, "d");
1692b22328f9Schristos 			}
1693b22328f9Schristos 		    }
1694b22328f9Schristos 		    break;
1695b22328f9Schristos 		default:
1696b22328f9Schristos 		    err  = 1;
1697b22328f9Schristos 		    *xerrmsg = xstrdup ("error in 'access' file format");
1698b22328f9Schristos 		    break;
1699b22328f9Schristos 		}
1700b22328f9Schristos 
1701b22328f9Schristos 		if (fperms[0] == '\0')
1702b22328f9Schristos 		    retperms = xstrdup ("none");
1703b22328f9Schristos 		else
1704b22328f9Schristos 		    retperms = xstrdup (fperms);
1705b22328f9Schristos 	    }
1706b22328f9Schristos 	}
1707b22328f9Schristos 	else
1708b22328f9Schristos 	{
1709b22328f9Schristos 	    err = 1;
1710b22328f9Schristos 	    *xerrmsg = xstrdup("user is not given any permissions to remove/add");
1711b22328f9Schristos 	}
1712b22328f9Schristos     }
1713b22328f9Schristos     else
1714b22328f9Schristos     {
1715b22328f9Schristos 	retperms = xstrdup (perms);
1716b22328f9Schristos     }
1717*cc7958a0Schristos     if (fperms)
1718*cc7958a0Schristos 	free (fperms);
1719*cc7958a0Schristos     if (err && retperms)
1720*cc7958a0Schristos 	free (retperms);
1721b22328f9Schristos 
1722b22328f9Schristos     return (err ? NULL : retperms);
1723b22328f9Schristos }
1724b22328f9Schristos 
1725b22328f9Schristos /* prepare and write resulting permissions to access file */
1726b22328f9Schristos static int
1727b22328f9Schristos write_perms (const char *user, const char *perms, const char *founduserpart,
1728b22328f9Schristos 	     int foundline, char *otheruserparts,
1729b22328f9Schristos 	     const char *part_type, const char *part_object,
1730b22328f9Schristos 	     const char *part_tag, int pos, const char *arepos)
1731b22328f9Schristos {
1732b22328f9Schristos     char *accessfile;
1733b22328f9Schristos     char *tmpaccessout;
1734b22328f9Schristos     FILE *accessfpin;
1735b22328f9Schristos     FILE *accessfpout;
1736b22328f9Schristos 
1737b22328f9Schristos     char *newline = NULL;
1738b22328f9Schristos     size_t newlinelen = 1;
1739b22328f9Schristos     char *object;
1740b22328f9Schristos 
1741b22328f9Schristos     char *line = NULL;
1742b22328f9Schristos     size_t line_allocated = 0;
1743b22328f9Schristos 
1744b22328f9Schristos     newline = xmalloc (newlinelen);
1745b22328f9Schristos     newline[0] = '\0';
1746b22328f9Schristos 
1747b22328f9Schristos     if (!strcasecmp (part_tag, "ALL"))
1748b22328f9Schristos 	part_tag = "ALL";
1749b22328f9Schristos 
1750b22328f9Schristos     /* strip any trailing slash if found */
1751b22328f9Schristos     object = xstrdup (part_object);
1752b22328f9Schristos     if (object[strlen (object) - 1] == '/')
1753b22328f9Schristos 	object[strlen (object) - 1] = '\0';
1754b22328f9Schristos 
1755b22328f9Schristos     /* first parts, part type, object, and tag */
1756b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, part_type);
1757b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, ":");
1758b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, object);
1759b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, ":");
1760b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, part_tag);
1761b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, ":");
1762b22328f9Schristos 
1763b22328f9Schristos     if (strncmp (perms, "none", 4) != 0)
1764b22328f9Schristos     {
1765b22328f9Schristos 	xrealloc_and_strcat (&newline, &newlinelen, user);
1766b22328f9Schristos 	xrealloc_and_strcat (&newline, &newlinelen, "!");
1767b22328f9Schristos 	xrealloc_and_strcat (&newline, &newlinelen, perms);
1768b22328f9Schristos 	if (otheruserparts != NULL)
1769b22328f9Schristos 	    xrealloc_and_strcat (&newline, &newlinelen, ",");
1770b22328f9Schristos     }
1771b22328f9Schristos 
1772b22328f9Schristos     if (otheruserparts != NULL)
1773b22328f9Schristos     {
1774b22328f9Schristos 	if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
1775b22328f9Schristos 	    otheruserparts[strlen (otheruserparts) - 1] = '\0';
1776b22328f9Schristos 
1777b22328f9Schristos 	xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
1778b22328f9Schristos     }
1779b22328f9Schristos 
1780b22328f9Schristos     xrealloc_and_strcat (&newline, &newlinelen, ":");
1781b22328f9Schristos 
1782b22328f9Schristos     if (foundline)
1783b22328f9Schristos     {
1784b22328f9Schristos 	accessfpout = cvs_temp_file (&tmpaccessout);
1785b22328f9Schristos 	if (accessfpout == NULL)
1786b22328f9Schristos 	    error (1, errno, "cannot open temporary file: %s", tmpaccessout);
1787b22328f9Schristos 
1788b22328f9Schristos 	accessfpin = open_accessfile ("r", arepos, &accessfile);
1789b22328f9Schristos 	if (accessfpout == NULL)
1790b22328f9Schristos 	    error (1, errno, "cannot open access file: %s", accessfile);
1791b22328f9Schristos 
1792b22328f9Schristos 	while (getline (&line, &line_allocated, accessfpin) >= 0)
1793b22328f9Schristos 	{
1794b22328f9Schristos 	    if (pos != ftell (accessfpin))
1795b22328f9Schristos 	    {
1796b22328f9Schristos 		if (fprintf (accessfpout, "%s", line) < 0)
1797b22328f9Schristos 		    error (1, errno, "writing temporary file: %s", tmpaccessout);
1798b22328f9Schristos 	    }
1799b22328f9Schristos 	    else
1800b22328f9Schristos 	    {
1801b22328f9Schristos 		if (fprintf (accessfpout, "%s\n", newline) < 0)
1802b22328f9Schristos 		    error (1, errno, "writing temporary file: %s", tmpaccessout);
1803b22328f9Schristos 	    }
1804b22328f9Schristos 
1805b22328f9Schristos 	}
1806b22328f9Schristos 	if (fclose (accessfpin) == EOF)
1807b22328f9Schristos 		error (1, errno, "cannot close access file: %s", accessfile);
1808b22328f9Schristos 
1809b22328f9Schristos 	if (fclose (accessfpout) == EOF)
1810b22328f9Schristos 	    error (1, errno, "cannot close temporary file: %s", tmpaccessout);
1811b22328f9Schristos 
1812b22328f9Schristos 	if (CVS_UNLINK (accessfile) < 0)
1813b22328f9Schristos 	    error (0, errno, "cannot remove %s", accessfile);
1814b22328f9Schristos 
1815b22328f9Schristos 	copy_file (tmpaccessout, accessfile);
1816b22328f9Schristos 
1817b22328f9Schristos 	if (CVS_UNLINK (tmpaccessout) < 0)
1818b22328f9Schristos 	    error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
1819b22328f9Schristos     }
1820b22328f9Schristos     else
1821b22328f9Schristos     {
1822b22328f9Schristos 	accessfpout = open_accessfile ("r+", arepos, &accessfile);
1823b22328f9Schristos 
1824b22328f9Schristos 	if (accessfpout == NULL)
1825b22328f9Schristos 	{
1826b22328f9Schristos 	    if (existence_error (errno))
1827b22328f9Schristos 	    {
1828b22328f9Schristos 		accessfpout = open_accessfile ("w+", arepos, &accessfile);
1829b22328f9Schristos 	    }
1830b22328f9Schristos 	    if (accessfpout == NULL)
1831b22328f9Schristos 		error (1, errno, "cannot open access file: %s", accessfile);
1832b22328f9Schristos 	}
1833b22328f9Schristos 	else {
1834b22328f9Schristos 	    if (fseek (accessfpout, 0, 2) != 0)
1835b22328f9Schristos 		error (1, errno, "cannot fseek access file: %s", accessfile);
1836b22328f9Schristos 	}
1837b22328f9Schristos 
1838b22328f9Schristos 	if (fprintf (accessfpout, "%s\n", newline) < 0)
1839b22328f9Schristos 	    error (1, errno, "writing access file: %s", accessfile);
1840b22328f9Schristos 
1841b22328f9Schristos 	if (fclose (accessfpout) == EOF)
1842b22328f9Schristos 	    error (1, errno, "cannot close access file: %s", accessfile);
1843b22328f9Schristos     }
1844b22328f9Schristos 
1845b22328f9Schristos     free (line);
1846b22328f9Schristos     free (newline);
1847b22328f9Schristos 
1848b22328f9Schristos     chmod (accessfile, 0644);
1849b22328f9Schristos 
1850b22328f9Schristos     return 0;
1851b22328f9Schristos }
1852b22328f9Schristos 
1853b22328f9Schristos static int
1854b22328f9Schristos acllist_fileproc (void *callerdat, struct file_info *finfo)
1855b22328f9Schristos {
1856b22328f9Schristos     char *filefullname;
1857b22328f9Schristos     const char *frepository;
1858b22328f9Schristos     char *line = NULL;
1859b22328f9Schristos     int pos;
1860b22328f9Schristos 
1861b22328f9Schristos     if (!aclfile)
1862b22328f9Schristos 	return 0;
1863b22328f9Schristos 
1864b22328f9Schristos     frepository = Short_Repository (finfo->repository);
1865b22328f9Schristos 
1866b22328f9Schristos     filefullname = Xasprintf("%s/%s", frepository, finfo->file);
1867b22328f9Schristos 
1868b22328f9Schristos     /* check that user, which run acl/racl command, has admin permisson,
1869b22328f9Schristos      * and also return the line with permissions from access file.  */
1870b22328f9Schristos     if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos,
1871b22328f9Schristos 			 0))
1872b22328f9Schristos 	error (1, 0, "You do not have admin rights on '%s'", frepository);
1873b22328f9Schristos 
1874b22328f9Schristos     acllist_print (line, filefullname);
1875b22328f9Schristos 
1876b22328f9Schristos     free (filefullname);
1877b22328f9Schristos 
1878b22328f9Schristos     return 0;
1879b22328f9Schristos }
1880b22328f9Schristos 
1881b22328f9Schristos static Dtype
1882b22328f9Schristos acllist_dirproc (void *callerdat, const char *dir, const char *repos,
1883b22328f9Schristos 		 const char *update_dir, List *entries)
1884b22328f9Schristos {
1885b22328f9Schristos     char *line = NULL;
1886b22328f9Schristos     const char *drepository;
1887b22328f9Schristos     int pos;
1888b22328f9Schristos 
1889b22328f9Schristos     if (repos[0] == '\0')
1890b22328f9Schristos 	repos = Name_Repository (dir, NULL);
1891b22328f9Schristos 
1892b22328f9Schristos     if (!acldir)
1893b22328f9Schristos 	return 0;
1894b22328f9Schristos 
1895b22328f9Schristos     drepository = Short_Repository (repos);
1896b22328f9Schristos 
1897b22328f9Schristos     /* check that user, which run acl/racl command, has admin permisson,
1898b22328f9Schristos      * and also return the line with permissions from access file.  */
1899b22328f9Schristos     if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
1900b22328f9Schristos 	error (1, 0, "You do not have admin rights on '%s'", drepository);
1901b22328f9Schristos 
1902b22328f9Schristos     acllist_print (line, drepository);
1903b22328f9Schristos 
1904b22328f9Schristos     return 0;
1905b22328f9Schristos }
1906b22328f9Schristos 
1907b22328f9Schristos /* Prints permissions to screen with -l option */
1908b22328f9Schristos void
1909b22328f9Schristos acllist_print (char *line, const char *obj)
1910b22328f9Schristos {
1911b22328f9Schristos     char *temp;
1912b22328f9Schristos     int c = 0;
1913b22328f9Schristos     int def = 0;
1914b22328f9Schristos 
1915b22328f9Schristos     char *printedusers[255];
1916b22328f9Schristos     printedusers[0] = NULL;
1917b22328f9Schristos 
1918b22328f9Schristos     if (line != NULL)
1919b22328f9Schristos     {
1920b22328f9Schristos 	temp = strtok (line, ":\t");
1921b22328f9Schristos 
1922b22328f9Schristos 	if (acldir)
1923b22328f9Schristos 	    cvs_output ("d ", 0);
1924b22328f9Schristos 	else if (aclfile)
1925b22328f9Schristos 	    cvs_output ("f ", 0);
1926b22328f9Schristos 
1927b22328f9Schristos 	temp = strtok (NULL, ":\t");
1928b22328f9Schristos 
1929b22328f9Schristos 	cvs_output(obj, 0);
1930b22328f9Schristos 	cvs_output (" | ", 0);
1931b22328f9Schristos 
1932b22328f9Schristos 	temp = strtok (NULL, ":\t");
1933b22328f9Schristos 	cvs_output (temp, 0);
1934b22328f9Schristos 	cvs_output (" | ", 0);
1935b22328f9Schristos 
1936b22328f9Schristos 	while ((temp = strtok (NULL, "!\t")) != NULL)
1937b22328f9Schristos 	{
1938b22328f9Schristos 	    if (strncmp (temp, ":", 1) == 0)
1939b22328f9Schristos 		break;
1940b22328f9Schristos 
1941b22328f9Schristos 	    if (strcmp (temp, "ALL") == 0)
1942b22328f9Schristos 	    {
1943b22328f9Schristos 		temp = strtok (NULL, ",\t");
1944b22328f9Schristos 		continue;
1945b22328f9Schristos 	    }
1946b22328f9Schristos 
1947b22328f9Schristos 	    cvs_output (temp, 0);
1948b22328f9Schristos 	    cvs_output (":", 0);
1949b22328f9Schristos 
1950b22328f9Schristos 	    while (printedusers[c] != NULL)
1951b22328f9Schristos 		c++;
1952b22328f9Schristos 
1953b22328f9Schristos 	    printedusers[c] = xstrdup (temp);
1954b22328f9Schristos 	    c++;
1955b22328f9Schristos 	    printedusers[c] = NULL;
1956b22328f9Schristos 
1957b22328f9Schristos 	    temp = strtok (NULL, ",\t");
1958b22328f9Schristos 
1959b22328f9Schristos 	    if (temp != NULL && temp[strlen (temp) - 2] == ':')
1960b22328f9Schristos 		temp[strlen (temp) - 2] = '\0';
1961b22328f9Schristos 
1962b22328f9Schristos 	    cvs_output (temp, 0);
1963b22328f9Schristos 	    cvs_output (" ", 0);
1964b22328f9Schristos 	}
1965b22328f9Schristos 
1966b22328f9Schristos 	if (default_perms_object)
1967b22328f9Schristos 	{
1968b22328f9Schristos 	    cvs_output ("| defaults ", 0);
1969b22328f9Schristos 	    cvs_output ("ALL:", 0);
1970b22328f9Schristos 	    cvs_output (default_perms_object, 0);
1971b22328f9Schristos 	    def = 1;
1972b22328f9Schristos 	}
1973b22328f9Schristos 	if (default_part_perms_accessfile)
1974b22328f9Schristos 	{
1975b22328f9Schristos 	    size_t i;
1976b22328f9Schristos 	    i = strlen (default_part_perms_accessfile);
1977b22328f9Schristos 	    xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
1978b22328f9Schristos 
1979b22328f9Schristos 	    free (line);
1980b22328f9Schristos 	    line = xstrdup (default_part_perms_accessfile);
1981b22328f9Schristos 
1982b22328f9Schristos 	    if (!def)
1983b22328f9Schristos 		cvs_output ("| defaults ", 0);
1984b22328f9Schristos 	    else
1985b22328f9Schristos 		cvs_output (" ", 0);
1986b22328f9Schristos 
1987b22328f9Schristos 	    temp = strtok (line, "!\t");
1988b22328f9Schristos 	    cvs_output (temp, 0);
1989b22328f9Schristos 	    cvs_output (":", 0);
1990b22328f9Schristos 
1991b22328f9Schristos 	    temp = strtok (NULL, ",\t");
1992b22328f9Schristos 
1993b22328f9Schristos 	    cvs_output (temp, 0);
1994b22328f9Schristos 	    cvs_output (" ", 0);
1995b22328f9Schristos 
1996b22328f9Schristos 	    while ((temp = strtok (NULL, "!\t")) != NULL)
1997b22328f9Schristos 	    {
1998b22328f9Schristos 		int printed = 0;
1999b22328f9Schristos 		int c2 = 0;
2000b22328f9Schristos 		while (printedusers[c2] != NULL && printed == 0)
2001b22328f9Schristos 		{
2002b22328f9Schristos 		    if (strcmp (printedusers[c2], temp) == 0)
2003b22328f9Schristos 		    {
2004b22328f9Schristos 			printed = 1;
2005b22328f9Schristos 			break;
2006b22328f9Schristos 		    }
2007b22328f9Schristos 		    c2++;
2008b22328f9Schristos 		}
2009b22328f9Schristos 
2010b22328f9Schristos 		if (printed == 0)
2011b22328f9Schristos 		{
2012b22328f9Schristos 		    cvs_output (temp, 0);
2013b22328f9Schristos 		    cvs_output (":", 0);
2014b22328f9Schristos 		}
2015b22328f9Schristos 
2016b22328f9Schristos 		temp = strtok (NULL, ",\t");
2017b22328f9Schristos 
2018b22328f9Schristos 		if (temp[strlen (temp) - 2] == ':')
2019b22328f9Schristos 		    temp[strlen (temp) - 2] = '\0';
2020b22328f9Schristos 
2021b22328f9Schristos 		if (printed == 0)
2022b22328f9Schristos 		{
2023b22328f9Schristos 		    cvs_output (temp, 0);
2024b22328f9Schristos 		    cvs_output (" ", 0);
2025b22328f9Schristos 		}
2026b22328f9Schristos 	    }
2027b22328f9Schristos 	    def = 1;
2028b22328f9Schristos 	}
2029b22328f9Schristos 	else if (cvs_acl_default_permissions)
2030b22328f9Schristos 	{
2031b22328f9Schristos 	    cvs_output ("| defaults ", 0);
2032b22328f9Schristos 	    cvs_output ("ALL: ", 0);
2033b22328f9Schristos 	    cvs_output (cvs_acl_default_permissions, 0);
2034b22328f9Schristos 	}
2035b22328f9Schristos     }
2036b22328f9Schristos     else
2037b22328f9Schristos     {
2038b22328f9Schristos 	if (acldir)
2039b22328f9Schristos 	    cvs_output ("d ", 0);
2040b22328f9Schristos 	else if (aclfile)
2041b22328f9Schristos 	    cvs_output ("f ", 0);
2042b22328f9Schristos 	cvs_output (obj, 0);
2043b22328f9Schristos 	cvs_output (" | ", 0);
2044b22328f9Schristos 	cvs_output (tag, 0);
2045b22328f9Schristos 	cvs_output (" | ", 0);
2046b22328f9Schristos 
2047b22328f9Schristos 	if (default_perms_object)
2048b22328f9Schristos 	{
2049b22328f9Schristos 	    cvs_output ("| defaults ", 0);
2050b22328f9Schristos 	    cvs_output ("ALL:", 0);
2051b22328f9Schristos 	    cvs_output (default_perms_object, 0);
2052b22328f9Schristos 	    def = 1;
2053b22328f9Schristos 	}
2054b22328f9Schristos 	if (default_part_perms_accessfile)
2055b22328f9Schristos 	{
2056b22328f9Schristos 	    free (line);
2057b22328f9Schristos 	    line = xstrdup (default_part_perms_accessfile);
2058b22328f9Schristos 
2059b22328f9Schristos 	    if (!def)
2060b22328f9Schristos 		cvs_output ("| defaults ", 0);
2061b22328f9Schristos 	    else
2062b22328f9Schristos 		cvs_output (" ", 0);
2063b22328f9Schristos 
2064b22328f9Schristos 	    temp = strtok (line, "!\t");
2065b22328f9Schristos 	    cvs_output (temp, 0);
2066b22328f9Schristos 	    cvs_output (":", 0);
2067b22328f9Schristos 
2068b22328f9Schristos 	    temp = strtok (NULL, ",\t");
2069b22328f9Schristos 
2070b22328f9Schristos 	    if (temp[strlen (temp) - 2] == ':')
2071b22328f9Schristos 		temp[strlen (temp) - 2] = '\0';
2072b22328f9Schristos 
2073b22328f9Schristos 	    cvs_output (temp, 0);
2074b22328f9Schristos 	    cvs_output (" ", 0);
2075b22328f9Schristos 
2076b22328f9Schristos 	    while ((temp = strtok (NULL, "!\t")) != NULL)
2077b22328f9Schristos 	    {
2078b22328f9Schristos 		cvs_output (temp, 0);
2079b22328f9Schristos 		cvs_output (":", 0);
2080b22328f9Schristos 
2081b22328f9Schristos 		if ((temp = strtok (NULL, ",\t")) != NULL)
2082b22328f9Schristos 		{
2083b22328f9Schristos 		    if (temp[strlen (temp) - 2] == ':')
2084b22328f9Schristos 			temp[strlen (temp) - 2] = '\0';
2085b22328f9Schristos 
2086b22328f9Schristos 		    cvs_output (temp, 0);
2087b22328f9Schristos 		    cvs_output (" ", 0);
2088b22328f9Schristos 		}
2089b22328f9Schristos 	    }
2090b22328f9Schristos 	    cvs_output ("\n", 0);
2091b22328f9Schristos 	}
2092b22328f9Schristos 	else if (cvs_acl_default_permissions)
2093b22328f9Schristos 	{
2094b22328f9Schristos 	    cvs_output ("| defaults ", 0);
2095b22328f9Schristos 	    cvs_output ("ALL: ", 0);
2096b22328f9Schristos 	    cvs_output (cvs_acl_default_permissions, 0);
2097b22328f9Schristos 	}
2098b22328f9Schristos 	else
2099b22328f9Schristos 	    cvs_output ("default:p (no perms)", 0);
2100b22328f9Schristos     }
2101b22328f9Schristos     cvs_output ("\n", 0);
2102b22328f9Schristos 
2103b22328f9Schristos     while (c >= 0)  {
2104b22328f9Schristos 	free (printedusers[c]);
2105b22328f9Schristos 	c--;
2106b22328f9Schristos     }
2107b22328f9Schristos 
2108b22328f9Schristos     free (line);
2109b22328f9Schristos }
2110b22328f9Schristos 
2111b22328f9Schristos /* find username
2112b22328f9Schristos  * returns username with its permissions if user found
2113b22328f9Schristos  * returns NULL if user not found */
2114b22328f9Schristos char *findusername (const char *string1, const char *string2)
2115b22328f9Schristos {
2116b22328f9Schristos     char *tmp1, *tmp2;
2117b22328f9Schristos 
2118b22328f9Schristos     if (string1 != NULL && string2 != NULL)
2119b22328f9Schristos     {
2120b22328f9Schristos 	tmp1 = xstrdup (string1);
2121b22328f9Schristos 	tmp2 = strtok (tmp1, ",\t");
2122b22328f9Schristos 
2123b22328f9Schristos 	do
2124b22328f9Schristos 	{
2125b22328f9Schristos 	    if (strncmp (tmp2, string2, strlen (string2)) == 0 &&
2126b22328f9Schristos 				     tmp2[strlen (string2)] == '!')
2127b22328f9Schristos 	    {
2128*cc7958a0Schristos 		tmp2 = xstrdup (tmp2);
2129*cc7958a0Schristos 		free (tmp1);
2130b22328f9Schristos 		return tmp2;
2131b22328f9Schristos 	    }
2132b22328f9Schristos 	    tmp2 = strtok (NULL, ",\t");
2133b22328f9Schristos 	}
2134b22328f9Schristos 	while (tmp2 != NULL);
2135b22328f9Schristos 
2136b22328f9Schristos 	free (tmp1);
2137b22328f9Schristos 
2138b22328f9Schristos 	return NULL;
2139b22328f9Schristos     }
2140b22328f9Schristos     else
2141b22328f9Schristos 	return NULL;
2142b22328f9Schristos }
2143b22328f9Schristos 
2144b22328f9Schristos /* find user name in group file
2145b22328f9Schristos  * returns group name if user found
2146b22328f9Schristos  * returns NULL if user not found */
2147b22328f9Schristos char *findgroupname (const char *string1, const char *string2)
2148b22328f9Schristos {
2149b22328f9Schristos     char *tmp1, *tmp2;
2150b22328f9Schristos     char *grpname;
2151b22328f9Schristos 
2152b22328f9Schristos     if (string1 != NULL && string2 != NULL)
2153b22328f9Schristos     {
2154b22328f9Schristos 	tmp1 = xstrdup (string1);
2155b22328f9Schristos 	grpname = strtok (tmp1, ":\t");
2156b22328f9Schristos 
2157b22328f9Schristos 	while (tmp2 = strtok(NULL, ",\t"))
2158b22328f9Schristos 	{
2159b22328f9Schristos 	    if (strcmp (tmp2, string2) == 0)
2160b22328f9Schristos 	    {
2161*cc7958a0Schristos 		grpname = xstrdup (grpname);
2162*cc7958a0Schristos 		free (tmp1);
2163b22328f9Schristos 		return grpname;
2164b22328f9Schristos 	    }
2165b22328f9Schristos 	}
2166b22328f9Schristos 
2167b22328f9Schristos 	free (tmp1);
2168b22328f9Schristos 
2169b22328f9Schristos 	return NULL;
2170b22328f9Schristos     }
2171b22328f9Schristos     else
2172b22328f9Schristos 	return NULL;
2173b22328f9Schristos }
2174