From fe7dcf3190aa41acb64be69a9a3fa8846ae1cd77 Mon Sep 17 00:00:00 2001 From: hawk Date: Thu, 1 Dec 2005 23:43:02 +0000 Subject: [PATCH] - buggy and no longer maintained Changed files: cvs-acl.patch -> 1.6 --- cvs-acl.patch | 3381 ------------------------------------------------- 1 file changed, 3381 deletions(-) delete mode 100644 cvs-acl.patch diff --git a/cvs-acl.patch b/cvs-acl.patch deleted file mode 100644 index c6874d1..0000000 --- a/cvs-acl.patch +++ /dev/null @@ -1,3381 +0,0 @@ -diff -urN cvs-1.11.19.orig/INSTALL.cvsacl cvs-1.11.19/INSTALL.cvsacl ---- cvs-1.11.19.orig/INSTALL.cvsacl 1970-01-01 01:00:00.000000000 +0100 -+++ cvs-1.11.19/INSTALL.cvsacl 2004-11-26 13:48:57.000000000 +0100 -@@ -0,0 +1,23 @@ -+ -+Installation -+ -+- copy the file acl.c under src directory of CVS source distribution. -+ "cp acl.c /path/to/cvs-1.11.18/src/" -+- copy the patch file cvsacl-patch-1.2.2 under CVS source distribution -+ directory. -+ "cp cvsacl-patch-1.2.2 /path/to/cvs-1.11.18/" -+- cd to CVS source directory. -+ "cd /path/to/cvs-1.11.18/" -+- apply the patch. -+ "patch -p0 < cvsacl-patch-1.2.2" -+- if you are initializing the repository after applying patch, related -+ config files will be created with init command. -+ "cvs -d /path/to/repository init" -+- if you already have a repository, you have to add the aclconfig file -+ to your $CVSROOT/CVSROOT/. aclconfig.default is the default configuration -+ file, you can rename it to aclconfig, and use it . -+- modify aclconfig file, if you need to change some options. -+- as the last step, you have to define yourself as acl administrator. -+ "cvs -d /path/to/repository racl yourname:p -r ALL -d ALL" -+ this command gives p (acl admin) rights to user (yourname), -+ on all repository and tags/branches. -diff -urN cvs-1.11.19.orig/README.cvsacl cvs-1.11.19/README.cvsacl ---- cvs-1.11.19.orig/README.cvsacl 1970-01-01 01:00:00.000000000 +0100 -+++ cvs-1.11.19/README.cvsacl 2004-11-26 13:47:23.000000000 +0100 -@@ -0,0 +1,282 @@ -+ -+CVS Access Control List Extension Patch -+ -+http://cvsacl.sourceforge.net/ -+sbaris@users.sourceforge.net -+ -+CVSACL is a patch for CVS. It adds two new subcommands -+(acl & racl) to cvs for access control list management. It -+provides advanced ACL definitions per modules, directories, -+and files on branch/tag for remote cvs repository connections. -+Execution of all CVS subcommands can be controlled with eight -+different permissions. -+ACL definitions works for only remote connections, local users -+can access and modify repository, if unix file system permissions -+allow. If you want all users to make remote connections to -+repository, and not allow local users to access repository, you -+have to set CVSServerRunAsUser keyword in aclconfig file -+(explained below). -+Still local users can use acl and racl subcommands to set -+permissions on directories or files if they have acl admin rights (p) -+on related directories or files. -+So, in order to control all access to repository with this ACL -+extension, you should use CVSServerRunAsUser keyword and force all -+users to make remote connections. CVS repository administrator or -+project managers have to use acl and racl subcommands to manage -+permissions. But there is no gui client supporting these subcommands, -+so you have to use cvs client itself either locally or remotely. -+ -+ -+ -+ -+Permission Types -+ -+- no access -+ Command line character: n -+ If a user given n permission, it is not allowed for any action on repository. -+- read -+ Command line character: r -+ r permission gives only read access on repository. -+ With r permission you are allowed to run cvs subcommands: annotate, -+ checkout, diff, export, log, rannotate, rdiff, rlog, status. -+- write -+ Command line character: w -+ w permission allows only cvs commit/checkin action. -+ With w permission, you are not allowed to add/remove any file to/from -+ repository, other permissions should be defines for that. -+- tag -+ Command line character: t -+ t permission allows cvs tag and rtag subcommands to run, so you may -+ control tagging and untagging operations. t permission includes r -+ permission, since without reading you can not tag/untag a file. -+ However t permission does not include write permission, you can not -+ commit a file with only t permission. -+- create -+ Command line character: c -+ c permission allows cvs add and import subcommands to run. To add or -+ import a file/directory to repository, you have to given a c -+ permission. Again, c permission does not include write permission, -+ thus you may only add or import files, but you can not modify any -+ existing file. After issuing add subcommand, you have to commit the file -+ to complete adding. This commit subcommand is allowed because you are -+ adding file and not modifying existing one. -+- delete -+ Command line character: d -+ d permission allows cvs remove command to run. To remove a file/directory -+ from repository, d permission have to set. It does not include write -+ permission, so you can not modify contents of an existing file on repository. -+- full access except admin rights -+ Command line character: a -+ a permission gives all access (above permissions) to repository, but it -+ can not modify permissions. Only acl admins may modify the acl definitions. -+- acl admin -+ Command line character: p -+ p permission means that user is an acl admin, so it is allowed to make anything on repository. -+ -+ -+ACL Config Keywords -+The administrative file aclconfig contains miscellaneous settings which -+affect the behaviour of ACL extension. Currently defined keywords are: -+ -+UseCVSACL=value -+Use ACL definitions if set to yes. If you do not want to use ACLs for -+some repositories in a patched CVS server, set this keyword to no. The default is no. -+ -+UseCVSACLDefaultPermissions=value -+Value can be any combination of valid permission types (w,r,t,c,d,t,a,p). -+if there is no defined ACL and default permission in access file, or no -+access file at all, this permissions are used. The default is p (admin rights), -+if aclconfig file is created with cvs init. -+ -+UseCVSGroups=value -+CVS does not have a CVSROOT/passwd file. However it can be created manually -+(format should be same as /etc/group). If value set to yes, CVS checks for -+groups in file $CVSROOT/CVSROOT/group The default value is no. -+ -+UseSystemGroups=value -+Group memberships for users are checked in file /etc/group, if value is set -+to yes. The default value is no. -+ -+CVSACLFileLocation=value -+Originally access file is put under CVSROOT/CVSROOT, if you want a different -+location, set value to a valid path. The default value is $CVSROOT/CVSROOT/access. -+ -+CVSGroupsFileLocation=value -+IF UseCVSGroups is set to yes, CVS looks for a group file under $CVSROOT/CVSROOT. -+To use a different location for group file set value to a valid path to group. -+The default value is $CVSROOT/CVSROOT/group. -+ -+UseSeparateACLFileForEachDir=value -+If value is set to yes, a separate ACL file (access) is created for each -+directory in repository. If you have a really big repository -+(directories>10,000 and files>100,000), performance may drop due to a big -+acl file, access. Setting the value to yes, may increase performance. Normally, -+you will not need this. The default value is no. -+ -+StopAtFirstPermissionDenied=value -+If StopAtFirstPermissionDenied is set to yes -+operation will stop at first permission denied message. -+e.g. when you send commit command for a directory, if you dont -+have write permission for just one file under the directory, -+by default you will have a warning and commit will continue -+on the other files. If you set this keyword to 'no', then -+commit operation will be stopped when inaccassable file found. -+Default is no. -+ -+CVSServerRunAsUser=value -+Set CVSServerRunAsUser keyword to a valid system user. -+When a user make a remote connection to CVS, after successfull authentication -+cvs process switch to run as that user, or defined system user in -+$CVSROOT/CVSROOT/passwd. So, you also have to set unix file permissions accordingly. -+A better solution: -+Add a user and group such as both cvsadm. -+Set CVSServerRunAsUser keyword to cvsadm. -+Change unix file system permissions for your repository, -+make cvsadm user and group owner, and read,write,execute permissions and setgid. -+(chown cvsadm -R /path/to/your/repository) -+(chgrp cvsadm -R /path/to/your/repository) -+(chmod 2770 -R /path/to/your/repository) -+Add yourself to cvsadm group (since you are ACL administrator). -+Therefore, only users making remote connections will have access to repository -+if you give rights. Local users can not access to repository via a cvs client or directly. -+ -+ -+Command Line Usage Information -+acl command is used on checked out files or directories. racl command is -+used on repository without a working copy. Usage information can be obtained -+with standard cvs --help command. -+Output of cvs --help acl and cvs --help racl: -+ -+Usage: cvs racl [user||group:permissions] [-Rl] [-r tag] -+ -d [directory] -f [file] -+ -R Process directories recursively. -+ -r rev Existing revision/tag. -+ -l List defined ACLs. -+ -d dir Process on given directory. -+ -f file Process on given file. -+ -+Usage: cvs acl [user||group:permissions] [-Rl] [-r tag] -+ -d [directory] -f [file] -+ -R Process directories recursively. -+ -r rev Existing revision/tag. -+ -l List defined ACLs. -+ -d dir Process on given directory. -+ -f file Process on given file. -+ -+You may directly set permissions for a user or group or add/remove -+permissions with + and - signs to/from existing permissions. -+If you do not give the branch/tag information, default value of HEAD -+(main branch) will be used. You have to give branch/tag name with -r option. -+You may type ALL for branch/tag field. -+ -+While checking for permissions, it goes thorough the list below. So the highest -+significant permission is the first item in list. -+ -+- permissions assigned to username for specific directory or file. -+- permissions assigned to group name for specific directory or file. -+- permissions as defaults for specific directory or file. -+- permissions assigned to parent folders (inherits from the first parent -+ which permissions are assigned). -+- permissions as repository defaults. -+- permissions in aclconfig file. -+ -+ -+ -+ -+Examples -+ /cvs/ -+ | -+ | -+ +--projectA/ -+ | | -+ | +---CVSROOT/ -+ | | -+ | +---lib/ -+ | | | -+ | | +---gnulib/ -+ | | | -+ | | +---zlib/ -+ | | -+ | +---src/ -+ | | | -+ | | +---main.c -+ | | | -+ | | +---server.c -+ | | | -+ | | +---client.c -+ | | -+ | +---gui/ -+ | -+ +--projectB/ -+We have above directory structure for a cvs repository, and no defined permissions. -+ -+Setting main default permissions: -+ -+$ cvs -d /cvs/projectA racl cvsadmin:p -r ALL -d ALL -+$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL -+User cvsadmin will be an acl admin, and all other users will have only read -+rights on all branches/tags in projectA repository. This is the default acl -+definition and it overwrites default permissions in $CVSROOT/CVSROOT/aclconfig file. -+ -+$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL -+$ cvs -d /cvs/projectA racl ALL:n -r ALL -d gui -+After executing these two commands, all users will have read access on all -+directories and files except gui directory. Everyone will be denied to access to gui -+directory becase no access, n, permissions is set. -+ -+Setting permissions directly on a file or directory: -+ -+$ cvs -d /cvs/projectA racl userX:wcd -d lib -+$ cvs -d /cvs/projectA racl group1:w -d lib -+First command will set write, create, and delete permissions for userX on directory -+lib with branch HEAD (since no branch/tag information given, branch defaults to HEAD). -+Second command will set only write permission for group1 on directory lib with branch HEAD. -+Members of group1 will have only commit rights on lib directory, branch HEAD, they can -+not add or remove any file, just modify existing files. -+If userX is also a member of group1, userX will have write, create, and delete permissions -+because it is specifically given these permissions. -+ -+$ cvs -d /cvs/projectA racl userY:wcd -r develStream -d lib -+$ cvs -d /cvs/projectA racl userY:r -r integStream -d lib -+These commands will give wcd permissions to userY on lib directory with tag develstream, -+and r permissions on lib directory with tag integStream. -+ -+$ cvs -d /cvs/projectA racl userZ:wcd -d src -+$ cvs -d /cvs/projectA racl userZ:r -f src/main.c -+First command will give wcd permissions to userZ on src directory, but only read -+permission on file main.c in src directory. -+ -+Using + and - signs to set permissions on a file or directory: -+ -+$ cvs -d /cvs/projectA racl userZ:+t -d src -+$ cvs -d /cvs/projectA racl userZ:-cd -d src -+$ cvs -d /cvs/projectA racl userZ:-wt -d src -+Before the first command, userZ has wcd permissions on src directory, after issuing -+command it will have wcdt permissions. Tag permission will be added. UserZ has wcdt -+permissions, and we execute the second command to remove create and delete permissions. -+So userZ has wt permissions. In the last command we also remove wt permissions, finally -+userZ has no defined permissions left, and it will use the default permissions if set. -+ -+Listing permissions on a file or directory: -+ -+$ cvs -d /cvs/projectA racl -l -d src -+$ cvs -d /cvs/projectA racl -l -f src -+$ cvs -d /cvs/projectA racl -l -f src/main.c -+ -+First command will list the permissions for src directory. -+Example output: -+d src HEAD | userX:wcd group1:r | defaults:r -+userX and group1 has assigned permissions, all other users will have default -+permissions, which is only read. -+ -+Second command will list the permissions for files in src directory. -+Example output: -+f src/main.c HEAD | userX:wcd group1:r | defaults:r -+f src/server.c HEAD | userX:wcd group1:r | defaults:r -+f src/client.c HEAD | userX:wcd group1:r | defaults:r -+ -+Third command will list the permissions for main.c file in src directory. -+Example output: -+f src/main.c HEAD | userX:wcd group1:r | defaults:r -+ -+ -diff -urN cvs-1.11.19.orig/aclconfig.default cvs-1.11.19/aclconfig.default ---- cvs-1.11.19.orig/aclconfig.default 1970-01-01 01:00:00.000000000 +0100 -+++ cvs-1.11.19/aclconfig.default 2004-11-26 13:47:34.000000000 +0100 -@@ -0,0 +1,33 @@ -+# Set `UseCVSACL' to yes to use CVS ACL feature. -+UseCVSACL=yes -+ -+# Default CVS ACL Permission are to use. -+#CVSACLDefaultPermissions=a -+ -+# Default file location for CVS ACL file (access) is CVSROOT/access. -+# If you want to use a different location, define it below. -+#CVSACLFileLocation=/path/to/cvs/access -+ -+# Set `UseSystemGroups' to yes to use system group definitions (/etc/group). -+UseSystemGroups=yes -+ -+# Set `UseCVSGroups' to yes to use another group file. -+#UseCVSGroups=yes -+ -+# Default file location for CVS groups file is CVSROOT/group. -+# If you want to use a different location, define it below. -+#CVSGroupsFileLocation=/path/to/cvs/group -+ -+# Set UseSeparateACLFileForEachDir to yes in order to use a -+# separate 'access' file for each directory. -+# This increased the performance if you have really big repository. -+#UseSeparateACLFileForEachDir=no -+ -+# If StopAtFirstPermissionDenied is set to yes -+# operation will stop at first permission denied message. -+# Default is no. -+#StopAtFirstPermissionDenied=no -+ -+# Set CVSServerRunAsUser to a system user, in order CVS server -+# to run as. -+#CVSServerRunAsUser=runascvsuser -diff -urN cvs-1.11.19.orig/src/Makefile.am cvs-1.11.19/src/Makefile.am ---- cvs-1.11.19.orig/src/Makefile.am 2005-03-14 19:49:29.000000000 +0100 -+++ cvs-1.11.19/src/Makefile.am 2005-03-14 19:55:09.000000000 +0100 -@@ -31,6 +31,7 @@ - - # The cvs executable - cvs_SOURCES = \ -+ acl.c \ - add.c \ - admin.c \ - annotate.c \ -diff -urN cvs-1.11.19.orig/src/Makefile.in cvs-1.11.19/src/Makefile.in ---- cvs-1.11.19.orig/src/Makefile.in 2005-02-01 00:11:15.000000000 +0100 -+++ cvs-1.11.19/src/Makefile.in 2005-03-14 19:55:09.000000000 +0100 -@@ -69,20 +69,20 @@ - am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" - binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) - PROGRAMS = $(bin_PROGRAMS) --am_cvs_OBJECTS = add.$(OBJEXT) admin.$(OBJEXT) annotate.$(OBJEXT) \ -- buffer.$(OBJEXT) checkin.$(OBJEXT) checkout.$(OBJEXT) \ -- classify.$(OBJEXT) client.$(OBJEXT) commit.$(OBJEXT) \ -- create_adm.$(OBJEXT) cvsrc.$(OBJEXT) diff.$(OBJEXT) \ -- edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \ -- expand_path.$(OBJEXT) fileattr.$(OBJEXT) filesubr.$(OBJEXT) \ -- find_names.$(OBJEXT) hardlink.$(OBJEXT) hash.$(OBJEXT) \ -- history.$(OBJEXT) ignore.$(OBJEXT) import.$(OBJEXT) \ -- lock.$(OBJEXT) log.$(OBJEXT) login.$(OBJEXT) logmsg.$(OBJEXT) \ -- main.$(OBJEXT) mkmodules.$(OBJEXT) modules.$(OBJEXT) \ -- myndbm.$(OBJEXT) no_diff.$(OBJEXT) parseinfo.$(OBJEXT) \ -- patch.$(OBJEXT) rcs.$(OBJEXT) rcscmds.$(OBJEXT) \ -- recurse.$(OBJEXT) release.$(OBJEXT) remove.$(OBJEXT) \ -- repos.$(OBJEXT) root.$(OBJEXT) run.$(OBJEXT) \ -+am_cvs_OBJECTS = acl.$(OBJEXT) add.$(OBJEXT) admin.$(OBJEXT) \ -+ annotate.$(OBJEXT) buffer.$(OBJEXT) checkin.$(OBJEXT) \ -+ checkout.$(OBJEXT) classify.$(OBJEXT) client.$(OBJEXT) \ -+ commit.$(OBJEXT) create_adm.$(OBJEXT) cvsrc.$(OBJEXT) \ -+ diff.$(OBJEXT) edit.$(OBJEXT) entries.$(OBJEXT) \ -+ error.$(OBJEXT) expand_path.$(OBJEXT) fileattr.$(OBJEXT) \ -+ filesubr.$(OBJEXT) find_names.$(OBJEXT) hardlink.$(OBJEXT) \ -+ hash.$(OBJEXT) history.$(OBJEXT) ignore.$(OBJEXT) \ -+ import.$(OBJEXT) lock.$(OBJEXT) log.$(OBJEXT) login.$(OBJEXT) \ -+ logmsg.$(OBJEXT) main.$(OBJEXT) mkmodules.$(OBJEXT) \ -+ modules.$(OBJEXT) myndbm.$(OBJEXT) no_diff.$(OBJEXT) \ -+ parseinfo.$(OBJEXT) patch.$(OBJEXT) rcs.$(OBJEXT) \ -+ rcscmds.$(OBJEXT) recurse.$(OBJEXT) release.$(OBJEXT) \ -+ remove.$(OBJEXT) repos.$(OBJEXT) root.$(OBJEXT) run.$(OBJEXT) \ - scramble.$(OBJEXT) server.$(OBJEXT) stack.$(OBJEXT) \ - status.$(OBJEXT) subr.$(OBJEXT) tag.$(OBJEXT) update.$(OBJEXT) \ - version.$(OBJEXT) vers_ts.$(OBJEXT) watch.$(OBJEXT) \ -@@ -206,6 +206,7 @@ - - # The cvs executable - cvs_SOURCES = \ -+ acl.c \ - add.c \ - admin.c \ - annotate.c \ -@@ -384,6 +385,7 @@ - distclean-compile: - -rm -f *.tab.c - -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/admin.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate.Po@am__quote@ -diff -urN cvs-1.11.19.orig/src/acl.c cvs-1.11.19/src/acl.c ---- cvs-1.11.19.orig/src/acl.c 1970-01-01 01:00:00.000000000 +0100 -+++ cvs-1.11.19/src/acl.c 2004-11-26 13:50:48.000000000 +0100 -@@ -0,0 +1,2032 @@ -+/* -+ * -+ * CVS ACCESS CONTROL LIST EXTENSION -+ * -+ * sbaris@users.sourceforge.net -+ * -+ * http://cvsacl.sourceforge.net/ -+ * -+ * CVSACL is a patch for CVS versions -+ * - cvs-1.11.18 -+ * -+ * It adds two new subcommands (acl & racl) to cvs for access control -+ * list management. -+ * It provides advanced ACL definitions per modules, directories, -+ * and files on branch/tag for remote cvs repository connections. -+ * Execution of all CVS subcommands can be controlled with eight -+ * different permissions. -+ * ACL definitions works for only remote connections, local users can -+ * access and modify repository, if unix file system permissions allow. -+ * If you want all users to make remote connections to repository, -+ * and not allow local users to access repository, you have to set -+ * CVSServerRunAsUser keyword in aclconfig file (explained below). -+ * Still local users can use acl and racl subcommands to set permissions -+ * on directories or files if they have acl admin rights (p) on related -+ * directories or files. -+ * So, in order to control all access to repository with this ACL extension, -+ * you should use CVSServerRunAsUser keyword and force all users to make -+ * remote connections. -+ * CVS repository administrator or project managers have to use acl and racl -+ * subcommands to manage permissions. But there is no gui client supporting -+ * these subcommands, so you have to use cvs client itself either -+ * locally or remotely. -+ * -+ * -+ * Permission Types: -+ * - no permission (n) (1) -+ * - all permissions (a) (2) -+ * - write permission (w) (3) -+ * - tag permission (t) (4) -+ * - read permission (r) (5) -+ * - add permission (c) (6) -+ * - remove permission (d) (7) -+ * - permission change (p) (8) -+ * -+ * -+ * -+ * -+ * ******************************************************************** -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 1, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * ******************************************************************* -+ * -+ */ -+ -+#include "cvs.h" -+#include "getline.h" -+#include -+ -+static int acl_fileproc PROTO ((void *callerdat, struct file_info *finfo)); -+static Dtype acl_dirproc PROTO ((void *callerdat, const char *dir, const char *repos, -+ const char *update_dir, List *entries)); -+ -+static int acllist_fileproc PROTO ((void *callerdat, struct file_info *finfo)); -+static Dtype acllist_dirproc PROTO ((void *callerdat, const char *dir, const char *repos, -+ const char *update_dir, List *entries)); -+ -+static void acllist_print PROTO ((char *line, const char *obj)); -+ -+static int racl_proc PROTO((int argc, char **argv, char *xwhere, -+ char *mwhere, char *mfile, int shorten, -+ int local_specified, char *mname, char *msg)); -+ -+FILE *open_accessfile (char *xmode, const char *repos, char **fname); -+FILE *open_groupfile (char *xmode); -+ -+char *get_perms (char *xperms); -+char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg); -+ -+static char *cache_repository; -+static int cache_retval; -+static int founddeniedfile; -+static int cache_perm; -+ -+static int is_racl; -+ -+int use_cvs_acl = 0; -+char *cvs_acl_default_permissions; -+int use_cvs_groups = 0; -+int use_system_groups = 0; -+int use_separate_acl_file_for_each_dir = 0; -+char *cvs_acl_file_location = NULL; -+char *cvs_groups_file_location = NULL; -+char *cvs_server_run_as = NULL; -+int stop_at_first_permission_denied = 0; -+ -+char *tag = NULL; -+ -+char *muser; -+char *mperms; -+static int defaultperms; -+ -+static char *default_perms_object; -+char *default_part_perms_accessfile; -+ -+int acldir = 0; -+int aclfile = 0; -+int listacl = 0; -+ -+int userfound; -+int groupfound; -+ -+char *dirs[25]; -+ -+int aclconfig_default_used; -+ -+static const char *const acl_usage[] = -+ { -+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n", -+ "\t-R\tProcess directories recursively.\n", -+ "\t-r rev\tExisting revision/tag.\n", -+ "\t-l\tList defined ACLs.\n", -+ "\t-d dir\tProcess on given directory.\n", -+ "\t-f file\tProcess on given file.\n", -+ "(Specify the --help global option for a list of other help options)\n", -+ NULL -+ }; -+ -+static const char *const racl_usage[] = -+ { -+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n", -+ "\t-R\tProcess directories recursively.\n", -+ "\t-r rev\tExisting revision/tag.\n", -+ "\t-l\tList defined ACLs.\n", -+ "\t-d dir\tProcess on given directory.\n", -+ "\t-f file\tProcess on given file.\n", -+ "(Specify the --help global option for a list of other help options)\n", -+ NULL -+ }; -+ -+ -+int -+access_allowed (file, repos, tag, perm, mline, mpos, usecache) -+char *file; -+char *repos; -+char *tag; -+int perm; -+char **mline; -+int *mpos; -+int usecache; -+{ -+ int retval = 0; -+ int foundline = 0; -+ FILE *accessfp; -+ -+ char *line = NULL; -+ size_t line_allocated = 0; -+ -+ char *part_type = NULL; -+ char *part_object = NULL; -+ char *part_tag = NULL; -+ char *part_perms = NULL; -+ char *xline; -+ int x; -+ -+ char *iline; -+ -+ char *tempv; -+ char *tempc; -+ size_t tempsize; -+ int intcount; -+ -+ int oneaccessfile = 0; -+ int accessfilecount; -+ -+ int signlevel = -1; -+ -+ int dadmin = 0; -+ -+ const char *repository; -+ char *filefullname = NULL; -+ -+ -+ userfound = 0; -+ groupfound = 0; -+ -+ -+ if (defaultperms) -+ { -+ repository = xstrdup ("ALL"); -+ } -+ else -+ repository = Short_Repository (repos); -+ -+ /* cache */ -+ if (usecache -+ && cache_repository != NULL -+ && strcmp (cache_repository, repository) == 0 -+ && !founddeniedfile -+ && perm == cache_perm) -+ return (cache_retval); -+ else -+ { -+ free(cache_repository); -+ cache_repository = xstrdup(repository); -+ cache_perm = perm; -+ } -+ -+ if (file != NULL) -+ { -+ filefullname = xmalloc (strlen (repository) -+ + strlen (file) -+ + 2); -+ -+ strcpy (filefullname, repository); -+ strcat (filefullname, "/"); -+ strcat (filefullname, file); -+ } -+ -+ -+ iline = xstrdup(repository); -+ -+ tempv = strtok(iline, "/\t"); -+ tempc = xstrdup(tempv); -+ tempsize = strlen(tempc); -+ -+ intcount = 0; -+ -+ dirs[intcount] = xstrdup(tempc); -+ -+ while ((tempv = strtok(NULL, "/\t")) != NULL) -+ { -+ intcount++; -+ -+ xrealloc_and_strcat(&tempc, &tempsize, "/"); -+ xrealloc_and_strcat(&tempc, &tempsize, tempv); -+ -+ dirs[intcount] = xstrdup(tempc); -+ } -+ -+ accessfilecount = intcount; -+ -+ if (file != NULL) -+ { -+ intcount++; -+ dirs[intcount] = xstrdup(filefullname); -+ } -+ -+ for (accessfilecount; accessfilecount >= 0 && !oneaccessfile; accessfilecount--) -+ { -+ if (!use_separate_acl_file_for_each_dir) -+ oneaccessfile = 1; -+ else if (use_separate_acl_file_for_each_dir) -+ oneaccessfile = 0; -+ -+ if (acldir || aclfile) -+ oneaccessfile = 1; -+ -+ if (oneaccessfile) -+ accessfp = open_accessfile ("r", repository, NULL); -+ else -+ accessfp = open_accessfile ("r", dirs[accessfilecount], NULL); -+ -+ if (accessfp != NULL) -+ { -+ while (getline (&line, &line_allocated, accessfp) >= 0) -+ { -+ -+ if (line[0] == '#' || line[0] == '\0' || line[0] == '\n') -+ continue; -+ -+ xline = xstrdup (line); -+ part_type = strtok (line, ":\t"); -+ part_object = strtok (NULL, ":\t"); -+ part_tag = strtok (NULL, ":\t"); -+ part_perms = strtok (NULL, ":\t"); -+ -+ for (x = intcount; x >= signlevel && x != -1; x--) -+ { -+ if (strcmp (dirs[x], part_object) == 0) -+ { -+ if (valid_tag (part_tag, tag)) -+ { -+ foundline = 1; -+ -+ if (listacl || acldir || aclfile) -+ { -+ *mline = xstrdup (xline); -+ *mpos = ftell (accessfp); -+ } -+ -+ if (valid_perm (part_perms, perm)) -+ { -+ if (signlevel == x) -+ { -+ if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used) -+ retval = 1; -+ } -+ else if (!aclconfig_default_used) -+ { -+ signlevel = x; -+ retval = 1; -+ } -+ else { -+ } -+ } -+ else -+ { -+ if (signlevel == x) -+ { -+ if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used) -+ retval = 0; -+ } -+ else if (!aclconfig_default_used) -+ { -+ signlevel = x; -+ retval = 0; -+ -+ if (strncmp (part_type, "f", 1) == 0) -+ founddeniedfile = 1; -+ } -+ else { -+ } -+ } -+ } -+ } -+ } -+ if (strncmp (xline, "d:ALL", 5) == 0 && (!groupfound && !userfound || listacl)) -+ { -+ /* a default found */ -+ if (valid_tag (part_tag, tag)) -+ { -+ foundline = 1; -+ -+ default_part_perms_accessfile = xstrdup (part_perms); -+ -+ if (valid_perm (part_perms, perm)) -+ { -+ retval = 1; -+ -+ if (perm == 8) -+ dadmin = 1; -+ } -+ else -+ retval = 0; -+ } -+ } -+ -+ } -+ if (fclose (accessfp) == EOF) -+ error (1, errno, "cannot close 'access' file"); -+ -+ } -+ } -+ -+ if (!foundline) -+ { -+ /* DEFAULT */ -+ if (valid_perm (NULL, perm)) -+ retval = 1; -+ else -+ retval = 0; -+ } -+ -+ if (dadmin) -+ { -+ retval = dadmin; -+ } -+ -+ cache_retval = retval; -+ -+ free (filefullname); -+ -+ return (retval); -+} -+ -+/* Returns 1 if successful, 0 if not. */ -+int -+valid_tag (part_tag, tag) -+char *part_tag; -+char *tag; -+{ -+ if (acldir || aclfile) -+ return (0); -+ -+ if (tag == NULL) -+ tag = xstrdup ("HEAD"); -+ -+ if (strcmp (part_tag, "ALL") == 0) -+ return (1); -+ -+ if (strcmp (tag, part_tag) == 0) -+ return (1); -+ else -+ return (0); -+} -+ -+/* Returns 1 if successful, 0 if not. */ -+int -+valid_perm (part_perms, perm) -+char *part_perms; -+int perm; -+{ -+ char *perms; -+ int retval = 0; -+ -+ perms = get_perms (part_perms); -+ -+ /* Allow, if nothing found. */ -+ if (perms[0] == '\0') -+ return (1); -+ -+ -+ if (strstr (perms, "n")) -+ retval = 0; /* no access allowed, exit */ -+ if (strstr (perms, "p")) -+ retval = 1; /* admin rights */ -+ else if (strstr (perms, "a") && perm != 8) -+ retval = 1; /* all access allowed, exit */ -+ else -+ switch (perm) -+ { -+ case 3: /* write permission */ -+ if (strstr (perms, "w")) -+ retval = 1; -+ break; -+ case 4: /* tag permission */ -+ if (strstr (perms, "t")) -+ retval = 1; -+ break; -+ case 5: /* read permission */ -+ if (strstr (perms, "w") || strstr (perms, "t") || strstr (perms, "c") || -+ strstr (perms, "d") || strstr (perms, "r")) -+ retval = 1; -+ break; -+ case 6: /* create permission */ -+ if (strstr (perms, "c")) -+ retval = 1; -+ break; -+ case 7: /* delete permission */ -+ if (strstr (perms, "d")) -+ retval = 1; -+ break; -+ case 8: /* permission change */ -+ if (strstr (perms, "p")) -+ retval = 1; -+ break; -+ default: -+ retval = 0; /* never reached */ -+ break; -+ } -+ -+ return (retval); -+} -+ -+char * -+get_perms (part_perms) -+char *part_perms; -+ -+{ -+ char *username; -+ char *xperms; -+ size_t xperms_len = 1; -+ -+ FILE *groupfp; -+ -+ char *usr; -+ char *per; -+ char *founduser = NULL; -+ char *foundall = NULL; -+ int default_checked = 0; -+ -+ aclconfig_default_used = 0; -+ -+ xperms = xmalloc (xperms_len); -+ xperms[0] = '\0'; -+ -+ username = getcaller (); -+ -+ /* no defined acl, no default acl in access file, -+ or no access file at all */ -+ if (part_perms == NULL) -+ if (cvs_acl_default_permissions) -+ { -+ aclconfig_default_used = 1; -+ return (cvs_acl_default_permissions); -+ } -+ else -+ return (xperms); -+ -+check_default: -+ founduser = strstr (part_perms, username); -+ foundall = strstr (part_perms, "ALL!"); -+ -+ if (founduser) -+ { -+ usr = strtok (founduser, "!\t"); -+ per = strtok (NULL, ",\t"); -+ -+ if (strcmp (usr, username) == 0) -+ { -+ xperms = xstrdup (per); -+ xperms_len = strlen (xperms); -+ -+ userfound = 1; -+ } -+ } -+ else -+ { -+ if (use_system_groups) { -+ struct group *griter; -+ setgrent (); -+ while (griter = getgrent ()) { -+ char **users=griter->gr_mem; -+ int index = 0; -+ char *userchk = users [index++]; -+ while(userchk != NULL) { -+ if(strcmp (userchk, username) == 0) -+ break; -+ userchk = users[index++]; -+ } -+ if (userchk != NULL) { -+ char *grp; -+ if ((grp = strstr (part_perms, griter->gr_name)) && grp[strlen (griter->gr_name)] == '!') { -+ char *gperm = strtok (grp, "!\t"); -+ gperm = strtok (NULL, ",\t"); -+ xrealloc_and_strcat (&xperms, &xperms_len, gperm); -+ -+ groupfound = 1; -+ } -+ } -+ } -+ endgrent (); -+ } -+ else if (use_cvs_groups) { -+ groupfp = open_groupfile ("r"); -+ if (groupfp != NULL) -+ { -+ char *line = NULL; -+ size_t line_allocated = 0; -+ -+ while (getline (&line, &line_allocated, groupfp) >= 0) -+ { -+ if (strstr (line, username)) -+ { -+ char *temp; -+ temp = strstr (line, username); -+ -+ if (temp[strlen (username)] == ',' -+ || temp[strlen (username)] == ' ' -+ || temp[strlen (username)] == '\n') -+ { -+ char *tmp; -+ tmp = strtok (line, ":\t"); -+ if (strcmp (tmp, username) != 0) -+ { -+ char *grp; -+ if ((grp = strstr (part_perms, tmp))) -+ if (grp[strlen (tmp)] == '!') -+ { -+ char *gperm; -+ gperm = strtok (grp, "!\t"); -+ gperm = strtok (NULL, ",\t"); -+ -+ xrealloc_and_strcat (&xperms, &xperms_len, gperm); -+ -+ groupfound = 1; -+ } -+ } -+ } -+ } -+ } -+ if (fclose (groupfp) == EOF) -+ error (1, errno, "cannot close 'group' file"); -+ } -+ } -+ } -+ -+ if (foundall && (!groupfound && !userfound)) -+ { -+ usr = strtok (strstr (part_perms, "ALL!"), "!\t"); -+ per = strtok (NULL, ",\t"); -+ -+ if (!default_checked) -+ default_perms_object = xstrdup (per); -+ -+ if (xperms[0] == '\0') -+ { -+ xperms = xstrdup (per); -+ xperms_len = strlen (xperms); -+ } -+ } -+ else if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile) -+ { -+ part_perms = xstrdup (default_part_perms_accessfile); -+ default_checked = 1; -+ -+ goto check_default; -+ } -+ -+ if (xperms[0] != '\0' && strcmp (xperms, "x") == 0) -+ { -+ if (default_perms_object) -+ xperms = xstrdup (default_perms_object); -+ else if (default_part_perms_accessfile) -+ { -+ part_perms = default_part_perms_accessfile; -+ default_checked = 1; -+ goto check_default; -+ } -+ else if (cvs_acl_default_permissions) -+ { -+ aclconfig_default_used = 1; -+ xperms = xstrdup (cvs_acl_default_permissions); -+ } -+ } -+ -+ if (xperms[0] == '\0' && cvs_acl_default_permissions) -+ { -+ aclconfig_default_used = 1; -+ xperms = xstrdup (cvs_acl_default_permissions); -+ } -+ -+ return (xperms); -+} -+ -+ -+int -+cvsacl (argc, argv) -+int argc; -+char **argv; -+{ -+ char *chdirrepository; -+ int c; -+ int err = 0; -+ int usetag = 0; -+ int recursive = 0; -+ -+ int k; -+ -+ int which; -+ char *where; -+ -+ is_racl = (strcmp (cvs_cmd_name, "racl") == 0); -+ -+ if (argc == -1) -+ usage (is_racl ? racl_usage : acl_usage); -+ -+ /* parse the args */ -+ optind = 0; -+ -+ while ((c = getopt (argc, argv, "Rr:dfl")) != -1) -+ { -+ switch (c) -+ { -+ case 'R': -+ recursive = 1; -+ break; -+ case 'r': -+ tag = xstrdup (optarg); -+ break; -+ case 'd': -+ acldir = 1; -+ break; -+ case 'f': -+ aclfile = 1; -+ break; -+ case 'l': -+ listacl = 1; -+ break; -+ case '?': -+ default: -+ usage (is_racl ? racl_usage : acl_usage); -+ break; -+ } -+ } -+ -+ argc -= optind; -+ argv += optind; -+ -+ if (!acldir && !aclfile) -+ usage (is_racl ? racl_usage : acl_usage); -+ if (acldir && aclfile) -+ usage (is_racl ? racl_usage : acl_usage); -+ -+ if (listacl) -+ if (strstr (argv[0], ":")) -+ usage (is_racl ? racl_usage : acl_usage); -+ if (!listacl) -+ if (!strstr (argv[0], ":")) -+ usage (is_racl ? racl_usage : acl_usage); -+ -+ if (argc < (is_racl ? 1 : 1)) -+ usage (is_racl ? racl_usage : acl_usage); -+ -+#ifdef CLIENT_SUPPORT -+ -+ if (current_parsed_root->isremote) -+ { -+ start_server (); -+ ign_setup (); -+ -+ if(recursive) -+ send_arg ("-R"); -+ -+ if (acldir) -+ send_arg ("-d"); -+ -+ if (aclfile) -+ send_arg ("-f"); -+ -+ if (listacl) -+ send_arg ("-l"); -+ -+ if(tag) -+ { -+ send_arg ("-r"); -+ send_arg (tag); -+ } -+ -+ send_arg ("--"); -+ -+ if (!listacl) -+ { -+ send_arg (argv[0]); -+ -+ argc--; -+ argv++; -+ } -+ -+ if (is_racl) -+ { -+ int i; -+ for (i = 0; i < argc; ++i) -+ send_arg (argv[i]); -+ -+ send_to_server ("racl\012",0); -+ } -+ else -+ { -+ send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS); -+ send_file_names (argc, argv, SEND_EXPAND_WILD); -+ send_to_server ("acl\012", 0); -+ } -+ -+ return get_responses_and_close (); -+ } -+#endif -+ -+#ifdef SERVER_SUPPORT -+ -+ if (!listacl) -+ { -+ muser = strtok (argv[0], ":\t"); -+ mperms = strtok (NULL, ":\t"); -+ -+ /* if set to 'default' */ -+ if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0)) -+ mperms = xstrdup ("x"); -+ -+ /* Check that the given permissions are valid. */ -+ if (!given_perms_valid (mperms)) -+ error (1,0,"Invalid permissions: '%s'", mperms); -+ -+ argc--; -+ argv++; -+ } -+ -+ -+ if (!tag) -+ tag = xstrdup ("HEAD"); -+ -+ if (!cvs_casecmp (argv[0], "ALL")) -+ { -+ argv[0] = xstrdup ("."); -+ defaultperms = 1; -+ if (!use_separate_acl_file_for_each_dir) -+ { -+ recursive = 0; -+ } -+ -+ } -+ -+ if (is_racl) -+ { -+ DBM *db; -+ int i; -+ db = open_module (); -+ for (i = 0; i < argc; i++) -+ { -+ err += do_module (db, argv[i], MISC, "ACL ing: ", -+ racl_proc, (char *) NULL, 0, !recursive, 0, -+ 0, NULL); -+ } -+ close_module (db); -+ } -+ else -+ { -+ err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive, NULL, -+ NULL); -+ } -+ if (err) -+ error (1, 0, "an error accured"); -+ -+ return (err); -+ -+#endif -+} -+ -+static int -+racl_proc (argc, argv, xwhere, mwhere, mfile, shorten, local, mname, msg) -+int argc; -+char **argv; -+char *xwhere; -+char *mwhere; -+char *mfile; -+int shorten; -+int local; -+char *mname; -+char *msg; -+{ -+ char *myargv[2]; -+ int err = 0; -+ int which; -+ char *repository; -+ char *where; -+ -+ if (is_racl) -+ { -+ repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0]) -+ + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2); -+ -+ (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]); -+ where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1) -+ + 1); -+ (void) strcpy (where, argv[0]); -+ -+ /* if mfile isn't null, we need to set up to do only part of the module */ -+ if (mfile != NULL) -+ { -+ char *cp; -+ char *path; -+ -+ /* if the portion of the module is a path, put the dir part on repos */ -+ if ((cp = strrchr (mfile, '/')) != NULL) -+ { -+ *cp = '\0'; -+ (void) strcat (repository, "/"); -+ (void) strcat (repository, mfile); -+ (void) strcat (where, "/"); -+ (void) strcat (where, mfile); -+ mfile = cp + 1; -+ } -+ -+ /* take care of the rest */ -+ path = xmalloc (strlen (repository) + strlen (mfile) + 5); -+ (void) sprintf (path, "%s/%s", repository, mfile); -+ if (isdir (path)) -+ { -+ /* directory means repository gets the dir tacked on */ -+ (void) strcpy (repository, path); -+ (void) strcat (where, "/"); -+ (void) strcat (where, mfile); -+ } -+ else -+ { -+ myargv[0] = argv[0]; -+ myargv[1] = mfile; -+ argc = 2; -+ argv = myargv; -+ } -+ free (path); -+ } -+ -+ /* cd to the starting repository */ -+ if ( CVS_CHDIR (repository) < 0) -+ { -+ error (0, errno, "cannot chdir to %s", repository); -+ free (repository); -+ return (1); -+ } -+ -+ /* End section which is identical to patch_proc. */ -+ -+ which = W_REPOS | W_ATTIC; -+ } -+ else -+ { -+ where = NULL; -+ which = W_LOCAL | W_REPOS | W_ATTIC; -+ } -+ if (listacl) -+ err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL, NULL, -+ argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1, -+ repository); -+ else -+ err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL, -+ argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1, -+ repository); -+ -+ return (err); -+} -+ -+ -+static int -+acl_fileproc (callerdat, finfo) -+void *callerdat; -+struct file_info *finfo; -+{ -+ Vers_TS *vers; -+ -+ FILE *accessfp; -+ -+ char *filefullname; -+ -+ char *founduserpart = NULL; -+ char *newuserpart = NULL; -+ char *otheruserparts = NULL; -+ size_t otherslen = 0; -+ -+ const char *frepository; -+ int foundline = 0; -+ -+ char *line = NULL; -+ size_t line_allocated = 0; -+ int linelen; -+ -+ char *part_type = NULL; -+ char *part_object = NULL; -+ char *part_tag = NULL; -+ char *part_perms = NULL; -+ char *wperms; -+ char *userpart; -+ -+ char *errmsg; -+ -+ int pos; -+ -+ if (!aclfile) -+ return (0); -+ -+ frepository = Short_Repository (finfo->repository); -+ -+ filefullname = xmalloc (strlen (frepository) -+ + strlen (finfo->file) -+ + 2); -+ strcpy (filefullname, frepository); -+ strcat (filefullname, "/"); -+ strcat (filefullname, finfo->file); -+ -+ if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos, 0)) -+ error (1,0,"You do not have acl admin rights on '%s'", frepository); -+ -+ if (line != NULL) -+ { -+ part_type = strtok (line, ":\t"); -+ part_object = strtok (NULL, ":\t"); -+ part_tag = strtok (NULL, ":\t"); -+ part_perms = strtok (NULL, ":\t"); -+ -+ foundline = 1; -+ userpart = strtok (part_perms, ",\t"); -+ -+ if (strstr (userpart, muser)) -+ founduserpart = xstrdup (userpart); -+ else -+ { -+ otheruserparts = xstrdup (userpart); -+ otherslen = strlen (otheruserparts); -+ } -+ -+ while ((userpart = strtok (NULL, ",\t")) != NULL) -+ { -+ if (strncmp (userpart, muser, strlen (muser)) == 0) -+ founduserpart = xstrdup (userpart); -+ else -+ { -+ if (otheruserparts != NULL) -+ { -+ xrealloc_and_strcat (&otheruserparts, &otherslen, ","); -+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart); -+ } -+ else -+ { -+ otheruserparts = xstrdup (userpart); -+ otherslen = strlen (otheruserparts); -+ } -+ } -+ } -+ } -+ -+ wperms = make_perms (mperms, founduserpart, &errmsg); -+ if (wperms == NULL) -+ { -+ if (errmsg) -+ error (0, 0, "%s %s", filefullname, errmsg); -+ -+ return (0); -+ } -+ else -+ { -+ cvs_output ("X ", 0); -+ cvs_output (filefullname, 0); -+ cvs_output ("\n", 0); -+ -+ write_perms (muser, wperms, founduserpart, foundline, -+ otheruserparts, "f", filefullname, tag, pos, finfo->repository); -+ } -+ -+ return (0); -+} -+ -+static Dtype -+acl_dirproc (callerdat, dir, repos, update_dir, entries) -+void *callerdat; -+const char *dir; -+const char *repos; -+const char *update_dir; -+List *entries; -+{ -+ const char *drepository; -+ char *founduserpart = NULL; -+ char *newuserpart = NULL; -+ char *otheruserparts = NULL; -+ size_t otherslen = 0; -+ int foundline = 0; -+ -+ char *line = NULL; -+ size_t line_allocated = 0; -+ int linelen; -+ -+ FILE *accessfp; -+ char *part_type = NULL; -+ char *part_object = NULL; -+ char *part_tag = NULL; -+ char *part_perms = NULL; -+ char *wperms; -+ int i = 0; -+ char *userpart; -+ int pos; -+ -+ char *errmsg; -+ -+ if (repos[0] == '\0') -+ repos = Name_Repository (dir, NULL); -+ -+ if (!acldir) -+ return (0); -+ -+ if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0)) -+ error (1,0,"You do not have admin rights on '%s'", Short_Repository (repos)); -+ -+ drepository = Short_Repository (repos); -+ -+ if (line != NULL) -+ { -+ part_type = strtok (line, ":\t"); -+ part_object = strtok (NULL, ":\t"); -+ part_tag = strtok (NULL, ":\t"); -+ part_perms = strtok (NULL, ":\t"); -+ -+ foundline = 1; -+ userpart = strtok (part_perms, ",\t"); -+ -+ if (strstr (userpart, muser)) -+ founduserpart = xstrdup (userpart); -+ else -+ { -+ otheruserparts = xstrdup (userpart); -+ otherslen = strlen (otheruserparts); -+ } -+ -+ while ((userpart = strtok (NULL, ",\t")) != NULL) -+ { -+ if (strncmp (userpart, muser, strlen (muser)) == 0) -+ founduserpart = xstrdup (userpart); -+ else -+ { -+ if (otheruserparts != NULL) -+ { -+ xrealloc_and_strcat (&otheruserparts, &otherslen, ","); -+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart); -+ } -+ else -+ { -+ otheruserparts = xstrdup (userpart); -+ otherslen = strlen (otheruserparts); -+ } -+ } -+ } -+ } -+ -+ wperms = make_perms (mperms, founduserpart, &errmsg); -+ if (wperms == NULL) -+ { -+ if (errmsg) -+ error (0, 0, "%s %s", drepository, errmsg); -+ -+ return (0); -+ } -+ else -+ { -+ if (defaultperms) -+ { -+ cvs_output ("X ", 0); -+ cvs_output ("ALL", 0); -+ cvs_output ("\n", 0); -+ write_perms (muser, wperms, founduserpart, foundline, -+ otheruserparts, "d", "ALL", tag, pos, drepository);//baris -+ -+ } -+ else -+ { -+ cvs_output ("X ", 0); -+ cvs_output (drepository, 0); -+ cvs_output ("\n", 0); -+ write_perms (muser, wperms, founduserpart, foundline, -+ otheruserparts, "d", drepository, tag, pos, drepository);//baris `repos` -+ } -+ } -+ -+ return (0); -+} -+ -+/* Open CVSROOT/access or defined CVSACLFileLocation file. */ -+FILE * -+open_accessfile (fmode, adir, fname) -+char *fmode; -+const char *adir; -+char **fname; -+{ -+ char *accessfile; -+ FILE *accessfp; -+ -+ if (!use_separate_acl_file_for_each_dir) -+ { -+ if (cvs_acl_file_location == NULL) -+ { -+ accessfile = xmalloc (strlen (current_parsed_root->directory) -+ + sizeof (CVSROOTADM) -+ + sizeof (CVSROOTADM_ACCESS) -+ + 3); -+ -+ strcpy (accessfile, current_parsed_root->directory); -+ strcat (accessfile, "/"); -+ strcat (accessfile, CVSROOTADM); -+ strcat (accessfile, "/"); -+ strcat (accessfile, CVSROOTADM_ACCESS); -+ } -+ else -+ { -+ accessfile = xmalloc (strlen (cvs_acl_file_location)); -+ strcpy (accessfile, cvs_acl_file_location); -+ } -+ } -+ else -+ { -+ accessfile = xmalloc (strlen (current_parsed_root->directory) -+ + strlen (adir) -+ + strlen ("access") -+ + 3); -+ -+ strcpy (accessfile, current_parsed_root->directory); -+ strcat (accessfile, "/"); -+ strcat (accessfile, adir); -+ strcat (accessfile, "/"); -+ strcat (accessfile, "access"); -+ } -+ -+ accessfp = CVS_FOPEN (accessfile, fmode); -+ -+ if (accessfp == NULL) -+ error (0, 0, "cannot open file: %s", accessfile); -+ -+ if (fname != NULL) -+ *fname = xstrdup (accessfile); -+ -+ free (accessfile); -+ -+ return (accessfp); -+} -+ -+/* Open /etc/group file if UseSystemGroups=yes in config file. */ -+/* Open CVSROOT/group file if UseCVSGroups=yes in config file. */ -+FILE * -+open_groupfile (fmode) -+char *fmode; -+{ -+ char *groupfile; -+ FILE *groupfp; -+ -+ if (use_cvs_groups) -+ { -+ if (cvs_groups_file_location != NULL) -+ { -+ groupfile = xmalloc (strlen (cvs_groups_file_location)); -+ strcpy (groupfile, cvs_groups_file_location); -+ } -+ else -+ { -+ groupfile = xmalloc (strlen (current_parsed_root->directory) -+ + sizeof (CVSROOTADM) -+ + sizeof (CVSROOTADM_GROUP) -+ + 3); -+ -+ strcpy (groupfile, current_parsed_root->directory); -+ strcat (groupfile, "/"); -+ strcat (groupfile, CVSROOTADM); -+ strcat (groupfile, "/"); -+ strcat (groupfile, CVSROOTADM_GROUP); -+ } -+ } -+ -+ else -+ { -+ return (NULL); -+ } -+ -+ groupfp = CVS_FOPEN (groupfile, "r"); -+ -+ if (groupfp == NULL) -+ error (0, 0, "cannot open file: %s", groupfile); -+ -+ free (groupfile); -+ -+ return (groupfp); -+} -+ -+ -+/* Check whether given permissions are valid or not. */ -+/* Returns 1 if permissions are valid. */ -+/* Returns 0 if permissions are NOT valid. */ -+int -+given_perms_valid (cperms) -+char *cperms; -+{ -+ int cperms_len; -+ int retval; -+ int index, i; -+ -+ if (cperms[0] == '+' || cperms[0] == '-') -+ index = 1; -+ else -+ index = 0; -+ -+ cperms_len = strlen (cperms); -+ -+ switch (cperms[index]) -+ { -+ case 'x': -+ if ((cperms_len - index) == 1 && cperms_len == 1) -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'n': -+ if ((cperms_len - index) == 1 && cperms_len == 1) -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'p': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'a': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ for (i = index + 1; i < cperms_len; i++) -+ if (cperms[i] == 'p') -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'r': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ for (i = index + 1; i < cperms_len; i++) -+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd') -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'w': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ for (i = index + 1; i < cperms_len; i++) -+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd') -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 't': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ for (i = index + 1; i < cperms_len; i++) -+ if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd') -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'c': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ for (i = index + 1; i < cperms_len; i++) -+ if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd') -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ case 'd': -+ if ((cperms_len - index) == 1) -+ retval = 1; -+ else -+ for (i = index + 1; i < cperms_len; i++) -+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w') -+ retval = 1; -+ else -+ retval = 0; -+ break; -+ default: -+ retval = 0; -+ break; -+ } -+ return (retval); -+} -+ -+char * -+make_perms (perms, founduserpart, xerrmsg) -+char *perms; -+char *founduserpart; -+char **xerrmsg; -+{ -+ char *fperms; -+ size_t perms_len; -+ size_t fperms_len; -+ char *retperms = NULL; -+ char *xperms; -+ int i, j; -+ int err = 0; -+ char *errmsg = NULL; -+ size_t retperms_len = 1; -+ -+ retperms = xmalloc (retperms_len); -+ retperms[0] = '\0'; -+ -+ perms_len = strlen (perms); -+ -+ if (perms[0] == '+' || perms[0] == '-') -+ { -+ if (founduserpart) -+ { -+ char *temp; -+ temp = strtok (founduserpart, "!\t"); -+ fperms = strtok (NULL, "!\t"); -+ fperms_len = strlen (fperms); -+ -+ if (strncmp (fperms, "x", 1) == 0) -+ { -+ err = 1; -+ if (perms[0] == '+') -+ *xerrmsg = xstrdup ("cannot add default permission 'x'"); -+ else -+ *xerrmsg = xstrdup ("cannot remove default permission 'x'"); -+ } -+ -+ for (i = 1; i < perms_len && !err; i++) -+ { -+ switch (perms[i]) -+ { -+ case 'n': -+ err = 1; -+ break; -+ case 'p': -+ if (perms[0] == '+') -+ fperms = xstrdup ("p"); -+ else if (perms[0] == '-') -+ { -+ fperms_len = 1; -+ fperms = xmalloc (fperms_len); -+ fperms[0] = '\0'; -+ } -+ break; -+ case 'a': -+ for (j = 0; j < fperms_len; j++) -+ { -+ if (fperms[j] == 'p') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has admin rights, cannot use +/- permissions"); -+ } -+ else if (fperms[j] == 'a' && perms[0] == '+') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user already has all ('a') permission"); -+ } -+ else if (fperms[j] != 'a' && perms[0] == '-') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user does not have all ('a') permission"); -+ } -+ } -+ if (perms[0] == '+') -+ { -+ fperms = xstrdup ("a"); -+ fperms_len = strlen (fperms); -+ } -+ else if (perms[0] == '-') -+ { -+ fperms_len = 1; -+ fperms = xmalloc (fperms_len); -+ fperms[0] = '\0'; -+ } -+ -+ break; -+ case 'r': -+ for (i = 0; i < fperms_len; i++) -+ { -+ if (fperms[i] == 'n' && perms[0] == '+') -+ { -+ fperms = xstrdup ("r"); -+ fperms_len = strlen (fperms); -+ } -+ else if (fperms[i] == 'r' && perms[0] == '-') -+ { -+ fperms_len = 1; -+ fperms = xmalloc (fperms_len); -+ fperms[0] = '\0'; -+ } -+ else if (perms[0] == '-') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission"); -+ } -+ else -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission"); -+ } -+ } -+ break; -+ case 'w': -+ { -+ char *tempfperms; -+ size_t tempfperms_len = 1; -+ -+ tempfperms = xmalloc (tempfperms_len); -+ tempfperms[0] = '\0'; -+ -+ for (j = 0; j < fperms_len; j++) -+ { -+ if (fperms[j] == 't' || fperms[j] == 'c' || fperms[j] == 'd') -+ { -+ char *temp; -+ temp = xmalloc (2); -+ temp[0] = fperms[j]; -+ temp[1] = '\0'; -+ -+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp); -+ free (temp); -+ } -+ else if (fperms[j] == 'a' || fperms[j] == 'p') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- write permissions"); -+ } -+ else if (fperms[j] == 'n' || fperms[j] == 'r') -+ { -+ if (perms[0] == '-') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user does not have write ('w') permission"); -+ } -+ } -+ } -+ -+ fperms = xstrdup (tempfperms); -+ fperms_len = strlen (fperms); -+ free (tempfperms); -+ -+ if (perms[0] == '+') -+ { -+ xrealloc_and_strcat (&fperms, &fperms_len, "w"); -+ } -+ } -+ break; -+ case 't': -+ { -+ char *tempfperms; -+ size_t tempfperms_len = 1; -+ -+ tempfperms = xmalloc (tempfperms_len); -+ tempfperms[0] = '\0'; -+ -+ for (j = 0; j < fperms_len; j++) -+ { -+ if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 'd') -+ { -+ char *temp; -+ temp = xmalloc (2); -+ temp[0] = fperms[j]; -+ temp[1] = '\0'; -+ -+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp); -+ free (temp); -+ } -+ else if (fperms[j] == 'a' || fperms[j] == 'p') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- tag permissions"); -+ } -+ else if (fperms[i] == 'n' || fperms[i] == 'r') -+ { -+ if (perms[0] == '-') -+ *xerrmsg = xstrdup ("user does not have tag ('t') permission"); -+ } -+ } -+ -+ fperms = xstrdup (tempfperms); -+ fperms_len = strlen (fperms); -+ free (tempfperms); -+ -+ if (perms[0] == '+') -+ { -+ xrealloc_and_strcat (&fperms, &fperms_len, "t"); -+ } -+ } -+ break; -+ case 'c': -+ { -+ char *tempfperms; -+ size_t tempfperms_len = 1; -+ -+ tempfperms = xmalloc (tempfperms_len); -+ tempfperms[0] = '\0'; -+ -+ for (j = 0; j < fperms_len; j++) -+ { -+ if (fperms[j] == 'w' || fperms[j] == 't' || fperms[j] == 'd') -+ { -+ char *temp; -+ temp = xmalloc (2); -+ temp[0] = fperms[j]; -+ temp[1] = '\0'; -+ -+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp); -+ free (temp); -+ } -+ else if (fperms[j] == 'a' || fperms[j] == 'p') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- create permissions"); -+ } -+ else if (fperms[i] == 'n' || fperms[i] == 'r') -+ { -+ if (perms[0] == '-') -+ err = 1; -+ *xerrmsg = xstrdup ("user does not have create ('c') permission"); -+ } -+ -+ } -+ -+ fperms = xstrdup (tempfperms); -+ fperms_len = strlen (fperms); -+ free (tempfperms); -+ -+ if (perms[0] == '+') -+ { -+ xrealloc_and_strcat (&fperms, &fperms_len, "c"); -+ } -+ } -+ break; -+ case 'd': -+ { -+ char *tempfperms; -+ size_t tempfperms_len = 1; -+ -+ tempfperms = xmalloc (tempfperms_len); -+ tempfperms[0] = '\0'; -+ -+ for (j = 0; j < fperms_len; j++) -+ { -+ if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 't') -+ { -+ char *temp; -+ temp = xmalloc (2); -+ temp[0] = fperms[j]; -+ temp[1] = '\0'; -+ -+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp); -+ free (temp); -+ } -+ else if (fperms[j] == 'a' || fperms[j] == 'p') -+ { -+ err = 1; -+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- delete permissions"); -+ } -+ else if (fperms[i] == 'n' || fperms[i] == 'r') -+ { -+ if (perms[0] == '-') -+ err = 1; -+ *xerrmsg = xstrdup ("user does not have delete ('d') permission"); -+ } -+ } -+ -+ fperms = xstrdup (tempfperms); -+ fperms_len = strlen (fperms); -+ free (tempfperms); -+ -+ if (perms[0] == '+') -+ { -+ xrealloc_and_strcat (&fperms, &fperms_len, "d"); -+ } -+ } -+ break; -+ default: -+ err = 1; -+ *xerrmsg = xstrdup ("error in 'access' file format"); -+ break; -+ } -+ if (fperms[0] == '\0') -+ retperms = xstrdup ("none"); -+ else -+ retperms = xstrdup (fperms); -+ } -+ } -+ else -+ { -+ err = 1; -+ *xerrmsg = xstrdup("user is not given any permissions to remove/add"); -+ } -+ } -+ -+ else -+ { -+ retperms = xstrdup (perms); -+ } -+ -+ if (err) -+ return (NULL); -+ else -+ return (retperms); -+} -+ -+int -+write_perms (user, perms, founduserpart, foundline, otheruserparts, -+ part_type, part_object, part_tag, pos, arepos) -+char *user; -+char *perms; -+char *founduserpart; -+int foundline; -+char *otheruserparts; -+char *part_type; -+char *part_object; -+char *part_tag; -+int pos; -+char *arepos; -+{ -+ char *accessfile; -+ char *tmpaccessout; -+ FILE *accessfpin; -+ FILE *accessfpout; -+ -+ char *newline = NULL; -+ size_t newlinelen = 1; -+ -+ char *line = NULL; -+ size_t line_allocated = 0; -+ -+ newline = xmalloc (newlinelen); -+ newline[0] = '\0'; -+ -+ if (!cvs_casecmp (part_tag, "ALL")) -+ part_tag = xstrdup ("ALL"); -+ -+ xrealloc_and_strcat (&newline, &newlinelen, part_type); -+ xrealloc_and_strcat (&newline, &newlinelen, ":"); -+ xrealloc_and_strcat (&newline, &newlinelen, part_object); -+ xrealloc_and_strcat (&newline, &newlinelen, ":"); -+ xrealloc_and_strcat (&newline, &newlinelen, part_tag); -+ xrealloc_and_strcat (&newline, &newlinelen, ":"); -+ -+ if (strncmp (perms, "none", 4) != 0) -+ { -+ xrealloc_and_strcat (&newline, &newlinelen, user); -+ xrealloc_and_strcat (&newline, &newlinelen, "!"); -+ xrealloc_and_strcat (&newline, &newlinelen, perms); -+ if (otheruserparts != NULL) -+ xrealloc_and_strcat (&newline, &newlinelen, ","); -+ } -+ -+ if (otheruserparts != NULL) -+ { -+ if (otheruserparts[strlen (otheruserparts) - 1] == '\n') -+ otheruserparts[strlen (otheruserparts) - 1] = '\0'; -+ -+ xrealloc_and_strcat (&newline, &newlinelen, otheruserparts); -+ } -+ -+ xrealloc_and_strcat (&newline, &newlinelen, ":"); -+ -+ if (foundline) -+ { -+ accessfpout = cvs_temp_file (&tmpaccessout); -+ accessfpin = open_accessfile ("r", arepos, &accessfile); -+ -+ while (getline (&line, &line_allocated, accessfpin) >= 0) -+ { -+ if (pos != ftell (accessfpin)) -+ { -+ if (fprintf (accessfpout, line) < 0) -+ error (1, errno, "writing temporary file: %s", tmpaccessout); -+ } -+ else -+ { -+ if (fprintf (accessfpout, "%s\n", newline) < 0) -+ error (1, errno, "writing temporary file: %s", tmpaccessout); -+ } -+ -+ } -+ if (fclose (accessfpin) == EOF) -+ error (1, errno, "cannot close access file: %s", accessfile); -+ -+ if (fclose (accessfpout) == EOF) -+ error (1, errno, "cannot close temporary file: %s", tmpaccessout); -+ -+ if (CVS_UNLINK (accessfile) < 0) -+ error (0, errno, "cannot remove %s", accessfile); -+ -+ copy_file (tmpaccessout, accessfile); -+ -+ if (CVS_UNLINK (tmpaccessout) < 0) -+ error (0, errno, "cannot remove temporary file: %s", tmpaccessout); -+ } -+ else -+ { -+ accessfpout = open_accessfile ("r+", arepos, &accessfile); -+ -+ if (accessfpout == NULL) -+ { -+ if (existence_error (errno)) -+ { -+ accessfpout = open_accessfile ("w+", arepos, &accessfile); -+ } -+ } -+ else { -+ if (fseek (accessfpout, 0, 2) != 0) -+ error (1, errno, "cannot fseek access file: %s", accessfile); -+ } -+ -+ if (fprintf (accessfpout, "%s\n", newline) < 0) -+ error (1, errno, "writing access file: %s", accessfile); -+ -+ if (fclose (accessfpout) == EOF) -+ error (1, errno, "cannot close access file: %s", accessfile); -+ } -+ -+ free (newline); -+ -+ chmod(accessfile, 0644); -+ -+ return (0); -+} -+ -+ -+static int -+acllist_fileproc (callerdat, finfo) -+void *callerdat; -+struct file_info *finfo; -+{ -+ -+ char *filefullname; -+ const char *frepository; -+ char *line = NULL; -+ int pos; -+ -+ if (!aclfile) -+ return (0); -+ -+ frepository = Short_Repository (finfo->repository); -+ -+ filefullname = xmalloc (strlen (frepository) -+ + strlen (finfo->file) -+ + 2); -+ strcpy (filefullname, frepository); -+ strcat (filefullname, "/"); -+ strcat (filefullname, finfo->file); -+ -+ if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos, 0)) -+ error (1,0,"You do not have admin rights on '%s'", frepository); -+ -+ acllist_print (line, filefullname); -+ -+ return (0); -+} -+ -+static Dtype -+acllist_dirproc (callerdat, dir, repos, update_dir, entries) -+void *callerdat; -+const char *dir; -+const char *repos; -+const char *update_dir; -+List *entries; -+{ -+ -+ char *line = NULL; -+ const char *drepository; -+ int pos; -+ -+ if (repos[0] == '\0') -+ repos = Name_Repository (dir, NULL); -+ -+ if (!acldir) -+ return (0); -+ -+ drepository = Short_Repository (repos); -+ -+ if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0)) -+ error (1, 0, "You do not have admin rights on '%s'", drepository); -+ -+ acllist_print (line, drepository); -+ -+ return (0); -+} -+ -+ -+void -+acllist_print (line, obj) -+char *line; -+const char *obj; -+{ -+ char *temp; -+ char *temp2; -+ int x; -+ int c = 0; -+ -+ char *printedusers[255]; -+ printedusers[0] = NULL; -+ -+ if (line != NULL) -+ { -+ temp = strtok (line, ":\t"); -+ -+ if (acldir) -+ cvs_output ("d ", 0); -+ else if (aclfile) -+ cvs_output ("f ", 0); -+ -+ temp = strtok (NULL, ":\t"); -+ -+ cvs_output(obj, 0); -+ cvs_output (" | ", 0); -+ -+ temp = strtok (NULL, ":\t"); -+ cvs_output (temp, 0); -+ cvs_output (" | ", 0); -+ -+ while ((temp = strtok (NULL, "!\t")) != NULL) -+ { -+ if (strncmp (temp, ":", 1) == 0) -+ break; -+ -+ if (strcmp (temp, "ALL") == 0) -+ { -+ temp = strtok (NULL, ",\t"); -+ continue; -+ } -+ -+ cvs_output (temp, 0); -+ cvs_output (":", 0); -+ -+ while (printedusers[c] != NULL) -+ c++; -+ -+ printedusers[c] = xstrdup (temp); -+ c++; -+ printedusers[c] = NULL; -+ -+ temp = strtok (NULL, ",\t"); -+ -+ if (temp != NULL && temp[strlen (temp) - 2] == ':') -+ temp[strlen (temp) - 2] = '\0'; -+ -+ cvs_output (temp, 0); -+ cvs_output (" ", 0); -+ } -+ -+ if (default_perms_object) -+ { -+ cvs_output ("| defaults ", 0); -+ cvs_output ("ALL:", 0); -+ cvs_output (default_perms_object, 0); -+ } -+ else if (default_part_perms_accessfile) -+ { -+ size_t i; -+ i = strlen (default_part_perms_accessfile); -+ xrealloc_and_strcat (&default_part_perms_accessfile, &i, ","); -+ -+ free(line); -+ line = xstrdup(default_part_perms_accessfile); -+ -+ cvs_output ("| defaults ", 0); -+ -+ temp = strtok (line, "!\t"); -+ cvs_output (temp, 0); -+ cvs_output (":", 0); -+ -+ temp = strtok (NULL, ",\t"); -+ -+ cvs_output (temp, 0); -+ cvs_output (" ", 0); -+ -+ while ((temp = strtok (NULL, "!\t")) != NULL) -+ { -+ int printed = 0; -+ int c2 = 0; -+ while (printedusers[c2] != NULL && printed == 0) -+ { -+ if (strcmp (printedusers[c2], temp) == 0) -+ { -+ printed = 1; -+ break; -+ } -+ c2++; -+ } -+ -+ if (printed == 0) -+ { -+ cvs_output (temp, 0); -+ cvs_output (":", 0); -+ } -+ -+ temp = strtok (NULL, ",\t"); -+ -+ if (temp[strlen (temp) - 2] == ':') -+ temp[strlen (temp) - 2] = '\0'; -+ -+ if (printed == 0) -+ { -+ cvs_output (temp, 0); -+ cvs_output (" ", 0); -+ } -+ } -+ } -+ else if (cvs_acl_default_permissions) -+ { -+ cvs_output ("| defaults ", 0); -+ cvs_output ("ALL: ", 0); -+ cvs_output (cvs_acl_default_permissions, 0); -+ } -+ -+ cvs_output ("\n", 0); -+ -+ } -+ else -+ { -+ if (acldir) -+ cvs_output ("d ", 0); -+ else if (aclfile) -+ cvs_output ("f ", 0); -+ cvs_output (obj, 0); -+ cvs_output (" | ", 0); -+ cvs_output (tag, 0); -+ cvs_output (" | ", 0); -+ -+ if (default_perms_object) -+ { -+ cvs_output ("| defaults ", 0); -+ cvs_output ("ALL:", 0); -+ cvs_output (default_perms_object, 0); -+ cvs_output ("\n", 0); -+ } -+ else if (default_part_perms_accessfile) -+ { -+ free(line); -+ line = xstrdup(default_part_perms_accessfile); -+ -+ cvs_output ("| defaults ", 0); -+ -+ temp = strtok (line, "!\t"); -+ cvs_output (temp, 0); -+ cvs_output (":", 0); -+ -+ temp = strtok (NULL, ",\t"); -+ -+ if (temp[strlen (temp) - 2] == ':') -+ temp[strlen (temp) - 2] = '\0'; -+ -+ cvs_output (temp, 0); -+ cvs_output (" ", 0); -+ -+ while ((temp = strtok (NULL, "!\t")) != NULL) -+ { -+ cvs_output (temp, 0); -+ cvs_output (":", 0); -+ -+ temp = strtok (NULL, ",\t"); -+ -+ if (temp[strlen (temp) - 2] == ':') -+ temp[strlen (temp) - 2] = '\0'; -+ -+ cvs_output (temp, 0); -+ cvs_output (" ", 0); -+ } -+ cvs_output ("\n", 0); -+ } -+ else if (cvs_acl_default_permissions) -+ { -+ cvs_output ("| defaults ", 0); -+ cvs_output ("ALL: ", 0); -+ cvs_output (cvs_acl_default_permissions, 0); -+ cvs_output ("\n", 0); -+ } -+ else -+ cvs_output ("default:p (no perms)\n", 0); -+ } -+ -+} -diff -urN cvs-1.11.19.orig/src/add.c cvs-1.11.19/src/add.c ---- cvs-1.11.19.orig/src/add.c 2005-01-31 23:09:18.000000000 +0100 -+++ cvs-1.11.19/src/add.c 2005-03-14 19:55:09.000000000 +0100 -@@ -405,6 +405,24 @@ - } - else - { -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo.file, repository, vers->tag, 6, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo.repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo.repository), finfo.file); -+ -+ return (0); -+ } -+ } -+#endif - /* There is a user file, so build the entry for it */ - if (build_entry (repository, finfo.file, vers->options, - message, entries, vers->tag) != 0) -@@ -679,6 +697,26 @@ - && isdir (finfo.file) - && !wrap_name_has (finfo.file, WRAP_TOCVS)) - { -+ -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (NULL, repository, NULL, 6, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo.repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo.repository), finfo.file); -+ -+ return (0); -+ } -+ } -+#endif -+ - err += add_directory (&finfo); - } - else -diff -urN cvs-1.11.19.orig/src/admin.c cvs-1.11.19/src/admin.c ---- cvs-1.11.19.orig/src/admin.c 2005-01-31 23:09:57.000000000 +0100 -+++ cvs-1.11.19/src/admin.c 2005-03-14 19:55:09.000000000 +0100 -@@ -566,6 +566,25 @@ - - vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0); - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, NULL, 2, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - version = vers->vn_user; - if (version != NULL && strcmp (version, "0") == 0) - { -diff -urN cvs-1.11.19.orig/src/annotate.c cvs-1.11.19/src/annotate.c ---- cvs-1.11.19.orig/src/annotate.c 2005-01-31 23:10:09.000000000 +0100 -+++ cvs-1.11.19/src/annotate.c 2005-03-14 19:55:09.000000000 +0100 -@@ -281,6 +281,25 @@ - if (version == NULL) - return 0; - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, version, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - /* Distinguish output for various files if we are processing - several files. */ - cvs_outerr ("\nAnnotations for ", 0); -diff -urN cvs-1.11.19.orig/src/commit.c cvs-1.11.19/src/commit.c ---- cvs-1.11.19.orig/src/commit.c 2005-01-31 23:11:19.000000000 +0100 -+++ cvs-1.11.19/src/commit.c 2005-03-14 19:55:09.000000000 +0100 -@@ -1304,6 +1304,34 @@ - return 0; - - ci = p->data; -+ -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ int whichperm; -+ if (ci->status == T_MODIFIED) -+ whichperm = 3; -+ else if (ci->status == T_ADDED) -+ whichperm = 6; -+ else if (ci->status == T_REMOVED) -+ whichperm = 7; -+ -+ if (!access_allowed (finfo->file, finfo->repository, ci->tag, whichperm, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - if (ci->status == T_MODIFIED) - { - if (finfo->rcs == NULL) -diff -urN cvs-1.11.19.orig/src/cvs.h cvs-1.11.19/src/cvs.h ---- cvs-1.11.19.orig/src/cvs.h 2005-03-14 19:49:29.000000000 +0100 -+++ cvs-1.11.19/src/cvs.h 2005-03-14 19:55:09.000000000 +0100 -@@ -200,6 +200,11 @@ - #define CVSROOTADM_PASSWD "passwd" - #define CVSROOTADM_CONFIG "config" - -+/* cvsacl patch */ -+#define CVSROOTADM_ACLCONFIG "aclconfig" -+#define CVSROOTADM_ACCESS "access" -+#define CVSROOTADM_GROUP "group" -+ - #define CVSNULLREPOS "Emptydir" /* an empty directory */ - - /* Other CVS file names */ -@@ -572,6 +577,18 @@ - /* LockDir setting from CVSROOT/config. */ - extern char *lock_dir; - -+/* cvsacl patch */ -+/* ACL Patch settings from CVSROOT/config */ -+extern int use_cvs_acl; -+extern char *cvs_acl_default_permissions; -+extern int use_cvs_groups; -+extern int use_system_groups; -+extern int use_separate_acl_file_for_each_dir; -+extern char *cvs_acl_file_location; -+extern char *cvs_groups_file_location; -+extern char *cvs_server_run_as; -+extern int stop_at_first_permission_denied; -+ - void Scratch_Entry PROTO((List * list, const char *fname)); - void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp)); - void WriteTag PROTO ((const char *dir, const char *tag, const char *date, -@@ -867,6 +884,10 @@ - int editors PROTO ((int argc, char **argv)); - int watchers PROTO ((int argc, char **argv)); - extern int annotate PROTO ((int argc, char **argv)); -+ -+/* cvsacl patch */ -+extern int cvsacl PROTO ((int argc, char **argv)); -+ - extern int add PROTO ((int argc, char **argv)); - extern int admin PROTO ((int argc, char **argv)); - extern int checkout PROTO ((int argc, char **argv)); -diff -urN cvs-1.11.19.orig/src/diff.c cvs-1.11.19/src/diff.c ---- cvs-1.11.19.orig/src/diff.c 2005-01-31 23:12:09.000000000 +0100 -+++ cvs-1.11.19/src/diff.c 2005-03-14 19:55:09.000000000 +0100 -@@ -479,6 +479,43 @@ - { - /* Skip all the following checks regarding the user file; we're - not using it. */ -+ -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (diff_rev1) -+ { -+ if (!access_allowed (NULL, finfo->repository, diff_rev1, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+ if (diff_rev2) -+ { -+ if (!access_allowed (NULL, finfo->repository, diff_rev2, 5)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+ } -+#endif -+ - } - else if (vers->vn_user == NULL) - { -@@ -832,6 +869,42 @@ - if (!isdir (dir)) - return (R_SKIP_ALL); - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (diff_rev1) -+ { -+ if (!access_allowed (NULL, update_dir, diff_rev1, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (update_dir)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (update_dir), update_dir); -+ -+ return (0); -+ } -+ } -+ if (diff_rev2) -+ { -+ if (!access_allowed (NULL, update_dir, diff_rev2, 5)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (update_dir)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (update_dir), update_dir); -+ -+ return (0); -+ } -+ } -+ } -+#endif -+ - if (!quiet) - error (0, 0, "Diffing %s", update_dir); - return (R_PROCESS); -diff -urN cvs-1.11.19.orig/src/import.c cvs-1.11.19/src/import.c ---- cvs-1.11.19.orig/src/import.c 2005-01-31 23:13:00.000000000 +0100 -+++ cvs-1.11.19/src/import.c 2005-03-14 19:55:09.000000000 +0100 -@@ -319,6 +319,20 @@ - error (1, 0, "attempt to import the repository"); - } - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (NULL, repository, argv[1], 6, NULL, NULL, 1)) -+ { -+ error (stop_at_first_permission_denied, 0, "permission denied for %s", -+ Short_Repository (repository)); -+ -+ return (0); -+ } -+ } -+#endif -+ - /* - * Make all newly created directories writable. Should really use a more - * sophisticated security mechanism here. -diff -urN cvs-1.11.19.orig/src/log.c cvs-1.11.19/src/log.c ---- cvs-1.11.19.orig/src/log.c 2005-02-03 15:50:51.000000000 +0100 -+++ cvs-1.11.19/src/log.c 2005-03-14 19:55:09.000000000 +0100 -@@ -853,6 +853,25 @@ - return 1; - } - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, NULL, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - if (log_data->sup_header || !log_data->nameonly) - { - -diff -urN cvs-1.11.19.orig/src/main.c cvs-1.11.19/src/main.c ---- cvs-1.11.19.orig/src/main.c 2005-03-14 19:49:29.000000000 +0100 -+++ cvs-1.11.19/src/main.c 2005-03-14 19:55:09.000000000 +0100 -@@ -102,6 +102,10 @@ - } cmds[] = - - { -+ /* cvsacl patch */ -+ { "acl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, -+ { "racl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, -+ - { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, - { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, - { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR }, -@@ -968,6 +972,9 @@ - if we didn't, then there would be no way to check in a new - CVSROOT/config file to fix the broken one! */ - parse_config (current_parsed_root->directory); -+ -+ /* cvsacl patch */ -+ parse_aclconfig (current_parsed_root->directory); - } - - #ifdef CLIENT_SUPPORT -diff -urN cvs-1.11.19.orig/src/mkmodules.c cvs-1.11.19/src/mkmodules.c ---- cvs-1.11.19.orig/src/mkmodules.c 2005-01-31 23:14:17.000000000 +0100 -+++ cvs-1.11.19/src/mkmodules.c 2005-03-14 19:55:09.000000000 +0100 -@@ -316,6 +316,44 @@ - NULL - }; - -+/* cvsacl patch */ -+static const char *const aclconfig_contents[] = { -+ "# Set `UseCVSACL' to yes to use CVSACL feature.\n", -+ "UseCVSACL=yes\n", -+ "\n", -+ "# Default CVSACL Permission to use.\n", -+ "#CVSACLDefaultPermissions=p\n", -+ "\n", -+ "# Default file location for CVS ACL file (access) is CVSROOT/access.\n", -+ "# If you want to use a different location, define it below.\n", -+ "#CVSACLFileLocation=/path/to/cvs/access\n", -+ "\n", -+ "# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).\n", -+ "UseSystemGroups=yes\n", -+ "\n", -+ "# Set `UseCVSGroups' to yes to use another group file.\n", -+ "#UseCVSGroups=yes\n", -+ "\n", -+ "# Default file location for CVS groups file is CVSROOT/group.\n", -+ "# If you want to use a different location, define it below.\n", -+ "#CVSGroupsFileLocation=/path/to/cvs/group\n", -+ "\n", -+ "# Set UseSeparateACLFileForEachDir to yes in order to use a\n", -+ "# separate 'access' file for each directory.\n", -+ "# This increased the performance if you have really big repository.\n", -+ "#UseSeparateACLFileForEachDir=no\n", -+ "\n", -+ "# If StopAtFirstPermissionDenied is set to yes\n", -+ "# operation will stop at first permission denied message.\n", -+ "# Default is no.\n", -+ "#StopAtFirstPermissionDenied=no\n", -+ "\n", -+ "# Set CVSServerRunAsUser to a system user, in order CVS server\n", -+ "# to run as.\n", -+ "#CVSServerRunAsUser=runascvsuser", -+ NULL -+}; -+ - static const struct admin_file filelist[] = { - {CVSROOTADM_LOGINFO, - "no logging of 'cvs commit' messages is done without a %s file", -@@ -378,7 +416,12 @@ - {CVSROOTADM_CONFIG, - "a %s file configures various behaviors", - config_contents}, -- {NULL, NULL, NULL} -+ -+ /* cvsacl patch */ -+ {CVSROOTADM_ACLCONFIG, -+ "a %s file configures Access Control List behaviors", -+ aclconfig_contents}, -+ {NULL, NULL, NULL} - }; - - /* Rebuild the checked out administrative files in directory DIR. */ -@@ -962,6 +1005,26 @@ - because xchmod() is too shy. */ - chmod (info, 0666); - } -+ -+ /* cvsacl patch */ -+ /* Make an empty 'CVSROOT/access' file */ -+ strcpy (info, adm); -+ strcat (info, "/"); -+ strcat (info, CVSROOTADM_ACCESS); -+ if (!isfile (info)) -+ { -+ FILE *fp; -+ -+ fp = open_file (info, "w"); -+ if (fputs ("# CVS ACL definitions file. DO NOT EDIT MANUALLY\n", -+ fp) < 0) -+ error (1, errno, "cannot write %s", info); -+ -+ if (fclose (fp) < 0) -+ error (1, errno, "cannot close %s", info); -+ -+ chmod (info, 0644); -+ } - - /* Make an empty val-tags file to prevent problems creating it later. */ - strcpy (info, adm); -diff -urN cvs-1.11.19.orig/src/parseinfo.c cvs-1.11.19/src/parseinfo.c ---- cvs-1.11.19.orig/src/parseinfo.c 2005-01-31 23:14:54.000000000 +0100 -+++ cvs-1.11.19/src/parseinfo.c 2005-03-14 19:55:09.000000000 +0100 -@@ -453,3 +453,192 @@ - free (line); - return -1; - } -+/* cvsacl patch */ -+int -+parse_aclconfig (cvsroot) -+ char *cvsroot; -+{ -+ char *infopath; -+ FILE *fp_info; -+ char *line = NULL; -+ size_t line_allocated = 0; -+ size_t len; -+ char *p; -+ /* FIXME-reentrancy: If we do a multi-threaded server, this would need -+ to go to the per-connection data structures. */ -+ static int parsed = 0; -+ -+ /* Authentication code and serve_root might both want to call us. -+ Let this happen smoothly. */ -+ if (parsed) -+ return 0; -+ parsed = 1; -+ -+ infopath = xmalloc (strlen (cvsroot) -+ + sizeof (CVSROOTADM_ACLCONFIG) -+ + sizeof (CVSROOTADM) -+ + 10); -+ if (infopath == NULL) -+ { -+ error (0, 0, "out of memory; cannot allocate infopath"); -+ goto error_return; -+ } -+ -+ strcpy (infopath, cvsroot); -+ strcat (infopath, "/"); -+ strcat (infopath, CVSROOTADM); -+ strcat (infopath, "/"); -+ strcat (infopath, CVSROOTADM_ACLCONFIG); -+ -+ fp_info = CVS_FOPEN (infopath, "r"); -+ if (fp_info == NULL) -+ { -+ /* If no file, don't do anything special. */ -+ if (!existence_error (errno)) -+ { -+ /* Just a warning message; doesn't affect return -+ value, currently at least. */ -+ error (0, errno, "cannot open %s", infopath); -+ } -+ free (infopath); -+ return 0; -+ } -+ -+ while (getline (&line, &line_allocated, fp_info) >= 0) -+ { -+ /* Skip comments. */ -+ if (line[0] == '#') -+ continue; -+ -+ len = strlen (line) - 1; -+ if (line[len] == '\n') -+ line[len] = '\0'; -+ -+ /* Skip blank lines. */ -+ if (line[0] == '\0') -+ continue; -+ -+ /* The first '=' separates keyword from value. */ -+ p = strchr (line, '='); -+ if (p == NULL) -+ { -+ /* Probably should be printing line number. */ -+ error (0, 0, "syntax error in %s: line '%s' is missing '='", -+ infopath, line); -+ goto error_return; -+ } -+ -+ *p++ = '\0'; -+ -+ if (strcmp (line, "UseCVSACL") == 0) -+ { -+ if (strcmp (p, "no") == 0) -+ use_cvs_acl = 0; -+ else if (strcmp (p, "yes") == 0) -+ use_cvs_acl = 1; -+ else -+ { -+ error (0, 0, "unrecognized value '%s' for UseCVSACL", p); -+ goto error_return; -+ } -+ } -+ else if (strcmp (line, "UseSeparateACLFileForEachDir") == 0) -+ { -+ if (strcmp (p, "no") == 0) -+ use_separate_acl_file_for_each_dir = 0; -+ else if (strcmp (p, "yes") == 0) -+ use_separate_acl_file_for_each_dir = 1; -+ else -+ { -+ error (0, 0, "unrecognized value '%s' for UseSeparateACLFileForEachDir", p); -+ goto error_return; -+ } -+ } -+ else if (strcmp (line, "StopAtFirstPermissionDenied") == 0) -+ { -+ if (strcmp (p, "no") == 0) -+ stop_at_first_permission_denied = 0; -+ else if (strcmp (p, "yes") == 0) -+ stop_at_first_permission_denied = 1; -+ else -+ { -+ error (0, 0, "unrecognized value '%s' for StopAtFirstPermissionDenied", p); -+ goto error_return; -+ } -+ } -+ else if (strcmp (line, "CVSACLDefaultPermissions") == 0) -+ { -+ if (cvs_acl_default_permissions != NULL) -+ free (cvs_acl_default_permissions); -+ if (!given_perms_valid (p)) -+ error (1,0,"Invalid CVS ACL Default Permissions: '%s' in CVSROOT/aclconfig", p); -+ cvs_acl_default_permissions = xstrdup (p); -+ } -+ else if (strcmp (line, "UseCVSGroups") == 0) -+ { -+ if (strcmp (p, "no") == 0) -+ use_cvs_groups = 0; -+ else if (strcmp (p, "yes") == 0) -+ use_cvs_groups = 1; -+ else -+ { -+ error (0, 0, "unrecognized value '%s' for UseCVSGroups", p); -+ goto error_return; -+ } -+ } -+ else if (strcmp (line, "UseSystemGroups") == 0) -+ { -+ if (strcmp (p, "no") == 0) -+ use_system_groups = 0; -+ else if (strcmp (p, "yes") == 0) -+ use_system_groups = 1; -+ else -+ { -+ error (0, 0, "unrecognized value '%s' for UseSystemGroups", p); -+ goto error_return; -+ } -+ } -+ else if (strcmp (line, "CVSACLFileLocation") == 0) -+ { -+ if (cvs_acl_file_location != NULL) -+ free (cvs_acl_file_location); -+ cvs_acl_file_location = xstrdup (p); -+ } -+ else if (strcmp (line, "CVSGroupsFileLocation") == 0) -+ { -+ if (cvs_groups_file_location != NULL) -+ free (cvs_groups_file_location); -+ cvs_groups_file_location = xstrdup (p); -+ } -+ else if (strcmp (line, "CVSServerRunAsUser") == 0) -+ { -+ if (cvs_server_run_as != NULL) -+ free (cvs_server_run_as); -+ cvs_server_run_as = xstrdup (p); -+ } -+ -+ } -+ -+ if (ferror (fp_info)) -+ { -+ error (0, errno, "cannot read %s", infopath); -+ goto error_return; -+ } -+ if (fclose (fp_info) < 0) -+ { -+ error (0, errno, "cannot close %s", infopath); -+ goto error_return; -+ } -+ free (infopath); -+ if (line != NULL) -+ free (line); -+ return 0; -+ -+ error_return: -+ if (infopath != NULL) -+ free (infopath); -+ if (line != NULL) -+ free (line); -+ return -1; -+} -+ -diff -urN cvs-1.11.19.orig/src/patch.c cvs-1.11.19/src/patch.c ---- cvs-1.11.19.orig/src/patch.c 2005-01-31 23:15:02.000000000 +0100 -+++ cvs-1.11.19/src/patch.c 2005-03-14 19:55:09.000000000 +0100 -@@ -503,6 +503,43 @@ - goto out2; - } - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (rev1) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, rev1, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+ if (rev2) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, rev2, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+ } -+#endif -+ - /* Create 3 empty files. I'm not really sure there is any advantage - * to doing so now rather than just waiting until later. - * -diff -urN cvs-1.11.19.orig/src/remove.c cvs-1.11.19/src/remove.c ---- cvs-1.11.19.orig/src/remove.c 2005-01-31 23:15:31.000000000 +0100 -+++ cvs-1.11.19/src/remove.c 2005-03-14 19:55:09.000000000 +0100 -@@ -255,6 +255,25 @@ - { - char *fname; - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 7, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - /* Re-register it with a negative version number. */ - fname = xmalloc (strlen (vers->vn_user) + 5); - (void) strcpy (fname, "-"); -diff -urN cvs-1.11.19.orig/src/server.c cvs-1.11.19/src/server.c ---- cvs-1.11.19.orig/src/server.c 2005-03-14 19:49:29.000000000 +0100 -+++ cvs-1.11.19/src/server.c 2005-03-14 19:55:09.000000000 +0100 -@@ -773,6 +773,10 @@ - nothing. But for rsh, we need to do it now. */ - parse_config (current_parsed_root->directory); - -+ /* cvsacl patch */ -+ parse_aclconfig (current_parsed_root->directory); -+ -+ - path = xmalloc (strlen (current_parsed_root->directory) - + sizeof (CVSROOTADM) - + 2); -@@ -3761,6 +3765,23 @@ - do_cvs_command ("rlog", cvslog); - } - -+/* cvsacl patch */ -+static void -+serve_acl (arg) -+ char *arg; -+{ -+ do_cvs_command ("acl", cvsacl); -+} -+ -+/* cvsacl patch */ -+static void -+serve_racl (arg) -+ char *arg; -+{ -+ cvs_cmd_name = "racl"; -+ do_cvs_command ("racl", cvsacl); -+} -+ - static void - serve_add (arg) - char *arg; -@@ -4821,6 +4842,11 @@ - REQ_LINE("diff", serve_diff, 0), - REQ_LINE("log", serve_log, 0), - REQ_LINE("rlog", serve_rlog, 0), -+ -+ /* cvsacl patch */ -+ REQ_LINE("acl", serve_acl, 0), -+ REQ_LINE("racl", serve_racl, 0), -+ - REQ_LINE("add", serve_add, 0), - REQ_LINE("remove", serve_remove, 0), - REQ_LINE("update-patches", serve_ignore, 0), -@@ -5294,6 +5320,10 @@ - { - struct passwd *pw; - -+ /* cvsacl patch */ -+ if (use_cvs_acl && cvs_server_run_as) -+ username = cvs_server_run_as; -+ - pw = getpwnam (username); - if (pw == NULL) - { -@@ -5876,6 +5906,9 @@ - in a new CVSROOT/config file to fix the broken one! */ - parse_config (repository); - -+ /* cvsacl patch */ -+ parse_aclconfig (repository); -+ - /* We need the real cleartext before we hash it. */ - descrambled_password = descramble (password); - host_user = check_password (username, descrambled_password, repository); -diff -urN cvs-1.11.19.orig/src/status.c cvs-1.11.19/src/status.c ---- cvs-1.11.19.orig/src/status.c 2005-01-31 23:17:28.000000000 +0100 -+++ cvs-1.11.19/src/status.c 2005-03-14 19:55:09.000000000 +0100 -@@ -133,7 +133,27 @@ - - status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL, - 1, 0, &vers, 0); -- sstat = "Classify Error"; -+ -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ -+ sstat = "Classify Error"; - switch (status) - { - case T_UNKNOWN: -diff -urN cvs-1.11.19.orig/src/tag.c cvs-1.11.19/src/tag.c ---- cvs-1.11.19.orig/src/tag.c 2005-01-31 23:17:45.000000000 +0100 -+++ cvs-1.11.19/src/tag.c 2005-03-14 19:55:09.000000000 +0100 -@@ -665,6 +665,25 @@ - * correctly without breaking your link! - */ - -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, numtag, 4, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - if (delete_flag) - return (rtag_delete (rcsfile)); - -@@ -885,6 +904,21 @@ - if (nversion == NULL) - goto free_vars_and_return; - } -+ -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 4, -+ NULL, NULL, 1)) -+ { -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ return (0); -+ } -+ } -+#endif -+ - if (delete_flag) - { - -diff -urN cvs-1.11.19.orig/src/update.c cvs-1.11.19/src/update.c ---- cvs-1.11.19.orig/src/update.c 2005-01-31 23:18:01.000000000 +0100 -+++ cvs-1.11.19/src/update.c 2005-03-14 19:55:09.000000000 +0100 -@@ -601,6 +601,26 @@ - status = Classify_File (finfo, tag, date, options, force_tag_match, - aflag, &vers, pipeout); - -+ -+/* cvsacl patch */ -+#ifdef SERVER_SUPPORT -+ if (use_cvs_acl && server_active) -+ { -+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5, -+ NULL, NULL, 1)) -+ { -+ if (stop_at_first_permission_denied) -+ error (1, 0, "permission denied for %s", -+ Short_Repository (finfo->repository)); -+ else -+ error (0, 0, "permission denied for %s/%s", -+ Short_Repository (finfo->repository), finfo->file); -+ -+ return (0); -+ } -+ } -+#endif -+ - /* Keep track of whether TAG is a branch tag. - Note that if it is a branch tag in some files and a nonbranch tag - in others, treat it as a nonbranch tag. It is possible that case -diff -urN cvs-1.11.19.orig/src/version.c cvs-1.11.19/src/version.c ---- cvs-1.11.19.orig/src/version.c 2005-01-31 23:18:34.000000000 +0100 -+++ cvs-1.11.19/src/version.c 2005-03-14 19:55:09.000000000 +0100 -@@ -30,7 +30,8 @@ - #endif - #endif - -- -+/* cvsacl patch */ -+char *aclpatch_string = "with CVSACL Patch 1.2.2 (cvsacl.sourceforge.net)\n"; - - static const char *const version_usage[] = - { -@@ -67,6 +68,8 @@ - released. */ - (void) fputs (PACKAGE_STRING, stdout); - (void) fputs (config_string, stdout); -+ /* cvsacl patch */ -+ (void) fputs (aclpatch_string, stdout); - - #ifdef CLIENT_SUPPORT - if (current_parsed_root && current_parsed_root->isremote) -- 2.43.0