Index: src/README.RSE
===================================================================
RCS file: src/REAME.RSE
diff -N src/README.RSE
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/README.RSE	29 Jul 2003 07:05:45 -0000
@@ -0,0 +1,34 @@
+
+  CVS RSE Patches
+  ===============
+
+  This is the patched version of CVS from Ralf S. Engelschall
+  <rse@engelschall.com> - an enhanced version of the official CVS
+  (see http://www.cvshome.org/).
+
+  The following changes against the vendor CVS version are provided:
+    - support for an `importinfo' hook to ACL `cvs import' commands.
+
+  Some of my RSE functional patches are only useful for the server side,
+  others are also useful on the client side. All source patches to
+  *.[ch] files were entirely wrapped with ``#ifdef RSE_PATCH_<NAME> ...
+  #endif'' pairs. So, a particular patch is enabled by building CVS with
+  -DRSE_PATCH_<NAME>. All patches are enabled with -DRSE_PATCHES.
+
+                                       Ralf S. Engelschall
+                                       rse@engelschall.com
+                                       www.engelschall.com
+  ________________________________________________________________________
+
+  The following particular patches are available:
+
+  RSE_PATCH_IMPORTINFO:
+    This adds the feature of an extra `$CVSROOT/CVSROOT/importinfo'
+    configuration file which can be used for access controlling
+    `cvs import'. The specified filters in this info file receives
+    the following arguments: the vendor branch tag, the (absolute)
+    repository path which is the root of the import and then zero or
+    more relative file paths under this repository. If the filter
+    returns 0, the operation is allowed. If it returns not 0, the
+    operation is denied.
+    [Origin: Ralf S. Engelschall]
Index: src/cvs.h
===================================================================
RCS file: /cvs/ccvs/src/cvs.h,v
retrieving revision 1.269
diff -u -p -r1.269 cvs.h
--- src/cvs.h	25 Jul 2003 20:17:06 -0000	1.269
+++ src/cvs.h	29 Jul 2003 06:33:43 -0000
@@ -7,6 +7,13 @@
  */
 
 /*
+ * Support for compiling in various RSE extension
+ */
+#ifdef RSE_PATCHES
+#define RSE_PATCH_IMPORTINFO
+#endif
+
+/*
  * basic information used in all source files
  *
  */
@@ -167,6 +174,9 @@ char *strerror (int);
 #define CVSROOTADM_WRITERS	"writers"
 #define CVSROOTADM_PASSWD	"passwd"
 #define CVSROOTADM_CONFIG	"config"
+#ifdef RSE_PATCH_IMPORTINFO
+#define CVSROOTADM_IMPORTINFO	"importinfo"
+#endif
 
 #define CVSNULLREPOS		"Emptydir"	/* an empty directory */
 
Index: src/import.c
===================================================================
RCS file: /cvs/ccvs/src/import.c,v
retrieving revision 1.138
diff -u -p -r1.138 import.c
--- src/import.c	23 Jul 2003 20:42:26 -0000	1.138
+++ src/import.c	29 Jul 2003 06:33:45 -0000
@@ -57,6 +57,141 @@ static const char *const import_usage[] 
     NULL
 };
 
