Module Name:    src
Committed By:   christos
Date:           Thu Mar  8 20:32:31 UTC 2012

Added Files:
        src/external/gpl2/xcvs/dist/src: acl.c

Log Message:
acl support


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/external/gpl2/xcvs/dist/src/acl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/external/gpl2/xcvs/dist/src/acl.c
diff -u /dev/null src/external/gpl2/xcvs/dist/src/acl.c:1.1
--- /dev/null	Thu Mar  8 15:32:31 2012
+++ src/external/gpl2/xcvs/dist/src/acl.c	Thu Mar  8 15:32:31 2012
@@ -0,0 +1,2162 @@
+/*
+ * Copyright (C) 2006 The Free Software Foundation, Inc.
+ *
+ * Portions Copyright (C) 2006, Baris Sahin <sbaris at users.sourceforge.net>
+ *                                          <http://cvsacl.sourceforge.net>
+ *
+ * 
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS source distribution.
+ * 
+ * 
+ *
+ * CVS ACCESS CONTROL LIST EXTENSION
+ *
+ * It provides advanced access control 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.
+ *
+ * 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)
+ * 
+ */
+#include "cvs.h"
+#include "getline.h"
+#include <grp.h>
+
+#define free(x) (void)(x)
+
+static int acl_fileproc (void *callerdat, struct file_info *finfo);
+
+static Dtype acl_dirproc (void *callerdat, const char *dir, const char *repos,
+			  const char *update_dir, List *entries);
+
+static int acllist_fileproc (void *callerdat, struct file_info *finfo);
+static Dtype acllist_dirproc (void *callerdat, const char *dir,
+			      const char *repos, const char *update_dir,
+			      List *entries);
+
+static void acllist_print (char *line, const char *obj);
+
+static int racl_proc (int argc, char **argv, char *xwhere,
+		      char *mwhere, char *mfile, int shorten,
+		      int local_specified, char *mname, char *msg);
+
+static FILE *open_accessfile (char *xmode, const char *repos, char **fname);
+static FILE *open_groupfile (char *xmode);
+
+static char *get_perms (const char *xperms);
+static char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
+
+static char *findusername (const char *string1, const char *string2);
+static char *findgroupname (const char *string1, const char *string2);
+static int valid_tag (const char *part_tag, const char *tag);
+static int valid_perm (const char *part_perms, int perm);
+static int write_perms (const char *user, const char *perms,
+			const char *founduserpart, int foundline,
+			char *otheruserparts, const char *part_type,
+			const char *part_object, const char *part_tag, int pos,
+			const char *arepos);
+
+static char *cache_repository;
+static int cache_retval;
+static int founddeniedfile;
+static int cache_perm;
+
+static int is_racl;
+static int debug = 0;
+
+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 aclconfig_default_used;
+
+int acldir = 0;
+int aclfile = 0;
+int listacl = 0;
+
+int userfound = 0;
+int groupfound = 0;
+
+/* directory depth ... */
+char *dirs[255];
+
+static const char *const acl_usage[] =
+        {
+                "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...] [files...]\n",
+                "\t-R\tProcess directories recursively.\n",
+                "\t-r rev\tExisting revision/tag.\n",
+                "\t-l\tList defined ACLs.\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] [directories...]"
+    " [files...]\n",
+    "\t-R\tProcess directories recursively.\n",
+    "\t-r rev\tExisting revision/tag.\n",
+    "\t-l\tList defined ACLs.\n",
+    "(Specify the --help global option for a list of other help options)\n",
+    NULL
+};
+
+
+int
+access_allowed (const char *file, const char *repos, const char *tag,
+		int perm, char **mline, int *mpos, int usecache)
+{
+    int retval = 0;
+    int foundline = 0;
+    FILE *accessfp;
+
+    int flag = 1;
+
+    char *iline;
+    char *tempv;
+    char *tempc;
+    size_t tempsize;
+    
+    int intcount;
+    int accessfilecount;
+    int signlevel = -1;
+    int dadmin = 0;
+
+    const char *repository;
+    char *filefullname = NULL;
+    userfound = 0;
+    groupfound = 0;
+
+    if (defaultperms)
+    {
+	repository = xstrdup ("ALL");
+    }
+    else {
+	if (strlen(repository = Short_Repository (repos)) == 0)
+	{
+	    repository = xstrdup (".");
+	}
+    }
+
+    /* 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;
+    }
+
+    iline = xstrdup(repository);
+
+    tempv = strtok(iline, "/\t");
+    tempc = xstrdup(tempv);
+    tempsize = ( tempc != NULL ) ? strlen(tempc) : 0;
+
+    intcount = 0;
+    /* store paths from object to cvsroot */
+    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);
+    }
+
+    /* free not needed variables here */
+    free (tempv);
+    free (tempc);
+    free (iline);
+
+    /* accessfilecount will used
+     * if UseSeparateACLFile keyword is set to yes*/
+    accessfilecount = intcount;
+
+    /* if file is not null add it to dirs array */
+    if (file != NULL)
+    {
+	filefullname = Xasprintf("%s/%s", repository, file);
+	intcount++;
+	dirs[intcount] = xstrdup(filefullname);
+    }
+
+    for (accessfilecount; accessfilecount >= 0 && flag; accessfilecount--)
+    {
+	if (!use_separate_acl_file_for_each_dir) {
+	    flag = 0;
+	    accessfp = open_accessfile ("r", repository, NULL);
+	}
+	else
+	{
+	    flag = 1;
+	    accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
+	}
+
+	if (accessfp != NULL)
+	{
+	    char *line = NULL;
+	    size_t line_allocated = 0;
+
+	    char *xline;
+	    char *part_type = NULL;
+	    char *part_object = NULL;
+	    char *part_tag = NULL;
+	    char *part_perms = NULL;
+
+	    int x;
+
+	    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");
+
+		if (part_type == NULL || part_object == NULL ||
+		    part_tag == NULL || part_perms == NULL)
+		{
+		    free (line);
+		    error(1, 0, "access file is corrupted or has invalid"
+				" format");
+		}
+
+		if (debug) fprintf (stderr, "type %s object %s tag %s perms"
+				    "%s\n", part_type, part_object, part_tag,
+				    part_perms);
+		for (x = intcount; x >= signlevel && x != -1; x--)
+		{
+		    if (debug) fprintf (stderr, "dirs[%d] = %s, part_object="
+					"%s\n", x, dirs[x], part_object);
+		    if (strcmp (dirs[x], part_object) == 0)
+		    {
+			if (debug) fprintf(stderr, "tag %s \n", tag);
+			if (valid_tag (part_tag, tag))
+			{
+			    foundline  = 1;
+			    if (debug) fprintf(stderr, "foundline\n");
+
+			    if (listacl || ((acldir || aclfile) &&
+					    x == intcount) &&
+				strcmp(part_tag, tag) == 0)
+			    {
+				*mline = xstrdup (xline);
+				*mpos = ftell (accessfp);
+			    }
+
+			    if (debug) fprintf(stderr, "perm %d\n", perm);
+			    if (valid_perm (part_perms, perm))
+			    {
+				if (signlevel == x)
+				{
+				    if (strcmp(part_tag, "ALL") != 0 &&
+					!aclconfig_default_used)
+					retval = 1;
+				}
+				else if (!aclconfig_default_used)
+				{
+				    signlevel = x;
+				    retval = 1;
+				}
+				else {
+				    /* nothing... */
+				}
+			    }
+			    else
+			    {
+				if (signlevel == x)
+				{
+				    if (strcmp(part_tag, "ALL") != 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 (debug) fprintf (stderr, "xline tag = %s %d %d\n", xline,
+				    groupfound, userfound);
+		if (strncmp (xline, "d:ALL:", 6) == 0 &&
+		    ((!groupfound && !userfound) || listacl))
+		{
+		    if (debug) fprintf (stderr, "ALL tag = %s\n", tag);
+		    /* a default found */
+		    if (valid_tag (part_tag, tag) > 0)
+		    {
+			foundline = 1;
+
+			default_part_perms_accessfile = xstrdup (part_perms);
+
+			if (debug) fprintf (stderr, "valid perm = %d\n", perm);
+			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)
+    {
+	if (debug) fprintf(stderr, "not found line\n");
+	/* DEFAULT */
+	if (valid_perm (NULL, perm))
+	    retval = 1;
+	else
+	    retval = 0;
+    }
+
+    /* acl admin rigths 'p' */
+    if (dadmin)
+    {
+	retval = dadmin;
+    }
+
+    cache_retval = retval;
+
+    free (filefullname);
+    /* free directories array */
+    while (intcount >= 0)
+    {
+	free (dirs[intcount]);
+	intcount--;
+    }
+
+    return retval;
+}
+
+/* Returns 1 if tag is valid, 0 if not */
+static int
+valid_tag (const char *part_tag, const char *tag)
+{
+    int retval;
+
+    if (tag == NULL)
+	tag = "HEAD";
+
+    if (strcmp (tag, part_tag) == 0 || strcmp (part_tag, "ALL") == 0)
+	retval = 1;
+    else
+	retval = 0;
+
+    return retval;
+}
+
+/* Returns 1 if successful, 0 if not. */
+static int
+valid_perm (const 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);
+
+    /* no access allowed, exit */
+    if (strstr (perms, "n"))
+	retval = 0;
+    
+    if (strstr (perms, "p"))
+	/* admin rights */
+	retval = 1;
+    else if (strstr (perms, "a") && perm != 8)
+	/* all access allowed, exit */
+	retval = 1;
+    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:/* never reached */
+	    retval = 0;
+	    break;
+	}
+
+    free (perms);
+
+    return (retval);
+}
+
+/* returns permissions found */
+char *
+get_perms (const char *part_perms)
+{
+    char *username;
+    char *xperms;
+    size_t xperms_len = 1;
+
+    FILE *groupfp;
+
+    char *founduser = NULL;
+    char *foundall = NULL;
+    int default_checked = 0;
+
+    if (debug) fprintf (stderr, "get_perms %s...", part_perms);
+    aclconfig_default_used = 0;
+
+    xperms = xmalloc (xperms_len);
+    xperms[0] = '\0';
+
+    /* use CVS_Username if set */
+    if (CVS_Username == NULL)
+	username = getcaller ();
+    else
+	username = CVS_Username;
+
+    /* 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;
+	    if (debug) fprintf (stderr, "default %s\n",
+			        cvs_acl_default_permissions);
+	    return (cvs_acl_default_permissions);
+	}
+	else {
+	    if (debug) fprintf (stderr, "early %s\n", xperms);
+	    return xperms;
+	}
+    }
+
+check_default:
+    founduser = findusername (part_perms, username);
+    foundall = strstr (part_perms, "ALL!");
+
+    if (debug) fprintf (stderr, "founduser=%s foundALL=%s\n",
+		        founduser, foundall);
+    if (founduser)
+    {
+	char *usr;
+	char *per;
+			
+	usr = strtok (founduser, "!\t");
+	per = strtok (NULL, ",\t");
+
+	xperms = xstrdup (per);
+	xperms_len = strlen (xperms);
+
+	userfound = 1;
+    }
+    else
+    {
+	if (debug) fprintf (stderr, "usesystemgroups=%d\n", use_system_groups);
+	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 (debug) fprintf (stderr, "usercheck=%s\n", userchk);
+		if (userchk != NULL) {
+		    char *grp;
+		    if ((grp = findusername (part_perms, griter->gr_name)))
+		    {
+			char *gperm = strtok (grp, "!\t");
+			if (debug) fprintf (stderr, "usercheck=%s, grp=%s\n",
+					    userchk, grp);
+			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;
+		char *grp;
+		char *gperm;
+		int read;
+		
+		size_t line_allocated = 0;
+
+		while ((read = getline (&line, &line_allocated, groupfp)) >= 0)
+		{
+		    if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
+			continue;
+		    
+		    if (line[read - 1] == '\n')
+			line[--read] = '\0';
+
+		    if (grp = findusername (part_perms,
+					    findgroupname (line, username)))
+		    {
+			gperm = strtok (grp, "!\t");
+			gperm = strtok (NULL, ",\t");
+			xrealloc_and_strcat (&xperms, &xperms_len, gperm);
+			groupfound = 1;
+		    }
+		}
+		
+		free (line);
+						
+		if (fclose (groupfp) == EOF)
+		    error (1, errno, "cannot close 'group' file");
+	    }
+	}
+    }
+
+    if (foundall)
+    {
+	char *usr;
+	char *per;
+	
+	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);
+	}
+	
+	free(foundall);
+
+	/* You don't free pointers from strtok()! */
+	//free(usr);
+	//free(per);
+    }
+    
+    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);
+    }
+
+    if (debug) fprintf (stderr, "late %s\n", xperms);
+    return xperms;
+}
+
+
+int
+cvsacl (int argc, char **argv)
+{
+    char *chdirrepository;
+    int c;
+    int err = 0;
+    int usetag = 0;
+    int recursive = 0;
+
+    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, "dRr:l")) != -1)
+    {
+	switch (c)
+	{
+	case 'd':
+	    debug++;
+	    break;
+	case 'R':
+	    recursive = 1;
+	    break;
+	case 'r': // baris
+	    tag = xstrdup (optarg);
+	    break;
+	case 'l':
+	    listacl = 1;
+	    break;
+	case '?':
+	default:
+	    usage (is_racl ? racl_usage : acl_usage);
+	    break;
+	}
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc < (is_racl ? 1 : 1))
+	usage (is_racl ? racl_usage : acl_usage);
+    if (listacl) {
+	if (strstr (argv[0], ":"))
+	    usage (is_racl ? racl_usage : acl_usage);
+    } else {
+	if (!strstr (argv[0], ":"))
+	    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 (listacl)
+	    send_arg ("-l");
+
+	if(tag)
+	{
+	    option_with_arg ("-r", 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 (!strcasecmp (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, NULL, 0, !recursive, 0,
+			      0, NULL);
+	}
+	close_module (db);
+    }
+    else
+    {
+	err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive,
+			 NULL, NULL);
+    }
+
+    return err;
+
+#endif
+}
+
+static int
+racl_proc (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 = NULL;
+    char *where;
+    char *obj;
+    size_t objlen = 0;
+
+    if (!use_cvs_acl)
+    {
+	error(1, 0, "CVSACL extension is not enabled, set `UseCVSACL=yes'"
+	      " in aclconfig file");
+    }
+
+    if (is_racl)
+    {
+	repository = Xasprintf ("%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 = Xasprintf ("%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);
+	    free (where);
+	    return 1;
+	}
+
+	/* End section which is identical to patch_proc.  */
+
+	which = W_REPOS | W_ATTIC;
+
+	if (argc > 1)
+	{
+		obj = Xasprintf ("%s/%s", repository, argv[1]);
+	}
+	else
+	{
+		obj = xstrdup(repository);
+	}
+    }
+    else
+    {
+	where = NULL;
+	which = W_LOCAL | W_REPOS | W_ATTIC;
+
+	obj = xstrdup (argv[1]);
+    }
+
+    if (isdir (obj))
+	acldir = 1;
+    else if (isfile (obj))
+	aclfile = 1;
+    else
+	error(1, 0, "no such file or directory");
+    
+    free (obj);
+
+    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);
+
+    if (repository != NULL)
+	free (repository);
+    
+    return err;
+}
+
+
+static int
+acl_fileproc (void *callerdat, struct file_info *finfo)
+{
+    char *filefullname;
+    char *founduserpart = 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 *wperms;
+    char *errmsg;
+
+    int pos;
+    
+    if (!aclfile)
+	return 0;
+
+    frepository = Short_Repository (finfo->repository);
+
+    filefullname = Xasprintf("%s/%s", frepository, 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)
+    {
+	char *part_type = NULL;
+	char *part_object = NULL;
+	char *part_tag = NULL;
+	char *part_perms = NULL;
+	char *userpart;
+		
+	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");
+
+	do
+	{
+	    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);
+		}
+	    }
+	} while ((userpart = strtok (NULL, ",\t")) != NULL);
+	
+	free (userpart);
+    }
+
+    wperms = make_perms (mperms, founduserpart, &errmsg);
+    if (wperms == NULL)
+    {
+	if (errmsg)
+	    error (0, 0, "`%s' %s", filefullname, errmsg);
+    }
+    else
+    {
+	cvs_output ("X ", 0);
+	cvs_output (filefullname, 0);
+	cvs_output ("\n", 0);
+
+	write_perms (muser, wperms, founduserpart, foundline,
+		     otheruserparts, "f", filefullname, tag, pos,
+		     Short_Repository(finfo->repository));
+    }
+
+    free (line);
+    free (founduserpart);
+    free (otheruserparts);
+    free (wperms);
+    free (filefullname);
+    
+    return 0;
+}
+
+static Dtype
+acl_dirproc (void *callerdat, const char *dir, const char *repos,
+	     const char *update_dir, List *entries)
+{
+    const char *drepository;
+    char *founduserpart = NULL;
+    char *otheruserparts = NULL;
+    size_t otherslen = 0;
+    int foundline = 0;
+
+    char *line = NULL;
+    size_t line_allocated = 0;
+    int linelen;
+
+    int pos;
+
+    char *wperms;
+    char *errmsg;
+
+    if (!acldir)
+	return 0;
+
+    if (repos[0] == '\0')
+	repos = Name_Repository (dir, NULL);
+
+    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)
+    {
+	char *part_type = NULL;
+	char *part_object = NULL;
+	char *part_tag = NULL;
+	char *part_perms = NULL;
+	char *userpart;
+			
+	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");
+
+	do
+	{
+	    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);
+		}
+	    }
+	} while ((userpart = strtok (NULL, ",\t")) != NULL);
+    }
+
+    wperms = make_perms (mperms, founduserpart, &errmsg);
+    if (wperms == NULL)
+    {
+	if (errmsg)
+	    error (0, 0, "`%s' %s", drepository, errmsg);
+    }
+    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);
+
+	}
+	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);
+	}
+    }
+    
+    free (line);
+    free (founduserpart);
+    free (otheruserparts);
+    free (wperms);
+    
+    return 0;
+}
+
+/* Open CVSROOT/access or defined CVSACLFileLocation file 
+ * Open access file In each directory if UseSeparateACLFileForEachDir=yes
+ * returns file pointer to access file or NULL if access file not found */
+FILE *
+open_accessfile (char *fmode, const char *adir, char **fname)
+{
+    char *accessfile = NULL;
+    FILE *accessfp;
+
+    if (!use_separate_acl_file_for_each_dir)
+    {
+	if (cvs_acl_file_location == NULL)
+	{
+	    accessfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
+				   CVSROOTADM, CVSROOTADM_ACCESS);
+	}
+	else
+	{
+	    accessfile = xstrdup(cvs_acl_file_location);
+	}
+    }
+    else
+    {
+	size_t accessfilelen = 0;
+	xrealloc_and_strcat (&accessfile, &accessfilelen,
+			     current_parsed_root->directory);
+	xrealloc_and_strcat (&accessfile, &accessfilelen, "/");
+	xrealloc_and_strcat (&accessfile, &accessfilelen, adir);
+	xrealloc_and_strcat (&accessfile, &accessfilelen, "/access");
+    }
+
+    accessfp = CVS_FOPEN (accessfile, fmode);
+
+    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
+ * Open group file if specified in CVSGroupsFileLocation 
+ * returns group file pointer if UseSystemGroups=yes
+ * returns NULL if UseSystemGroups=no or group file not found */
+FILE *
+open_groupfile (char *fmode)
+{
+    char *groupfile;
+    FILE *groupfp;
+
+    if (use_cvs_groups)
+    {
+	if (cvs_groups_file_location != NULL)
+	{
+	    groupfile = xstrdup (cvs_groups_file_location);
+	}
+	else
+	{
+	    groupfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
+				  CVSROOTADM, 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 (const 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
+	    retval = 0;
+	break;
+    case 'r':
+	if ((cperms_len - index) == 1)
+	    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;
+}
+
+/* prepare permsissions string to be written to access file
+ * returns permissions or NULL if */
+char *
+make_perms (char *perms, char *founduserpart, char **xerrmsg)
+{
+    char *fperms;
+    size_t perms_len;
+    size_t fperms_len;
+    
+    int i, j;
+    int err = 0;
+    char *errmsg = NULL;
+    
+    char *retperms;
+    size_t retperms_len = 1;
+
+    retperms = xmalloc (retperms_len);
+    retperms[0] = '\0';
+
+    perms_len = strlen (perms);
+
+    if (perms[0] == '+' || perms[0] == '-')
+    {
+	if (founduserpart)
+	{
+	    char *tempfperms;
+	    size_t tempfperms_len;
+	    
+	    char *temp;
+	    int per = 0;
+	    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'");
+	    }
+
+	    /* go through perms */
+	    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 have 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':
+		    {
+			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");
+				}
+			    }
+			    else if (fperms[j] == 'w')
+			    {
+				per = 1;
+				if (perms[0] == '+') {
+				    err = 1;
+				    *xerrmsg = xstrdup ("user already have"
+							" write ('w')"
+							"permission");
+				}
+			    }
+			}
+
+			fperms = xstrdup (tempfperms);
+			fperms_len = strlen (fperms);
+			free (tempfperms);
+
+			if (!per && !err && (perms[0] == '-')) {
+			    err = 1;
+			    *xerrmsg = xstrdup ("user does not have write"
+						" ('w') permission");
+			}
+
+			if (perms[0] == '+')
+			{
+			    xrealloc_and_strcat (&fperms, &fperms_len, "w");
+			}
+		    }
+		    break;
+		case '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[j] == 'n' || fperms[i] == 'r')
+			    {
+				if (perms[0] == '-')
+				    *xerrmsg = xstrdup ("user does not have tag"
+							" ('t') permission");
+			    }
+			    else if (fperms[j] == 't')
+			    {
+				per = 1;
+				if (perms[0] == '+')
+				{
+				    err = 1;
+				    *xerrmsg = xstrdup ("user already have tag"
+							" ('t') permission");
+				}
+			    }
+			}
+
+			fperms = xstrdup (tempfperms);
+			fperms_len = strlen (fperms);
+			free (tempfperms);
+
+			if (!per && !err && (perms[0] == '-'))
+			{
+			    err = 1;
+			    *xerrmsg = xstrdup ("user does not have tag ('t')"
+						" permission");
+			}
+
+			if (perms[0] == '+')
+			{
+			    xrealloc_and_strcat (&fperms, &fperms_len, "t");
+			}
+		    }
+		    break;
+		case 'c':
+		    {
+			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[j] == 'n' || fperms[i] == 'r')
+			    {
+				if (perms[0] == '-')
+				    err = 1;
+				*xerrmsg = xstrdup ("user does not have create"
+						    " ('c') permission");
+			    }
+			    else if (fperms[j] == 'c')
+			    {
+				per = 1;
+				if (perms[0] == '+') {
+				    err = 1;
+				    *xerrmsg = xstrdup ("user already have"
+							" create ('c')"
+							" permission");
+				}
+			    }
+			}
+
+			fperms = xstrdup (tempfperms);
+			fperms_len = strlen (fperms);
+			free (tempfperms);
+
+			if (!per && !err && (perms[0] == '-')) {
+			    err = 1;
+			    *xerrmsg = xstrdup ("user does not have create"
+						" ('c') permission");
+			}
+
+			if (perms[0] == '+')
+			{
+			    xrealloc_and_strcat (&fperms, &fperms_len, "c");
+			}
+		    }
+		    break;
+		case 'd':
+		    {
+			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[j] == 'n' || fperms[i] == 'r')
+			    {
+				if (perms[0] == '-')
+				    err = 1;
+				*xerrmsg = xstrdup ("user does not have delete"
+						    " ('d') permission");
+			    }
+			    else if (fperms[j] == 'd')
+			    {
+				per = 1;
+				if (perms[0] == '+') {
+				    err = 1;
+				    *xerrmsg = xstrdup ("user already have"
+							" delete ('d')"
+							" permission");
+				}
+			    }
+			}
+
+			fperms = xstrdup (tempfperms);
+			fperms_len = strlen (fperms);
+			free (tempfperms);
+			
+			if (!per && !err && (perms[0] == '-')) {
+				err = 1;
+				*xerrmsg = xstrdup ("user does not have delete"
+						    " ('d') permission");
+			}
+
+			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);
+    }
+    
+    return (err ? NULL : retperms);
+}
+
+/* prepare and write resulting permissions to access file */
+static int
+write_perms (const char *user, const char *perms, const char *founduserpart,
+	     int foundline, char *otheruserparts,
+	     const char *part_type, const char *part_object,
+	     const char *part_tag, int pos, const char *arepos)
+{
+    char *accessfile;
+    char *tmpaccessout;
+    FILE *accessfpin;
+    FILE *accessfpout;
+
+    char *newline = NULL;
+    size_t newlinelen = 1;
+    char *object;
+
+    char *line = NULL;
+    size_t line_allocated = 0;
+
+    newline = xmalloc (newlinelen);
+    newline[0] = '\0';
+
+    if (!strcasecmp (part_tag, "ALL"))
+	part_tag = "ALL";
+
+    /* strip any trailing slash if found */
+    object = xstrdup (part_object);
+    if (object[strlen (object) - 1] == '/')
+	object[strlen (object) - 1] = '\0';
+
+    /* first parts, part type, object, and tag */
+    xrealloc_and_strcat (&newline, &newlinelen, part_type);
+    xrealloc_and_strcat (&newline, &newlinelen, ":");
+    xrealloc_and_strcat (&newline, &newlinelen, 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);
+	if (accessfpout == NULL)
+	    error (1, errno, "cannot open temporary file: %s", tmpaccessout);
+
+	accessfpin = open_accessfile ("r", arepos, &accessfile);
+	if (accessfpout == NULL)
+	    error (1, errno, "cannot open access file: %s", accessfile);
+
+	while (getline (&line, &line_allocated, accessfpin) >= 0)
+	{
+	    if (pos != ftell (accessfpin))
+	    {
+		if (fprintf (accessfpout, "%s", 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);
+	    }
+	    if (accessfpout == NULL)
+		error (1, errno, "cannot open access file: %s", 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 (line);
+    free (newline);
+
+    chmod (accessfile, 0644);
+
+    return 0;
+}
+
+static int
+acllist_fileproc (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 = Xasprintf("%s/%s", frepository, finfo->file);
+
+    /* check that user, which run acl/racl command, has admin permisson,
+     * and also return the line with permissions from access 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);
+
+    free (filefullname);
+
+    return 0;
+}
+
+static Dtype
+acllist_dirproc (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);
+    
+    /* check that user, which run acl/racl command, has admin permisson,
+     * and also return the line with permissions from access file.  */
+    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;
+}
+
+/* Prints permissions to screen with -l option */
+void
+acllist_print (char *line, const char *obj)
+{
+    char *temp;
+    int c = 0;
+    int def = 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);
+	    def = 1;
+	}
+	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);
+
+	    if (!def)
+		cvs_output ("| defaults ", 0);
+	    else
+		cvs_output (" ", 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);
+		}
+	    }
+	    def = 1;
+	}
+	else if (cvs_acl_default_permissions)
+	{
+	    cvs_output ("| defaults ", 0);
+	    cvs_output ("ALL: ", 0);
+	    cvs_output (cvs_acl_default_permissions, 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);
+	    def = 1;
+	}
+	if (default_part_perms_accessfile)
+	{
+	    free (line);
+	    line = xstrdup (default_part_perms_accessfile);
+
+	    if (!def)
+		cvs_output ("| defaults ", 0);
+	    else
+		cvs_output (" ", 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);
+
+		if ((temp = strtok (NULL, ",\t")) != NULL)
+		{
+		    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);
+	}
+	else
+	    cvs_output ("default:p (no perms)", 0);
+    }
+    cvs_output ("\n", 0);
+	
+    while (c >= 0)  {
+	free (printedusers[c]);
+	c--;
+    }
+	
+    free (line);
+}
+
+/* find username
+ * returns username with its permissions if user found
+ * returns NULL if user not found */
+char *findusername (const char *string1, const char *string2)
+{
+    char *tmp1, *tmp2;
+
+    if (string1 != NULL && string2 != NULL)
+    {
+	tmp1 = xstrdup (string1);
+	tmp2 = strtok (tmp1, ",\t");
+	
+	do
+	{
+	    if (strncmp (tmp2, string2, strlen (string2)) == 0 &&
+				     tmp2[strlen (string2)] == '!')
+	    {
+		return tmp2;
+	    }
+	    tmp2 = strtok (NULL, ",\t");
+	}
+	while (tmp2 != NULL);
+
+	free (tmp1);
+	free (tmp2);
+	
+	return NULL;
+    }
+    else
+	return NULL;
+}
+
+/* find user name in group file
+ * returns group name if user found
+ * returns NULL if user not found */
+char *findgroupname (const char *string1, const char *string2)
+{
+    char *tmp1, *tmp2;
+    char *grpname;
+    
+    if (string1 != NULL && string2 != NULL)
+    {
+	tmp1 = xstrdup (string1);
+	grpname = strtok (tmp1, ":\t");
+
+	while (tmp2 = strtok(NULL, ",\t"))
+	{
+	    if (strcmp (tmp2, string2) == 0)
+	    {
+		return grpname;
+	    }
+	}
+	
+	free (tmp1);
+	free (tmp2);
+	
+	return NULL;
+    }
+    else
+	return NULL;
+}

Reply via email to