]> git.pld-linux.org Git - packages/cvs.git/blame - cvs-acl.patch
- rel 1 for RA, 2 for AC
[packages/cvs.git] / cvs-acl.patch
CommitLineData
09f63587 1diff -urN cvs-1.11.15/aclconfig.default cvs-1.11.15-cvsacl/aclconfig.default
2--- cvs-1.11.15/aclconfig.default 1970-01-01 01:00:00.000000000 +0100
3+++ cvs-1.11.15-cvsacl/aclconfig.default 2004-04-25 20:04:51.637863856 +0200
4@@ -0,0 +1,33 @@
5+# Set `UseCVSACL' to yes to use CVS ACL feature.
6+UseCVSACL=yes
7+
8+# Default CVS ACL Permission are to use.
9+#CVSACLDefaultPermissions=a
10+
11+# Default file location for CVS ACL file (access) is CVSROOT/access.
12+# If you want to use a different location, define it below.
13+#CVSACLFileLocation=/path/to/cvs/access
14+
15+# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).
16+UseSystemGroups=yes
17+
18+# Set `UseCVSGroups' to yes to use another group file.
19+#UseCVSGroups=yes
20+
21+# Default file location for CVS groups file is CVSROOT/group.
22+# If you want to use a different location, define it below.
23+#CVSGroupsFileLocation=/path/to/cvs/group
24+
25+# Set UseSeperateACLFileForEachDir to yes in order to use a
26+# seperate 'access' file for each directory.
27+# This increased the performance if you have really big repository.
28+#UseSeperateACLFileForEachDir=no
29+
30+# If StopAtFirstPermissionDenied is set to yes
31+# operation will stop at first permission denied message.
32+# Default is no.
33+#StopAtFirstPermissionDenied=no
34+
35+# Set CVSServerRunAsUser to a system user, in order CVS server
36+# to run as.
37+#CVSServerRunAsUser=runascvsuser
38diff -urN cvs-1.11.15/CHANGELOG.cvsacl cvs-1.11.15-cvsacl/CHANGELOG.cvsacl
39--- cvs-1.11.15/CHANGELOG.cvsacl 1970-01-01 01:00:00.000000000 +0100
40+++ cvs-1.11.15-cvsacl/CHANGELOG.cvsacl 2004-04-25 20:04:51.660860360 +0200
41@@ -0,0 +1,12 @@
42+Release 1.2.0
43+ - implemented permission inheritance from parents.
44+ - new config keyword: StopAtFirstPermissionDenied.
45+ - fixed some errors.
46+
47+Release 1.1.3
48+ - fixed a bug related with default permissions.
49+ - fixed a bug related with setting permissions using + - signs.
50+
51+Release 1.1.2
52+ - fixed bugs reported on sourceforge.
53+
54diff -urN cvs-1.11.15/INSTALL.cvsacl cvs-1.11.15-cvsacl/INSTALL.cvsacl
55--- cvs-1.11.15/INSTALL.cvsacl 1970-01-01 01:00:00.000000000 +0100
56+++ cvs-1.11.15-cvsacl/INSTALL.cvsacl 2004-04-25 20:04:51.661860208 +0200
57@@ -0,0 +1,23 @@
58+
59+Installation
60+
61+- copy the file acl.c under src directory of CVS source distribution.
62+ "cp acl.c /path/to/cvs-1.11.14/src/"
63+- copy the patch file cvsacl-patch-1.2.0.beta2 under CVS source distribution
64+ directory.
65+ "cp cvsacl-patch-1.2.0.beta2 /path/to/cvs-1.11.14/"
66+- cd to CVS source directory.
67+ "cd /path/to/cvs-1.11.14/"
68+- apply the patch.
69+ "patch -p0 < cvsacl-patch-1.2.0.beta2"
70+- if you are initializing the repository after applying patch, related
71+ config files will be created with init command.
72+ "cvs -d /path/to/repository init"
73+- if you already have a repository, you have to add the aclconfig file
74+ to your $CVSROOT/CVSROOT/. aclconfig.default is the default configuration
75+ file, you can rename it to aclconfig, and use it .
76+- modify aclconfig file, if you need to change some options.
77+- as the last step, you have to define yourself as acl administrator.
78+ "cvs -d /path/to/repository racl yourname:p -r ALL -d ALL"
79+ this command gives p (acl admin) rights to user (yourname),
80+ on all repository and tags/branches.
81diff -urN cvs-1.11.15/README.cvsacl cvs-1.11.15-cvsacl/README.cvsacl
82--- cvs-1.11.15/README.cvsacl 1970-01-01 01:00:00.000000000 +0100
83+++ cvs-1.11.15-cvsacl/README.cvsacl 2004-04-25 20:04:51.666859448 +0200
84@@ -0,0 +1,282 @@
85+
86+CVS Access Control List Extension Patch
87+
88+http://cvsacl.sourceforge.net/
89+sbaris@users.sourceforge.net
90+
91+CVSACL is a patch for CVS. It adds two new subcommands
92+(acl & racl) to cvs for access control list management. It
93+provides advanced ACL definitions per modules, directories,
94+and files on branch/tag for remote cvs repository connections.
95+Execution of all CVS subcommands can be controlled with eight
96+different permissions.
97+ACL definitions works for only remote connections, local users
98+can access and modify repository, if unix file system permissions
99+allow. If you want all users to make remote connections to
100+repository, and not allow local users to access repository, you
101+have to set CVSServerRunAsUser keyword in aclconfig file
102+(explained below).
103+Still local users can use acl and racl subcommands to set
104+permissions on directories or files if they have acl admin rights (p)
105+on related directories or files.
106+So, in order to control all access to repository with this ACL
107+extension, you should use CVSServerRunAsUser keyword and force all
108+users to make remote connections. CVS repository administrator or
109+project managers have to use acl and racl subcommands to manage
110+permissions. But there is no gui client supporting these subcommands,
111+so you have to use cvs client itself either locally or remotely.
112+
113+
114+
115+
116+Permission Types
117+
118+- no access
119+ Command line character: n
120+ If a user given n permission, it is not allowed for any action on repository.
121+- read
122+ Command line character: r
123+ r permission gives only read access on repository.
124+ With r permission you are allowed to run cvs subcommands: annotate,
125+ checkout, diff, export, log, rannotate, rdiff, rlog, status.
126+- write
127+ Command line character: w
128+ w permission allows only cvs commit/checkin action.
129+ With w permission, you are not allowed to add/remove any file to/from
130+ repository, other permissions should be defines for that.
131+- tag
132+ Command line character: t
133+ t permission allows cvs tag and rtag subcommands to run, so you may
134+ control tagging and untagging operations. t permission includes r
135+ permission, since without reading you can not tag/untag a file.
136+ However t permission does not include write permission, you can not
137+ commit a file with only t permission.
138+- create
139+ Command line character: c
140+ c permission allows cvs add and import subcommands to run. To add or
141+ import a file/directory to repository, you have to given a c
142+ permission. Again, c permission does not include write permission,
143+ thus you may only add or import files, but you can not modify any
144+ existing file. After issuing add subcommand, you have to commit the file
145+ to complete adding. This commit subcommand is allowed because you are
146+ adding file and not modifying existing one.
147+- delete
148+ Command line character: d
149+ d permission allows cvs remove command to run. To remove a file/directory
150+ from repository, d permission have to set. It does not include write
151+ permission, so you can not modify contents of an existing file on repository.
152+- full access except admin rights
153+ Command line character: a
154+ a permission gives all access (above permissions) to repository, but it
155+ can not modify permissions. Only acl admins may modify the acl definitions.
156+- acl admin
157+ Command line character: p
158+ p permission means that user is an acl admin, so it is allowed to make anything on repository.
159+
160+
161+ACL Config Keywords
162+The administrative file aclconfig contains miscellaneous settings which
163+affect the behaviour of ACL extension. Currently defined keywords are:
164+
165+UseCVSACL=value
166+Use ACL definitions if set to yes. If you do not want to use ACLs for
167+some repositories in a patched CVS server, set this keyword to no. The default is no.
168+
169+UseCVSACLDefaultPermissions=value
170+Value can be any combination of valid permission types (w,r,t,c,d,t,a,p).
171+if there is no defined ACL and default permission in access file, or no
172+access file at all, this permissions are used. The default is p (admin rights),
173+if aclconfig file is created with cvs init.
174+
175+UseCVSGroups=value
176+CVS does not have a CVSROOT/passwd file. However it can be created manually
177+(format should be same as /etc/group). If value set to yes, CVS checks for
178+groups in file $CVSROOT/CVSROOT/group The default value is no.
179+
180+UseSystemGroups=value
181+Group memberships for users are checked in file /etc/group, if value is set
182+to yes. The default value is no.
183+
184+CVSACLFileLocation=value
185+Originally access file is put under CVSROOT/CVSROOT, if you want a different
186+location, set value to a valid path. The default value is $CVSROOT/CVSROOT/access.
187+
188+CVSGroupsFileLocation=value
189+IF UseCVSGroups is set to yes, CVS looks for a group file under $CVSROOT/CVSROOT.
190+To use a different location for group file set value to a valid path to group.
191+The default value is $CVSROOT/CVSROOT/group.
192+
193+UseSeperateACLFileForEachDir=value
194+If value is set to yes, a seperate ACL file (access) is created for each
195+directory in repository. If you have a really big repository
196+(directories>10,000 and files>100,000), performance may drop due to a big
197+acl file, access. Setting the value to yes, may increase performance. Normally,
198+you will not need this. The default value is no.
199+
200+StopAtFirstPermissionDenied=value
201+If StopAtFirstPermissionDenied is set to yes
202+operation will stop at first permission denied message.
203+e.g. when you send commit command for a directory, if you dont
204+have write permission for just one file under the directory,
205+by default you will have a warning and commit will continue
206+on the other files. If you set this keyword to 'no', then
207+commit operation will be stopped when inaccassable file found.
208+Default is no.
209+
210+CVSServerRunAsUser=value
211+Set CVSServerRunAsUser keyword to a valid system user.
212+When a user make a remote connection to CVS, after successfull authentication
213+cvs process switch to run as that user, or defined system user in
214+$CVSROOT/CVSROOT/passwd. So, you also have to set unix file permissions accordingly.
215+A better solution:
216+Add a user and group such as both cvsadm.
217+Set CVSServerRunAsUser keyword to cvsadm.
218+Change unix file system permissions for your repository,
219+make cvsadm user and group owner, and read,write,execute permissions and setgid.
220+(chown cvsadm -R /path/to/your/repository)
221+(chgrp cvsadm -R /path/to/your/repository)
222+(chmod 2770 -R /path/to/your/repository)
223+Add yourself to cvsadm group (since you are ACL administrator).
224+Therefore, only users making remote connections will have access to repository
225+if you give rights. Local users can not access to repository via a cvs client or directly.
226+
227+
228+Command Line Usage Information
229+acl command is used on checked out files or directories. racl command is
230+used on repository without a working copy. Usage information can be obtained
231+with standard cvs --help command.
232+Output of cvs --help acl and cvs --help racl:
233+
234+Usage: cvs racl [user||group:permissions] [-Rl] [-r tag]
235+ -d [directory] -f [file]
236+ -R Process directories recursively.
237+ -r rev Existing revision/tag.
238+ -l List defined ACLs.
239+ -d dir Process on given directory.
240+ -f file Process on given file.
241+
242+Usage: cvs acl [user||group:permissions] [-Rl] [-r tag]
243+ -d [directory] -f [file]
244+ -R Process directories recursively.
245+ -r rev Existing revision/tag.
246+ -l List defined ACLs.
247+ -d dir Process on given directory.
248+ -f file Process on given file.
249+
250+You may directly set permissions for a user or group or add/remove
251+permissions with + and - signs to/from existing permissions.
252+If you do not give the branch/tag information, default value of HEAD
253+(main branch) will be used. You have to give branch/tag name with -r option.
254+You may type ALL for branch/tag field.
255+
256+While checking for permissions, it goes thorough the list below. So the highest
257+significant permission is the first item in list.
258+
259+- permissions assigned to username for specific directory or file.
260+- permissions assigned to group name for specific directory or file.
261+- permissions as defaults for specific directory or file.
262+- permissions assigned to parent folders (inherits from the first parent
263+ which permissions are assigned).
264+- permissions as repository defaults.
265+- permissions in aclconfig file.
266+
267+
268+
269+
270+Examples
271+ /cvs/
272+ |
273+ |
274+ +--projectA/
275+ | |
276+ | +---CVSROOT/
277+ | |
278+ | +---lib/
279+ | | |
280+ | | +---gnulib/
281+ | | |
282+ | | +---zlib/
283+ | |
284+ | +---src/
285+ | | |
286+ | | +---main.c
287+ | | |
288+ | | +---server.c
289+ | | |
290+ | | +---client.c
291+ | |
292+ | +---gui/
293+ |
294+ +--projectB/
295+We have above directory structure for a cvs repository, and no defined permissions.
296+
297+Setting main default permissions:
298+
299+$ cvs -d /cvs/projectA racl cvsadmin:p -r ALL -d ALL
300+$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL
301+User cvsadmin will be an acl admin, and all other users will have only read
302+rights on all branches/tags in projectA repository. This is the default acl
303+definition and it overwrites default permissions in $CVSROOT/CVSROOT/aclconfig file.
304+
305+$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL
306+$ cvs -d /cvs/projectA racl ALL:n -r ALL -d gui
307+After executing these two commands, all users will have read access on all
308+directories and files except gui directory. Everyone will be denied to access to gui
309+directory becase no access, n, permissions is set.
310+
311+Setting permissions directly on a file or directory:
312+
313+$ cvs -d /cvs/projectA racl userX:wcd -d lib
314+$ cvs -d /cvs/projectA racl group1:w -d lib
315+First command will set write, create, and delete permissions for userX on directory
316+lib with branch HEAD (since no branch/tag information given, branch defaults to HEAD).
317+Second command will set only write permission for group1 on directory lib with branch HEAD.
318+Members of group1 will have only commit rights on lib directory, branch HEAD, they can
319+not add or remove any file, just modify existing files.
320+If userX is also a member of group1, userX will have write, create, and delete permissions
321+because it is specifically given these permissions.
322+
323+$ cvs -d /cvs/projectA racl userY:wcd -r develStream -d lib
324+$ cvs -d /cvs/projectA racl userY:r -r integStream -d lib
325+These commands will give wcd permissions to userY on lib directory with tag develstream,
326+and r permissions on lib directory with tag integStream.
327+
328+$ cvs -d /cvs/projectA racl userZ:wcd -d src
329+$ cvs -d /cvs/projectA racl userZ:r -f src/main.c
330+First command will give wcd permissions to userZ on src directory, but only read
331+permission on file main.c in src directory.
332+
333+Using + and - signs to set permissions on a file or directory:
334+
335+$ cvs -d /cvs/projectA racl userZ:+t -d src
336+$ cvs -d /cvs/projectA racl userZ:-cd -d src
337+$ cvs -d /cvs/projectA racl userZ:-wt -d src
338+Before the first command, userZ has wcd permissions on src directory, after issuing
339+command it will have wcdt permissions. Tag permission will be added. UserZ has wcdt
340+permissions, and we execute the second command to remove create and delete permissions.
341+So userZ has wt permissions. In the last command we also remove wt permissions, finally
342+userZ has no defined permissions left, and it will use the default permissions if set.
343+
344+Listing permissions on a file or directory:
345+
346+$ cvs -d /cvs/projectA racl -l -d src
347+$ cvs -d /cvs/projectA racl -l -f src
348+$ cvs -d /cvs/projectA racl -l -f src/main.c
349+
350+First command will list the permissions for src directory.
351+Example output:
352+d src HEAD | userX:wcd group1:r | defaults:r
353+userX and group1 has assigned permissions, all other users will have default
354+permissions, which is only read.
355+
356+Second command will list the permissions for files in src directory.
357+Example output:
358+f src/main.c HEAD | userX:wcd group1:r | defaults:r
359+f src/server.c HEAD | userX:wcd group1:r | defaults:r
360+f src/client.c HEAD | userX:wcd group1:r | defaults:r
361+
362+Third command will list the permissions for main.c file in src directory.
363+Example output:
364+f src/main.c HEAD | userX:wcd group1:r | defaults:r
365+
366+
367diff -urN cvs-1.11.15/src/acl.c cvs-1.11.15-cvsacl/src/acl.c
368--- cvs-1.11.15/src/acl.c 1970-01-01 01:00:00.000000000 +0100
369+++ cvs-1.11.15-cvsacl/src/acl.c 2004-04-25 20:19:28.506559552 +0200
370@@ -0,0 +1,2028 @@
371+/*
372+ *
373+ * CVS ACCESS CONTROL LIST EXTENSION
374+ *
375+ * sbaris@users.sourceforge.net
376+ *
377+ * http://cvsacl.sourceforge.net/
378+ *
379+ * CVSACL is a patch for CVS
380+ * It adds two new subcommands (acl & racl) to cvs for access control
381+ * list management.
382+ * It provides advanced ACL definitions per modules, directories,
383+ * and files on branch/tag for remote cvs repository connections.
384+ * Execution of all CVS subcommands can be controlled with eight
385+ * different permissions.
386+ * ACL definitions works for only remote connections, local users can
387+ * access and modify repository, if unix file system permissions allow.
388+ * If you want all users to make remote connections to repository,
389+ * and not allow local users to access repository, you have to set
390+ * CVSServerRunAsUser keyword in aclconfig file (explained below).
391+ * Still local users can use acl and racl subcommands to set permissions
392+ * on directories or files if they have acl admin rights (p) on related
393+ * directories or files.
394+ * So, in order to control all access to repository with this ACL extension,
395+ * you should use CVSServerRunAsUser keyword and force all users to make
396+ * remote connections.
397+ * CVS repository administrator or project managers have to use acl and racl
398+ * subcommands to manage permissions. But there is no gui client supporting
399+ * these subcommands, so you have to use cvs client itself either
400+ * locally or remotely.
401+ *
402+ *
403+ * Permission Types:
404+ * - no permission (n) (1)
405+ * - all permissions (a) (2)
406+ * - write permission (w) (3)
407+ * - tag permission (t) (4)
408+ * - read permission (r) (5)
409+ * - add permission (c) (6)
410+ * - remove permission (d) (7)
411+ * - permission change (p) (8)
412+ *
413+ *
414+ *
415+ *
416+ * ********************************************************************
417+ * This program is free software; you can redistribute it and/or modify
418+ * it under the terms of the GNU General Public License as published by
419+ * the Free Software Foundation; either version 1, or (at your option)
420+ * any later version.
421+ *
422+ * This program is distributed in the hope that it will be useful,
423+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
424+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
425+ * GNU General Public License for more details.
426+ * *******************************************************************
427+ *
428+ */
429+
430+#include "cvs.h"
431+#include "getline.h"
432+#include <grp.h>
433+
434+static int acl_fileproc PROTO ((void *callerdat, struct file_info *finfo));
435+static Dtype acl_dirproc PROTO ((void *callerdat, const char *dir, const char *repos,
436+ const char *update_dir, List *entries));
437+
438+static int acllist_fileproc PROTO ((void *callerdat, struct file_info *finfo));
439+static Dtype acllist_dirproc PROTO ((void *callerdat, const char *dir, const char *repos,
440+ const char *update_dir, List *entries));
441+
442+static void acllist_print PROTO ((char *line, const char *obj));
443+
444+static int racl_proc PROTO((int argc, char **argv, char *xwhere,
445+ char *mwhere, char *mfile, int shorten,
446+ int local_specified, char *mname, char *msg));
447+
448+FILE *open_accessfile (char *xmode, char *repos, char **fname);
449+FILE *open_groupfile (char *xmode);
450+
451+char *get_perms (char *xperms);
452+char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
453+
454+static char *cache_repository;
455+static int cache_retval;
456+static int founddeniedfile;
457+static int cache_perm;
458+
459+static int is_racl;
460+
461+int use_cvs_acl = 0;
462+char *cvs_acl_default_permissions;
463+int use_cvs_groups = 0;
464+int use_system_groups = 0;
465+int use_seperate_acl_file_for_each_dir = 0;
466+char *cvs_acl_file_location = NULL;
467+char *cvs_groups_file_location = NULL;
468+char *cvs_server_run_as = NULL;
469+int stop_at_first_permission_denied = 0;
470+
471+char *tag = NULL;
472+
473+char *muser;
474+char *mperms;
475+static int defaultperms;
476+
477+static char *default_perms_object;
478+char *default_part_perms_accessfile;
479+
480+int acldir = 0;
481+int aclfile = 0;
482+int listacl = 0;
483+
484+int userfound;
485+int groupfound;
486+
487+char *dirs[25];
488+
489+int aclconfig_default_used;
490+
491+static const char *const acl_usage[] =
492+ {
493+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n",
494+ "\t-R\tProcess directories recursively.\n",
495+ "\t-r rev\tExisting revision/tag.\n",
496+ "\t-l\tList defined ACLs.\n",
497+ "\t-d dir\tProcess on given directory.\n",
498+ "\t-f file\tProcess on given file.\n",
499+ "(Specify the --help global option for a list of other help options)\n",
500+ NULL
501+ };
502+
503+static const char *const racl_usage[] =
504+ {
505+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n",
506+ "\t-R\tProcess directories recursively.\n",
507+ "\t-r rev\tExisting revision/tag.\n",
508+ "\t-l\tList defined ACLs.\n",
509+ "\t-d dir\tProcess on given directory.\n",
510+ "\t-f file\tProcess on given file.\n",
511+ "(Specify the --help global option for a list of other help options)\n",
512+ NULL
513+ };
514+
515+
516+int
517+access_allowed (file, repos, tag, perm, mline, mpos, usecache)
518+char *file;
519+char *repos;
520+char *tag;
521+int perm;
522+char **mline;
523+int *mpos;
524+int usecache;
525+{
526+ int retval = 0;
527+ int foundline = 0;
528+ FILE *accessfp;
529+
530+ char *line = NULL;
531+ size_t line_allocated = 0;
532+
533+ char *part_type = NULL;
534+ char *part_object = NULL;
535+ char *part_tag = NULL;
536+ char *part_perms = NULL;
537+ char *xline;
538+
539+ char *iline;
540+
541+ char *tempv;
542+ char *tempc;
543+ size_t tempsize;
544+ int intcount;
545+
546+ int oneaccessfile = 0;
547+ int accessfilecount;
548+
549+ int signlevel = 0;
550+
551+ int dadmin = 0;
552+
553+ const char *repository;
554+ char *filefullname = NULL;
555+
556+
557+ userfound = 0;
558+ groupfound = 0;
559+
560+
561+ if (defaultperms)
562+ {
563+ repository = xstrdup ("ALL");
564+ }
565+ else
566+ repository = Short_Repository (repos);
567+
568+ /* cache */
569+ if (usecache
570+ && cache_repository != NULL
571+ && strcmp (cache_repository, repository) == 0
572+ && !founddeniedfile
573+ && perm == cache_perm)
574+ return (cache_retval);
575+ else
576+ {
577+ free(cache_repository);
578+ cache_repository = xstrdup(repository);
579+ cache_perm = perm;
580+ }
581+
582+ if (file != NULL)
583+ {
584+ filefullname = xmalloc (strlen (repository)
585+ + strlen (file)
586+ + 2);
587+
588+ strcpy (filefullname, repository);
589+ strcat (filefullname, "/");
590+ strcat (filefullname, file);
591+ }
592+
593+
594+ iline = xstrdup(repository);
595+
596+ tempv = strtok(iline, "/\t");
597+ tempc = xstrdup(tempv);
598+ tempsize = strlen(tempc);
599+
600+ intcount = 0;
601+
602+ dirs[intcount] = xstrdup(tempc);
603+
604+ while ((tempv = strtok(NULL, "/\t")) != NULL)
605+ {
606+ intcount++;
607+
608+ xrealloc_and_strcat(&tempc, &tempsize, "/");
609+ xrealloc_and_strcat(&tempc, &tempsize, tempv);
610+
611+ dirs[intcount] = xstrdup(tempc);
612+ }
613+
614+ if (file != NULL)
615+ {
616+ intcount++;
617+ dirs[intcount] = xstrdup(filefullname);
618+ }
619+
620+ for (accessfilecount = intcount; accessfilecount >= 0 && !oneaccessfile; accessfilecount--)
621+ {
622+ if (!use_seperate_acl_file_for_each_dir)
623+ oneaccessfile = 1;
624+ else if (use_seperate_acl_file_for_each_dir)
625+ oneaccessfile = 0;
626+
627+ if (oneaccessfile)
628+ accessfp = open_accessfile ("r", repos, NULL);
629+ else
630+ accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
631+
632+ if (accessfp != NULL)
633+ {
634+ while (getline (&line, &line_allocated, accessfp) >= 0)
635+ {
636+ int x;
637+
638+ if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
639+ continue;
640+
641+ xline = xstrdup (line);
642+ part_type = strtok (line, ":\t");
643+ part_object = strtok (NULL, ":\t");
644+ part_tag = strtok (NULL, ":\t");
645+ part_perms = strtok (NULL, ":\t");
646+
647+ for (x = intcount; x >= signlevel; x--)
648+ {
649+ if (strcmp (dirs[x], part_object) == 0)
650+ {
651+ if (valid_tag (part_tag, tag))
652+ {
653+ foundline = 1;
654+
655+ if (listacl)
656+ {
657+ *mline = xstrdup (xline);
658+ *mpos = ftell (accessfp);
659+ }
660+
661+ if (valid_perm (part_perms, perm))
662+ {
663+ if (signlevel == x)
664+ {
665+ if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used)
666+ retval = 1;
667+ }
668+ else if (!aclconfig_default_used)
669+ {
670+ signlevel = x;
671+ retval = 1;
672+ }
673+ }
674+ else
675+ {
676+ if (signlevel == x)
677+ {
678+ if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used)
679+ retval = 0;
680+ }
681+ else if (!aclconfig_default_used)
682+ {
683+ signlevel = x;
684+ retval = 0;
685+
686+ if (strncmp (part_type, "f", 1) == 0)
687+ founddeniedfile = 1;
688+
689+ }
690+ }
691+ }
692+ }
693+ }
694+ if (strncmp (xline, "d:ALL", 5) == 0 && (!groupfound && !userfound || listacl))
695+ {
696+ /* a default found */
697+ if (valid_tag (part_tag, tag))
698+ {
699+ foundline = 1;
700+
701+ default_part_perms_accessfile = xstrdup (part_perms);
702+
703+ if (valid_perm (part_perms, perm))
704+ {
705+ retval = 1;
706+
707+ if (perm == 8)
708+ dadmin = 1;
709+ }
710+ else
711+ retval = 0;
712+ }
713+ }
714+
715+ }
716+ if (fclose (accessfp) == EOF)
717+ error (1, errno, "cannot close 'access' file");
718+
719+ }
720+ }
721+
722+ if (!foundline)
723+ {
724+ /* DEFAULT */
725+ if (valid_perm (NULL, perm))
726+ retval = 1;
727+ else
728+ retval = 0;
729+ }
730+
731+ if (dadmin)
732+ {
733+ retval = dadmin;
734+ }
735+
736+ cache_retval = retval;
737+
738+ free (filefullname);
739+
740+ return (retval);
741+}
742+
743+/* Returns 1 if successful, 0 if not. */
744+int
745+valid_tag (part_tag, tag)
746+char *part_tag;
747+char *tag;
748+{
749+ if (tag == NULL)
750+ tag = xstrdup ("HEAD");
751+
752+ if (strcmp (part_tag, "ALL") == 0)
753+ return (1);
754+
755+ if (strcmp (tag, part_tag) == 0)
756+ return (1);
757+ else
758+ return (0);
759+}
760+
761+/* Returns 1 if successful, 0 if not. */
762+int
763+valid_perm (part_perms, perm)
764+char *part_perms;
765+int perm;
766+{
767+ char *perms;
768+ int retval = 0;
769+
770+ perms = get_perms (part_perms);
771+
772+ /* Allow, if nothing found. */
773+ if (perms[0] == '\0')
774+ return (1);
775+
776+
777+ if (strstr (perms, "n"))
778+ retval = 0; /* no access allowed, exit */
779+ if (strstr (perms, "p"))
780+ retval = 1; /* admin rights */
781+ else if (strstr (perms, "a") && perm != 8)
782+ retval = 1; /* all access allowed, exit */
783+ else
784+ switch (perm)
785+ {
786+ case 3: /* write permission */
787+ if (strstr (perms, "w"))
788+ retval = 1;
789+ break;
790+ case 4: /* tag permission */
791+ if (strstr (perms, "t"))
792+ retval = 1;
793+ break;
794+ case 5: /* read permission */
795+ if (strstr (perms, "w") || strstr (perms, "t") || strstr (perms, "c") ||
796+ strstr (perms, "d") || strstr (perms, "r"))
797+ retval = 1;
798+ break;
799+ case 6: /* create permission */
800+ if (strstr (perms, "c"))
801+ retval = 1;
802+ break;
803+ case 7: /* delete permission */
804+ if (strstr (perms, "d"))
805+ retval = 1;
806+ break;
807+ case 8: /* permission change */
808+ if (strstr (perms, "p"))
809+ retval = 1;
810+ break;
811+ default:
812+ retval = 0; /* never reached */
813+ break;
814+ }
815+
816+ return (retval);
817+}
818+
819+char *
820+get_perms (part_perms)
821+char *part_perms;
822+
823+{
824+ char *username;
825+ char *xperms;
826+ size_t xperms_len = 1;
827+
828+ FILE *groupfp;
829+
830+ char *usr;
831+ char *per;
832+ char *founduser = NULL;
833+ char *foundall = NULL;
834+ int default_checked = 0;
835+
836+ aclconfig_default_used = 0;
837+
838+ xperms = xmalloc (xperms_len);
839+ xperms[0] = '\0';
840+
841+ username = getcaller ();
842+
843+ /* no defined acl, no default acl in access file,
844+ or no access file at all */
845+ if (part_perms == NULL)
846+ if (cvs_acl_default_permissions)
847+ {
848+ aclconfig_default_used = 1;
849+ return (cvs_acl_default_permissions);
850+ }
851+ else
852+ return (xperms);
853+
854+check_default:
855+ founduser = strstr (part_perms, username);
856+ foundall = strstr (part_perms, "ALL!");
857+
858+ if (founduser)
859+ {
860+ usr = strtok (founduser, "!\t");
861+ per = strtok (NULL, ",\t");
862+
863+ if (strcmp (usr, username) == 0)
864+ {
865+ xperms = xstrdup (per);
866+ xperms_len = strlen (xperms);
867+
868+ userfound = 1;
869+ }
870+ }
871+ else
872+ {
873+ if (use_system_groups) {
874+ struct group *griter;
875+ setgrent ();
876+ while (griter = getgrent ()) {
877+ char **users=griter->gr_mem;
878+ int index = 0;
879+ char *userchk = users [index++];
880+ while(userchk != NULL) {
881+ if(strcmp (userchk, username) == 0)
882+ break;
883+ userchk = users[index++];
884+ }
885+ if (userchk != NULL) {
886+ char *grp;
887+ if ((grp = strstr (part_perms, griter->gr_name)) && grp[strlen (griter->gr_name)] == '!') {
888+ char *gperm = strtok (grp, "!\t");
889+ gperm = strtok (NULL, ",\t");
890+ xrealloc_and_strcat (&xperms, &xperms_len, gperm);
891+
892+ groupfound = 1;
893+ }
894+ }
895+ }
896+ endgrent ();
897+ }
898+ else if (use_cvs_groups) {
899+ groupfp = open_groupfile ("r");
900+ if (groupfp != NULL)
901+ {
902+ char *line = NULL;
903+ size_t line_allocated = 0;
904+
905+ while (getline (&line, &line_allocated, groupfp) >= 0)
906+ {
907+ if (strstr (line, username))
908+ {
909+ char *temp;
910+ temp = strstr (line, username);
911+
912+ if (temp[strlen (username)] == ','
913+ || temp[strlen (username)] == ' '
914+ || temp[strlen (username)] == '\n')
915+ {
916+ char *tmp;
917+ tmp = strtok (line, ":\t");
918+ if (strcmp (tmp, username) != 0)
919+ {
920+ char *grp;
921+ if ((grp = strstr (part_perms, tmp)))
922+ if (grp[strlen (tmp)] == '!')
923+ {
924+ char *gperm;
925+ gperm = strtok (grp, "!\t");
926+ gperm = strtok (NULL, ",\t");
927+
928+ xrealloc_and_strcat (&xperms, &xperms_len, gperm);
929+
930+ groupfound = 1;
931+ }
932+ }
933+ }
934+ }
935+ }
936+ if (fclose (groupfp) == EOF)
937+ error (1, errno, "cannot close 'group' file");
938+ }
939+ }
940+ }
941+
942+ if (foundall && (!groupfound && !userfound))
943+ {
944+ usr = strtok (strstr (part_perms, "ALL!"), "!\t");
945+ per = strtok (NULL, ",\t");
946+
947+ if (!default_checked)
948+ default_perms_object = xstrdup (per);
949+
950+ if (xperms[0] == '\0')
951+ {
952+ xperms = xstrdup (per);
953+ xperms_len = strlen (xperms);
954+ }
955+ }
956+ else if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
957+ {
958+ part_perms = xstrdup (default_part_perms_accessfile);
959+ default_checked = 1;
960+
961+ goto check_default;
962+ }
963+
964+ if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
965+ {
966+ if (default_perms_object)
967+ xperms = xstrdup (default_perms_object);
968+ else if (default_part_perms_accessfile)
969+ {
970+ part_perms = default_part_perms_accessfile;
971+ default_checked = 1;
972+ goto check_default;
973+ }
974+ else if (cvs_acl_default_permissions)
975+ {
976+ aclconfig_default_used = 1;
977+ xperms = xstrdup (cvs_acl_default_permissions);
978+ }
979+ }
980+
981+ if (xperms[0] == '\0' && cvs_acl_default_permissions)
982+ {
983+ aclconfig_default_used = 1;
984+ xperms = xstrdup (cvs_acl_default_permissions);
985+ }
986+
987+ return (xperms);
988+}
989+
990+
991+int
992+cvsacl (argc, argv)
993+int argc;
994+char **argv;
995+{
996+ char *chdirrepository;
997+ int c;
998+ int err = 0;
999+ int usetag = 0;
1000+ int recursive = 0;
1001+
1002+ int k;
1003+
1004+ int which;
1005+ char *where;
1006+
1007+ is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
1008+
1009+ if (argc == -1)
1010+ usage (is_racl ? racl_usage : acl_usage);
1011+
1012+ /* parse the args */
1013+ optind = 0;
1014+
1015+ while ((c = getopt (argc, argv, "Rr:dfl")) != -1)
1016+ {
1017+ switch (c)
1018+ {
1019+ case 'R':
1020+ recursive = 1;
1021+ break;
1022+ case 'r':
1023+ tag = xstrdup (optarg);
1024+ break;
1025+ case 'd':
1026+ acldir = 1;
1027+ break;
1028+ case 'f':
1029+ aclfile = 1;
1030+ break;
1031+ case 'l':
1032+ listacl = 1;
1033+ break;
1034+ case '?':
1035+ default:
1036+ usage (is_racl ? racl_usage : acl_usage);
1037+ break;
1038+ }
1039+ }
1040+
1041+ argc -= optind;
1042+ argv += optind;
1043+
1044+ if (!acldir && !aclfile)
1045+ usage (is_racl ? racl_usage : acl_usage);
1046+ if (acldir && aclfile)
1047+ usage (is_racl ? racl_usage : acl_usage);
1048+
1049+ if (listacl)
1050+ if (strstr (argv[0], ":"))
1051+ usage (is_racl ? racl_usage : acl_usage);
1052+ if (!listacl)
1053+ if (!strstr (argv[0], ":"))
1054+ usage (is_racl ? racl_usage : acl_usage);
1055+
1056+ if (argc < (is_racl ? 1 : 1))
1057+ usage (is_racl ? racl_usage : acl_usage);
1058+
1059+#ifdef CLIENT_SUPPORT
1060+
1061+ if (current_parsed_root->isremote)
1062+ {
1063+ start_server ();
1064+ ign_setup ();
1065+
1066+ if(recursive)
1067+ send_arg ("-R");
1068+
1069+ if (acldir)
1070+ send_arg ("-d");
1071+
1072+ if (aclfile)
1073+ send_arg ("-f");
1074+
1075+ if (listacl)
1076+ send_arg ("-l");
1077+
1078+ if(tag)
1079+ {
1080+ send_arg ("-r");
1081+ send_arg (tag);
1082+ }
1083+
1084+ send_arg ("--");
1085+
1086+ if (!listacl)
1087+ {
1088+ send_arg (argv[0]);
1089+
1090+ argc--;
1091+ argv++;
1092+ }
1093+
1094+ if (is_racl)
1095+ {
1096+ int i;
1097+ for (i = 0; i < argc; ++i)
1098+ send_arg (argv[i]);
1099+
1100+ send_to_server ("racl\012",0);
1101+ }
1102+ else
1103+ {
1104+ send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
1105+ send_file_names (argc, argv, SEND_EXPAND_WILD);
1106+ send_to_server ("acl\012", 0);
1107+ }
1108+
1109+ return get_responses_and_close ();
1110+ }
1111+#endif
1112+
1113+#ifdef SERVER_SUPPORT
1114+
1115+ if (!listacl)
1116+ {
1117+ muser = strtok (argv[0], ":\t");
1118+ mperms = strtok (NULL, ":\t");
1119+
1120+ /* if set to 'default' */
1121+ if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
1122+ mperms = xstrdup ("x");
1123+
1124+ /* Check that the given permissions are valid. */
1125+ if (!given_perms_valid (mperms))
1126+ error (1,0,"Invalid permissions: '%s'", mperms);
1127+
1128+ argc--;
1129+ argv++;
1130+ }
1131+
1132+
1133+ if (!tag)
1134+ tag = xstrdup ("HEAD");
1135+
1136+ if (!cvs_casecmp (argv[0], "ALL"))
1137+ {
1138+ argv[0] = xstrdup (".");
1139+ defaultperms = 1;
1140+ if (!use_seperate_acl_file_for_each_dir)
1141+ {
1142+ recursive = 0;
1143+ }
1144+
1145+ }
1146+
1147+ if (is_racl)
1148+ {
1149+ DBM *db;
1150+ int i;
1151+ db = open_module ();
1152+ for (i = 0; i < argc; i++)
1153+ {
1154+ err += do_module (db, argv[i], MISC, "ACL ing: ",
1155+ racl_proc, (char *) NULL, 0, !recursive, 0,
1156+ 0, NULL);
1157+ }
1158+ close_module (db);
1159+ }
1160+ else
1161+ {
1162+ err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive, NULL,
1163+ NULL);
1164+ }
1165+ if (err)
1166+ error (1, 0, "an error accured");
1167+
1168+ return (err);
1169+
1170+#endif
1171+}
1172+
1173+static int
1174+racl_proc (argc, argv, xwhere, mwhere, mfile, shorten, local, mname, msg)
1175+int argc;
1176+char **argv;
1177+char *xwhere;
1178+char *mwhere;
1179+char *mfile;
1180+int shorten;
1181+int local;
1182+char *mname;
1183+char *msg;
1184+{
1185+ char *myargv[2];
1186+ int err = 0;
1187+ int which;
1188+ char *repository;
1189+ char *where;
1190+
1191+ if (is_racl)
1192+ {
1193+ repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
1194+ + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
1195+
1196+ (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
1197+ where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
1198+ + 1);
1199+ (void) strcpy (where, argv[0]);
1200+
1201+ /* if mfile isn't null, we need to set up to do only part of the module */
1202+ if (mfile != NULL)
1203+ {
1204+ char *cp;
1205+ char *path;
1206+
1207+ /* if the portion of the module is a path, put the dir part on repos */
1208+ if ((cp = strrchr (mfile, '/')) != NULL)
1209+ {
1210+ *cp = '\0';
1211+ (void) strcat (repository, "/");
1212+ (void) strcat (repository, mfile);
1213+ (void) strcat (where, "/");
1214+ (void) strcat (where, mfile);
1215+ mfile = cp + 1;
1216+ }
1217+
1218+ /* take care of the rest */
1219+ path = xmalloc (strlen (repository) + strlen (mfile) + 5);
1220+ (void) sprintf (path, "%s/%s", repository, mfile);
1221+ if (isdir (path))
1222+ {
1223+ /* directory means repository gets the dir tacked on */
1224+ (void) strcpy (repository, path);
1225+ (void) strcat (where, "/");
1226+ (void) strcat (where, mfile);
1227+ }
1228+ else
1229+ {
1230+ myargv[0] = argv[0];
1231+ myargv[1] = mfile;
1232+ argc = 2;
1233+ argv = myargv;
1234+ }
1235+ free (path);
1236+ }
1237+
1238+ /* cd to the starting repository */
1239+ if ( CVS_CHDIR (repository) < 0)
1240+ {
1241+ error (0, errno, "cannot chdir to %s", repository);
1242+ free (repository);
1243+ return (1);
1244+ }
1245+
1246+ /* End section which is identical to patch_proc. */
1247+
1248+ which = W_REPOS | W_ATTIC;
1249+ }
1250+ else
1251+ {
1252+ where = NULL;
1253+ which = W_LOCAL | W_REPOS | W_ATTIC;
1254+ }
1255+ if (listacl)
1256+ err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL, NULL,
1257+ argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1,
1258+ repository);
1259+ else
1260+ err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
1261+ argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1,
1262+ repository);
1263+
1264+ return (err);
1265+}
1266+
1267+
1268+static int
1269+acl_fileproc (callerdat, finfo)
1270+void *callerdat;
1271+struct file_info *finfo;
1272+{
1273+ Vers_TS *vers;
1274+
1275+ FILE *accessfp;
1276+
1277+ char *filefullname;
1278+
1279+ char *founduserpart = NULL;
1280+ char *newuserpart = NULL;
1281+ char *otheruserparts = NULL;
1282+ size_t otherslen = 0;
1283+
1284+ const char *frepository;
1285+ int foundline = 0;
1286+
1287+ char *line = NULL;
1288+ size_t line_allocated = 0;
1289+ int linelen;
1290+
1291+ char *part_type = NULL;
1292+ char *part_object = NULL;
1293+ char *part_tag = NULL;
1294+ char *part_perms = NULL;
1295+ char *wperms;
1296+ char *userpart;
1297+
1298+ char *errmsg;
1299+
1300+ int pos;
1301+
1302+ if (!aclfile)
1303+ return (0);
1304+
1305+ frepository = Short_Repository (finfo->repository);
1306+
1307+ filefullname = xmalloc (strlen (frepository)
1308+ + strlen (finfo->file)
1309+ + 2);
1310+ strcpy (filefullname, frepository);
1311+ strcat (filefullname, "/");
1312+ strcat (filefullname, finfo->file);
1313+
1314+ if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos, 0))
1315+ error (1,0,"You do not have acl admin rights on '%s'", frepository);
1316+
1317+ if (line != NULL)
1318+ {
1319+ part_type = strtok (line, ":\t");
1320+ part_object = strtok (NULL, ":\t");
1321+ part_tag = strtok (NULL, ":\t");
1322+ part_perms = strtok (NULL, ":\t");
1323+
1324+ foundline = 1;
1325+ userpart = strtok (part_perms, ",\t");
1326+
1327+ if (strstr (userpart, muser))
1328+ founduserpart = xstrdup (userpart);
1329+ else
1330+ {
1331+ otheruserparts = xstrdup (userpart);
1332+ otherslen = strlen (otheruserparts);
1333+ }
1334+
1335+ while ((userpart = strtok (NULL, ",\t")) != NULL)
1336+ {
1337+ if (strncmp (userpart, muser, strlen (muser)) == 0)
1338+ founduserpart = xstrdup (userpart);
1339+ else
1340+ {
1341+ if (otheruserparts != NULL)
1342+ {
1343+ xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1344+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1345+ }
1346+ else
1347+ {
1348+ otheruserparts = xstrdup (userpart);
1349+ otherslen = strlen (otheruserparts);
1350+ }
1351+ }
1352+ }
1353+ }
1354+
1355+ wperms = make_perms (mperms, founduserpart, &errmsg);
1356+ if (wperms == NULL)
1357+ {
1358+ if (errmsg)
1359+ error (0, 0, "%s %s", filefullname, errmsg);
1360+
1361+ return (0);
1362+ }
1363+ else
1364+ {
1365+ cvs_output ("X ", 0);
1366+ cvs_output (filefullname, 0);
1367+ cvs_output ("\n", 0);
1368+
1369+ write_perms (muser, wperms, founduserpart, foundline,
1370+ otheruserparts, "f", filefullname, tag, pos, finfo->repository);
1371+ }
1372+
1373+ return (0);
1374+}
1375+
1376+static Dtype
1377+acl_dirproc (callerdat, dir, repos, update_dir, entries)
1378+void *callerdat;
1379+const char *dir;
1380+const char *repos;
1381+const char *update_dir;
1382+List *entries;
1383+{
1384+ const char *drepository;
1385+ char *founduserpart = NULL;
1386+ char *newuserpart = NULL;
1387+ char *otheruserparts = NULL;
1388+ size_t otherslen = 0;
1389+ int foundline = 0;
1390+
1391+ char *line = NULL;
1392+ size_t line_allocated = 0;
1393+ int linelen;
1394+
1395+ FILE *accessfp;
1396+ char *part_type = NULL;
1397+ char *part_object = NULL;
1398+ char *part_tag = NULL;
1399+ char *part_perms = NULL;
1400+ char *wperms;
1401+ int i = 0;
1402+ char *userpart;
1403+ int pos;
1404+
1405+ char *errmsg;
1406+
1407+ if (repos[0] == '\0')
1408+ repos = Name_Repository (dir, NULL);
1409+
1410+ if (!acldir)
1411+ return (0);
1412+
1413+ if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
1414+ error (1,0,"You do not have admin rights on '%s'", Short_Repository (repos));
1415+
1416+ drepository = Short_Repository (repos);
1417+
1418+ if (line != NULL)
1419+ {
1420+ part_type = strtok (line, ":\t");
1421+ part_object = strtok (NULL, ":\t");
1422+ part_tag = strtok (NULL, ":\t");
1423+ part_perms = strtok (NULL, ":\t");
1424+
1425+ foundline = 1;
1426+ userpart = strtok (part_perms, ",\t");
1427+
1428+ if (strstr (userpart, muser))
1429+ founduserpart = xstrdup (userpart);
1430+ else
1431+ {
1432+ otheruserparts = xstrdup (userpart);
1433+ otherslen = strlen (otheruserparts);
1434+ }
1435+
1436+ while ((userpart = strtok (NULL, ",\t")) != NULL)
1437+ {
1438+ if (strncmp (userpart, muser, strlen (muser)) == 0)
1439+ founduserpart = xstrdup (userpart);
1440+ else
1441+ {
1442+ if (otheruserparts != NULL)
1443+ {
1444+ xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1445+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1446+ }
1447+ else
1448+ {
1449+ otheruserparts = xstrdup (userpart);
1450+ otherslen = strlen (otheruserparts);
1451+ }
1452+ }
1453+ }
1454+ }
1455+
1456+ wperms = make_perms (mperms, founduserpart, &errmsg);
1457+ if (wperms == NULL)
1458+ {
1459+ if (errmsg)
1460+ error (0, 0, "%s %s", drepository, errmsg);
1461+
1462+ return (0);
1463+ }
1464+ else
1465+ {
1466+ if (defaultperms)
1467+ {
1468+ cvs_output ("X ", 0);
1469+ cvs_output ("ALL", 0);
1470+ cvs_output ("\n", 0);
1471+ write_perms (muser, wperms, founduserpart, foundline,
1472+ otheruserparts, "d", "ALL", tag, pos, repos);
1473+
1474+ }
1475+ else
1476+ {
1477+ cvs_output ("X ", 0);
1478+ cvs_output (drepository, 0);
1479+ cvs_output ("\n", 0);
1480+ write_perms (muser, wperms, founduserpart, foundline,
1481+ otheruserparts, "d", drepository, tag, pos, repos);
1482+ }
1483+ }
1484+
1485+ return (0);
1486+}
1487+
1488+/* Open CVSROOT/access or defined CVSACLFileLocation file. */
1489+FILE *
1490+open_accessfile (fmode, adir, fname)
1491+char *fmode;
1492+char *adir;
1493+char **fname;
1494+{
1495+ char *accessfile;
1496+ FILE *accessfp;
1497+
1498+ if (!use_seperate_acl_file_for_each_dir)
1499+ {
1500+ if (cvs_acl_file_location == NULL)
1501+ {
1502+ accessfile = xmalloc (strlen (current_parsed_root->directory)
1503+ + sizeof (CVSROOTADM)
1504+ + sizeof (CVSROOTADM_ACCESS)
1505+ + 3);
1506+
1507+ strcpy (accessfile, current_parsed_root->directory);
1508+ strcat (accessfile, "/");
1509+ strcat (accessfile, CVSROOTADM);
1510+ strcat (accessfile, "/");
1511+ strcat (accessfile, CVSROOTADM_ACCESS);
1512+ }
1513+ else
1514+ {
1515+ accessfile = xmalloc (strlen (cvs_acl_file_location));
1516+ strcpy (accessfile, cvs_acl_file_location);
1517+ }
1518+ }
1519+ else
1520+ {
1521+ accessfile = xmalloc (strlen (current_parsed_root->directory)
1522+ + strlen (adir)
1523+ + strlen ("access")
1524+ + 3);
1525+
1526+ strcpy (accessfile, current_parsed_root->directory);
1527+ strcat (accessfile, "/");
1528+ strcat (accessfile, adir);
1529+ strcat (accessfile, "/");
1530+ strcat (accessfile, "access");
1531+ }
1532+
1533+ accessfp = CVS_FOPEN (accessfile, fmode);
1534+
1535+ if (accessfp == NULL)
1536+ error (0, 0, "cannot open file: %s", accessfile);
1537+
1538+ if (fname != NULL)
1539+ *fname = xstrdup (accessfile);
1540+
1541+ free (accessfile);
1542+
1543+ return (accessfp);
1544+}
1545+
1546+/* Open /etc/group file if UseSystemGroups=yes in config file. */
1547+/* Open CVSROOT/group file if UseCVSGroups=yes in config file. */
1548+FILE *
1549+open_groupfile (fmode)
1550+char *fmode;
1551+{
1552+ char *groupfile;
1553+ FILE *groupfp;
1554+
1555+ if (use_cvs_groups)
1556+ {
1557+ if (cvs_groups_file_location != NULL)
1558+ {
1559+ groupfile = xmalloc (strlen (cvs_groups_file_location));
1560+ strcpy (groupfile, cvs_groups_file_location);
1561+ }
1562+ else
1563+ {
1564+ groupfile = xmalloc (strlen (current_parsed_root->directory)
1565+ + sizeof (CVSROOTADM)
1566+ + sizeof (CVSROOTADM_GROUP)
1567+ + 3);
1568+
1569+ strcpy (groupfile, current_parsed_root->directory);
1570+ strcat (groupfile, "/");
1571+ strcat (groupfile, CVSROOTADM);
1572+ strcat (groupfile, "/");
1573+ strcat (groupfile, CVSROOTADM_GROUP);
1574+ }
1575+ }
1576+
1577+ else
1578+ {
1579+ return (NULL);
1580+ }
1581+
1582+ groupfp = CVS_FOPEN (groupfile, "r");
1583+
1584+ if (groupfp == NULL)
1585+ error (0, 0, "cannot open file: %s", groupfile);
1586+
1587+ free (groupfile);
1588+
1589+ return (groupfp);
1590+}
1591+
1592+
1593+/* Check whether given permissions are valid or not. */
1594+/* Returns 1 if permissions are valid. */
1595+/* Returns 0 if permissions are NOT valid. */
1596+int
1597+given_perms_valid (cperms)
1598+char *cperms;
1599+{
1600+ int cperms_len;
1601+ int retval;
1602+ int index, i;
1603+
1604+ if (cperms[0] == '+' || cperms[0] == '-')
1605+ index = 1;
1606+ else
1607+ index = 0;
1608+
1609+ cperms_len = strlen (cperms);
1610+
1611+ switch (cperms[index])
1612+ {
1613+ case 'x':
1614+ if ((cperms_len - index) == 1 && cperms_len == 1)
1615+ retval = 1;
1616+ else
1617+ retval = 0;
1618+ break;
1619+ case 'n':
1620+ if ((cperms_len - index) == 1 && cperms_len == 1)
1621+ retval = 1;
1622+ else
1623+ retval = 0;
1624+ break;
1625+ case 'p':
1626+ if ((cperms_len - index) == 1)
1627+ retval = 1;
1628+ else
1629+ retval = 0;
1630+ break;
1631+ case 'a':
1632+ if ((cperms_len - index) == 1)
1633+ retval = 1;
1634+ else
1635+ for (i = index + 1; i < cperms_len; i++)
1636+ if (cperms[i] == 'p')
1637+ retval = 1;
1638+ else
1639+ retval = 0;
1640+ break;
1641+ case 'r':
1642+ if ((cperms_len - index) == 1)
1643+ retval = 1;
1644+ else
1645+ for (i = index + 1; i < cperms_len; i++)
1646+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1647+ retval = 1;
1648+ else
1649+ retval = 0;
1650+ break;
1651+ case 'w':
1652+ if ((cperms_len - index) == 1)
1653+ retval = 1;
1654+ else
1655+ for (i = index + 1; i < cperms_len; i++)
1656+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1657+ retval = 1;
1658+ else
1659+ retval = 0;
1660+ break;
1661+ case 't':
1662+ if ((cperms_len - index) == 1)
1663+ retval = 1;
1664+ else
1665+ for (i = index + 1; i < cperms_len; i++)
1666+ if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
1667+ retval = 1;
1668+ else
1669+ retval = 0;
1670+ break;
1671+ case 'c':
1672+ if ((cperms_len - index) == 1)
1673+ retval = 1;
1674+ else
1675+ for (i = index + 1; i < cperms_len; i++)
1676+ if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
1677+ retval = 1;
1678+ else
1679+ retval = 0;
1680+ break;
1681+ case 'd':
1682+ if ((cperms_len - index) == 1)
1683+ retval = 1;
1684+ else
1685+ for (i = index + 1; i < cperms_len; i++)
1686+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
1687+ retval = 1;
1688+ else
1689+ retval = 0;
1690+ break;
1691+ default:
1692+ retval = 0;
1693+ break;
1694+ }
1695+ return (retval);
1696+}
1697+
1698+char *
1699+make_perms (perms, founduserpart, xerrmsg)
1700+char *perms;
1701+char *founduserpart;
1702+char **xerrmsg;
1703+{
1704+ char *fperms;
1705+ size_t perms_len;
1706+ size_t fperms_len;
1707+ char *retperms = NULL;
1708+ char *xperms;
1709+ int i, j;
1710+ int err = 0;
1711+ char *errmsg = NULL;
1712+ size_t retperms_len = 1;
1713+
1714+ retperms = xmalloc (retperms_len);
1715+ retperms[0] = '\0';
1716+
1717+ perms_len = strlen (perms);
1718+
1719+ if (perms[0] == '+' || perms[0] == '-')
1720+ {
1721+ if (founduserpart)
1722+ {
1723+ char *temp;
1724+ temp = strtok (founduserpart, "!\t");
1725+ fperms = strtok (NULL, "!\t");
1726+ fperms_len = strlen (fperms);
1727+
1728+ if (strncmp (fperms, "x", 1) == 0)
1729+ {
1730+ err = 1;
1731+ if (perms[0] == '+')
1732+ *xerrmsg = xstrdup ("cannot add default permission 'x'");
1733+ else
1734+ *xerrmsg = xstrdup ("cannot remove default permission 'x'");
1735+ }
1736+
1737+ for (i = 1; i < perms_len && !err; i++)
1738+ {
1739+ switch (perms[i])
1740+ {
1741+ case 'n':
1742+ err = 1;
1743+ break;
1744+ case 'p':
1745+ if (perms[0] == '+')
1746+ fperms = xstrdup ("p");
1747+ else if (perms[0] == '-')
1748+ {
1749+ fperms_len = 1;
1750+ fperms = xmalloc (fperms_len);
1751+ fperms[0] = '\0';
1752+ }
1753+ break;
1754+ case 'a':
1755+ for (j = 0; j < fperms_len; j++)
1756+ {
1757+ if (fperms[j] == 'p')
1758+ {
1759+ err = 1;
1760+ *xerrmsg = xstrdup ("user has admin rights, cannot use +/- permissions");
1761+ }
1762+ else if (fperms[j] == 'a' && perms[0] == '+')
1763+ {
1764+ err = 1;
1765+ *xerrmsg = xstrdup ("user already has all ('a') permission");
1766+ }
1767+ else if (fperms[j] != 'a' && perms[0] == '-')
1768+ {
1769+ err = 1;
1770+ *xerrmsg = xstrdup ("user does not have all ('a') permission");
1771+ }
1772+ }
1773+ if (perms[0] == '+')
1774+ {
1775+ fperms = xstrdup ("a");
1776+ fperms_len = strlen (fperms);
1777+ }
1778+ else if (perms[0] == '-')
1779+ {
1780+ fperms_len = 1;
1781+ fperms = xmalloc (fperms_len);
1782+ fperms[0] = '\0';
1783+ }
1784+
1785+ break;
1786+ case 'r':
1787+ for (i = 0; i < fperms_len; i++)
1788+ {
1789+ if (fperms[i] == 'n' && perms[0] == '+')
1790+ {
1791+ fperms = xstrdup ("r");
1792+ fperms_len = strlen (fperms);
1793+ }
1794+ else if (fperms[i] == 'r' && perms[0] == '-')
1795+ {
1796+ fperms_len = 1;
1797+ fperms = xmalloc (fperms_len);
1798+ fperms[0] = '\0';
1799+ }
1800+ else if (perms[0] == '-')
1801+ {
1802+ err = 1;
1803+ *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission");
1804+ }
1805+ else
1806+ {
1807+ err = 1;
1808+ *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission");
1809+ }
1810+ }
1811+ break;
1812+ case 'w':
1813+ {
1814+ char *tempfperms;
1815+ size_t tempfperms_len = 1;
1816+
1817+ tempfperms = xmalloc (tempfperms_len);
1818+ tempfperms[0] = '\0';
1819+
1820+ for (j = 0; j < fperms_len; j++)
1821+ {
1822+ if (fperms[j] == 't' || fperms[j] == 'c' || fperms[j] == 'd')
1823+ {
1824+ char *temp;
1825+ temp = xmalloc (2);
1826+ temp[0] = fperms[j];
1827+ temp[1] = '\0';
1828+
1829+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1830+ free (temp);
1831+ }
1832+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1833+ {
1834+ err = 1;
1835+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- write permissions");
1836+ }
1837+ else if (fperms[j] == 'n' || fperms[j] == 'r')
1838+ {
1839+ if (perms[0] == '-')
1840+ {
1841+ err = 1;
1842+ *xerrmsg = xstrdup ("user does not have write ('w') permission");
1843+ }
1844+ }
1845+ }
1846+
1847+ fperms = xstrdup (tempfperms);
1848+ fperms_len = strlen (fperms);
1849+ free (tempfperms);
1850+
1851+ if (perms[0] == '+')
1852+ {
1853+ xrealloc_and_strcat (&fperms, &fperms_len, "w");
1854+ }
1855+ }
1856+ break;
1857+ case 't':
1858+ {
1859+ char *tempfperms;
1860+ size_t tempfperms_len = 1;
1861+
1862+ tempfperms = xmalloc (tempfperms_len);
1863+ tempfperms[0] = '\0';
1864+
1865+ for (j = 0; j < fperms_len; j++)
1866+ {
1867+ if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 'd')
1868+ {
1869+ char *temp;
1870+ temp = xmalloc (2);
1871+ temp[0] = fperms[j];
1872+ temp[1] = '\0';
1873+
1874+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1875+ free (temp);
1876+ }
1877+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1878+ {
1879+ err = 1;
1880+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- tag permissions");
1881+ }
1882+ else if (fperms[i] == 'n' || fperms[i] == 'r')
1883+ {
1884+ if (perms[0] == '-')
1885+ *xerrmsg = xstrdup ("user does not have tag ('t') permission");
1886+ }
1887+ }
1888+
1889+ fperms = xstrdup (tempfperms);
1890+ fperms_len = strlen (fperms);
1891+ free (tempfperms);
1892+
1893+ if (perms[0] == '+')
1894+ {
1895+ xrealloc_and_strcat (&fperms, &fperms_len, "t");
1896+ }
1897+ }
1898+ break;
1899+ case 'c':
1900+ {
1901+ char *tempfperms;
1902+ size_t tempfperms_len = 1;
1903+
1904+ tempfperms = xmalloc (tempfperms_len);
1905+ tempfperms[0] = '\0';
1906+
1907+ for (j = 0; j < fperms_len; j++)
1908+ {
1909+ if (fperms[j] == 'w' || fperms[j] == 't' || fperms[j] == 'd')
1910+ {
1911+ char *temp;
1912+ temp = xmalloc (2);
1913+ temp[0] = fperms[j];
1914+ temp[1] = '\0';
1915+
1916+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1917+ free (temp);
1918+ }
1919+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1920+ {
1921+ err = 1;
1922+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- create permissions");
1923+ }
1924+ else if (fperms[i] == 'n' || fperms[i] == 'r')
1925+ {
1926+ if (perms[0] == '-')
1927+ err = 1;
1928+ *xerrmsg = xstrdup ("user does not have create ('c') permission");
1929+ }
1930+
1931+ }
1932+
1933+ fperms = xstrdup (tempfperms);
1934+ fperms_len = strlen (fperms);
1935+ free (tempfperms);
1936+
1937+ if (perms[0] == '+')
1938+ {
1939+ xrealloc_and_strcat (&fperms, &fperms_len, "c");
1940+ }
1941+ }
1942+ break;
1943+ case 'd':
1944+ {
1945+ char *tempfperms;
1946+ size_t tempfperms_len = 1;
1947+
1948+ tempfperms = xmalloc (tempfperms_len);
1949+ tempfperms[0] = '\0';
1950+
1951+ for (j = 0; j < fperms_len; j++)
1952+ {
1953+ if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 't')
1954+ {
1955+ char *temp;
1956+ temp = xmalloc (2);
1957+ temp[0] = fperms[j];
1958+ temp[1] = '\0';
1959+
1960+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1961+ free (temp);
1962+ }
1963+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1964+ {
1965+ err = 1;
1966+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- delete permissions");
1967+ }
1968+ else if (fperms[i] == 'n' || fperms[i] == 'r')
1969+ {
1970+ if (perms[0] == '-')
1971+ err = 1;
1972+ *xerrmsg = xstrdup ("user does not have delete ('d') permission");
1973+ }
1974+ }
1975+
1976+ fperms = xstrdup (tempfperms);
1977+ fperms_len = strlen (fperms);
1978+ free (tempfperms);
1979+
1980+ if (perms[0] == '+')
1981+ {
1982+ xrealloc_and_strcat (&fperms, &fperms_len, "d");
1983+ }
1984+ }
1985+ break;
1986+ default:
1987+ err = 1;
1988+ *xerrmsg = xstrdup ("error in 'access' file format");
1989+ break;
1990+ }
1991+ if (fperms[0] == '\0')
1992+ retperms = xstrdup ("none");
1993+ else
1994+ retperms = xstrdup (fperms);
1995+ }
1996+ }
1997+ else
1998+ {
1999+ err = 1;
2000+ *xerrmsg = xstrdup("user is not given any permissions to remove/add");
2001+ }
2002+ }
2003+
2004+ else
2005+ {
2006+ retperms = xstrdup (perms);
2007+ }
2008+
2009+ if (err)
2010+ return (NULL);
2011+ else
2012+ return (retperms);
2013+}
2014+
2015+int
2016+write_perms (user, perms, founduserpart, foundline, otheruserparts,
2017+ part_type, part_object, part_tag, pos, arepos)
2018+char *user;
2019+char *perms;
2020+char *founduserpart;
2021+int foundline;
2022+char *otheruserparts;
2023+char *part_type;
2024+char *part_object;
2025+char *part_tag;
2026+int pos;
2027+char *arepos;
2028+{
2029+
2030+ char *accessfile;
2031+ char *tmpaccessout;
2032+ FILE *accessfpin;
2033+ FILE *accessfpout;
2034+
2035+ char *newline = NULL;
2036+ size_t newlinelen = 1;
2037+
2038+ char *line = NULL;
2039+ size_t line_allocated = 0;
2040+
2041+ newline = xmalloc (newlinelen);
2042+ newline[0] = '\0';
2043+
2044+ if (!cvs_casecmp (part_tag, "ALL"))
2045+ part_tag = xstrdup ("ALL");
2046+
2047+ xrealloc_and_strcat (&newline, &newlinelen, part_type);
2048+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2049+ xrealloc_and_strcat (&newline, &newlinelen, part_object);
2050+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2051+ xrealloc_and_strcat (&newline, &newlinelen, part_tag);
2052+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2053+
2054+ if (strncmp (perms, "none", 4) != 0)
2055+ {
2056+ xrealloc_and_strcat (&newline, &newlinelen, user);
2057+ xrealloc_and_strcat (&newline, &newlinelen, "!");
2058+ xrealloc_and_strcat (&newline, &newlinelen, perms);
2059+ if (otheruserparts != NULL)
2060+ xrealloc_and_strcat (&newline, &newlinelen, ",");
2061+ }
2062+
2063+ if (otheruserparts != NULL)
2064+ {
2065+ if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
2066+ otheruserparts[strlen (otheruserparts) - 1] = '\0';
2067+
2068+ xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
2069+ }
2070+
2071+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2072+
2073+ if (foundline)
2074+ {
2075+ accessfpout = cvs_temp_file (&tmpaccessout);
2076+ accessfpin = open_accessfile ("r", arepos, &accessfile);
2077+
2078+ while (getline (&line, &line_allocated, accessfpin) >= 0)
2079+ {
2080+ if (pos != ftell (accessfpin))
2081+ {
2082+ if (fprintf (accessfpout, line) < 0)
2083+ error (1, errno, "writing temporary file: %s", tmpaccessout);
2084+ }
2085+ else
2086+ {
2087+ if (fprintf (accessfpout, "%s\n", newline) < 0)
2088+ error (1, errno, "writing temporary file: %s", tmpaccessout);
2089+ }
2090+
2091+ }
2092+ if (fclose (accessfpin) == EOF)
2093+ error (1, errno, "cannot close access file: %s", accessfile);
2094+
2095+ if (fclose (accessfpout) == EOF)
2096+ error (1, errno, "cannot close temporary file: %s", tmpaccessout);
2097+
2098+ if (CVS_UNLINK (accessfile) < 0)
2099+ error (0, errno, "cannot remove %s", accessfile);
2100+
2101+ copy_file (tmpaccessout, accessfile);
2102+
2103+ if (CVS_UNLINK (tmpaccessout) < 0)
2104+ error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
2105+ }
2106+ else
2107+ {
2108+ accessfpout = open_accessfile ("r+", arepos, &accessfile);
2109+
2110+ if (accessfpout == NULL)
2111+ {
2112+ if (existence_error (errno))
2113+ {
2114+ accessfpout = open_accessfile ("w+", arepos, &accessfile);
2115+ }
2116+ }
2117+
2118+
2119+ if (fseek (accessfpout, 0, 2) != 0)
2120+ error (1, errno, "cannot fseek access file: %s", accessfile);
2121+
2122+ if (fprintf (accessfpout, "%s\n", newline) < 0)
2123+ error (1, errno, "writing access file: %s", accessfile);
2124+
2125+ if (fclose (accessfpout) == EOF)
2126+ error (1, errno, "cannot close access file: %s", accessfile);
2127+ }
2128+
2129+ free (newline);
2130+
2131+ chmod(accessfile, 0644);
2132+
2133+ return (0);
2134+}
2135+
2136+
2137+static int
2138+acllist_fileproc (callerdat, finfo)
2139+void *callerdat;
2140+struct file_info *finfo;
2141+{
2142+
2143+ char *filefullname;
2144+ const char *frepository;
2145+ char *line = NULL;
2146+ int pos;
2147+
2148+ if (!aclfile)
2149+ return (0);
2150+
2151+ frepository = Short_Repository (finfo->repository);
2152+
2153+ filefullname = xmalloc (strlen (frepository)
2154+ + strlen (finfo->file)
2155+ + 2);
2156+ strcpy (filefullname, frepository);
2157+ strcat (filefullname, "/");
2158+ strcat (filefullname, finfo->file);
2159+
2160+ if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos, 0))
2161+ error (1,0,"You do not have admin rights on '%s'", frepository);
2162+
2163+ /*if (line == NULL) {
2164+ acldir = 1;
2165+ inherited = 1;
2166+ if (!access_allowed (NULL, finfo->repository, tag, 5, &line, &pos, 0))
2167+ error (1, 0, "You do not have admin rights on '%s'", frepository);
2168+ acldir = 0;
2169+ }
2170+*/
2171+ acllist_print (line, filefullname);
2172+
2173+ return (0);
2174+}
2175+
2176+static Dtype
2177+acllist_dirproc (callerdat, dir, repos, update_dir, entries)
2178+void *callerdat;
2179+const char *dir;
2180+const char *repos;
2181+const char *update_dir;
2182+List *entries;
2183+{
2184+
2185+ char *line = NULL;
2186+ const char *drepository;
2187+ int pos;
2188+
2189+ if (repos[0] == '\0')
2190+ repos = Name_Repository (dir, NULL);
2191+
2192+ if (!acldir)
2193+ return (0);
2194+
2195+ drepository = Short_Repository (repos);
2196+
2197+ if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
2198+ error (1, 0, "You do not have admin rights on '%s'", drepository);
2199+
2200+ acllist_print (line, drepository);
2201+
2202+ return (0);
2203+}
2204+
2205+
2206+void
2207+acllist_print (line, obj)
2208+char *line;
2209+const char *obj;
2210+{
2211+ char *temp;
2212+ char *temp2;
2213+ int x;
2214+ int c = 0;
2215+
2216+ char *printedusers[255];
2217+ printedusers[0] = NULL;
2218+
2219+ if (line != NULL)
2220+ {
2221+ temp = strtok (line, ":\t");
2222+
2223+ if (acldir)
2224+ cvs_output ("d ", 0);
2225+ else if (aclfile)
2226+ cvs_output ("f ", 0);
2227+
2228+ temp = strtok (NULL, ":\t");
2229+
2230+ cvs_output(obj, 0);
2231+ cvs_output (" | ", 0);
2232+
2233+ temp = strtok (NULL, ":\t");
2234+ cvs_output (temp, 0);
2235+ cvs_output (" | ", 0);
2236+
2237+ while ((temp = strtok (NULL, "!\t")) != NULL)
2238+ {
2239+ if (strncmp (temp, ":", 1) == 0)
2240+ break;
2241+
2242+ if (strcmp (temp, "ALL") == 0)
2243+ {
2244+ temp = strtok (NULL, ",\t");
2245+ continue;
2246+ }
2247+
2248+ cvs_output (temp, 0);
2249+ cvs_output (":", 0);
2250+
2251+ while (printedusers[c] != NULL)
2252+ c++;
2253+
2254+ printedusers[c] = xstrdup (temp);
2255+ c++;
2256+ printedusers[c] = NULL;
2257+
2258+ temp = strtok (NULL, ",\t");
2259+
2260+ if (temp != NULL && temp[strlen (temp) - 2] == ':')
2261+ temp[strlen (temp) - 2] = '\0';
2262+
2263+ cvs_output (temp, 0);
2264+ cvs_output (" ", 0);
2265+ }
2266+
2267+ if (default_perms_object)
2268+ {
2269+ cvs_output ("| defaults ", 0);
2270+ cvs_output ("ALL:", 0);
2271+ cvs_output (default_perms_object, 0);
2272+ }
2273+ else if (default_part_perms_accessfile)
2274+ {
2275+ size_t i;
2276+ i = strlen (default_part_perms_accessfile);
2277+ xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
2278+
2279+ free(line);
2280+ line = xstrdup(default_part_perms_accessfile);
2281+
2282+ cvs_output ("| defaults ", 0);
2283+
2284+ temp = strtok (line, "!\t");
2285+ cvs_output (temp, 0);
2286+ cvs_output (":", 0);
2287+
2288+ temp = strtok (NULL, ",\t");
2289+
2290+ cvs_output (temp, 0);
2291+ cvs_output (" ", 0);
2292+
2293+ while ((temp = strtok (NULL, "!\t")) != NULL)
2294+ {
2295+ int printed = 0;
2296+ int c2 = 0;
2297+ while (printedusers[c2] != NULL && printed == 0)
2298+ {
2299+ if (strcmp (printedusers[c2], temp) == 0)
2300+ {
2301+ printed = 1;
2302+ break;
2303+ }
2304+ c2++;
2305+ }
2306+
2307+ if (printed == 0)
2308+ {
2309+ cvs_output (temp, 0);
2310+ cvs_output (":", 0);
2311+ }
2312+
2313+ temp = strtok (NULL, ",\t");
2314+
2315+ if (temp[strlen (temp) - 2] == ':')
2316+ temp[strlen (temp) - 2] = '\0';
2317+
2318+ if (printed == 0)
2319+ {
2320+ cvs_output (temp, 0);
2321+ cvs_output (" ", 0);
2322+ }
2323+ }
2324+ }
2325+ else if (cvs_acl_default_permissions)
2326+ {
2327+ cvs_output ("| defaults ", 0);
2328+ cvs_output ("ALL: ", 0);
2329+ cvs_output (cvs_acl_default_permissions, 0);
2330+ }
2331+
2332+ cvs_output ("\n", 0);
2333+
2334+ }
2335+ else
2336+ {
2337+ if (acldir)
2338+ cvs_output ("d ", 0);
2339+ else if (aclfile)
2340+ cvs_output ("f ", 0);
2341+ cvs_output (obj, 0);
2342+ cvs_output (" | ", 0);
2343+ cvs_output (tag, 0);
2344+ cvs_output (" | ", 0);
2345+
2346+ if (default_perms_object)
2347+ {
2348+ cvs_output ("| defaults ", 0);
2349+ cvs_output ("ALL:", 0);
2350+ cvs_output (default_perms_object, 0);
2351+ cvs_output ("\n", 0);
2352+ }
2353+ else if (default_part_perms_accessfile)
2354+ {
2355+ free(line);
2356+ line = xstrdup(default_part_perms_accessfile);
2357+
2358+ cvs_output ("| defaults ", 0);
2359+
2360+ temp = strtok (line, "!\t");
2361+ cvs_output (temp, 0);
2362+ cvs_output (":", 0);
2363+
2364+ temp = strtok (NULL, ",\t");
2365+
2366+ if (temp[strlen (temp) - 2] == ':')
2367+ temp[strlen (temp) - 2] = '\0';
2368+
2369+ cvs_output (temp, 0);
2370+ cvs_output (" ", 0);
2371+
2372+ while ((temp = strtok (NULL, "!\t")) != NULL)
2373+ {
2374+ cvs_output (temp, 0);
2375+ cvs_output (":", 0);
2376+
2377+ temp = strtok (NULL, ",\t");
2378+
2379+ if (temp[strlen (temp) - 2] == ':')
2380+ temp[strlen (temp) - 2] = '\0';
2381+
2382+ cvs_output (temp, 0);
2383+ cvs_output (" ", 0);
2384+ }
2385+ cvs_output ("\n", 0);
2386+ }
2387+ else if (cvs_acl_default_permissions)
2388+ {
2389+ cvs_output ("| defaults ", 0);
2390+ cvs_output ("ALL: ", 0);
2391+ cvs_output (cvs_acl_default_permissions, 0);
2392+ cvs_output ("\n", 0);
2393+ }
2394+ else
2395+ cvs_output ("default:p (no perms)\n", 0);
2396+ }
2397+
2398+}
2399diff -urN cvs-1.11.15/src/add.c cvs-1.11.15-cvsacl/src/add.c
2400--- cvs-1.11.15/src/add.c 2004-03-22 16:44:26.000000000 +0100
2401+++ cvs-1.11.15-cvsacl/src/add.c 2004-04-25 20:04:51.687856256 +0200
2402@@ -410,6 +410,24 @@
2403 }
2404 else
2405 {
2406+/* cvsacl patch */
2407+#ifdef SERVER_SUPPORT
2408+ if (use_cvs_acl && server_active)
2409+ {
2410+ if (!access_allowed (finfo.file, repository, vers->tag, 6,
2411+ NULL, NULL, 1))
2412+ {
2413+ if (stop_at_first_permission_denied)
2414+ error (1, 0, "permission denied for %s",
2415+ Short_Repository (finfo.repository));
2416+ else
2417+ error (0, 0, "permission denied for %s/%s",
2418+ Short_Repository (finfo.repository), finfo.file);
2419+
2420+ return (0);
2421+ }
2422+ }
2423+#endif
2424 /* There is a user file, so build the entry for it */
2425 if (build_entry (repository, finfo.file, vers->options,
2426 message, entries, vers->tag) != 0)
2427@@ -666,6 +684,26 @@
2428 && isdir (finfo.file)
2429 && !wrap_name_has (finfo.file, WRAP_TOCVS))
2430 {
2431+
2432+/* cvsacl patch */
2433+#ifdef SERVER_SUPPORT
2434+ if (use_cvs_acl && server_active)
2435+ {
2436+ if (!access_allowed (NULL, repository, NULL, 6,
2437+ NULL, NULL, 1))
2438+ {
2439+ if (stop_at_first_permission_denied)
2440+ error (1, 0, "permission denied for %s",
2441+ Short_Repository (finfo.repository));
2442+ else
2443+ error (0, 0, "permission denied for %s/%s",
2444+ Short_Repository (finfo.repository), finfo.file);
2445+
2446+ return (0);
2447+ }
2448+ }
2449+#endif
2450+
2451 err += add_directory (&finfo);
2452 }
2453 else
2454diff -urN cvs-1.11.15/src/annotate.c cvs-1.11.15-cvsacl/src/annotate.c
2455--- cvs-1.11.15/src/annotate.c 2004-03-22 16:44:27.000000000 +0100
2456+++ cvs-1.11.15-cvsacl/src/annotate.c 2004-04-25 20:04:51.689855952 +0200
2457@@ -276,6 +276,25 @@
2458 if (version == NULL)
2459 return 0;
2460
2461+/* cvsacl patch */
2462+#ifdef SERVER_SUPPORT
2463+ if (use_cvs_acl && server_active)
2464+ {
2465+ if (!access_allowed (finfo->file, finfo->repository, version, 5,
2466+ NULL, NULL, 1))
2467+ {
2468+ if (stop_at_first_permission_denied)
2469+ error (1, 0, "permission denied for %s",
2470+ Short_Repository (finfo->repository));
2471+ else
2472+ error (0, 0, "permission denied for %s/%s",
2473+ Short_Repository (finfo->repository), finfo->file);
2474+
2475+ return (0);
2476+ }
2477+ }
2478+#endif
2479+
2480 /* Distinguish output for various files if we are processing
2481 several files. */
2482 cvs_outerr ("\nAnnotations for ", 0);
2483diff -urN cvs-1.11.15/src/commit.c cvs-1.11.15-cvsacl/src/commit.c
2484--- cvs-1.11.15/src/commit.c 2004-04-01 20:53:22.000000000 +0200
2485+++ cvs-1.11.15-cvsacl/src/commit.c 2004-04-25 20:04:51.696854888 +0200
2486@@ -1276,6 +1276,34 @@
2487 return (0);
2488
2489 ci = p->data;
2490+
2491+/* cvsacl patch */
2492+#ifdef SERVER_SUPPORT
2493+ if (use_cvs_acl && server_active)
2494+ {
2495+ int whichperm;
2496+ if (ci->status == T_MODIFIED)
2497+ whichperm = 3;
2498+ else if (ci->status == T_ADDED)
2499+ whichperm = 6;
2500+ else if (ci->status == T_REMOVED)
2501+ whichperm = 7;
2502+
2503+ if (!access_allowed (finfo->file, finfo->repository, ci->tag, whichperm,
2504+ NULL, NULL, 1))
2505+ {
2506+ if (stop_at_first_permission_denied)
2507+ error (1, 0, "permission denied for %s",
2508+ Short_Repository (finfo->repository));
2509+ else
2510+ error (0, 0, "permission denied for %s/%s",
2511+ Short_Repository (finfo->repository), finfo->file);
2512+
2513+ return (0);
2514+ }
2515+ }
2516+#endif
2517+
2518 if (ci->status == T_MODIFIED)
2519 {
2520 if (finfo->rcs == NULL)
2521diff -urN cvs-1.11.15/src/cvs.h cvs-1.11.15-cvsacl/src/cvs.h
2522--- cvs-1.11.15/src/cvs.h 2004-04-01 20:53:22.000000000 +0200
2523+++ cvs-1.11.15-cvsacl/src/cvs.h 2004-04-25 20:05:38.416752384 +0200
2524@@ -191,6 +191,11 @@
2525 #define CVSROOTADM_PASSWD "passwd"
2526 #define CVSROOTADM_CONFIG "config"
2527
2528+/* cvsacl patch */
2529+#define CVSROOTADM_ACLCONFIG "aclconfig"
2530+#define CVSROOTADM_ACCESS "access"
2531+#define CVSROOTADM_GROUP "group"
2532+
2533 #define CVSNULLREPOS "Emptydir" /* an empty directory */
2534
2535 /* Other CVS file names */
2536@@ -567,6 +572,18 @@
2537 /* LockDir setting from CVSROOT/config. */
2538 extern char *lock_dir;
2539
2540+/* cvsacl patch */
2541+/* ACL Patch settings from CVSROOT/config */
2542+extern int use_cvs_acl;
2543+extern char *cvs_acl_default_permissions;
2544+extern int use_cvs_groups;
2545+extern int use_system_groups;
2546+extern int use_seperate_acl_file_for_each_dir;
2547+extern char *cvs_acl_file_location;
2548+extern char *cvs_groups_file_location;
2549+extern char *cvs_server_run_as;
2550+extern int stop_at_first_permission_denied;
2551+
2552 void Scratch_Entry PROTO((List * list, const char *fname));
2553 void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp));
2554 void WriteTag PROTO ((const char *dir, const char *tag, const char *date,
2555@@ -863,6 +880,10 @@
2556 int editors PROTO ((int argc, char **argv));
2557 int watchers PROTO ((int argc, char **argv));
2558 extern int annotate PROTO ((int argc, char **argv));
2559+
2560+/* cvsacl patch */
2561+extern int cvsacl PROTO ((int argc, char **argv));
2562+
2563 extern int add PROTO ((int argc, char **argv));
2564 extern int admin PROTO ((int argc, char **argv));
2565 extern int checkout PROTO ((int argc, char **argv));
2566diff -urN cvs-1.11.15/src/diff.c cvs-1.11.15-cvsacl/src/diff.c
2567--- cvs-1.11.15/src/diff.c 2004-03-20 03:06:45.000000000 +0100
2568+++ cvs-1.11.15-cvsacl/src/diff.c 2004-04-25 20:04:51.708853064 +0200
2569@@ -474,6 +474,43 @@
2570 {
2571 /* Skip all the following checks regarding the user file; we're
2572 not using it. */
2573+
2574+/* cvsacl patch */
2575+#ifdef SERVER_SUPPORT
2576+ if (use_cvs_acl && server_active)
2577+ {
2578+ if (diff_rev1)
2579+ {
2580+ if (!access_allowed (NULL, finfo->repository, diff_rev1, 5,
2581+ NULL, NULL, 1))
2582+ {
2583+ if (stop_at_first_permission_denied)
2584+ error (1, 0, "permission denied for %s",
2585+ Short_Repository (finfo->repository));
2586+ else
2587+ error (0, 0, "permission denied for %s/%s",
2588+ Short_Repository (finfo->repository), finfo->file);
2589+
2590+ return (0);
2591+ }
2592+ }
2593+ if (diff_rev2)
2594+ {
2595+ if (!access_allowed (NULL, finfo->repository, diff_rev2, 5))
2596+ {
2597+ if (stop_at_first_permission_denied)
2598+ error (1, 0, "permission denied for %s",
2599+ Short_Repository (finfo->repository));
2600+ else
2601+ error (0, 0, "permission denied for %s/%s",
2602+ Short_Repository (finfo->repository), finfo->file);
2603+
2604+ return (0);
2605+ }
2606+ }
2607+ }
2608+#endif
2609+
2610 }
2611 else if (vers->vn_user == NULL)
2612 {
2613@@ -827,6 +864,42 @@
2614 if (!isdir (dir))
2615 return (R_SKIP_ALL);
2616
2617+/* cvsacl patch */
2618+#ifdef SERVER_SUPPORT
2619+ if (use_cvs_acl && server_active)
2620+ {
2621+ if (diff_rev1)
2622+ {
2623+ if (!access_allowed (NULL, update_dir, diff_rev1, 5,
2624+ NULL, NULL, 1))
2625+ {
2626+ if (stop_at_first_permission_denied)
2627+ error (1, 0, "permission denied for %s",
2628+ Short_Repository (update_dir));
2629+ else
2630+ error (0, 0, "permission denied for %s/%s",
2631+ Short_Repository (update_dir), update_dir);
2632+
2633+ return (0);
2634+ }
2635+ }
2636+ if (diff_rev2)
2637+ {
2638+ if (!access_allowed (NULL, update_dir, diff_rev2, 5))
2639+ {
2640+ if (stop_at_first_permission_denied)
2641+ error (1, 0, "permission denied for %s",
2642+ Short_Repository (update_dir));
2643+ else
2644+ error (0, 0, "permission denied for %s/%s",
2645+ Short_Repository (update_dir), update_dir);
2646+
2647+ return (0);
2648+ }
2649+ }
2650+ }
2651+#endif
2652+
2653 if (!quiet)
2654 error (0, 0, "Diffing %s", update_dir);
2655 return (R_PROCESS);
2656diff -urN cvs-1.11.15/src/import.c cvs-1.11.15-cvsacl/src/import.c
2657--- cvs-1.11.15/src/import.c 2004-04-02 20:55:49.000000000 +0200
2658+++ cvs-1.11.15-cvsacl/src/import.c 2004-04-25 20:04:51.714852152 +0200
2659@@ -304,6 +304,20 @@
2660 error (1, 0, "attempt to import the repository");
2661 }
2662
2663+/* cvsacl patch */
2664+#ifdef SERVER_SUPPORT
2665+ if (use_cvs_acl && server_active)
2666+ {
2667+ if (!access_allowed (NULL, repository, argv[1], 6, NULL, NULL, 1))
2668+ {
2669+ error (stop_at_first_permission_denied, 0, "permission denied for %s",
2670+ Short_Repository (repository));
2671+
2672+ return (0);
2673+ }
2674+ }
2675+#endif
2676+
2677 /*
2678 * Make all newly created directories writable. Should really use a more
2679 * sophisticated security mechanism here.
2680diff -urN cvs-1.11.15/src/log.c cvs-1.11.15-cvsacl/src/log.c
2681--- cvs-1.11.15/src/log.c 2004-04-06 20:54:52.000000000 +0200
2682+++ cvs-1.11.15-cvsacl/src/log.c 2004-04-25 20:04:51.722850936 +0200
2683@@ -837,6 +837,25 @@
2684 return 1;
2685 }
2686
2687+/* cvsacl patch */
2688+#ifdef SERVER_SUPPORT
2689+ if (use_cvs_acl && server_active)
2690+ {
2691+ if (!access_allowed (finfo->file, finfo->repository, NULL, 5,
2692+ NULL, NULL, 1))
2693+ {
2694+ if (stop_at_first_permission_denied)
2695+ error (1, 0, "permission denied for %s",
2696+ Short_Repository (finfo->repository));
2697+ else
2698+ error (0, 0, "permission denied for %s/%s",
2699+ Short_Repository (finfo->repository), finfo->file);
2700+
2701+ return (0);
2702+ }
2703+ }
2704+#endif
2705+
2706 if (log_data->sup_header || !log_data->nameonly)
2707 {
2708
2709diff -urN cvs-1.11.15/src/main.c cvs-1.11.15-cvsacl/src/main.c
2710--- cvs-1.11.15/src/main.c 2004-03-22 16:44:27.000000000 +0100
2711+++ cvs-1.11.15-cvsacl/src/main.c 2004-04-25 20:04:51.726850328 +0200
2712@@ -104,6 +104,10 @@
2713 } cmds[] =
2714
2715 {
2716+ /* cvsacl patch */
2717+ { "acl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2718+ { "racl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2719+
2720 { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2721 { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2722 { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR },
2723@@ -974,6 +978,9 @@
2724 if we didn't, then there would be no way to check in a new
2725 CVSROOT/config file to fix the broken one! */
2726 parse_config (current_parsed_root->directory);
2727+
2728+ /* cvsacl patch */
2729+ parse_aclconfig (current_parsed_root->directory);
2730 }
2731
2732 #ifdef CLIENT_SUPPORT
2733diff -urN cvs-1.11.15/src/Makefile.am cvs-1.11.15-cvsacl/src/Makefile.am
2734--- cvs-1.11.15/src/Makefile.am 2004-02-03 20:05:36.000000000 +0100
2735+++ cvs-1.11.15-cvsacl/src/Makefile.am 2004-04-25 20:04:51.728850024 +0200
2736@@ -29,6 +29,7 @@
2737
2738 # The cvs executable
2739 cvs_SOURCES = \
2740+ acl.c \
2741 add.c \
2742 admin.c \
2743 annotate.c \
2744diff -urN cvs-1.11.15/src/Makefile.in cvs-1.11.15-cvsacl/src/Makefile.in
2745--- cvs-1.11.15/src/Makefile.in 2004-04-14 04:42:00.000000000 +0200
2746+++ cvs-1.11.15-cvsacl/src/Makefile.in 2004-04-25 20:04:51.732849416 +0200
2747@@ -153,6 +153,7 @@
2748
2749 # The cvs executable
2750 cvs_SOURCES = \
2751+ acl.c \
2752 add.c \
2753 admin.c \
2754 annotate.c \
2755@@ -253,11 +254,11 @@
2756 bin_PROGRAMS = cvs$(EXEEXT)
2757 PROGRAMS = $(bin_PROGRAMS)
2758
2759-am_cvs_OBJECTS = add.$(OBJEXT) admin.$(OBJEXT) annotate.$(OBJEXT) \
2760- buffer.$(OBJEXT) checkin.$(OBJEXT) checkout.$(OBJEXT) \
2761- classify.$(OBJEXT) client.$(OBJEXT) commit.$(OBJEXT) \
2762- create_adm.$(OBJEXT) cvsrc.$(OBJEXT) diff.$(OBJEXT) \
2763- edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
2764+am_cvs_OBJECTS = acl.$(OBJEXT) add.$(OBJEXT) admin.$(OBJEXT) \
2765+ annotate.$(OBJEXT) buffer.$(OBJEXT) checkin.$(OBJEXT) \
2766+ checkout.$(OBJEXT) classify.$(OBJEXT) client.$(OBJEXT) \
2767+ commit.$(OBJEXT) create_adm.$(OBJEXT) cvsrc.$(OBJEXT) \
2768+ diff.$(OBJEXT) edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
2769 expand_path.$(OBJEXT) fileattr.$(OBJEXT) filesubr.$(OBJEXT) \
2770 find_names.$(OBJEXT) hardlink.$(OBJEXT) hash.$(OBJEXT) \
2771 history.$(OBJEXT) ignore.$(OBJEXT) import.$(OBJEXT) \
2772@@ -280,34 +281,34 @@
2773 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
2774 depcomp = $(SHELL) $(top_srcdir)/depcomp
2775 am__depfiles_maybe = depfiles
2776-@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/add.Po ./$(DEPDIR)/admin.Po \
2777-@AMDEP_TRUE@ ./$(DEPDIR)/annotate.Po ./$(DEPDIR)/buffer.Po \
2778-@AMDEP_TRUE@ ./$(DEPDIR)/checkin.Po ./$(DEPDIR)/checkout.Po \
2779-@AMDEP_TRUE@ ./$(DEPDIR)/classify.Po ./$(DEPDIR)/client.Po \
2780-@AMDEP_TRUE@ ./$(DEPDIR)/commit.Po ./$(DEPDIR)/create_adm.Po \
2781-@AMDEP_TRUE@ ./$(DEPDIR)/cvsrc.Po ./$(DEPDIR)/diff.Po \
2782-@AMDEP_TRUE@ ./$(DEPDIR)/edit.Po ./$(DEPDIR)/entries.Po \
2783-@AMDEP_TRUE@ ./$(DEPDIR)/error.Po ./$(DEPDIR)/expand_path.Po \
2784-@AMDEP_TRUE@ ./$(DEPDIR)/fileattr.Po ./$(DEPDIR)/filesubr.Po \
2785-@AMDEP_TRUE@ ./$(DEPDIR)/find_names.Po ./$(DEPDIR)/hardlink.Po \
2786-@AMDEP_TRUE@ ./$(DEPDIR)/hash.Po ./$(DEPDIR)/history.Po \
2787-@AMDEP_TRUE@ ./$(DEPDIR)/ignore.Po ./$(DEPDIR)/import.Po \
2788-@AMDEP_TRUE@ ./$(DEPDIR)/lock.Po ./$(DEPDIR)/log.Po \
2789-@AMDEP_TRUE@ ./$(DEPDIR)/login.Po ./$(DEPDIR)/logmsg.Po \
2790-@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/mkmodules.Po \
2791-@AMDEP_TRUE@ ./$(DEPDIR)/modules.Po ./$(DEPDIR)/myndbm.Po \
2792-@AMDEP_TRUE@ ./$(DEPDIR)/no_diff.Po ./$(DEPDIR)/parseinfo.Po \
2793-@AMDEP_TRUE@ ./$(DEPDIR)/patch.Po ./$(DEPDIR)/rcs.Po \
2794-@AMDEP_TRUE@ ./$(DEPDIR)/rcscmds.Po ./$(DEPDIR)/recurse.Po \
2795-@AMDEP_TRUE@ ./$(DEPDIR)/release.Po ./$(DEPDIR)/remove.Po \
2796-@AMDEP_TRUE@ ./$(DEPDIR)/repos.Po ./$(DEPDIR)/root.Po \
2797-@AMDEP_TRUE@ ./$(DEPDIR)/run.Po ./$(DEPDIR)/scramble.Po \
2798-@AMDEP_TRUE@ ./$(DEPDIR)/server.Po ./$(DEPDIR)/stack.Po \
2799-@AMDEP_TRUE@ ./$(DEPDIR)/status.Po ./$(DEPDIR)/subr.Po \
2800-@AMDEP_TRUE@ ./$(DEPDIR)/tag.Po ./$(DEPDIR)/update.Po \
2801-@AMDEP_TRUE@ ./$(DEPDIR)/vers_ts.Po ./$(DEPDIR)/version.Po \
2802-@AMDEP_TRUE@ ./$(DEPDIR)/watch.Po ./$(DEPDIR)/wrapper.Po \
2803-@AMDEP_TRUE@ ./$(DEPDIR)/zlib.Po
2804+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/acl.Po ./$(DEPDIR)/add.Po \
2805+@AMDEP_TRUE@ ./$(DEPDIR)/admin.Po ./$(DEPDIR)/annotate.Po \
2806+@AMDEP_TRUE@ ./$(DEPDIR)/buffer.Po ./$(DEPDIR)/checkin.Po \
2807+@AMDEP_TRUE@ ./$(DEPDIR)/checkout.Po ./$(DEPDIR)/classify.Po \
2808+@AMDEP_TRUE@ ./$(DEPDIR)/client.Po ./$(DEPDIR)/commit.Po \
2809+@AMDEP_TRUE@ ./$(DEPDIR)/create_adm.Po ./$(DEPDIR)/cvsrc.Po \
2810+@AMDEP_TRUE@ ./$(DEPDIR)/diff.Po ./$(DEPDIR)/edit.Po \
2811+@AMDEP_TRUE@ ./$(DEPDIR)/entries.Po ./$(DEPDIR)/error.Po \
2812+@AMDEP_TRUE@ ./$(DEPDIR)/expand_path.Po ./$(DEPDIR)/fileattr.Po \
2813+@AMDEP_TRUE@ ./$(DEPDIR)/filesubr.Po ./$(DEPDIR)/find_names.Po \
2814+@AMDEP_TRUE@ ./$(DEPDIR)/hardlink.Po ./$(DEPDIR)/hash.Po \
2815+@AMDEP_TRUE@ ./$(DEPDIR)/history.Po ./$(DEPDIR)/ignore.Po \
2816+@AMDEP_TRUE@ ./$(DEPDIR)/import.Po ./$(DEPDIR)/lock.Po \
2817+@AMDEP_TRUE@ ./$(DEPDIR)/log.Po ./$(DEPDIR)/login.Po \
2818+@AMDEP_TRUE@ ./$(DEPDIR)/logmsg.Po ./$(DEPDIR)/main.Po \
2819+@AMDEP_TRUE@ ./$(DEPDIR)/mkmodules.Po ./$(DEPDIR)/modules.Po \
2820+@AMDEP_TRUE@ ./$(DEPDIR)/myndbm.Po ./$(DEPDIR)/no_diff.Po \
2821+@AMDEP_TRUE@ ./$(DEPDIR)/parseinfo.Po ./$(DEPDIR)/patch.Po \
2822+@AMDEP_TRUE@ ./$(DEPDIR)/rcs.Po ./$(DEPDIR)/rcscmds.Po \
2823+@AMDEP_TRUE@ ./$(DEPDIR)/recurse.Po ./$(DEPDIR)/release.Po \
2824+@AMDEP_TRUE@ ./$(DEPDIR)/remove.Po ./$(DEPDIR)/repos.Po \
2825+@AMDEP_TRUE@ ./$(DEPDIR)/root.Po ./$(DEPDIR)/run.Po \
2826+@AMDEP_TRUE@ ./$(DEPDIR)/scramble.Po ./$(DEPDIR)/server.Po \
2827+@AMDEP_TRUE@ ./$(DEPDIR)/stack.Po ./$(DEPDIR)/status.Po \
2828+@AMDEP_TRUE@ ./$(DEPDIR)/subr.Po ./$(DEPDIR)/tag.Po \
2829+@AMDEP_TRUE@ ./$(DEPDIR)/update.Po ./$(DEPDIR)/vers_ts.Po \
2830+@AMDEP_TRUE@ ./$(DEPDIR)/version.Po ./$(DEPDIR)/watch.Po \
2831+@AMDEP_TRUE@ ./$(DEPDIR)/wrapper.Po ./$(DEPDIR)/zlib.Po
2832 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
2833 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
2834 CCLD = $(CC)
2835@@ -381,6 +382,7 @@
2836 distclean-compile:
2837 -rm -f *.tab.c
2838
2839+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl.Po@am__quote@
2840 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add.Po@am__quote@
2841 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/admin.Po@am__quote@
2842 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate.Po@am__quote@
2843diff -urN cvs-1.11.15/src/mkmodules.c cvs-1.11.15-cvsacl/src/mkmodules.c
2844--- cvs-1.11.15/src/mkmodules.c 2004-02-03 15:39:40.000000000 +0100
2845+++ cvs-1.11.15-cvsacl/src/mkmodules.c 2004-04-25 20:04:51.736848808 +0200
2846@@ -311,6 +311,44 @@
2847 NULL
2848 };
2849
2850+/* cvsacl patch */
2851+static const char *const aclconfig_contents[] = {
2852+ "# Set `UseCVSACL' to yes to use CVSACL feature.\n",
2853+ "UseCVSACL=yes\n",
2854+ "\n",
2855+ "# Default CVSACL Permission to use.\n",
2856+ "#CVSACLDefaultPermissions=p\n",
2857+ "\n",
2858+ "# Default file location for CVS ACL file (access) is CVSROOT/access.\n",
2859+ "# If you want to use a different location, define it below.\n",
2860+ "#CVSACLFileLocation=/path/to/cvs/access\n",
2861+ "\n",
2862+ "# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).\n",
2863+ "UseSystemGroups=yes\n",
2864+ "\n",
2865+ "# Set `UseCVSGroups' to yes to use another group file.\n",
2866+ "#UseCVSGroups=yes\n",
2867+ "\n",
2868+ "# Default file location for CVS groups file is CVSROOT/group.\n",
2869+ "# If you want to use a different location, define it below.\n",
2870+ "#CVSGroupsFileLocation=/path/to/cvs/group\n",
2871+ "\n",
2872+ "# Set UseSeperateACLFileForEachDir to yes in order to use a\n",
2873+ "# seperate 'access' file for each directory.\n",
2874+ "# This increased the performance if you have really big repository.\n",
2875+ "#UseSeperateACLFileForEachDir=no\n",
2876+ "\n",
2877+ "# If StopAtFirstPermissionDenied is set to yes\n",
2878+ "# operation will stop at first permission denied message.\n",
2879+ "# Default is no.\n",
2880+ "#StopAtFirstPermissionDenied=no\n",
2881+ "\n",
2882+ "# Set CVSServerRunAsUser to a system user, in order CVS server\n",
2883+ "# to run as.\n",
2884+ "#CVSServerRunAsUser=runascvsuser",
2885+ NULL
2886+};
2887+
2888 static const struct admin_file filelist[] = {
2889 {CVSROOTADM_LOGINFO,
2890 "no logging of 'cvs commit' messages is done without a %s file",
2891@@ -373,7 +411,12 @@
2892 {CVSROOTADM_CONFIG,
2893 "a %s file configures various behaviors",
2894 config_contents},
2895- {NULL, NULL, NULL}
2896+
2897+ /* cvsacl patch */
2898+ {CVSROOTADM_ACLCONFIG,
2899+ "a %s file configures Access Control List behaviors",
2900+ aclconfig_contents},
2901+ {NULL, NULL, NULL}
2902 };
2903
2904 /* Rebuild the checked out administrative files in directory DIR. */
2905@@ -957,6 +1000,26 @@
2906 because xchmod() is too shy. */
2907 chmod (info, 0666);
2908 }
2909+
2910+ /* cvsacl patch */
2911+ /* Make an empty 'CVSROOT/access' file */
2912+ strcpy (info, adm);
2913+ strcat (info, "/");
2914+ strcat (info, CVSROOTADM_ACCESS);
2915+ if (!isfile (info))
2916+ {
2917+ FILE *fp;
2918+
2919+ fp = open_file (info, "w");
2920+ if (fputs ("# CVS ACL definitions file. DO NOT EDIT MANUALLY\n",
2921+ fp) < 0)
2922+ error (1, errno, "cannot write %s", info);
2923+
2924+ if (fclose (fp) < 0)
2925+ error (1, errno, "cannot close %s", info);
2926+
2927+ chmod (info, 0644);
2928+ }
2929
2930 /* Make an empty val-tags file to prevent problems creating it later. */
2931 strcpy (info, adm);
2932diff -urN cvs-1.11.15/src/parseinfo.c cvs-1.11.15-cvsacl/src/parseinfo.c
2933--- cvs-1.11.15/src/parseinfo.c 2004-03-19 21:36:39.000000000 +0100
2934+++ cvs-1.11.15-cvsacl/src/parseinfo.c 2004-04-25 20:04:51.740848200 +0200
2935@@ -448,3 +448,192 @@
2936 free (line);
2937 return -1;
2938 }
2939+/* cvsacl patch */
2940+int
2941+parse_aclconfig (cvsroot)
2942+ char *cvsroot;
2943+{
2944+ char *infopath;
2945+ FILE *fp_info;
2946+ char *line = NULL;
2947+ size_t line_allocated = 0;
2948+ size_t len;
2949+ char *p;
2950+ /* FIXME-reentrancy: If we do a multi-threaded server, this would need
2951+ to go to the per-connection data structures. */
2952+ static int parsed = 0;
2953+
2954+ /* Authentication code and serve_root might both want to call us.
2955+ Let this happen smoothly. */
2956+ if (parsed)
2957+ return 0;
2958+ parsed = 1;
2959+
2960+ infopath = xmalloc (strlen (cvsroot)
2961+ + sizeof (CVSROOTADM_ACLCONFIG)
2962+ + sizeof (CVSROOTADM)
2963+ + 10);
2964+ if (infopath == NULL)
2965+ {
2966+ error (0, 0, "out of memory; cannot allocate infopath");
2967+ goto error_return;
2968+ }
2969+
2970+ strcpy (infopath, cvsroot);
2971+ strcat (infopath, "/");
2972+ strcat (infopath, CVSROOTADM);
2973+ strcat (infopath, "/");
2974+ strcat (infopath, CVSROOTADM_ACLCONFIG);
2975+
2976+ fp_info = CVS_FOPEN (infopath, "r");
2977+ if (fp_info == NULL)
2978+ {
2979+ /* If no file, don't do anything special. */
2980+ if (!existence_error (errno))
2981+ {
2982+ /* Just a warning message; doesn't affect return
2983+ value, currently at least. */
2984+ error (0, errno, "cannot open %s", infopath);
2985+ }
2986+ free (infopath);
2987+ return 0;
2988+ }
2989+
2990+ while (getline (&line, &line_allocated, fp_info) >= 0)
2991+ {
2992+ /* Skip comments. */
2993+ if (line[0] == '#')
2994+ continue;
2995+
2996+ len = strlen (line) - 1;
2997+ if (line[len] == '\n')
2998+ line[len] = '\0';
2999+
3000+ /* Skip blank lines. */
3001+ if (line[0] == '\0')
3002+ continue;
3003+
3004+ /* The first '=' separates keyword from value. */
3005+ p = strchr (line, '=');
3006+ if (p == NULL)
3007+ {
3008+ /* Probably should be printing line number. */
3009+ error (0, 0, "syntax error in %s: line '%s' is missing '='",
3010+ infopath, line);
3011+ goto error_return;
3012+ }
3013+
3014+ *p++ = '\0';
3015+
3016+ if (strcmp (line, "UseCVSACL") == 0)
3017+ {
3018+ if (strcmp (p, "no") == 0)
3019+ use_cvs_acl = 0;
3020+ else if (strcmp (p, "yes") == 0)
3021+ use_cvs_acl = 1;
3022+ else
3023+ {
3024+ error (0, 0, "unrecognized value '%s' for UseCVSACL", p);
3025+ goto error_return;
3026+ }
3027+ }
3028+ else if (strcmp (line, "UseSeperateACLFileForEachDir") == 0)
3029+ {
3030+ if (strcmp (p, "no") == 0)
3031+ use_seperate_acl_file_for_each_dir = 0;
3032+ else if (strcmp (p, "yes") == 0)
3033+ use_seperate_acl_file_for_each_dir = 1;
3034+ else
3035+ {
3036+ error (0, 0, "unrecognized value '%s' for UseSeperateACLFileForEachDir", p);
3037+ goto error_return;
3038+ }
3039+ }
3040+ else if (strcmp (line, "StopAtFirstPermissionDenied") == 0)
3041+ {
3042+ if (strcmp (p, "no") == 0)
3043+ stop_at_first_permission_denied = 0;
3044+ else if (strcmp (p, "yes") == 0)
3045+ stop_at_first_permission_denied = 1;
3046+ else
3047+ {
3048+ error (0, 0, "unrecognized value '%s' for StopAtFirstPermissionDenied", p);
3049+ goto error_return;
3050+ }
3051+ }
3052+ else if (strcmp (line, "CVSACLDefaultPermissions") == 0)
3053+ {
3054+ if (cvs_acl_default_permissions != NULL)
3055+ free (cvs_acl_default_permissions);
3056+ if (!given_perms_valid (p))
3057+ error (1,0,"Invalid CVS ACL Default Permissions: '%s' in CVSROOT/aclconfig", p);
3058+ cvs_acl_default_permissions = xstrdup (p);
3059+ }
3060+ else if (strcmp (line, "UseCVSGroups") == 0)
3061+ {
3062+ if (strcmp (p, "no") == 0)
3063+ use_cvs_groups = 0;
3064+ else if (strcmp (p, "yes") == 0)
3065+ use_cvs_groups = 1;
3066+ else
3067+ {
3068+ error (0, 0, "unrecognized value '%s' for UseCVSGroups", p);
3069+ goto error_return;
3070+ }
3071+ }
3072+ else if (strcmp (line, "UseSystemGroups") == 0)
3073+ {
3074+ if (strcmp (p, "no") == 0)
3075+ use_system_groups = 0;
3076+ else if (strcmp (p, "yes") == 0)
3077+ use_system_groups = 1;
3078+ else
3079+ {
3080+ error (0, 0, "unrecognized value '%s' for UseSystemGroups", p);
3081+ goto error_return;
3082+ }
3083+ }
3084+ else if (strcmp (line, "CVSACLFileLocation") == 0)
3085+ {
3086+ if (cvs_acl_file_location != NULL)
3087+ free (cvs_acl_file_location);
3088+ cvs_acl_file_location = xstrdup (p);
3089+ }
3090+ else if (strcmp (line, "CVSGroupsFileLocation") == 0)
3091+ {
3092+ if (cvs_groups_file_location != NULL)
3093+ free (cvs_groups_file_location);
3094+ cvs_groups_file_location = xstrdup (p);
3095+ }
3096+ else if (strcmp (line, "CVSServerRunAsUser") == 0)
3097+ {
3098+ if (cvs_server_run_as != NULL)
3099+ free (cvs_server_run_as);
3100+ cvs_server_run_as = xstrdup (p);
3101+ }
3102+
3103+ }
3104+
3105+ if (ferror (fp_info))
3106+ {
3107+ error (0, errno, "cannot read %s", infopath);
3108+ goto error_return;
3109+ }
3110+ if (fclose (fp_info) < 0)
3111+ {
3112+ error (0, errno, "cannot close %s", infopath);
3113+ goto error_return;
3114+ }
3115+ free (infopath);
3116+ if (line != NULL)
3117+ free (line);
3118+ return 0;
3119+
3120+ error_return:
3121+ if (infopath != NULL)
3122+ free (infopath);
3123+ if (line != NULL)
3124+ free (line);
3125+ return -1;
3126+}
3127+
3128diff -urN cvs-1.11.15/src/patch.c cvs-1.11.15-cvsacl/src/patch.c
3129--- cvs-1.11.15/src/patch.c 2004-04-02 21:25:32.000000000 +0200
3130+++ cvs-1.11.15-cvsacl/src/patch.c 2004-04-25 20:04:51.744847592 +0200
3131@@ -498,6 +498,43 @@
3132 goto out2;
3133 }
3134
3135+/* cvsacl patch */
3136+#ifdef SERVER_SUPPORT
3137+ if (use_cvs_acl && server_active)
3138+ {
3139+ if (rev1)
3140+ {
3141+ if (!access_allowed (finfo->file, finfo->repository, rev1, 5,
3142+ NULL, NULL, 1))
3143+ {
3144+ if (stop_at_first_permission_denied)
3145+ error (1, 0, "permission denied for %s",
3146+ Short_Repository (finfo->repository));
3147+ else
3148+ error (0, 0, "permission denied for %s/%s",
3149+ Short_Repository (finfo->repository), finfo->file);
3150+
3151+ return (0);
3152+ }
3153+ }
3154+ if (rev2)
3155+ {
3156+ if (!access_allowed (finfo->file, finfo->repository, rev2, 5,
3157+ NULL, NULL, 1))
3158+ {
3159+ if (stop_at_first_permission_denied)
3160+ error (1, 0, "permission denied for %s",
3161+ Short_Repository (finfo->repository));
3162+ else
3163+ error (0, 0, "permission denied for %s/%s",
3164+ Short_Repository (finfo->repository), finfo->file);
3165+
3166+ return (0);
3167+ }
3168+ }
3169+ }
3170+#endif
3171+
3172 /* Create 3 empty files. I'm not really sure there is any advantage
3173 * to doing so now rather than just waiting until later.
3174 *
3175diff -urN cvs-1.11.15/src/remove.c cvs-1.11.15-cvsacl/src/remove.c
3176--- cvs-1.11.15/src/remove.c 2004-03-20 03:34:32.000000000 +0100
3177+++ cvs-1.11.15-cvsacl/src/remove.c 2004-04-25 20:04:51.746847288 +0200
3178@@ -250,6 +250,25 @@
3179 {
3180 char *fname;
3181
3182+/* cvsacl patch */
3183+#ifdef SERVER_SUPPORT
3184+ if (use_cvs_acl && server_active)
3185+ {
3186+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 7,
3187+ NULL, NULL, 1))
3188+ {
3189+ if (stop_at_first_permission_denied)
3190+ error (1, 0, "permission denied for %s",
3191+ Short_Repository (finfo->repository));
3192+ else
3193+ error (0, 0, "permission denied for %s/%s",
3194+ Short_Repository (finfo->repository), finfo->file);
3195+
3196+ return (0);
3197+ }
3198+ }
3199+#endif
3200+
3201 /* Re-register it with a negative version number. */
3202 fname = xmalloc (strlen (vers->vn_user) + 5);
3203 (void) strcpy (fname, "-");
3204diff -urN cvs-1.11.15/src/server.c cvs-1.11.15-cvsacl/src/server.c
3205--- cvs-1.11.15/src/server.c 2004-04-06 22:20:55.000000000 +0200
3206+++ cvs-1.11.15-cvsacl/src/server.c 2004-04-25 20:30:27.889318136 +0200
3207@@ -773,6 +773,10 @@
3208 nothing. But for rsh, we need to do it now. */
3209 parse_config (current_parsed_root->directory);
3210
3211+ /* cvsacl patch */
3212+ parse_aclconfig (current_parsed_root->directory);
3213+
3214+
3215 path = xmalloc (strlen (current_parsed_root->directory)
3216 + sizeof (CVSROOTADM)
3217 + 2);
3218@@ -3667,6 +3671,23 @@
3219 do_cvs_command ("rlog", cvslog);
3220 }
3221
3222+/* cvsacl patch */
3223+static void
3224+serve_acl (arg)
3225+ char *arg;
3226+{
3227+ do_cvs_command ("acl", cvsacl);
3228+}
3229+
3230+/* cvsacl patch */
3231+static void
3232+serve_racl (arg)
3233+ char *arg;
3234+{
3235+ cvs_cmd_name = "racl";
3236+ do_cvs_command ("racl", cvsacl);
3237+}
3238+
3239 static void
3240 serve_add (arg)
3241 char *arg;
3242@@ -4726,6 +4747,11 @@
3243 REQ_LINE("diff", serve_diff, 0),
3244 REQ_LINE("log", serve_log, 0),
3245 REQ_LINE("rlog", serve_rlog, 0),
3246+
3247+ /* cvsacl patch */
3248+ REQ_LINE("acl", serve_acl, 0),
3249+ REQ_LINE("racl", serve_racl, 0),
3250+
3251 REQ_LINE("add", serve_add, 0),
3252 REQ_LINE("remove", serve_remove, 0),
3253 REQ_LINE("update-patches", serve_ignore, 0),
3254@@ -5199,6 +5225,10 @@
3255 {
3256 struct passwd *pw;
3257
3258+ /* cvsacl patch */
3259+ if (use_cvs_acl && cvs_server_run_as)
3260+ username = cvs_server_run_as;
3261+
3262 pw = getpwnam (username);
3263 if (pw == NULL)
3264 {
3265@@ -5781,6 +5811,9 @@
3266 in a new CVSROOT/config file to fix the broken one! */
3267 parse_config (repository);
3268
3269+ /* cvsacl patch */
3270+ parse_aclconfig (repository);
3271+
3272 /* We need the real cleartext before we hash it. */
3273 descrambled_password = descramble (password);
3274 host_user = check_password (username, descrambled_password, repository);
3275diff -urN cvs-1.11.15/src/status.c cvs-1.11.15-cvsacl/src/status.c
3276--- cvs-1.11.15/src/status.c 2004-03-20 02:40:12.000000000 +0100
3277+++ cvs-1.11.15-cvsacl/src/status.c 2004-04-25 20:04:51.767844096 +0200
3278@@ -128,7 +128,27 @@
3279
3280 status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
3281 1, 0, &vers, 0);
3282- sstat = "Classify Error";
3283+
3284+/* cvsacl patch */
3285+#ifdef SERVER_SUPPORT
3286+ if (use_cvs_acl && server_active)
3287+ {
3288+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5,
3289+ NULL, NULL, 1))
3290+ {
3291+ if (stop_at_first_permission_denied)
3292+ error (1, 0, "permission denied for %s",
3293+ Short_Repository (finfo->repository));
3294+ else
3295+ error (0, 0, "permission denied for %s/%s",
3296+ Short_Repository (finfo->repository), finfo->file);
3297+
3298+ return (0);
3299+ }
3300+ }
3301+#endif
3302+
3303+ sstat = "Classify Error";
3304 switch (status)
3305 {
3306 case T_UNKNOWN:
3307diff -urN cvs-1.11.15/src/tag.c cvs-1.11.15-cvsacl/src/tag.c
3308--- cvs-1.11.15/src/tag.c 2004-04-06 20:37:10.000000000 +0200
3309+++ cvs-1.11.15-cvsacl/src/tag.c 2004-04-25 20:04:51.772843336 +0200
3310@@ -660,6 +660,25 @@
3311 * correctly without breaking your link!
3312 */
3313
3314+/* cvsacl patch */
3315+#ifdef SERVER_SUPPORT
3316+ if (use_cvs_acl && server_active)
3317+ {
3318+ if (!access_allowed (finfo->file, finfo->repository, numtag, 4,
3319+ NULL, NULL, 1))
3320+ {
3321+ if (stop_at_first_permission_denied)
3322+ error (1, 0, "permission denied for %s",
3323+ Short_Repository (finfo->repository));
3324+ else
3325+ error (0, 0, "permission denied for %s/%s",
3326+ Short_Repository (finfo->repository), finfo->file);
3327+
3328+ return (0);
3329+ }
3330+ }
3331+#endif
3332+
3333 if (delete_flag)
3334 return (rtag_delete (rcsfile));
3335
3336@@ -880,6 +899,21 @@
3337 if (nversion == NULL)
3338 goto free_vars_and_return;
3339 }
3340+
3341+/* cvsacl patch */
3342+#ifdef SERVER_SUPPORT
3343+ if (use_cvs_acl && server_active)
3344+ {
3345+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 4,
3346+ NULL, NULL, 1))
3347+ {
3348+ error (0, 0, "permission denied for %s/%s",
3349+ Short_Repository (finfo->repository), finfo->file);
3350+ return (0);
3351+ }
3352+ }
3353+#endif
3354+
3355 if (delete_flag)
3356 {
3357
3358diff -urN cvs-1.11.15/src/update.c cvs-1.11.15-cvsacl/src/update.c
3359--- cvs-1.11.15/src/update.c 2004-03-22 18:20:26.000000000 +0100
3360+++ cvs-1.11.15-cvsacl/src/update.c 2004-04-25 20:04:51.782841816 +0200
3361@@ -594,6 +594,26 @@
3362 status = Classify_File (finfo, tag, date, options, force_tag_match,
3363 aflag, &vers, pipeout);
3364
3365+
3366+/* cvsacl patch */
3367+#ifdef SERVER_SUPPORT
3368+ if (use_cvs_acl && server_active)
3369+ {
3370+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5,
3371+ NULL, NULL, 1))
3372+ {
3373+ if (stop_at_first_permission_denied)
3374+ error (1, 0, "permission denied for %s",
3375+ Short_Repository (finfo->repository));
3376+ else
3377+ error (0, 0, "permission denied for %s/%s",
3378+ Short_Repository (finfo->repository), finfo->file);
3379+
3380+ return (0);
3381+ }
3382+ }
3383+#endif
3384+
3385 /* Keep track of whether TAG is a branch tag.
3386 Note that if it is a branch tag in some files and a nonbranch tag
3387 in others, treat it as a nonbranch tag. It is possible that case
3388diff -urN cvs-1.11.15/src/version.c cvs-1.11.15-cvsacl/src/version.c
3389--- cvs-1.11.15/src/version.c 2004-02-03 15:37:56.000000000 +0100
3390+++ cvs-1.11.15-cvsacl/src/version.c 2004-04-25 20:04:51.783841664 +0200
3391@@ -26,7 +26,8 @@
3392 #endif
3393 #endif
3394
3395-
3396+/* cvsacl patch */
3397+char *aclpatch_string = "with CVSACL Patch 1.2.0 (cvsacl.sourceforge.net)\n";
3398
3399 static const char *const version_usage[] =
3400 {
3401@@ -63,6 +64,8 @@
3402 released. */
3403 (void) fputs (PACKAGE_STRING, stdout);
3404 (void) fputs (config_string, stdout);
3405+ /* cvsacl patch */
3406+ (void) fputs (aclpatch_string, stdout);
3407
3408 #ifdef CLIENT_SUPPORT
3409 if (current_parsed_root && current_parsed_root->isremote)
This page took 0.404019 seconds and 4 git commands to generate.