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