[This is a very rough patch to let one specify the port on which to connect to pserver in CVSROOT (e.g. ":pserver;port=2402:user@machine:/home2/cvsroot"). It is far from suitable for making official, but I was sick of applying that environment variable patch over and over so I figured I'd at least make a baby step towards a nicer solution. 1. Needs documentation 2. From a unix shell using ";" instead of some other character will require the argument to be quoted. May or may not be worth changing syntax over that, but worth thinking about. "/" is not so good for cases like ":ext;rsh=/bin/remsh:". "-" has much the same problem (it is in the POSIX portable filename character set). "+" might be good. "," might work. 2a. The problem sort of seems to be calling out for URL syntax (maybe). Someone has suggested that the presence of "//" in the root could signal that it is URL syntax rather than traditional CVS. I don't know that URL syntax has any natural place to put things like "rsh=/bin/remsh" in the above example (or, on the other hand, whether the CVSROOT is a good place for such settings). 3. ";port=" gets written into .cvspass, and so you need to log in separately to servers on different ports. I guess that is right but this issue, and any related ones, might require further thought. 4. Probably want to think about what happens if ";port" is combined with an access method other than pserver. -kingdon] Index: ChangeLog =================================================================== RCS file: /home2/cvsroot/ccvs/src/ChangeLog,v retrieving revision 1.1400 diff -c -r1.1400 ChangeLog *** ChangeLog 1998/01/14 20:46:50 1.1400 --- ChangeLog 1998/01/15 23:15:25 *************** *** 1,3 **** --- 1,10 ---- + Thu Jan 15 18:08:47 1998 Jim Kingdon + + * client.h, client.c (client_port): New variable, for + user-supplied port number. + * client.c (auth_server_port_number): Use it if set. + * root.c (parse_cvsroot): Set it from CVSROOT. + Wed Jan 14 15:43:13 1998 Jim Kingdon * Split ChangeLog into ChangeLog-97 and ChangeLog. Index: client.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/client.c,v retrieving revision 1.240 diff -c -r1.240 client.c *** client.c 1998/01/14 04:08:12 1.240 --- client.c 1998/01/15 23:08:44 *************** *** 3401,3410 **** static int auth_server_port_number PROTO ((void)); static int auth_server_port_number () { ! struct servent *s = getservbyname ("cvspserver", "tcp"); if (s) return ntohs (s->s_port); --- 3401,3418 ---- static int auth_server_port_number PROTO ((void)); + int client_port; + static int auth_server_port_number () { ! struct servent *s; ! ! /* If the user explicitly specified a port use that one. */ ! if (client_port != 0) ! return client_port; ! ! s = getservbyname ("cvspserver", "tcp"); if (s) return ntohs (s->s_port); Index: client.h =================================================================== RCS file: /home2/cvsroot/ccvs/src/client.h,v retrieving revision 1.31 diff -c -r1.31 client.h *** client.h 1997/12/12 22:34:08 1.31 --- client.h 1998/01/15 23:08:43 *************** *** 56,61 **** --- 56,63 ---- /* Is the -P option to checkout or update specified? */ extern int client_prune_dirs; + extern int client_port; + #ifdef AUTH_CLIENT_SUPPORT extern int use_authenticating_server; void connect_to_pserver PROTO ((int *tofdp, int* fromfdp, int verify_only, Index: root.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/root.c,v retrieving revision 1.28 diff -c -r1.28 root.c *** root.c 1997/12/14 00:47:36 1.28 --- root.c 1998/01/15 23:17:48 *************** *** 315,320 **** --- 315,321 ---- if ((*cvsroot_copy == ':')) { char *method = ++cvsroot_copy; + int have_semicolon; /* Access method specified, as in * "cvs -d :pserver:user@host:/path", *************** *** 324,334 **** * rest of it. */ ! if (! (p = strchr (method, ':'))) { error (0, 0, "bad CVSroot: %s", CVSroot); return 1; } *p = '\0'; cvsroot_copy = ++p; --- 325,337 ---- * rest of it. */ ! p = strpbrk (method, ":;"); ! if (p == NULL) { error (0, 0, "bad CVSroot: %s", CVSroot); return 1; } + have_semicolon = *p == ';'; *p = '\0'; cvsroot_copy = ++p; *************** *** 350,355 **** --- 353,383 ---- { error (0, 0, "unknown method in CVSroot: %s", CVSroot); return 1; + } + + if (have_semicolon) + { + /* More elaborate implementation would allow multiple + semicolons, for example: + + :server;rsh=34;command=cvs-1.6: + + */ + /* FIXME: lots of error conditions should be better handled, + e.g. garbage after the number or no valid number. + + Would be nice to have testcases for some of these cases + including the error cases. */ + p = strchr (cvsroot_copy, ':'); + if (p == NULL) + error (1, 0, "semicolon missing in %s", CVSroot); + + if (strncmp (cvsroot_copy, "port=", 5) == 0) + client_port = atoi (cvsroot_copy + 5); + else + error (1, 0, "invalid semicolon expression in CVSROOT: %s", + cvsroot_copy); + cvsroot_copy = p + 1; } } else