(I hope this is the right forum.  If not, I guess I'll hear about it...)

I have found it very useful to be able to specify port number for pserver
(to support multiple repositories on the same host).  Following patch
implements ":pserver/port:" syntax (where "/port" is optional of course).  

I would really appreciate if someone on the development team could find
time to look at it, and tell me if it is possible to get it into the main
tree.  I will gladly modify the code to conform to any rules I may have
missed.  Note that I have added some comments about what I've done and not
done.  I'll be happy to remove them and produce a cleaner patch if needed.

Note that I have tried to modify the current code as little as
possible.  As my comments state, I believe more work could be done, but I
refrained from this in an attempt to make something that doesn't break
any old behaviour.  I haven't followed CVS development closely enough to
have a strong view about how to implement all this, so please disregard my
comments if you find them stupid! :-)

I _really_ need this functionality, so any comments about how to proceed
(if this isn't enough) are welcome.

/m

Index: client.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/client.c,v
retrieving revision 1.279
diff -u -r1.279 client.c
--- client.c    2000/05/20 22:00:32     1.279
+++ client.c    2000/05/28 20:01:23
@@ -3654,15 +3654,43 @@
 
 static int auth_server_port_number PROTO ((void));
 
+/*
+ * auth_server_port_number() returns numeric port number (host byte order)
+ * for the active root_method.  The port number, or service name, is
+ * specified in (global var) CVSroot_method_port, which is set by
+ * parse_cvsroot().
+ *
+ * XXX We should clean up the naming of the xxx_PORT defs.
+ * XXX We should clean up the port specification logic further;
+ *     start_tcp_server() still contains some logic (I didn't want to 
+ *     break old behavior)/<[EMAIL PROTECTED]>
+ */
 static int
 auth_server_port_number ()
 {
-    struct servent *s = getservbyname ("cvspserver", "tcp");
+    struct servent *s = getservbyname (CVSroot_method_port, "tcp");
+    int port;
+    char *p;
 
     if (s)
        return ntohs (s->s_port);
     else
-       return CVS_AUTH_PORT;
+    {
+        port = strtol (CVSroot_method_port, &p, 10);
+       if (strcmp (CVSroot_method_port, "cvspserver") == 0)
+           return CVS_AUTH_PORT;
+#if HAVE_KERBEROS
+       if (strcmp (CVSroot_method_port, "cvs") == 0)
+           return CVS_PORT;
+#endif /* HAVE_KERBEROS */
+       if (p == CVSroot_method_port || port < 1 || port > 65535)
+       {
+           fprintf (stderr, "Invalid root server port %s.\n",
+                    CVSroot_method_port);
+           error_exit ();
+       }
+       return port;
+    }
 }
 
 
@@ -3983,6 +4011,13 @@
     if (s < 0)
        error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
 
+    /* 
+     * XXX
+     * Old port selection logic is kept intact here; the env var
+     * CVS_CLIENT_PORT overrides the new spec "kserver/port".
+     * This should be fixed (remove env var usage!?)/<[EMAIL PROTECTED]>
+     */
+
     /* Get CVS_CLIENT_PORT or look up cvs/tcp with CVS_PORT as default */
     portenv = getenv ("CVS_CLIENT_PORT");
     if (portenv != NULL)
@@ -4000,13 +4035,11 @@
     }
     else
     {
-       struct servent *sp;
-
-       sp = getservbyname ("cvs", "tcp");
-       if (sp == NULL)
-           port = CVS_PORT;
-       else
-           port = ntohs (sp->s_port);
+        /*
+        * Get port number from CVSroot_method_port; it will try service
+        * "cvs", then CVS_PORT.
+        */
+        port = auth_server_port_number ();
     }
 
     hp = init_sockaddr (&sin, CVSroot_hostname, port);
Index: cvs.h
===================================================================
RCS file: /home2/cvsroot/ccvs/src/cvs.h,v
retrieving revision 1.201
diff -u -r1.201 cvs.h
--- cvs.h       2000/05/16 18:57:15     1.201
+++ cvs.h       2000/05/28 20:01:31
@@ -380,6 +380,7 @@
 extern char *CVSroot_original; /* the active, complete CVSroot string */
 extern int client_active;      /* nonzero if we are doing remote access */
 extern CVSmethod CVSroot_method; /* one of the enum values above */
+extern char *CVSroot_method_port; /* port no for method (cur only pserver) */
 extern char *CVSroot_username; /* the username or NULL if method == local */
 extern char *CVSroot_hostname; /* the hostname or NULL if method == local */
 extern char *CVSroot_directory;        /* the directory name */
Index: root.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/root.c,v
retrieving revision 1.36
diff -u -r1.36 root.c
--- root.c      1999/03/07 20:17:02     1.36
+++ root.c      2000/05/28 20:01:33
@@ -286,6 +286,7 @@
 char *CVSroot_original = NULL; /* the CVSroot that was passed in */
 int client_active;             /* nonzero if we are doing remote access */
 CVSmethod CVSroot_method;      /* one of the enum values defined in cvs.h */
+char *CVSroot_method_port;     /* port no for method (cur only pserver) */
 char *CVSroot_username;                /* the username or NULL if method == local */
 char *CVSroot_hostname;                /* the hostname or NULL if method == local */
 char *CVSroot_directory;       /* the directory name */
@@ -313,9 +314,10 @@
        char *method = ++cvsroot_copy;
 
        /* Access method specified, as in
-        * "cvs -d :pserver:user@host:/path",
         * "cvs -d :local:e:\path",
-        * "cvs -d :kserver:user@host:/path", or
+        * "cvs -d :pserver[/port]:user@host:/path",
+        * "cvs -d :gserver[/port]:user@host:/path",
+        * "cvs -d :kserver[/port]:user@host:/path", or
         * "cvs -d :fork:/path".
         * We need to get past that part of CVSroot before parsing the
         * rest of it.
@@ -329,16 +331,40 @@
        *p = '\0';
        cvsroot_copy = ++p;
 
+       CVSroot_method_port = NULL;
+
        /* Now we have an access method -- see if it's valid. */
 
        if (strcmp (method, "local") == 0)
            CVSroot_method = local_method;
-       else if (strcmp (method, "pserver") == 0)
+       else if ((strncmp (method, "pserver", 7) == 0) &&
+                (method[7] == '\0' || method[7] == '/'))
+       {
            CVSroot_method = pserver_method;
-       else if (strcmp (method, "kserver") == 0)
+           if (method[7] == '/')
+               CVSroot_method_port = method + 8;
+           else
+               CVSroot_method_port = "cvspserver";
+       }
+       else if ((strncmp (method, "kserver", 7) == 0) &&
+                (method[7] == '\0' || method[7] == '/'))
+       {
            CVSroot_method = kserver_method;
-       else if (strcmp (method, "gserver") == 0)
+           if (method[7] == '/')
+               CVSroot_method_port = method + 8;
+           else
+               CVSroot_method_port = "cvs";
+       }
+       else if ((strncmp (method, "gserver", 7) == 0) &&
+                (method[7] == '\0' || method[7] == '/'))
+       {
            CVSroot_method = gserver_method;
+           if (method[7] == '/')
+               CVSroot_method_port = method + 8;
+           else
+               /* GSSAPI auth is done via pserver, use pserver port */
+               CVSroot_method_port = "cvspserver";
+       }
        else if (strcmp (method, "server") == 0)
            CVSroot_method = server_method;
        else if (strcmp (method, "ext") == 0)

Reply via email to