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