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