+#ifdef RSE_PATCH_IMPORTINFO
+
+static char *importinfo_vtag;
+
+static int
+importinfo_descend(thisdir)
+    char *thisdir;
+{
+    DIR *dirp;
+    struct dirent *dp;
+    int err = 0;
+    List *dirlist = NULL;
+
+    if ((dirp = CVS_OPENDIR(thisdir)) == NULL) {
+	error(0, errno, "cannot open directory");
+	err++;
+    }
+    else {
+	errno = 0;
+	while ((dp = readdir(dirp)) != NULL) {
+	    if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+		goto one_more_time_boys;
+	    if (strcmp(dp->d_name, CVSADM) == 0)
+		goto one_more_time_boys;
+	    if (ign_name(dp->d_name))
+		goto one_more_time_boys;
+	    if (
+#ifdef DT_DIR
+		(dp->d_type == DT_DIR || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
+#else
+		isdir (dp->d_name)
+#endif
+		&& !wrap_name_has(dp->d_name, WRAP_TOCVS)
+		) {
+		Node *n;
+		if (dirlist == NULL)
+		    dirlist = getlist();
+		n = getnode();
+		n->key = xstrdup(dp->d_name);
+		addnode(dirlist, n);
+	    }
+	    else if (
+#ifdef DT_DIR
+		dp->d_type == DT_LNK || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
+#else
+		islink (dp->d_name)
+#endif
+		) {
+		err++;
+	    }
+	    else {
+                if (strcmp(thisdir, ".") == 0) {
+                    run_arg(dp->d_name);
+                }
+                else {
+                    char *p;
+                    p = xmalloc(strlen(thisdir)+1+strlen(dp->d_name)+1);
+                    (void)sprintf(p, "%s/%s", thisdir, dp->d_name);
+                    run_arg(p);
+                    free(p);
+                }
+	    }
+	    one_more_time_boys:
+	    errno = 0;
+	}
+	if (errno != 0) {
+	    error(0, errno, "cannot read directory");
+	    err++;
+	}
+	(void)closedir(dirp);
+    }
+    if (dirlist != NULL) {
+	Node *head, *p;
+	head = dirlist->list;
+	for (p = head->next; p != head; p = p->next) {
+            if (strcmp(thisdir, ".") == 0) {
+                err += importinfo_descend(p->key);
+            }
+            else {
+                char *nextdir;
+                nextdir = xmalloc(strlen(thisdir)+1+strlen(p->key)+1);
+                (void)sprintf(nextdir, "%s/%s", thisdir, p->key);
+                err += importinfo_descend(nextdir);
+                free(nextdir);
+            }
+        }
+	dellist(&dirlist);
+    }
+    return err;
+}
+
+/* importinfo configuration entry callback */
+static int
+importinfo_runproc(repository, filter, closure)
+    char *repository;
+    char *filter;
+    void *closure;
+{
+    char *s, *cp;
+    int rv;
+
+    /* if possible, do an own check to make sure that filter really exists */
+    if (filter[0] == '/') {
+        s = xstrdup(filter);
+        for (cp = s; *cp; cp++) {
+            if (isspace((unsigned char)*cp)) {
+                *cp = '\0';
+                break;
+            }
+        }
+        if (!isfile(s)) {
+            error (0, errno, "cannot find pre-admin filter '%s'", s);
+            free(s);
+            return (1);
+        }
+        free(s);
+    }
+
+    /* construct the filter command */
+    run_setup(filter);
+    run_arg(importinfo_vtag);
+    run_arg(repository);
+    ign_add_file(CVSDOTIGNORE, 1);
+    wrap_add_file(CVSDOTWRAPPER, 1);
+    rv = importinfo_descend(".");
+    if (rv > 0) 
+        return rv;
+
+    /* execute the filter command */
+    rv = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+
+    return rv;
+}
+#endif
+
 int
 import (int argc, char **argv)
 {
@@ -287,6 +422,13 @@ import (int argc, char **argv)
     {
 	error (1, 0, "attempt to import the repository");
     }
+
+#ifdef RSE_PATCH_IMPORTINFO
+    importinfo_vtag = argv[1];
+    if (Parse_Info (CVSROOTADM_IMPORTINFO, argv[0], importinfo_runproc,
+		    PIOPT_ALL, NULL) > 0)
+	error (1, 0, "Pre-import check failed");
+#endif
 
     /*
      * Make all newly created directories writable.  Should really use a more
Index: src/mkmodules.c
===================================================================
RCS file: /cvs/ccvs/src/mkmodules.c,v
retrieving revision 1.72
diff -u -p -r1.72 mkmodules.c
--- src/mkmodules.c	23 Jul 2003 20:42:26 -0000	1.72
+++ src/mkmodules.c	29 Jul 2003 06:33:46 -0000
@@ -186,6 +186,27 @@ static const char *const taginfo_content
     NULL
 };
 
+#ifdef RSE_PATCH_IMPORTINFO
+static const char *const importinfo_contents[] = {
+    "# The \"importinfo\" file is used to control pre-import checks.\n",
+    "# The filter on the right is invoked with the repository to check.\n",
+    "# A non-zero exit of the filter program will cause the import\n",
+    "# operation to be aborted.\n",
+    "#\n",
+    "# The first entry on a line is a regular expression which is tested\n",
+    "# against the directory that the change is being committed to, relative\n",
+    "# to the $CVSROOT.  For the first match that is found, then the remainder\n",
+    "# of the line is the name of the filter to run.\n",
+    "#\n",
+    "# If the repository name does not match any of the regular expressions in this\n",
+    "# file, the \"DEFAULT\" line is used, if it is specified.\n",
+    "#\n",
+    "# If the name \"ALL\" appears as a regular expression it is always used\n",
+    "# in addition to the first matching regex or \"DEFAULT\".\n",
+    NULL
+};
+#endif
+
 static const char *const checkoutlist_contents[] = {
     "# The \"checkoutlist\" file is used to support additional version controlled\n",
     "# administrative files in $CVSROOT/CVSROOT, such as template files.\n",
@@ -339,6 +360,11 @@ static const struct admin_file filelist[
     {CVSROOTADM_TAGINFO,
 	"a %s file can be used to configure 'cvs tag' checking",
 	taginfo_contents},
+#ifdef RSE_PATCH_IMPORTINFO
+    {CVSROOTADM_IMPORTINFO,
+	"a %s file can be used to configure 'cvs import' checking",
+	importinfo_contents},
+#endif
     {CVSROOTADM_IGNORE,
 	"a %s file can be used to specify files to ignore",
 	NULL},
Index: src/sanity.sh
===================================================================
RCS file: /cvs/ccvs/src/sanity.sh,v
retrieving revision 1.813
diff -u -p -r1.813 sanity.sh
--- src/sanity.sh	25 Jul 2003 16:25:25 -0000	1.813
+++ src/sanity.sh	29 Jul 2003 06:34:44 -0000
@@ -322,6 +322,7 @@ fi
 # "debugger"
 #set -x
 
+echo '[THIS PROCEDURE TAKES APPROX. 25min ON A PII/400MHz, SO BE PATIENT!]'
 echo 'This test should produce no other output than this message, and a final "OK".'
 echo '(Note that the test can take an hour or more to run and periodically stops'
 echo 'for as long as one minute.  Do not assume there is a problem just because'
@@ -10356,6 +10357,7 @@ U CVSROOT/commitinfo
 U CVSROOT/config
 U CVSROOT/cvswrappers
 U CVSROOT/editinfo
+U CVSROOT/importinfo
 U CVSROOT/loginfo
 U CVSROOT/modules
 U CVSROOT/notify
@@ -10380,6 +10382,7 @@ U CVSROOT/commitinfo
 U CVSROOT/config
 U CVSROOT/cvswrappers
 U CVSROOT/editinfo
+U CVSROOT/importinfo
 U CVSROOT/loginfo
 U CVSROOT/modules
 U CVSROOT/notify
@@ -10407,6 +10410,7 @@ U CVSROOT/commitinfo
 U CVSROOT/config
 U CVSROOT/cvswrappers
 U CVSROOT/editinfo
+U CVSROOT/importinfo
 U CVSROOT/loginfo
 U CVSROOT/modules
 U CVSROOT/notify
Index: src/version.c
===================================================================
RCS file: /cvs/ccvs/src/version.c,v
retrieving revision 1.120
diff -u -p -r1.120 version.c
--- src/version.c	23 Jul 2003 20:42:26 -0000	1.120
+++ src/version.c	29 Jul 2003 06:34:45 -0000
@@ -60,6 +60,9 @@ version (int argc, char **argv)
        some idea of how long ago their version of CVS was
        released.  */
     (void) fputs (PACKAGE_STRING, stdout);
+#ifdef RSE_PATCHES
+    (void) fputs (" [RSE-importinfo]", stdout);
+#endif
     (void) fputs (config_string, stdout);
 
 #ifdef CLIENT_SUPPORT
