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