summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src')
-rw-r--r--contrib/cvs/src/NOTES60
-rw-r--r--contrib/cvs/src/README-rm-add31
-rw-r--r--contrib/cvs/src/client.c351
-rw-r--r--contrib/cvs/src/commit.c93
-rw-r--r--contrib/cvs/src/cvs.h66
-rw-r--r--contrib/cvs/src/diff.c124
-rw-r--r--contrib/cvs/src/filesubr.c259
-rw-r--r--contrib/cvs/src/import.c32
-rw-r--r--contrib/cvs/src/lock.c31
-rw-r--r--contrib/cvs/src/login.c760
-rw-r--r--contrib/cvs/src/logmsg.c104
-rw-r--r--contrib/cvs/src/main.c316
-rw-r--r--contrib/cvs/src/mkmodules.c15
-rw-r--r--contrib/cvs/src/prepend_args.c86
-rw-r--r--contrib/cvs/src/prepend_args.h26
-rw-r--r--contrib/cvs/src/rcs.c413
-rw-r--r--contrib/cvs/src/rcs.h15
-rw-r--r--contrib/cvs/src/rcscmds.c10
-rw-r--r--contrib/cvs/src/recurse.c25
-rw-r--r--contrib/cvs/src/server.c457
-rw-r--r--contrib/cvs/src/update.c135
21 files changed, 1699 insertions, 1710 deletions
diff --git a/contrib/cvs/src/NOTES b/contrib/cvs/src/NOTES
deleted file mode 100644
index 646ebdf..0000000
--- a/contrib/cvs/src/NOTES
+++ /dev/null
@@ -1,60 +0,0 @@
-wishlist - Tue Nov 2 15:22:58 PST 1993
-
-* bcopy -> memcpy & friends.
- ** done 12/18/93
-
-* remove static buffers.
-* replace list & node cache with recursive obstacks, (xmalloc,
- getnode, getlist)
-* check all io functions for error return codes. also check all
- system calls.
-* error check mkdir.
-
----
-Old notes...
-
-* All sizing limits are gone. The rest of these items were incidental
- in that effort.
-
-* login name from history was duplicated. taught existing routine to
- cache and use that instead. Also add routines to cache uid, pid,
- etc.
-
-* ign strings were never freed. Now they are.
-
-* there was a printf("... %s ...", cp) vs *cp bug in history.c. Now
- fixed.
-
-* The environment variables TMPDIR, HOME, and LOGNAME were not
- honored. Now they are.
-
-* extra line inserted by do_editor() is gone. Then obviated. Editor
- is now called exactly once per checkin.
-
-* revised editor behaviour. Never use /dev/tty. If the editor
- session fails, we haven't yet done anything. Therefor the user can
- safely rerun cvs and we should just fail. Also use the editor for
- initial log messages on added files. Also omit the confirmation
- when adding directories. Adding directories will require an
- explicit "commit" step soon. Make it possible to prevent null login
- messages using #define REQUIRE_LOG_MESSAGES
-
-* prototypes for all callbacks.
-
-* all callbacks get ref pointers.
-
-* do_recursion/start_recursion now use recusion_frame's rather than a
- list of a lot of pointers and global variables.
-
-* corrected types on status_dirproc().
-
-* CONFIRM_DIRECTORY_ADDS
-
-* re_comp was innappropriate in a few places. I've eliminated it.
-
-* FORCE_MESSAGE_ON_ADD
-
-* So I built a regression test. Let's call it a sanity check to be
- less ambitious. It exposed that cvs is difficult to call from
- scripts.
-
diff --git a/contrib/cvs/src/README-rm-add b/contrib/cvs/src/README-rm-add
deleted file mode 100644
index 87fd7c6..0000000
--- a/contrib/cvs/src/README-rm-add
+++ /dev/null
@@ -1,31 +0,0 @@
-WHAT THE "DEATH SUPPORT" FEATURES DO:
-
-(Some of the death support stuff is documented in the main manual, but
-this file is for stuff which noone has gotten around to adding to the
-main manual yet).
-
-CVS with death support can record when a file is active, or alive, and
-when it is removed, or dead. With this facility you can record the
-history of a file, including the fact that at some point in its life
-the file was removed and then later added.
-
-Files can now be added or removed in a branch and later merged
-into the trunk.
-
- cvs update -A
- touch a b c
- cvs add a b c ; cvs ci -m "added" a b c
- cvs tag -b branchtag
- cvs update -r branchtag
- touch d ; cvs add d
- rm a ; cvs rm a
- cvs ci -m "added d, removed a"
- cvs update -A
- cvs update -jbranchtag
-
-Added and removed files may also be merged between branches.
-
-Files removed in the trunk may be merged into branches.
-
-Files added on the trunk are a special case. They cannot be merged
-into a branch. Instead, simply branch the file by hand.
diff --git a/contrib/cvs/src/client.c b/contrib/cvs/src/client.c
index 0b57b35..525cb79 100644
--- a/contrib/cvs/src/client.c
+++ b/contrib/cvs/src/client.c
@@ -12,6 +12,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. */
+/*
+ * $FreeBSD$
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
@@ -32,7 +36,6 @@
# else /* No winsock.h */
# include <sys/socket.h>
# include <netinet/in.h>
-# include <arpa/inet.h>
# include <netdb.h>
# endif /* No winsock.h */
#endif
@@ -78,7 +81,19 @@ static Key_schedule sched;
#ifdef HAVE_GSSAPI
-# include "xgssapi.h"
+#ifdef HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+
+#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif
/* This is needed for GSSAPI encryption. */
static gss_ctx_id_t gcontext;
@@ -86,7 +101,7 @@ static gss_ctx_id_t gcontext;
static int connect_to_gserver PROTO((int, struct hostent *));
#endif /* HAVE_GSSAPI */
-
+
static void add_prune_candidate PROTO((char *));
/* All the commands. */
@@ -187,7 +202,7 @@ arg_should_not_be_sent_to_server (arg)
4) the argument lies within one of the paths in
dirs_sent_to_server.
- */
+ 4) */
if (list_isempty (dirs_sent_to_server))
return 0; /* always send it */
@@ -252,8 +267,8 @@ arg_should_not_be_sent_to_server (arg)
}
/* Now check the value for root. */
- if (this_root && current_parsed_root
- && (strcmp (this_root, current_parsed_root->original) != 0))
+ if (CVSroot_cmdline == NULL && this_root && current_root
+ && (strcmp (this_root, current_root) != 0))
{
/* Don't send this, since the CVSROOTs don't match. */
free (this_root);
@@ -1266,32 +1281,6 @@ warning: server is not creating directories one at a time");
if ( CVS_CHDIR (dir_name) < 0)
error (1, errno, "could not chdir to %s", dir_name);
}
- else if (!isdir (CVSADM))
- {
- /*
- * Put repository in CVS/Repository. For historical
- * (pre-CVS/Root) reasons, this is an absolute pathname,
- * but what really matters is the part of it which is
- * relative to cvsroot.
- */
- char *repo;
-
- if (reposdirname_absolute)
- repo = reposdirname;
- else
- {
- repo = xmalloc (strlen (reposdirname)
- + strlen (toplevel_repos)
- + 10);
- strcpy (repo, toplevel_repos);
- strcat (repo, "/");
- strcat (repo, reposdirname);
- }
-
- Create_Admin (".", ".", repo, (char *)NULL, (char *)NULL, 0, 1, 1);
- if (repo != reposdirname)
- free (repo);
- }
if (strcmp (command_name, "export") != 0)
{
@@ -2297,7 +2286,7 @@ static int
is_cvsroot_level (pathname)
char *pathname;
{
- if (strcmp (toplevel_repos, current_parsed_root->directory) != 0)
+ if (strcmp (toplevel_repos, CVSroot_directory) != 0)
return 0;
return strchr (pathname, '/') == NULL;
@@ -2937,14 +2926,14 @@ send_a_repository (dir, repository, update_dir)
from REPOSITORY. If the path elements don't exist
in REPOSITORY, or the removal of those path
elements mean that we "step above"
- current_parsed_root->directory, set toplevel_repos to
- current_parsed_root->directory. */
+ CVSroot_directory, set toplevel_repos to
+ CVSroot_directory. */
if ((repository_len > update_dir_len)
&& (strcmp (repository + repository_len - update_dir_len,
update_dir) == 0)
- /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
+ /* TOPLEVEL_REPOS shouldn't be above CVSroot_directory */
&& ((repository_len - update_dir_len)
- > strlen (current_parsed_root->directory)))
+ > strlen (CVSroot_directory)))
{
/* The repository name contains UPDATE_DIR. Set
toplevel_repos to the repository name without
@@ -2958,7 +2947,7 @@ send_a_repository (dir, repository, update_dir)
}
else
{
- toplevel_repos = xstrdup (current_parsed_root->directory);
+ toplevel_repos = xstrdup (CVSroot_directory);
}
}
}
@@ -3016,7 +3005,7 @@ client_expand_modules (argc, argv, local)
for (i = 0; i < argc; ++i)
send_arg (argv[i]);
- send_a_repository ("", current_parsed_root->directory, "");
+ send_a_repository ("", CVSroot_directory, "");
send_to_server ("expand-modules\012", 0);
@@ -3054,13 +3043,13 @@ client_send_expansions (local, where, build_dirs)
if (isfile (argv[0]))
send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS : 0);
}
- send_a_repository ("", current_parsed_root->directory, "");
+ send_a_repository ("", CVSroot_directory, "");
}
void
client_nonexpanded_setup ()
{
- send_a_repository ("", current_parsed_root->directory, "");
+ send_a_repository ("", CVSroot_directory, "");
}
/* Receive a cvswrappers line from the server; it must be a line
@@ -3575,8 +3564,7 @@ get_responses_and_close ()
{
if (shutdown (server_fd, 1) < 0)
error (1, 0, "shutting down connection to %s: %s",
- current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO));
- server_fd = -1;
+ CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
/*
* This test will always be true because we dup the descriptor
*/
@@ -3585,7 +3573,7 @@ get_responses_and_close ()
if (fclose (to_server_fp) != 0)
error (1, errno,
"closing down connection to %s",
- current_parsed_root->hostname);
+ CVSroot_hostname);
}
}
else
@@ -3603,15 +3591,15 @@ get_responses_and_close ()
#endif /* START_RSH_WITH_POPEN_RW */
{
error (1, errno, "closing connection to %s",
- current_parsed_root->hostname);
+ CVSroot_hostname);
}
}
if (! buf_empty_p (from_server)
|| getc (from_server_fp) != EOF)
- error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname);
+ error (0, 0, "dying gasps from %s unexpected", CVSroot_hostname);
else if (ferror (from_server_fp))
- error (0, errno, "reading from %s", current_parsed_root->hostname);
+ error (0, errno, "reading from %s", CVSroot_hostname);
fclose (from_server_fp);
#endif /* SHUTDOWN_SERVER */
@@ -3628,7 +3616,8 @@ get_responses_and_close ()
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- sleep_past (last_register_time);
+ while (time ((time_t *) NULL) == last_register_time)
+ sleep (1);
}
return errs;
@@ -3652,8 +3641,7 @@ supported_request (name)
return 0;
}
-
-
+
#if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS)
static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *,
unsigned int));
@@ -3682,86 +3670,22 @@ init_sockaddr (name, hostname, port)
#endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) */
-
-
#ifdef AUTH_CLIENT_SUPPORT
-/* Generic function to do port number lookup tasks.
- *
- * In order of precedence, will return:
- * getenv (envname), if defined
- * getservbyname (portname), if defined
- * defaultport
- */
+static int auth_server_port_number PROTO ((void));
+
static int
-get_port_number (envname, portname, defaultport)
- const char *envname;
- const char *portname;
- int defaultport;
+auth_server_port_number ()
{
- struct servent *s;
- char *port_s;
+ struct servent *s = getservbyname ("cvspserver", "tcp");
- if (envname && (port_s = getenv (envname)))
- {
- int port = atoi (port_s);
- if (port <= 0)
- {
- error (0, 0, "%s must be a positive integer! If you", envname);
- error (0, 0, "are trying to force a connection via rsh, please");
- error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
- error (1, 0, "variable.");
- }
- return port;
- }
- else if (portname && (s = getservbyname (portname, "tcp")))
+ if (s)
return ntohs (s->s_port);
else
- return defaultport;
+ return CVS_AUTH_PORT;
}
-
-/* get the port number for a client to connect to based on the port
- * and method of a cvsroot_t.
- *
- * we do this here instead of in parse_cvsroot so that we can keep network
- * code confined to a localized area and also to delay the lookup until the
- * last possible moment so it remains possible to run cvs client commands that
- * skip opening connections to the server (i.e. skip network operations entirely)
- *
- * and yes, I know none of the the commands do that now, but here's to planning
- * for the future, eh? cheers.
- *
- * FIXME - We could cache the port lookup safely right now as we never change
- * it for a single root on the fly, but we'd have to un'const some other
- * functions
- */
-int
-get_cvs_port_number (root)
- const cvsroot_t *root;
-{
-
- if (root->port) return root->port;
-
- switch (root->method)
- {
- case gserver_method:
- case pserver_method:
- return get_port_number ("CVS_CLIENT_PORT", "cvspserver", CVS_AUTH_PORT);
-#ifdef HAVE_KERBEROS
- case kserver_method:
- return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
-#endif
- default:
- error(1, EINVAL, "internal error: get_cvs_port_number called for invalid connection method (%s)",
- method_names[root->method]);
- break;
- }
-}
-
-
-
/* Read a line from socket SOCK. Result does not include the
terminating linefeed. This is only used by the authentication
protocol, which we call before we set up all the buffering stuff.
@@ -3789,7 +3713,7 @@ recv_line (sock, resultp)
int n;
n = recv (sock, &ch, 1, 0);
if (n <= 0)
- error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
+ error (1, 0, "recv() from server %s: %s", CVSroot_hostname,
n == 0 ? "EOF" : SOCK_STRERROR (SOCK_ERRNO));
if (ch == '\012')
@@ -3827,15 +3751,11 @@ connect_to_forked_server (tofdp, fromfdp)
command[0] = getenv ("CVS_SERVER");
if (! command[0])
- command[0] = program_path;
+ command[0] = "cvs";
command[1] = "server";
command[2] = NULL;
- if (trace)
- {
- fprintf (stderr, " -> Forking server: %s %s\n", command[0], command[1]);
- }
if (! piped_child (command, tofdp, fromfdp))
error (1, 0, "could not fork server process");
}
@@ -3863,29 +3783,20 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
int tofd, fromfd;
#endif
int port_number;
- char *username; /* the username we use to connect */
struct sockaddr_in client_sai;
struct hostent *hostinfo;
- char no_passwd = 0; /* gets set if no password found */
+ char no_passwd = 0; /* gets set if no password found */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
}
- port_number = get_cvs_port_number (current_parsed_root);
- hostinfo = init_sockaddr (&client_sai, current_parsed_root->hostname, port_number);
- if (trace)
- {
- fprintf (stderr, " -> Connecting to %s(%s):%d\n",
- current_parsed_root->hostname,
- inet_ntoa (client_sai.sin_addr), port_number);
- }
+ port_number = auth_server_port_number ();
+ hostinfo = init_sockaddr (&client_sai, CVSroot_hostname, port_number);
if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai))
< 0)
- error (1, 0, "connect to %s(%s):%d failed: %s",
- current_parsed_root->hostname,
- inet_ntoa (client_sai.sin_addr),
+ error (1, 0, "connect to %s:%d failed: %s", CVSroot_hostname,
port_number, SOCK_STRERROR (SOCK_ERRNO));
/* Run the authorization mini-protocol before anything else. */
@@ -3893,12 +3804,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
{
#ifdef HAVE_GSSAPI
if (! connect_to_gserver (sock, hostinfo))
- {
- error (0, 0,
- "authorization failed: server %s rejected access to %s",
- current_parsed_root->hostname, current_parsed_root->directory);
goto rejected;
- }
#else
error (1, 0, "This client does not support GSSAPI authentication");
#endif
@@ -3906,9 +3812,11 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
else
{
char *begin = NULL;
+ char *repository = CVSroot_directory;
+ char *username = CVSroot_username;
char *password = NULL;
char *end = NULL;
-
+
if (verify_only)
{
begin = "BEGIN VERIFICATION REQUEST\012";
@@ -3922,8 +3830,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
/* Get the password, probably from ~/.cvspass. */
password = get_cvs_password ();
- username = current_parsed_root->username ? current_parsed_root->username : getcaller();
-
+
/* Send the empty string by default. This is so anonymous CVS
access doesn't require client to have done "cvs login". */
if (password == NULL)
@@ -3937,7 +3844,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
/* Send the data the server needs. */
- if (send (sock, current_parsed_root->directory, strlen (current_parsed_root->directory), 0) < 0)
+ if (send (sock, repository, strlen (repository), 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
if (send (sock, "\012", 1, 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
@@ -3968,29 +3875,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
if (strcmp (read_buf, "I HATE YOU") == 0)
{
- /* Authorization not granted.
- *
- * This is a little confusing since we can reach this while loop in GSSAPI
- * mode, but if GSSAPI authentication failed, we already jumped to the
- * rejected label (there is no case where the connect_to_gserver function
- * can return 1 and we will not receive "I LOVE YOU" from the server, barring
- * broken connections and garbled messages, of course).
- *
- * i.e. This is a pserver specific error message and shoiuld be since
- * GSSAPI doesn't use username.
- */
- error (0, 0,
- "authorization failed: server %s rejected access to %s for user %s",
- current_parsed_root->hostname, current_parsed_root->directory, username);
-
- /* Output a special error message if authentication was attempted
- with no password -- the user should be made aware that they may
- have missed a step. */
- if (no_passwd)
- {
- error (0, 0,
- "used empty password; try \"cvs login\" with a real password");
- }
+ /* Authorization not granted. */
goto rejected;
}
else if (strncmp (read_buf, "E ", 2) == 0)
@@ -4028,15 +3913,15 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
{
error (0, 0,
"unrecognized auth response from %s: %s",
- current_parsed_root->hostname, read_buf);
+ CVSroot_hostname, read_buf);
error (1, 0,
"shutdown() failed, server %s: %s",
- current_parsed_root->hostname,
+ CVSroot_hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
error (1, 0,
"unrecognized auth response from %s: %s",
- current_parsed_root->hostname, read_buf);
+ CVSroot_hostname, read_buf);
}
free (read_buf);
}
@@ -4045,7 +3930,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
if (verify_only)
{
if (shutdown (sock, 2) < 0)
- error (0, 0, "shutdown() failed, server %s: %s", current_parsed_root->hostname,
+ error (0, 0, "shutdown() failed, server %s: %s", CVSroot_hostname,
SOCK_STRERROR (SOCK_ERRNO));
return;
}
@@ -4070,11 +3955,24 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
return;
rejected:
+ error (0, 0,
+ "authorization failed: server %s rejected access to %s for user %s",
+ CVSroot_hostname, CVSroot_directory, CVSroot_username);
+
+ /* Output a special error message if authentication was attempted
+ with no password -- the user should be made aware that they may
+ have missed a step. */
+ if (no_passwd)
+ {
+ error (0, 0,
+ "used empty password; try \"cvs login\" with a real password");
+ }
+
if (shutdown (sock, 2) < 0)
{
error (0, 0,
"shutdown() failed (server %s): %s",
- current_parsed_root->hostname,
+ CVSroot_hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
@@ -4082,9 +3980,8 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
}
#endif /* AUTH_CLIENT_SUPPORT */
-
-
-#ifdef HAVE_KERBEROS
+
+#if HAVE_KERBEROS
/* This function has not been changed to deal with NO_SOCKET_TO_FD
(i.e., systems on which sockets cannot be converted to file
@@ -4106,26 +4003,42 @@ start_tcp_server (tofdp, fromfdp)
if (s < 0)
error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
- port = get_cvs_port_number (current_parsed_root);
+ /* Get CVS_CLIENT_PORT or look up cvs/tcp with CVS_PORT as default */
+ portenv = getenv ("CVS_CLIENT_PORT");
+ if (portenv != NULL)
+ {
+ port = atoi (portenv);
+ if (port <= 0)
+ {
+ error (0, 0, "CVS_CLIENT_PORT must be a positive number! If you");
+ error (0, 0, "are trying to force a connection via rsh, please");
+ error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
+ error (1, 0, "variable.");
+ }
+ if (trace)
+ fprintf(stderr, "Using TCP port %d to contact server.\n", port);
+ }
+ else
+ {
+ struct servent *sp;
+
+ sp = getservbyname ("cvs", "tcp");
+ if (sp == NULL)
+ port = CVS_PORT;
+ else
+ port = ntohs (sp->s_port);
+ }
- hp = init_sockaddr (&sin, current_parsed_root->hostname, port);
+ hp = init_sockaddr (&sin, CVSroot_hostname, port);
hname = xmalloc (strlen (hp->h_name) + 1);
strcpy (hname, hp->h_name);
- if (trace)
- {
- fprintf (stderr, " -> Connecting to %s(%s):%d\n",
- current_parsed_root->hostname,
- inet_ntoa (client_sai.sin_addr), port);
- }
-
if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
- error (1, 0, "connect to %s(%s):%d failed: %s",
- current_parsed_root->hostname,
- inet_ntoa (client_sai.sin_addr),
+ error (1, 0, "connect to %s:%d failed: %s", CVSroot_hostname,
port, SOCK_STRERROR (SOCK_ERRNO));
+#ifdef HAVE_KERBEROS
{
const char *realm;
struct sockaddr_in laddr;
@@ -4150,6 +4063,7 @@ start_tcp_server (tofdp, fromfdp)
krb_get_err_text (status));
memcpy (kblock, cred.session, sizeof (C_Block));
}
+#endif /* HAVE_KERBEROS */
server_fd = s;
close_on_exec (server_fd);
@@ -4178,10 +4092,9 @@ recv_bytes (sock, buf, need)
int got;
got = recv (sock, buf, need, 0);
- if (got <= 0)
- error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
- got == 0 ? "EOF" : SOCK_STRERROR (SOCK_ERRNO));
-
+ if (got < 0)
+ error (1, 0, "recv() from server %s: %s", CVSroot_hostname,
+ SOCK_STRERROR (SOCK_ERRNO));
buf += got;
need -= got;
}
@@ -4274,11 +4187,11 @@ connect_to_gserver (sock, hostinfo)
got = recv (sock, buf + 2, sizeof buf - 2, 0);
if (got < 0)
error (1, 0, "recv() from server %s: %s",
- current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO));
+ CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
buf[got + 2] = '\0';
if (buf[got + 1] == '\n')
buf[got + 1] = '\0';
- error (1, 0, "error from server %s: %s", current_parsed_root->hostname,
+ error (1, 0, "error from server %s: %s", CVSroot_hostname,
buf);
}
@@ -4330,7 +4243,7 @@ start_server ()
(*really* slow on a 14.4kbps link); the clean way to have a CVS
which supports several ways of connecting is with access methods. */
- switch (current_parsed_root->method)
+ switch (CVSroot_method)
{
#ifdef AUTH_CLIENT_SUPPORT
@@ -4347,7 +4260,7 @@ start_server ()
break;
#endif
-#ifdef HAVE_GSSAPI
+#if HAVE_GSSAPI
case gserver_method:
/* GSSAPI authentication is handled by the pserver. */
connect_to_pserver (&tofd, &fromfd, 0, 1);
@@ -4366,8 +4279,8 @@ start_server ()
case server_method:
#if defined(START_SERVER)
START_SERVER (&tofd, &fromfd, getcaller (),
- current_parsed_root->username, current_parsed_root->hostname,
- current_parsed_root->directory);
+ CVSroot_username, CVSroot_hostname,
+ CVSroot_directory);
# if defined (START_SERVER_RETURNS_SOCKET) && defined (NO_SOCKET_TO_FD)
/* This is a system on which we can only write to a socket
using send/recv. Therefore its START_SERVER needs to
@@ -4498,7 +4411,7 @@ the :server: access method is not supported by this port of CVS");
if (!rootless)
{
send_to_server ("Root ", 0);
- send_to_server (current_parsed_root->directory, 0);
+ send_to_server (CVSroot_directory, 0);
send_to_server ("\012", 1);
}
@@ -4628,7 +4541,7 @@ the :server: access method is not supported by this port of CVS");
on encryption, bomb out; don't let the user think the data
is being encrypted when it is not. */
#ifdef HAVE_KERBEROS
- if (current_parsed_root->method == kserver_method)
+ if (CVSroot_method == kserver_method)
{
if (! supported_request ("Kerberos-encrypt"))
error (1, 0, "This server does not support encryption");
@@ -4643,7 +4556,7 @@ the :server: access method is not supported by this port of CVS");
else
#endif /* HAVE_KERBEROS */
#ifdef HAVE_GSSAPI
- if (current_parsed_root->method == gserver_method)
+ if (CVSroot_method == gserver_method)
{
if (! supported_request ("Gssapi-encrypt"))
error (1, 0, "This server does not support encryption");
@@ -4716,7 +4629,7 @@ the :server: access method is not supported by this port of CVS");
ability to decrypt the data stream is itself a form of
authentication. */
#ifdef HAVE_GSSAPI
- if (current_parsed_root->method == gserver_method)
+ if (CVSroot_method == gserver_method)
{
if (! supported_request ("Gssapi-authenticate"))
error (1, 0,
@@ -4807,7 +4720,7 @@ start_rsh_server (tofdp, fromfdp)
example in CVS_RSH or other such mechanisms to be devised,
if that is what they want (the manual already tells them
that). */
- cvs_rsh = "rsh";
+ cvs_rsh = "ssh";
if (!cvs_server)
cvs_server = "cvs";
@@ -4820,13 +4733,13 @@ start_rsh_server (tofdp, fromfdp)
#endif /* RSH_NEEDS_BINARY_FLAG */
/* Then we strcat more things on the end one by one. */
- if (current_parsed_root->username != NULL)
+ if (CVSroot_username != NULL)
{
rsh_argv[i++] = "-l";
- rsh_argv[i++] = current_parsed_root->username;
+ rsh_argv[i++] = CVSroot_username;
}
- rsh_argv[i++] = current_parsed_root->hostname;
+ rsh_argv[i++] = CVSroot_hostname;
rsh_argv[i++] = cvs_server;
rsh_argv[i++] = "server";
@@ -4836,8 +4749,6 @@ start_rsh_server (tofdp, fromfdp)
if (trace)
{
fprintf (stderr, " -> Starting server: ");
- for (i = 0; rsh_argv[i]; i++)
- fprintf (stderr, "%s ", rsh_argv[i]);
putc ('\n', stderr);
}
@@ -4866,7 +4777,7 @@ start_rsh_server (tofdp, fromfdp)
char *command;
if (!cvs_rsh)
- cvs_rsh = "rsh";
+ cvs_rsh = "ssh";
if (!cvs_server)
cvs_server = "cvs";
@@ -4875,7 +4786,7 @@ start_rsh_server (tofdp, fromfdp)
versions of rsh that grab switches out of the middle of the
command (they're calling the GNU getopt routines incorrectly). */
command = xmalloc (strlen (cvs_server)
- + strlen (current_parsed_root->directory)
+ + strlen (CVSroot_directory)
+ 50);
/* If you are running a very old (Nov 3, 1994, before 1.5)
@@ -4889,15 +4800,15 @@ start_rsh_server (tofdp, fromfdp)
char **p = argv;
*p++ = cvs_rsh;
- *p++ = current_parsed_root->hostname;
+ *p++ = CVSroot_hostname;
/* If the login names differ between client and server
* pass it on to rsh.
*/
- if (current_parsed_root->username != NULL)
+ if (CVSroot_username != NULL)
{
*p++ = "-l";
- *p++ = current_parsed_root->username;
+ *p++ = CVSroot_username;
}
*p++ = command;
@@ -5624,7 +5535,7 @@ send_files (argc, argv, local, aflag, flags)
* latter case; I don't think toplevel_repos matters for the
* former.
*/
- toplevel_repos = xstrdup (current_parsed_root->directory);
+ toplevel_repos = xstrdup (CVSroot_directory);
send_repository ("", toplevel_repos, ".");
}
@@ -5743,7 +5654,7 @@ client_import_done ()
*/
/* FIXME: "can't happen" now that we call client_import_setup
at the beginning. */
- toplevel_repos = xstrdup (current_parsed_root->directory);
+ toplevel_repos = xstrdup (CVSroot_directory);
send_repository ("", toplevel_repos, ".");
}
@@ -5923,9 +5834,9 @@ client_senddate (date)
void
send_init_command ()
{
- /* This is here because we need the current_parsed_root->directory variable. */
+ /* This is here because we need the CVSroot_directory variable. */
send_to_server ("init ", 0);
- send_to_server (current_parsed_root->directory, 0);
+ send_to_server (CVSroot_directory, 0);
send_to_server ("\012", 0);
}
diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c
index 149da7c..3d46e25 100644
--- a/contrib/cvs/src/commit.c
+++ b/contrib/cvs/src/commit.c
@@ -12,6 +12,7 @@
*
* The call is: cvs commit [options] files...
*
+ * $FreeBSD$
*/
#include <assert.h>
@@ -85,13 +86,13 @@ static time_t last_register_time;
static const char *const commit_usage[] =
{
"Usage: %s %s [-nRlf] [-m msg | -F logfile] [-r rev] files...\n",
- " -n Do not run the module program (if any).\n",
- " -R Process directories recursively.\n",
- " -l Local directory only (not recursive).\n",
- " -f Force the file to be committed; disables recursion.\n",
- " -F logfile Read the log message from file.\n",
- " -m msg Log message.\n",
- " -r rev Commit to this branch or trunk revision.\n",
+ "\t-n\tDo not run the module program (if any).\n",
+ "\t-R\tProcess directories recursively.\n",
+ "\t-l\tLocal directory only (not recursive).\n",
+ "\t-f\tForce the file to be committed; disables recursion.\n",
+ "\t-F file\tRead the log message from file.\n",
+ "\t-m msg\tLog message.\n",
+ "\t-r rev\tCommit to this branch or trunk revision.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
@@ -344,7 +345,7 @@ commit (argc, argv)
if (geteuid () == (uid_t) 0
# ifdef CLIENT_SUPPORT
/* Who we are on the client side doesn't affect logging. */
- && !current_parsed_root->isremote
+ && !client_active
# endif
)
{
@@ -432,7 +433,7 @@ commit (argc, argv)
}
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
{
struct find_data find_args;
@@ -498,7 +499,7 @@ commit (argc, argv)
/* Run the user-defined script to verify/check information in
*the log message
*/
- do_verify (saved_message, (char *)NULL);
+ do_verify (&saved_message, (char *)NULL);
/* We always send some sort of message, even if empty. */
/* FIXME: is that true? There seems to be some code in do_editor
@@ -591,7 +592,8 @@ commit (argc, argv)
char *fname;
FILE *fp;
- fp = cvs_temp_file (&fname);
+ fname = cvs_temp_name ();
+ fp = CVS_FOPEN (fname, "w+");
if (fp == NULL)
error (1, 0, "cannot create temporary file %s", fname);
if (fwrite (saved_message, 1, strlen (saved_message), fp)
@@ -600,7 +602,6 @@ commit (argc, argv)
if (fclose (fp) < 0)
error (0, errno, "cannot close temporary file %s", fname);
error (0, 0, "saving log message in %s", fname);
- free (fname);
}
return err;
}
@@ -615,7 +616,7 @@ commit (argc, argv)
wrap_setup ();
- lock_tree_for_write (argc, argv, local, W_LOCAL, aflag);
+ lock_tree_for_write (argc, argv, local, aflag);
/*
* Set up the master update list and hard link list
@@ -663,15 +664,11 @@ commit (argc, argv)
Lock_Cleanup ();
dellist (&mulist);
-#ifdef SERVER_SUPPORT
- if (server_active)
- return err;
-#endif
-
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- sleep_past (last_register_time);
+ while (time ((time_t *) NULL) == last_register_time)
+ sleep (1);
}
return (err);
@@ -782,7 +779,7 @@ check_fileproc (callerdat, finfo)
struct commit_info *ci;
struct logfile_info *li;
- size_t cvsroot_len = strlen (current_parsed_root->directory);
+ size_t cvsroot_len = strlen (CVSroot_directory);
if (!finfo->repository)
{
@@ -790,7 +787,7 @@ check_fileproc (callerdat, finfo)
return (1);
}
- if (strncmp (finfo->repository, current_parsed_root->directory, cvsroot_len) == 0
+ if (strncmp (finfo->repository, CVSroot_directory, cvsroot_len) == 0
&& ISDIRSEP (finfo->repository[cvsroot_len])
&& strncmp (finfo->repository + cvsroot_len + 1,
CVSROOTADM,
@@ -814,7 +811,9 @@ check_fileproc (callerdat, finfo)
switch (status)
{
case T_CHECKOUT:
+#ifdef SERVER_SUPPORT
case T_PATCH:
+#endif
case T_NEEDS_MERGE:
case T_CONFLICT:
case T_REMOVE_ENTRY:
@@ -831,7 +830,7 @@ check_fileproc (callerdat, finfo)
* Also,
* - if status is T_REMOVED, can't have a numeric tag
* - if status is T_ADDED, rcs file must not exist unless on
- * a branch or head is dead
+ * a branch
* - if status is T_ADDED, can't have a non-trunk numeric rev
* - if status is T_MODIFIED and a Conflict marker exists, don't
* allow the commit if timestamp is identical or if we find
@@ -928,17 +927,29 @@ warning: file `%s' seems to still contain conflict indicators",
{
if (vers->tag == NULL)
{
- if (finfo->rcs != NULL &&
- !RCS_isdead (finfo->rcs, finfo->rcs->head))
+ char *rcs;
+
+ rcs = xmalloc (strlen (finfo->repository)
+ + strlen (finfo->file)
+ + sizeof RCSEXT
+ + 5);
+
+ /* Don't look in the attic; if it exists there we
+ will move it back out in checkaddfile. */
+ sprintf(rcs, "%s/%s%s", finfo->repository, finfo->file,
+ RCSEXT);
+ if (isreadable (rcs))
{
error (0, 0,
"cannot add file `%s' when RCS file `%s' already exists",
- finfo->fullname, finfo->rcs->path);
+ finfo->fullname, rcs);
freevers_ts (&vers);
+ free (rcs);
return (1);
}
+ free (rcs);
}
- else if (isdigit ((unsigned char) *vers->tag) &&
+ if (vers->tag && isdigit ((unsigned char) *vers->tag) &&
numdots (vers->tag) > 1)
{
error (0, 0,
@@ -1230,7 +1241,7 @@ commit_fileproc (callerdat, finfo)
if (use_editor)
do_editor (finfo->update_dir, &saved_message,
finfo->repository, ulist);
- do_verify (saved_message, finfo->repository);
+ do_verify (&saved_message, finfo->repository);
}
p = findnode (cilist, finfo->file);
@@ -1301,12 +1312,6 @@ commit_fileproc (callerdat, finfo)
/* find the max major rev number in this directory */
maxrev = 0;
(void) walklist (finfo->entries, findmaxrev, NULL);
- if (finfo->rcs->head) {
- /* resurrecting: include dead revision */
- int thisrev = atoi (finfo->rcs->head);
- if (thisrev > maxrev)
- maxrev = thisrev;
- }
if (maxrev == 0)
maxrev = 1;
xrev = xmalloc (20);
@@ -1426,12 +1431,12 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
{
char *p;
- if (strncmp (current_parsed_root->directory, repository,
- strlen (current_parsed_root->directory)) != 0)
+ if (strncmp (CVSroot_directory, repository,
+ strlen (CVSroot_directory)) != 0)
error (0, 0,
"internal error: repository (%s) doesn't begin with root (%s)",
- repository, current_parsed_root->directory);
- p = repository + strlen (current_parsed_root->directory);
+ repository, CVSroot_directory);
+ p = repository + strlen (CVSroot_directory);
if (*p == '/')
++p;
if (strcmp ("CVSROOT", p) == 0
@@ -1552,7 +1557,7 @@ commit_direntproc (callerdat, dir, repos, update_dir, entries)
got_message = 1;
if (use_editor)
do_editor (update_dir, &saved_message, real_repos, ulist);
- do_verify (saved_message, real_repos);
+ do_verify (&saved_message, real_repos);
free (real_repos);
return (R_PROCESS);
}
@@ -1592,13 +1597,19 @@ findmaxrev (p, closure)
Node *p;
void *closure;
{
+ char *cp;
int thisrev;
Entnode *entdata;
entdata = (Entnode *) p->data;
if (entdata->type != ENT_FILE)
return (0);
+ cp = strchr (entdata->version, '.');
+ if (cp != NULL)
+ *cp = '\0';
thisrev = atoi (entdata->version);
+ if (cp != NULL)
+ *cp = '.';
if (thisrev > maxrev)
maxrev = thisrev;
return (0);
@@ -1946,8 +1957,10 @@ checkaddfile (file, repository, tag, options, rcsnode)
Attic. */
if (!(rcsfile->flags & INATTIC))
{
- error (0, 0, "warning: expected %s to be in Attic",
+ error (0, 0, "internal error: confused about attic for %s",
rcsfile->path);
+ retval = 1;
+ goto out;
}
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
@@ -2134,6 +2147,8 @@ checkaddfile (file, repository, tag, options, rcsnode)
char *head;
char *magicrev;
+ fixbranch(rcsfile, sbranch);
+
head = RCS_getversion (rcsfile, NULL, NULL, 0, (int *) NULL);
magicrev = RCS_magicrev (rcsfile, head);
diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h
index b4e3fa1..6489f07 100644
--- a/contrib/cvs/src/cvs.h
+++ b/contrib/cvs/src/cvs.h
@@ -9,6 +9,7 @@
/*
* basic information used in all source files
*
+ * $FreeBSD$
*/
@@ -187,6 +188,7 @@ extern int errno;
#define CVSROOTADM_WRITERS "writers"
#define CVSROOTADM_PASSWD "passwd"
#define CVSROOTADM_CONFIG "config"
+#define CVSROOTADM_OPTIONS "options"
#define CVSNULLREPOS "Emptydir" /* an empty directory */
@@ -256,6 +258,8 @@ extern int errno;
#define CVSREAD_ENV "CVSREAD" /* make files read-only */
#define CVSREAD_DFLT 0 /* writable files by default */
+#define CVSREADONLYFS_ENV "CVSREADONLYFS" /* repository is read-only */
+
#define TMPDIR_ENV "TMPDIR" /* Temporary directory */
/* #define TMPDIR_DFLT Set by options.h */
@@ -314,7 +318,7 @@ typedef struct entnode Entnode;
/* The type of request that is being done in do_module() */
enum mtype
{
- CHECKOUT, TAG, PATCH, EXPORT, MISC
+ CHECKOUT, TAG, PATCH, EXPORT
};
/*
@@ -363,44 +367,41 @@ extern int really_quiet, quiet;
extern int use_editor;
extern int cvswrite;
extern mode_t cvsumask;
+extern char *RCS_citag;
/* Access method specified in CVSroot. */
typedef enum {
- null_method, local_method, server_method, pserver_method, kserver_method, gserver_method,
+ local_method, server_method, pserver_method, kserver_method, gserver_method,
ext_method, fork_method
} CVSmethod;
extern char *method_names[]; /* change this in root.c if you change
the enum above */
-typedef struct cvsroot_s {
- char *original; /* the complete source CVSroot string */
- CVSmethod method; /* one of the enum values above */
- char *username; /* the username or NULL if method == local */
- char *password; /* the username or NULL if method == local */
- char *hostname; /* the hostname or NULL if method == local */
- int port; /* the port or zero if method == local */
- char *directory; /* the directory name */
-#ifdef CLIENT_SUPPORT
- unsigned char isremote; /* nonzero if we are doing remote access */
-#endif /* CLIENT_SUPPORT */
-} cvsroot_t;
-
/* This global variable holds the global -d option. It is NULL if -d
was not used, which means that we must get the CVSroot information
from the CVSROOT environment variable or from a CVS/Root file. */
extern char *CVSroot_cmdline;
+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_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 */
+
/* These variables keep track of all of the CVSROOT directories that
have been seen by the client and the current one of those selected. */
extern List *root_directories;
-extern cvsroot_t *current_parsed_root;
+extern char *current_root;
extern char *emptydir_name PROTO ((void));
extern int safe_location PROTO ((void));
extern int trace; /* Show all commands */
extern int noexec; /* Don't modify disk anywhere */
+extern int readonlyfs; /* fail on all write locks; succeed all read locks */
extern int logoff; /* Don't write history entry */
+extern int require_real_user; /* skip CVSROOT/passwd, /etc/passwd users only*/
extern int top_level_admin;
@@ -428,9 +429,8 @@ extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile,
char *rev1, char *rev2,
char *label1, char *label2,
char *workfile));
-extern int diff_exec PROTO ((char *file1, char *file2,
- char *label1, char *label2,
- char *options, char *out));
+extern int diff_exec PROTO ((char *file1, char *file2, char *options,
+ char *out));
extern int diff_execv PROTO ((char *file1, char *file2,
char *label1, char *label2,
char *options, char *out));
@@ -450,18 +450,15 @@ void Subdir_Deregister PROTO((List *, const char *, const char *));
char *Make_Date PROTO((char *rawdate));
char *date_from_time_t PROTO ((time_t));
-void date_to_internet PROTO ((char *, const char *));
-void date_to_tm PROTO ((struct tm *, const char *));
-void tm_to_internet PROTO ((char *, const struct tm *));
+void date_to_internet PROTO ((char *, char *));
char *Name_Repository PROTO((char *dir, char *update_dir));
char *Short_Repository PROTO((char *repository));
void Sanitize_Repository_Name PROTO((char *repository));
char *Name_Root PROTO((char *dir, char *update_dir));
-void free_cvsroot_t PROTO((cvsroot_t *root_in));
-cvsroot_t *parse_cvsroot PROTO((char *root));
-cvsroot_t *local_cvsroot PROTO((char *dir));
+int parse_cvsroot PROTO((char *CVSroot));
+void set_local_cvsroot PROTO((char *dir));
void Create_Root PROTO((char *dir, char *rootdir));
void root_allow_add PROTO ((char *));
void root_allow_free PROTO ((void));
@@ -475,7 +472,6 @@ char *time_stamp PROTO((char *file));
void *xmalloc PROTO((size_t bytes));
void *xrealloc PROTO((void *ptr, size_t bytes));
void expand_string PROTO ((char **, size_t *, size_t));
-void allocate_and_strcat PROTO ((char **, size_t *, const char *));
char *xstrdup PROTO((const char *str));
void strip_trailing_newlines PROTO((char *str));
int pathname_levels PROTO ((char *path));
@@ -498,7 +494,7 @@ char *xreadlink PROTO((const char *link));
char *last_component PROTO((char *path));
char *get_homedir PROTO ((void));
char *cvs_temp_name PROTO ((void));
-FILE *cvs_temp_file PROTO ((char **filename));
+void parseopts PROTO ((const char *root));
int numdots PROTO((const char *s));
char *increment_revnum PROTO ((const char *));
@@ -522,8 +518,7 @@ void Lock_Cleanup PROTO((void));
/* Writelock an entire subtree, well the part specified by ARGC, ARGV, LOCAL,
and AFLAG, anyway. */
-void lock_tree_for_write PROTO ((int argc, char **argv, int local, int which,
- int aflag));
+void lock_tree_for_write PROTO ((int argc, char **argv, int local, int aflag));
/* See lock.c for description. */
extern void lock_dir_for_write PROTO ((char *));
@@ -560,6 +555,7 @@ void make_directories PROTO((const char *name));
void make_directory PROTO((const char *name));
extern int mkdir_if_needed PROTO ((char *name));
void rename_file PROTO((const char *from, const char *to));
+char *backup_file PROTO((const char *file, const char *suffix));
/* Expand wildcards in each element of (ARGC,ARGV). This is according to the
files which exist in the current directory, and accordingly to OS-specific
conventions regarding wildcard syntax. It might be desirable to change the
@@ -589,7 +585,7 @@ void Update_Logfile PROTO((char *repository, char *xmessage, FILE * xlogfp,
void do_editor PROTO((char *dir, char **messagep,
char *repository, List * changes));
-void do_verify PROTO((char *message, char *repository));
+void do_verify PROTO((char **messagep, char *repository));
typedef int (*CALLBACKPROC) PROTO((int argc, char *argv[], char *where,
char *mwhere, char *mfile, int shorten, int local_specified,
@@ -639,8 +635,7 @@ extern int init PROTO ((int argc, char **argv));
int do_module PROTO((DBM * db, char *mname, enum mtype m_type, char *msg,
CALLBACKPROC callback_proc, char *where, int shorten,
- int local_specified, int run_module_prog, int build_dirs,
- char *extra_arg));
+ int local_specified, int run_module_prog, char *extra_arg));
void history_write PROTO((int type, char *update_dir, char *revs, char *name,
char *repository));
int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
@@ -658,10 +653,7 @@ char *make_message_rcslegal PROTO((char *message));
extern int file_has_markers PROTO ((const struct file_info *));
extern void get_file PROTO ((const char *, const char *, const char *,
char **, size_t *, size_t *));
-extern char *shell_escape PROTO((char *buf, const char *str));
-char *backup_file PROTO((const char *file, const char *suffix));
extern void resolve_symlink PROTO ((char **filename));
-void sleep_past PROTO ((time_t desttime));
/* flags for run_exec(), the fast system() for CVS */
#define RUN_NORMAL 0x0000 /* no special behaviour */
@@ -791,7 +783,9 @@ enum classify_type
T_REMOVED, /* R (removed file) list */
T_REMOVE_ENTRY, /* W (removed entry) list */
T_UPTODATE, /* File is up-to-date */
+#ifdef SERVER_SUPPORT
T_PATCH, /* P Like C, but can patch */
+#endif
T_TITLE /* title for node type */
};
typedef enum classify_type Ctype;
@@ -881,8 +875,6 @@ char *descramble PROTO ((char *str));
#ifdef AUTH_CLIENT_SUPPORT
char *get_cvs_password PROTO((void));
-int get_cvs_port_number PROTO((const cvsroot_t *root));
-char *normalize_cvsroot PROTO((const cvsroot_t *root));
#endif /* AUTH_CLIENT_SUPPORT */
extern void tag_check_valid PROTO ((char *, int, char **, int, int, char *));
diff --git a/contrib/cvs/src/diff.c b/contrib/cvs/src/diff.c
index 9732f5d..15353e63 100644
--- a/contrib/cvs/src/diff.c
+++ b/contrib/cvs/src/diff.c
@@ -12,6 +12,8 @@
*
* Without any file arguments, runs diff against all the currently modified
* files.
+ *
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -117,7 +119,7 @@ static struct option const longopts[] =
{"ignore-matching-lines", 1, 0, 'I'},
{"label", 1, 0, 'L'},
{"new-file", 0, 0, 'N'},
- {"initial-tab", 0, 0, 'T'},
+ {"initial-tab", 0, 0, 148},
{"width", 1, 0, 'W'},
{"text", 0, 0, 'a'},
{"ignore-space-change", 0, 0, 'b'},
@@ -138,7 +140,7 @@ static struct option const longopts[] =
{"report-identical-files", 0, 0, 's'},
{"expand-tabs", 0, 0, 't'},
{"ignore-all-space", 0, 0, 'w'},
- {"side-by-side", 0, 0, 'y'},
+ {"side-by-side", 0, 0, 147},
{"unified", 2, 0, 146},
{"left-column", 0, 0, 129},
{"suppress-common-lines", 0, 0, 130},
@@ -186,6 +188,28 @@ static struct option const longopts[] =
mostly to ignore -q. Maybe this should be fixed, but I think it's
a larger issue than the changes included here. */
+static void strcat_and_allocate PROTO ((char **, size_t *, const char *));
+
+/* *STR is a pointer to a malloc'd string. *LENP is its allocated
+ length. Add SRC to the end of it, reallocating if necessary. */
+static void
+strcat_and_allocate (str, lenp, src)
+ char **str;
+ size_t *lenp;
+ const char *src;
+{
+ size_t new_size;
+
+ new_size = strlen (*str) + strlen (src) + 1;
+ if (*str == NULL || new_size >= *lenp)
+ {
+ while (new_size >= *lenp)
+ *lenp *= 2;
+ *str = xrealloc (*str, *lenp);
+ }
+ strcat (*str, src);
+}
+
int
diff (argc, argv)
int argc;
@@ -224,19 +248,18 @@ diff (argc, argv)
optind = 0;
while ((c = getopt_long (argc, argv,
- "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:",
+ "+abcdefhilnpstuw0123456789BHNRC:D:F:I:L:U:V:W:k:r:",
longopts, &option_index)) != -1)
{
switch (c)
{
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'h': case 'i': case 'n': case 'p': case 's': case 't':
- case 'u': case 'w': case 'y':
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- case 'B': case 'H': case 'T':
+ case 'u': case 'w': case '0': case '1': case '2':
+ case '3': case '4': case '5': case '6': case '7': case '8':
+ case '9': case 'B': case 'H':
(void) sprintf (tmp, " -%c", (char) c);
- allocate_and_strcat (&opts, &opts_allocated, tmp);
+ strcat_and_allocate (&opts, &opts_allocated, tmp);
break;
case 'L':
if (have_rev1_label++)
@@ -246,31 +269,32 @@ diff (argc, argv)
break;
}
- allocate_and_strcat (&opts, &opts_allocated, " -L");
- allocate_and_strcat (&opts, &opts_allocated, optarg);
+ strcat_and_allocate (&opts, &opts_allocated, " -L");
+ strcat_and_allocate (&opts, &opts_allocated, optarg);
break;
case 'C': case 'F': case 'I': case 'U': case 'V': case 'W':
(void) sprintf (tmp, " -%c", (char) c);
- allocate_and_strcat (&opts, &opts_allocated, tmp);
- allocate_and_strcat (&opts, &opts_allocated, optarg);
+ strcat_and_allocate (&opts, &opts_allocated, tmp);
+ strcat_and_allocate (&opts, &opts_allocated, optarg);
break;
case 131:
/* --ifdef. */
- allocate_and_strcat (&opts, &opts_allocated, " --ifdef=");
- allocate_and_strcat (&opts, &opts_allocated, optarg);
+ strcat_and_allocate (&opts, &opts_allocated, " --ifdef=");
+ strcat_and_allocate (&opts, &opts_allocated, optarg);
break;
case 129: case 130: case 132: case 133: case 134:
case 135: case 136: case 137: case 138: case 139: case 140:
case 141: case 142: case 143: case 144: case 145: case 146:
- allocate_and_strcat (&opts, &opts_allocated, " --");
- allocate_and_strcat (&opts, &opts_allocated,
+ case 147: case 148:
+ strcat_and_allocate (&opts, &opts_allocated, " --");
+ strcat_and_allocate (&opts, &opts_allocated,
longopts[option_index].name);
if (longopts[option_index].has_arg == 1
|| (longopts[option_index].has_arg == 2
&& optarg != NULL))
{
- allocate_and_strcat (&opts, &opts_allocated, "=");
- allocate_and_strcat (&opts, &opts_allocated, optarg);
+ strcat_and_allocate (&opts, &opts_allocated, "=");
+ strcat_and_allocate (&opts, &opts_allocated, optarg);
}
break;
case 'R':
@@ -319,7 +343,7 @@ diff (argc, argv)
options = xstrdup ("");
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote) {
+ if (client_active) {
/* We're the client side. Fire up the remote server. */
start_server ();
@@ -400,8 +424,6 @@ diff_fileproc (callerdat, finfo)
char *tmp;
char *tocvsPath;
char *fname;
- char *label1;
- char *label2;
/* Initialize these solely to avoid warnings from gcc -Wall about
variables that might be used uninitialized. */
@@ -437,7 +459,8 @@ diff_fileproc (callerdat, finfo)
(vers->vn_rcs == NULL
? NULL
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
- exists = head != NULL;
+ exists = (head != NULL
+ && !RCS_isdead (vers->srcfile, head));
if (head != NULL)
free (head);
}
@@ -447,7 +470,8 @@ diff_fileproc (callerdat, finfo)
xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1,
1, 0);
- exists = xvers->vn_rcs != NULL;
+ exists = (xvers->vn_rcs != NULL
+ && !RCS_isdead (xvers->srcfile, xvers->vn_rcs));
freevers_ts (&xvers);
}
if (exists)
@@ -612,53 +636,24 @@ diff_fileproc (callerdat, finfo)
copy_file (tocvsPath, finfo->file);
}
- /* Set up file labels appropriate for compatibility with the Larry Wall
- * implementation of patch if the user didn't specify. This is irrelevant
- * according to the POSIX.2 specification.
- */
- label1 = NULL;
- label2 = NULL;
- if (!have_rev1_label)
- {
- if (empty_file == DIFF_ADDED)
- label1 =
- make_file_label (DEVNULL, NULL, NULL);
- else
- label1 =
- make_file_label (finfo->fullname, use_rev1, vers ? vers->srcfile : NULL);
- }
-
- if (!have_rev2_label)
- {
- if (empty_file == DIFF_REMOVED)
- label2 =
- make_file_label (DEVNULL, NULL, NULL);
- else
- label2 =
- make_file_label (finfo->fullname, use_rev2, vers ? vers->srcfile : NULL);
- }
-
if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
{
- /* This is fullname, not file, possibly despite the POSIX.2
- * specification, because that's the way all the Larry Wall
- * implementations of patch (are there other implementations?) want
- * things and the POSIX.2 spec appears to leave room for this.
- */
+ /* This is file, not fullname, because it is the "Index:" line which
+ is supposed to contain the directory. */
cvs_output ("\
===================================================================\n\
RCS file: ", 0);
- cvs_output (finfo->fullname, 0);
+ cvs_output (finfo->file, 0);
cvs_output ("\n", 1);
cvs_output ("diff -N ", 0);
- cvs_output (finfo->fullname, 0);
+ cvs_output (finfo->file, 0);
cvs_output ("\n", 1);
if (empty_file == DIFF_ADDED)
{
if (use_rev2 == NULL)
- status = diff_exec (DEVNULL, finfo->file, label1, label2, opts, RUN_TTY);
+ status = diff_exec (DEVNULL, finfo->file, opts, RUN_TTY);
else
{
int retcode;
@@ -677,7 +672,7 @@ RCS file: ", 0);
return err;
}
- status = diff_exec (DEVNULL, tmp, label1, label2, opts, RUN_TTY);
+ status = diff_exec (DEVNULL, tmp, opts, RUN_TTY);
}
}
else
@@ -696,11 +691,22 @@ RCS file: ", 0);
return err;
}
- status = diff_exec (tmp, DEVNULL, label1, label2, opts, RUN_TTY);
+ status = diff_exec (tmp, DEVNULL, opts, RUN_TTY);
}
}
else
{
+ char *label1 = NULL;
+ char *label2 = NULL;
+
+ if (!have_rev1_label)
+ label1 =
+ make_file_label (finfo->fullname, use_rev1, vers->srcfile);
+
+ if (!have_rev2_label)
+ label2 =
+ make_file_label (finfo->fullname, use_rev2, vers->srcfile);
+
status = RCS_exec_rcsdiff (vers->srcfile, opts,
*options ? options : vers->options,
use_rev1, use_rev2,
diff --git a/contrib/cvs/src/filesubr.c b/contrib/cvs/src/filesubr.c
index 28575a3..2cccbcd 100644
--- a/contrib/cvs/src/filesubr.c
+++ b/contrib/cvs/src/filesubr.c
@@ -17,7 +17,10 @@
definitions under operating systems (like, say, Windows NT) with different
file system semantics. */
-#include <assert.h>
+/*
+ * $FreeBSD$
+ */
+
#include "cvs.h"
static int deep_remove_dir PROTO((const char *path));
@@ -414,12 +417,12 @@ unlink_file (f)
const char *f;
{
if (trace)
- (void) fprintf (stderr, "%s-> unlink_file(%s)\n",
+ (void) fprintf (stderr, "%s-> unlink(%s)\n",
CLIENT_SERVER_STR, f);
if (noexec)
return (0);
- return (CVS_UNLINK (f));
+ return (unlink (f));
}
/*
@@ -465,7 +468,7 @@ unlink_file_dir (f)
else if (S_ISDIR (sb.st_mode))
return deep_remove_dir (f);
- return CVS_UNLINK (f);
+ return unlink (f);
}
/* Remove a directory and everything it contains. Returns 0 for
@@ -488,14 +491,14 @@ deep_remove_dir (path)
returns 87). */
|| (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
{
- if ((dirp = CVS_OPENDIR (path)) == NULL)
+ if ((dirp = opendir (path)) == NULL)
/* If unable to open the directory return
* an error
*/
return -1;
errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
+ while ((dp = readdir (dirp)) != NULL)
{
char *buf;
@@ -513,16 +516,16 @@ deep_remove_dir (path)
{
if (deep_remove_dir(buf))
{
- CVS_CLOSEDIR(dirp);
+ closedir(dirp);
free (buf);
return -1;
}
}
else
{
- if (CVS_UNLINK (buf) != 0)
+ if (unlink (buf) != 0)
{
- CVS_CLOSEDIR(dirp);
+ closedir(dirp);
free (buf);
return -1;
}
@@ -534,11 +537,11 @@ deep_remove_dir (path)
if (errno != 0)
{
int save_errno = errno;
- CVS_CLOSEDIR (dirp);
+ closedir (dirp);
errno = save_errno;
return -1;
}
- CVS_CLOSEDIR (dirp);
+ closedir (dirp);
return rmdir (path);
}
else
@@ -685,167 +688,71 @@ xcmp (file1, file2)
}
/* Generate a unique temporary filename. Returns a pointer to a newly
- * malloc'd string containing the name. Returns successfully or not at
- * all.
- *
- * THIS FUNCTION IS DEPRECATED!!! USE cvs_temp_file INSTEAD!!!
- *
- * and yes, I know about the way the rcs commands use temp files. I think
- * they should be converted too but I don't have time to look into it right
- * now.
- */
+ malloc'd string containing the name. Returns successfully or not at
+ all. */
+/* There are at least three functions for generating temporary
+ filenames. We use tempnam (SVID 3) if possible, else mktemp (BSD
+ 4.3), and as last resort tmpnam (POSIX). Reason is that tempnam and
+ mktemp both allow to specify the directory in which the temporary
+ file will be created. */
+#if 1
char *
cvs_temp_name ()
{
- char *fn;
- FILE *fp;
+ char *value;
+ int retval;
- fp = cvs_temp_file (&fn);
- if (fp == NULL)
- error (1, errno, "Failed to create temporary file");
- if (fclose (fp) == EOF)
- error (0, errno, "Failed to close temporary file %s", fn);
- return fn;
-}
+ value = xmalloc (strlen (Tmpdir) + 40);
+ sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXXXXXX");
+ retval = mkstemp (value);
-/* Generate a unique temporary filename and return an open file stream
- * to the truncated file by that name
- *
- * INPUTS
- * filename where to place the pointer to the newly allocated file
- * name string
- *
- * OUTPUTS
- * filename dereferenced, will point to the newly allocated file
- * name string. This value is undefined if the function
- * returns an error.
- *
- * RETURNS
- * An open file pointer to a read/write mode empty temporary file with the
- * unique file name or NULL on failure.
- *
- * ERRORS
- * on error, errno will be set to some value either by CVS_FOPEN or
- * whatever system function is called to generate the temporary file name
- */
-/* There are at least four functions for generating temporary
- * filenames. We use mkstemp (BSD 4.3) if possible, else tempnam (SVID 3),
- * else mktemp (BSD 4.3), and as last resort tmpnam (POSIX). Reason is that
- * mkstemp, tempnam, and mktemp both allow to specify the directory in which
- * the temporary file will be created.
- *
- * And the _correct_ way to use the deprecated functions probably involves
- * opening file descriptors using O_EXCL & O_CREAT and even doing the annoying
- * NFS locking thing, but until I hear of more problems, I'm not going to
- * bother.
- */
-FILE *cvs_temp_file (filename)
- char **filename;
+ if (retval == -1)
+ error (1, errno, "cannot generate temporary filename");
+ close (retval);
+ return value;
+}
+#else
+#ifdef HAVE_TEMPNAM
+char *
+cvs_temp_name ()
{
- char *fn;
- FILE *fp;
-
- /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
- * some of the rcs & diff functions which rely on a temp file run in
- * noexec mode too.
- */
-
- assert (filename != NULL);
-
-#ifdef HAVE_MKSTEMP
-
- {
- int fd;
-
- fn = xmalloc (strlen (Tmpdir) + 11);
- sprintf (fn, "%s/%s", Tmpdir, "cvsXXXXXX" );
- fd = mkstemp (fn);
-
- /* a NULL return will be interpreted by callers as an error and
- * errno should still be set
- */
- if (fd == -1) fp = NULL;
- else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
- {
- /* attempt to close and unlink the file since mkstemp returned sucessfully and
- * we believe it's been created and opened
- */
- int save_errno = errno;
- if (close (fd))
- error (0, errno, "Failed to close temporary file %s", fn);
- if (CVS_UNLINK (fn))
- error (0, errno, "Failed to unlink temporary file %s", fn);
- errno = save_errno;
- }
-
- if (fp == NULL) free (fn);
- /* mkstemp is defined to open mode 0600 using glibc 2.0.7+ */
- /* FIXME - configure can probably tell us which version of glibc we are
- * linking to and not chmod for 2.0.7+
- */
- else chmod (fn, 0600);
-
- }
-
-#elif HAVE_TEMPNAM
-
- /* tempnam has been deprecated due to under-specification */
-
- fn = tempnam (Tmpdir, "cvs");
- if (fn == NULL) fp = NULL;
- else if ((fp = CVS_FOPEN (fn, "w+")) == NULL) free (fn);
- else chmod (fn, 0600);
+ char *retval;
+ retval = tempnam (Tmpdir, "cvs");
+ if (retval == NULL)
+ error (1, errno, "cannot generate temporary filename");
/* tempnam returns a pointer to a newly malloc'd string, so there's
- * no need for a xstrdup
- */
-
-#elif HAVE_MKTEMP
-
- /* mktemp has been deprecated due to the BSD 4.3 specification specifying
- * that XXXXXX will be replaced by a PID and a letter, creating only 26
- * possibilities, a security risk, and a race condition.
- */
-
- {
- char *ifn;
-
- ifn = xmalloc (strlen (Tmpdir) + 11);
- sprintf (ifn, "%s/%s", Tmpdir, "cvsXXXXXX" );
- fn = mktemp (ifn);
-
- if (fn == NULL) fp = NULL;
- else fp = CVS_FOPEN (fn, "w+");
-
- if (fp == NULL) free (ifn);
- else chmod (fn, 0600);
-
- }
-
-#else /* use tmpnam if all else fails */
-
- /* tmpnam is deprecated */
-
- {
- char ifn[L_tmpnam + 1];
-
- fn = tmpnam (ifn);
-
- if (fn == NULL) fp = NULL;
- else if ((fp = CVS_FOPEN (ifn, "w+")) != NULL)
- {
- fn = xstrdup (ifn);
- chmod (fn, 0600);
- }
-
- }
-
-#endif
-
- *filename = fn;
- return fp;
+ no need for a xstrdup */
+ return retval;
}
-
+#else
+char *
+cvs_temp_name ()
+{
+# ifdef HAVE_MKTEMP
+ char *value;
+ char *retval;
+
+ value = xmalloc (strlen (Tmpdir) + 40);
+ sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXX" );
+ retval = mktemp (value);
+
+ if (retval == NULL)
+ error (1, errno, "cannot generate temporary filename");
+ return value;
+# else
+ char value[L_tmpnam + 1];
+ char *retval;
+
+ retval = tmpnam (value);
+ if (retval == NULL)
+ error (1, errno, "cannot generate temporary filename");
+ return xstrdup (value);
+# endif
+}
+#endif
+#endif
+
/* Return non-zero iff FILENAME is absolute.
Trivial under Unix, but more complicated under other systems. */
int
@@ -865,8 +772,8 @@ xreadlink (link)
{
char *file = NULL;
char *tfile;
- int buflen = 128;
- int link_name_len;
+ int buflen = BUFSIZ;
+ int linklen;
if (!islink (link))
return NULL;
@@ -877,15 +784,15 @@ xreadlink (link)
do
{
file = xrealloc (file, buflen);
- link_name_len = readlink (link, file, buflen - 1);
+ errno = 0;
+ linklen = readlink (link, file, buflen - 1);
buflen *= 2;
}
- while (link_name_len < 0 && errno == ENAMETOOLONG);
+ while (linklen == -1 && errno == ENAMETOOLONG);
- if (link_name_len < 0)
+ if (linklen == -1)
error (1, errno, "cannot readlink %s", link);
-
- file[link_name_len] = '\0';
+ file[linklen] = '\0';
tfile = xstrdup (file);
free (file);
@@ -934,17 +841,13 @@ char *
get_homedir ()
{
static char *home = NULL;
- char *env;
+ char *env = getenv ("HOME");
struct passwd *pw;
if (home != NULL)
return home;
- if (
-#ifdef SERVER_SUPPORT
- !server_active &&
-#endif
- (env = getenv ("HOME")) != NULL)
+ if (env)
home = env;
else if ((pw = (struct passwd *) getpwuid (getuid ()))
&& pw->pw_dir)
@@ -1051,7 +954,7 @@ fopen_case (name, mode, fp, pathp)
}
}
errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
+ while ((dp = readdir (dirp)) != NULL)
{
if (cvs_casecmp (dp->d_name, fname) == 0)
{
@@ -1063,7 +966,7 @@ fopen_case (name, mode, fp, pathp)
}
if (errno != 0)
error (1, errno, "cannot read directory %s", dir);
- CVS_CLOSEDIR (dirp);
+ closedir (dirp);
if (found_name == NULL)
{
diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c
index 6bd6abd..3f77dc9 100644
--- a/contrib/cvs/src/import.c
+++ b/contrib/cvs/src/import.c
@@ -14,6 +14,8 @@
* VendorReleTag Tag for this particular release
*
* Additional arguments specify more Vendor Release Tags.
+ *
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -171,17 +173,16 @@ import (argc, argv)
if (! isabsolute (argv[0])
&& pathname_levels (argv[0]) == 0)
{
- if (current_parsed_root == NULL)
+ if (CVSroot_directory == NULL)
{
error (0, 0, "missing CVSROOT environment variable\n");
error (1, 0, "Set it or specify the '-d' option to %s.",
program_name);
}
- repository = xmalloc (strlen (current_parsed_root->directory)
- + strlen (argv[0])
- + 2);
- (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
- repos_len = strlen (current_parsed_root->directory);
+ repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0])
+ + 10);
+ (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
+ repos_len = strlen (CVSroot_directory);
}
else
{
@@ -208,7 +209,7 @@ import (argc, argv)
*cp = '\0';
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
{
/* For rationale behind calling start_server before do_editor, see
commit.c */
@@ -221,7 +222,7 @@ import (argc, argv)
do_editor ((char *) NULL, &message, repository,
(List *) NULL);
}
- do_verify (message, repository);
+ do_verify (&message, repository);
msglen = message == NULL ? 0 : strlen (message);
if (msglen == 0 || message[msglen - 1] != '\n')
{
@@ -237,7 +238,7 @@ import (argc, argv)
}
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
{
int err;
@@ -291,7 +292,8 @@ import (argc, argv)
make_directories (repository);
/* Create the logfile that will be logged upon completion */
- if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
+ tmpfile = cvs_temp_name ();
+ if ((logfp = CVS_FOPEN (tmpfile, "w+")) == NULL)
error (1, errno, "cannot create temporary file `%s'", tmpfile);
/* On systems where we can unlink an open file, do so, so it will go
away no matter how we exit. FIXME-maybe: Should be checking for
@@ -425,7 +427,7 @@ import_descend (message, vtag, targc, targv)
else
{
errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
+ while ((dp = readdir (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
goto one_more_time_boys;
@@ -476,7 +478,7 @@ import_descend (message, vtag, targc, targv)
else
{
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
err += client_process_import_file (message, dp->d_name,
vtag, targc, targv,
repository,
@@ -496,7 +498,7 @@ import_descend (message, vtag, targc, targv)
error (0, errno, "cannot read directory");
++err;
}
- (void) CVS_CLOSEDIR (dirp);
+ (void) closedir (dirp);
}
if (dirlist != NULL)
@@ -1567,7 +1569,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
}
#ifdef CLIENT_SUPPORT
- if (!quiet && !current_parsed_root->isremote)
+ if (!quiet && !client_active)
#else
if (!quiet)
#endif
@@ -1582,7 +1584,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
goto out;
}
#ifdef CLIENT_SUPPORT
- if (!current_parsed_root->isremote && !isdir (repository))
+ if (!client_active && !isdir (repository))
#else
if (!isdir (repository))
#endif
diff --git a/contrib/cvs/src/lock.c b/contrib/cvs/src/lock.c
index c05b83e..30c72f9 100644
--- a/contrib/cvs/src/lock.c
+++ b/contrib/cvs/src/lock.c
@@ -8,6 +8,8 @@
* Set Lock
*
* Lock file support for CVS.
+ *
+ * $FreeBSD$
*/
/* The node Concurrency in doc/cvs.texinfo has a brief introduction to
@@ -172,13 +174,12 @@ lock_name (repository, name)
/* The interesting part of the repository is the part relative
to CVSROOT. */
- assert (current_parsed_root != NULL);
- assert (current_parsed_root->directory != NULL);
- assert (strncmp (repository, current_parsed_root->directory,
- strlen (current_parsed_root->directory)) == 0);
- short_repos = repository + strlen (current_parsed_root->directory) + 1;
+ assert (CVSroot_directory != NULL);
+ assert (strncmp (repository, CVSroot_directory,
+ strlen (CVSroot_directory)) == 0);
+ short_repos = repository + strlen (CVSroot_directory) + 1;
- if (strcmp (repository, current_parsed_root->directory) == 0)
+ if (strcmp (repository, CVSroot_directory) == 0)
short_repos = ".";
else
assert (short_repos[-1] == '/');
@@ -396,7 +397,7 @@ Reader_Lock (xrepository)
FILE *fp;
char *tmp;
- if (noexec)
+ if (noexec || readonlyfs)
return (0);
/* we only do one directory at a time for read locks! */
@@ -471,6 +472,11 @@ Writer_Lock (list)
if (noexec)
return (0);
+ if (readonlyfs) {
+ error (0, 0, "write lock failed - read-only repository");
+ return (1);
+ }
+
/* We only know how to do one list at a time */
if (locklist != (List *) NULL)
{
@@ -634,7 +640,7 @@ again:
error (1, 0, "cannot open directory %s", repository);
errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
+ while ((dp = readdir (dirp)) != NULL)
{
if (CVS_FNMATCH (CVSRFLPAT, dp->d_name, 0) == 0)
{
@@ -655,7 +661,7 @@ again:
*/
if (now >= (sb.st_ctime + CVSLCKAGE) && CVS_UNLINK (line) != -1)
{
- (void) CVS_CLOSEDIR (dirp);
+ (void) closedir (dirp);
free (line);
goto again;
}
@@ -681,7 +687,7 @@ again:
if (errno != 0)
error (0, errno, "error reading directory %s", repository);
- CVS_CLOSEDIR (dirp);
+ closedir (dirp);
return (ret);
}
@@ -891,11 +897,10 @@ lock_filesdoneproc (callerdat, err, repository, update_dir, entries)
}
void
-lock_tree_for_write (argc, argv, local, which, aflag)
+lock_tree_for_write (argc, argv, local, aflag)
int argc;
char **argv;
int local;
- int which;
int aflag;
{
int err;
@@ -906,7 +911,7 @@ lock_tree_for_write (argc, argv, local, which, aflag)
lock_tree_list = getlist ();
err = start_recursion ((FILEPROC) NULL, lock_filesdoneproc,
(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, argc,
- argv, local, which, aflag, 0, (char *) NULL, 0);
+ argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0);
sortlist (lock_tree_list, fsortcmp);
if (Writer_Lock (lock_tree_list) != 0)
error (1, 0, "lock failed - giving up");
diff --git a/contrib/cvs/src/login.c b/contrib/cvs/src/login.c
index 9289737..cc564c06 100644
--- a/contrib/cvs/src/login.c
+++ b/contrib/cvs/src/login.c
@@ -5,6 +5,8 @@
* specified in the README file that comes with CVS.
*
* Allow user to log in for an authenticating server.
+ *
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -85,183 +87,26 @@ construct_cvspass_filename ()
return passfile;
}
-
-
-/*
- * static char *
- * password_entry_parseline (
- * const char *cvsroot_canonical,
- * const unsigned char warn,
- * const int linenumber,
- * char *linebuf
- * );
- *
- * Internal function used by password_entry_operation. Parse a single line
- * from a ~/.cvsroot password file and return a pointer to the password if the
- * line refers to the same cvsroot as cvsroot_canonical
- *
- * INPUTS
- * cvsroot_canonical the root we are looking for
- * warn Boolean: print warnings for invalid lines?
- * linenumber the line number for error messages
- * linebuf the current line
- *
- * RETURNS
- * NULL if the line doesn't match
- * char *password as a pointer into linebuf
- *
- * NOTES
- * This function temporarily alters linebuf, so it isn't thread safe when
- * called on the same linebuf
- */
-static char *
-password_entry_parseline (cvsroot_canonical, warn, linenumber, linebuf)
- const char *cvsroot_canonical;
- const unsigned char warn;
- const int linenumber;
- char *linebuf;
+static const char *const login_usage[] =
{
- char *password = NULL;
- char *p;
-
- /* look for '^/' */
- if (*linebuf == '/')
- {
- /* Yes: slurp '^/\d+\D' and parse the rest of the line according to version number */
- char *q;
- unsigned long int entry_version;
-
- if (isspace(*(linebuf + 1)))
- /* special case since strtoul ignores leading white space */
- entry_version = 0;
- else
- entry_version = strtoul (linebuf + 1, &q, 10);
-
- if (q == linebuf + 1)
- /* no valid digits found by strtoul */
- entry_version = 0;
- else
- /* assume a delimiting seperator */
- q++;
-
- switch (entry_version)
- {
- case 1:
- /* this means the same normalize_cvsroot we are using was
- * used to create this entry. strcmp is good enough for
- * us.
- */
- p = strchr (q, ' ');
- if (p == NULL)
- {
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping invalid entry in password file at line %d",
- linenumber);
- }
- else
- {
- *p = '\0';
- if (strcmp (cvsroot_canonical, q) == 0)
- password = p + 1;
- *p = ' ';
- }
- break;
- case ULONG_MAX:
- if (warn && !really_quiet)
- {
- error (0, errno, "warning: unable to convert version number in password file at line %d",
- linenumber);
- error (0, 0, "skipping entry");
- }
- break;
- case 0:
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping entry with invalid version string in password file at line %d",
- linenumber);
- break;
- default:
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping entry with unknown version (%lu) in password file at line %d",
- entry_version, linenumber);
- break;
- }
- }
- else
- {
- /* No: assume:
- *
- * ^cvsroot Aencoded_password$
- *
- * as header comment specifies and parse accordingly
- */
- cvsroot_t *tmp_root;
- char *tmp_root_canonical;
-
- p = strchr (linebuf, ' ');
- if (p == NULL)
- {
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping invalid entry in password file at line %d", linenumber);
- return NULL;;
- }
-
- *p = '\0';
- if ((tmp_root = parse_cvsroot (linebuf)) == NULL)
- {
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping invalid entry in password file at line %d", linenumber);
- *p = ' ';
- return NULL;
- }
- *p = ' ';
- tmp_root_canonical = normalize_cvsroot (tmp_root);
- if (strcmp (cvsroot_canonical, tmp_root_canonical) == 0)
- password = p + 1;
-
- free (tmp_root_canonical);
- free_cvsroot_t (tmp_root);
- }
-
- return password;
-}
-
-
+ "Usage: %s %s\n",
+ "(Specify the --help global option for a list of other help options)\n",
+ NULL
+};
-/*
- * static char *
- * password_entry_operation (
- * password_entry_operation_t operation,
- * cvsroot_t *root,
- * char *newpassword
- * );
- *
- * Search the password file and depending on the value of operation:
- *
- * Mode Action
- * password_entry_lookup Return the password
- * password_entry_delete Delete the entry from the file, if it exists
- * password_entry_add Replace the line with the new one, else append it
+/* Prompt for a password, and store it in the file "CVS/.cvspass".
*
* Because the user might be accessing multiple repositories, with
* different passwords for each one, the format of ~/.cvspass is:
*
- * [user@]host:[port]/path Aencoded_password
- * [user@]host:[port]/path Aencoded_password
+ * user@host:/path Acleartext_password
+ * user@host:/path Acleartext_password
* ...
*
- * New entries are always of the form:
+ * Of course, the "user@" might be left off -- it's just based on the
+ * value of CVSroot.
*
- * /1 user@host:port/path Aencoded_password
- *
- * but the old format is supported for backwards compatibility.
- * The entry version string wasn't strictly necessary, but it avoids the
- * overhead of parsing some entries since we know it is already in canonical
- * form and allows room for expansion later, say, if we want to allow spaces
- * and/or other characters to be escaped in the string. Also, the new entries
- * would have been ignored by old versions of CVS anyhow since those versions
- * didn't know how to parse a port number.
- *
- * The "A" before "encoded_password" is a literal capital A. It's a
+ * The "A" before "cleartext_password" is a literal capital A. It's a
* version number indicating which form of scrambling we're doing on
* the password -- someday we might provide something more secure than
* the trivial encoding we do now, and when that day comes, it would
@@ -271,318 +116,201 @@ password_entry_parseline (cvsroot_canonical, warn, linenumber, linebuf)
* it from being read by others. Unlike .netrc, we will not be
* fascist about it, at most issuing a warning, and never refusing to
* work.
- *
- * INPUTS
- * operation operation to perform
- * root cvsroot_t to look up
- * newpassword prescrambled new password, for password_entry_add_mode
- *
- * RETURNS
- * -1 if password_entry_lookup_mode not specified
- * NULL on failed lookup
- * pointer to a copy of the password string otherwise, which the caller is
- * responsible for disposing of
*/
-
-typedef enum password_entry_operation_e {
- password_entry_lookup,
- password_entry_delete,
- password_entry_add
-} password_entry_operation_t;
-
-static char *
-password_entry_operation (operation, root, newpassword)
- password_entry_operation_t operation;
- cvsroot_t *root;
- char *newpassword;
+int
+login (argc, argv)
+ int argc;
+ char **argv;
{
char *passfile;
FILE *fp;
- char *cvsroot_canonical = NULL;
- char *password = NULL;
- int line_length;
- long line;
- char *linebuf = NULL;
+ char *typed_password, *found_password;
+ char *linebuf = (char *) NULL;
size_t linebuf_len;
- char *p;
- int save_errno = 0;
-
- if (root->method != pserver_method)
- {
- error (0, 0, "internal error: can only call password_entry_operation with pserver method");
- error (1, 0, "CVSROOT: %s", root->original);
- }
+ int root_len, already_entered = 0;
+ int line_length;
- /* Yes, the method below reads the user's password file twice when we have
- * to delete an entry. It's inefficient, but we're not talking about a gig of
- * data here.
- */
+ if (argc < 0)
+ usage (login_usage);
- passfile = construct_cvspass_filename ();
- fp = CVS_FOPEN (passfile, "r");
- if (fp == NULL)
+ if (CVSroot_method != pserver_method)
{
- error (0, errno, "failed to open %s for reading", passfile);
- goto error_exit;
+ error (0, 0, "can only use pserver method with `login' command");
+ error (1, 0, "CVSROOT: %s", CVSroot_original);
}
- cvsroot_canonical = normalize_cvsroot (root);
-
- /* Check each line to see if we have this entry already. */
- line = 0;
- while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
- {
- line++;
- password = password_entry_parseline(cvsroot_canonical, 1, line, linebuf);
- if (password != NULL)
- /* this is it! break out and deal with linebuf */
- break;
- }
- if (line_length < 0 && !feof (fp))
+ if (! CVSroot_username)
{
- error (0, errno, "cannot read %s", passfile);
- goto error_exit;
+ error (0, 0, "CVSROOT \"%s\" is not fully-qualified.",
+ CVSroot_original);
+ error (1, 0, "Please make sure to specify \"user@host\"!");
}
- if (fclose (fp) < 0)
- /* not fatal, unless it cascades */
- error (0, errno, "cannot close %s", passfile);
- fp = NULL;
- /* Utter, total, raving paranoia, I know. */
- chmod (passfile, 0600);
+ printf ("(Logging in to %s@%s)\n", CVSroot_username, CVSroot_hostname);
+ fflush (stdout);
- /* a copy to return or keep around so we can reuse linebuf */
- if (password != NULL)
- {
- /* chomp the EOL */
- p = strchr (password, '\n');
- if (p != NULL)
- *p = '\0';
- password = xstrdup (password);
- }
+ passfile = construct_cvspass_filename ();
+ typed_password = GETPASS ("CVS password: ");
+ typed_password = scramble (typed_password);
- /* might as well return now */
- if (operation == password_entry_lookup)
- goto out;
+ /* Force get_cvs_password() to use this one (when the client
+ * confirms the new password with the server), instead of
+ * consulting the file. We make a new copy because cvs_password
+ * will get zeroed by connect_to_server(). */
- /* same here */
- if (operation == password_entry_delete && password == NULL)
- {
- error (0, 0, "Entry not found.");
- goto out;
- }
+ cvs_password = xstrdup (typed_password);
- /* okay, file errors can simply be fatal from now on since we don't do
- * anything else if we're in lookup mode
- */
+ connect_to_pserver (NULL, NULL, 1, 0);
- /* copy the file with the entry deleted unless we're in add
- * mode and the line we found contains the same password we're supposed to
- * add
+ /* IF we have a password for this "[user@]host:/path" already
+ * THEN
+ * IF it's the same as the password we read from the prompt
+ * THEN
+ * do nothing
+ * ELSE
+ * replace the old password with the new one
+ * ELSE
+ * append new entry to the end of the file.
*/
- if (!noexec && password != NULL && (operation == password_entry_delete
- || (operation == password_entry_add && strcmp (password, newpassword))))
- {
- long found_at = line;
- char *tmp_name;
- FILE *tmp_fp;
- /* open the original file again */
- fp = CVS_FOPEN (passfile, "r");
- if (fp == NULL)
- error (1, errno, "failed to open %s for reading", passfile);
+ root_len = strlen (CVSroot_original);
- /* create and open a temp file */
- if ((tmp_fp = cvs_temp_file (&tmp_name)) == NULL)
- error (1, errno, "unable to open temp file %s", tmp_name);
+ /* Yes, the method below reads the user's password file twice. It's
+ inefficient, but we're not talking about a gig of data here. */
- line = 0;
+ fp = CVS_FOPEN (passfile, "r");
+ /* FIXME: should be printing a message if fp == NULL and not
+ existence_error (errno). */
+ if (fp != NULL)
+ {
+ /* Check each line to see if we have this entry already. */
while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
- {
- line++;
- if (line < found_at
- || (line != found_at
- && !password_entry_parseline(cvsroot_canonical, 0, line, linebuf)))
- {
- if (fprintf (tmp_fp, "%s", linebuf) == EOF)
- {
- /* try and clean up anyhow */
- error (0, errno, "fatal error: cannot write %s", tmp_name);
- if (fclose (tmp_fp) == EOF)
- error (0, errno, "cannot close %s", tmp_name);
- /* call CVS_UNLINK instead of unlink_file since the file
- * got created in noexec mode
- */
- if (CVS_UNLINK (tmp_name) < 0)
- error (0, errno, "cannot remove %s", tmp_name);
- /* but quit so we don't remove all the entries from a
- * user's password file accidentally
- */
- error (1, 0, "exiting");
- }
- }
- }
- if (line_length < 0 && !feof (fp))
- {
- error (0, errno, "cannot read %s", passfile);
- goto error_exit;
- }
+ {
+ if (strncmp (CVSroot_original, linebuf, root_len) == 0)
+ {
+ already_entered = 1;
+ break;
+ }
+ }
if (fclose (fp) < 0)
- /* not fatal, unless it cascades */
error (0, errno, "cannot close %s", passfile);
- if (fclose (tmp_fp) < 0)
- /* not fatal, unless it cascades */
- /* FIXME - does copy_file return correct results if the file wasn't
- * closed? should this be fatal?
- */
- error (0, errno, "cannot close %s", tmp_name);
-
- /* FIXME: rename_file would make more sense (e.g. almost
- * always faster).
- *
- * I don't think so, unless we change the way rename_file works to
- * attempt a cp/rm sequence when rename fails since rename doesn't
- * work across file systems and it isn't uncommon to have /tmp
- * on its own partition.
- *
- * For that matter, it's probably not uncommon to have a home
- * directory on an NFS mount.
- */
- copy_file (tmp_name, passfile);
- if (CVS_UNLINK (tmp_name) < 0)
- error (0, errno, "cannot remove %s", tmp_name);
- free (tmp_name);
}
+ else if (!existence_error (errno))
+ error (0, errno, "cannot open %s", passfile);
- /* in add mode, if we didn't find an entry or found an entry with a
- * different password, append the new line
- */
- if (!noexec && operation == password_entry_add
- && (password == NULL || strcmp (password, newpassword)))
+ if (already_entered)
+ {
+ /* This user/host has a password in the file already. */
+
+ strtok (linebuf, " ");
+ found_password = strtok (NULL, "\n");
+ if (strcmp (found_password, typed_password))
+ {
+ /* typed_password and found_password don't match, so we'll
+ * have to update passfile. We replace the old password
+ * with the new one by writing a tmp file whose contents are
+ * exactly the same as passfile except that this one entry
+ * gets typed_password instead of found_password. Then we
+ * rename the tmp file on top of passfile.
+ */
+ char *tmp_name;
+ FILE *tmp_fp;
+
+ tmp_name = cvs_temp_name ();
+ if ((tmp_fp = CVS_FOPEN (tmp_name, "w")) == NULL)
+ {
+ error (1, errno, "unable to open temp file %s", tmp_name);
+ return 1;
+ }
+ chmod (tmp_name, 0600);
+
+ fp = CVS_FOPEN (passfile, "r");
+ if (fp == NULL)
+ {
+ error (1, errno, "unable to open %s", passfile);
+ if (linebuf)
+ free (linebuf);
+ return 1;
+ }
+ /* I'm not paranoid, they really ARE out to get me: */
+ chmod (passfile, 0600);
+
+ while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
+ {
+ if (strncmp (CVSroot_original, linebuf, root_len))
+ {
+ if (fprintf (tmp_fp, "%s", linebuf) == EOF)
+ error (0, errno, "cannot write %s", tmp_name);
+ }
+ else
+ {
+ if (fprintf (tmp_fp, "%s %s\n", CVSroot_original,
+ typed_password) == EOF)
+ error (0, errno, "cannot write %s", tmp_name);
+ }
+ }
+ if (line_length < 0 && !feof (fp))
+ error (0, errno, "cannot read %s", passfile);
+ if (linebuf)
+ free (linebuf);
+ if (fclose (tmp_fp) < 0)
+ error (0, errno, "cannot close %s", tmp_name);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", passfile);
+
+ /* FIXME: rename_file would make more sense (e.g. almost
+ always faster). */
+ copy_file (tmp_name, passfile);
+ if (unlink_file (tmp_name) < 0)
+ error (0, errno, "cannot remove %s", tmp_name);
+ chmod (passfile, 0600);
+
+ free (tmp_name);
+ }
+ }
+ else
{
+ if (linebuf)
+ free (linebuf);
if ((fp = CVS_FOPEN (passfile, "a")) == NULL)
- error (1, errno, "could not open %s for writing", passfile);
-
- if (fprintf (fp, "/1 %s %s\n", cvsroot_canonical, newpassword) == EOF)
- error (1, errno, "cannot write %s", passfile);
+ {
+ error (1, errno, "could not open %s", passfile);
+ free (passfile);
+ return 1;
+ }
+
+ if (fprintf (fp, "%s %s\n", CVSroot_original, typed_password) == EOF)
+ error (0, errno, "cannot write %s", passfile);
if (fclose (fp) < 0)
error (0, errno, "cannot close %s", passfile);
}
/* Utter, total, raving paranoia, I know. */
chmod (passfile, 0600);
-
- if (password)
- {
- free (password);
- password = NULL;
- }
- if (linebuf)
- free (linebuf);
-
-out:
- free (cvsroot_canonical);
- free (passfile);
- return password;
-
-error_exit:
- /* just exit when we're not in lookup mode */
- if (operation != password_entry_lookup)
- error (1, 0, "fatal error: exiting");
- /* clean up and exit in lookup mode so we can try a login with a NULL
- * password anyhow in case that's what we would have found
- */
- save_errno = errno;
- if (fp != NULL)
- {
- /* Utter, total, raving paranoia, I know. */
- chmod (passfile, 0600);
- if(fclose (fp) < 0)
- error (0, errno, "cannot close %s", passfile);
- }
- if (linebuf)
- free (linebuf);
- if (cvsroot_canonical)
- free (cvsroot_canonical);
- free (passfile);
- errno = save_errno;
- return NULL;
-}
-
-
-
-/* Prompt for a password, and store it in the file "CVS/.cvspass".
- */
-
-static const char *const login_usage[] =
-{
- "Usage: %s %s\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-login (argc, argv)
- int argc;
- char **argv;
-{
- char *typed_password;
- char *cvsroot_canonical;
-
- if (argc < 0)
- usage (login_usage);
-
- if (current_parsed_root->method != pserver_method)
- {
- error (0, 0, "can only use `login' command with the 'pserver' method");
- error (1, 0, "CVSROOT: %s", current_parsed_root->original);
- }
-
- cvsroot_canonical = normalize_cvsroot(current_parsed_root);
- printf ("Logging in to %s\n", cvsroot_canonical);
- fflush (stdout);
-
- if (current_parsed_root->password)
- {
- typed_password = scramble (current_parsed_root->password);
- }
- else
- {
- char *tmp;
- tmp = GETPASS ("CVS password: ");
- typed_password = scramble (tmp);
- memset (tmp, 0, strlen (tmp));
- }
-
- /* Force get_cvs_password() to use this one (when the client
- * confirms the new password with the server), instead of
- * consulting the file. We make a new copy because cvs_password
- * will get zeroed by connect_to_server(). */
- cvs_password = xstrdup (typed_password);
-
- connect_to_pserver (NULL, NULL, 1, 0);
-
- password_entry_operation (password_entry_add, current_parsed_root, typed_password);
-
memset (typed_password, 0, strlen (typed_password));
free (typed_password);
+ free (passfile);
free (cvs_password);
- free (cvsroot_canonical);
cvs_password = NULL;
-
return 0;
}
/* Returns the _scrambled_ password. The server must descramble
before hashing and comparing. If password file not found, or
- password not found in the file, just return NULL. */
+ password not found in the file, just return NULL. */
char *
get_cvs_password ()
{
- if (current_parsed_root->password)
- return (scramble(current_parsed_root->password));
-
+ int found_it = 0;
+ int root_len;
+ char *password = NULL;
+ char *linebuf = NULL;
+ size_t linebuf_len;
+ FILE *fp;
+ char *passfile;
+ int line_length;
+
/* If someone (i.e., login()) is calling connect_to_pserver() out of
context, then assume they have supplied the correct, scrambled
password. */
@@ -592,24 +320,76 @@ get_cvs_password ()
if (getenv ("CVS_PASSWORD") != NULL)
{
/* In previous versions of CVS one could specify a password in
- * CVS_PASSWORD. This is a bad idea, because in BSD variants
- * of unix anyone can see the environment variable with 'ps'.
- * But for users who were using that feature we want to at
- * least let them know what is going on. After printing this
- * warning, we should fall through to the regular error where
- * we tell them to run "cvs login" (unless they already ran
- * it, of course).
- */
- error (0, 0, "CVS_PASSWORD is no longer supported; ignored");
+ CVS_PASSWORD. This is a bad idea, because in BSD variants
+ of unix anyone can see the environment variable with 'ps'.
+ But for users who were using that feature we want to at
+ least let them know what is going on. After printing this
+ warning, we should fall through to the regular error where
+ we tell them to run "cvs login" (unless they already ran
+ it, of course). */
+ error (0, 0, "CVS_PASSWORD is no longer supported; ignored");
+ }
+
+ /* Else get it from the file. First make sure that the CVSROOT
+ variable has the appropriate fields filled in. */
+
+ if (CVSroot_method != pserver_method)
+ {
+ error (0, 0, "can only call GET_CVS_PASSWORD with pserver method");
+ error (1, 0, "CVSROOT: %s", CVSroot_original);
+ }
+
+ if (! CVSroot_username)
+ {
+ error (0, 0, "CVSROOT \"%s\" is not fully-qualified.",
+ CVSroot_original);
+ error (1, 0, "Please make sure to specify \"user@host\"!");
+ }
+
+ passfile = construct_cvspass_filename ();
+ fp = CVS_FOPEN (passfile, "r");
+ if (fp == NULL)
+ {
+ free (passfile);
+ return NULL;
+ }
+
+ root_len = strlen (CVSroot_original);
+
+ /* Check each line to see if we have this entry already. */
+ while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
+ {
+ if (strncmp (CVSroot_original, linebuf, root_len) == 0)
+ {
+ /* This is it! So break out and deal with linebuf. */
+ found_it = 1;
+ break;
+ }
}
+ if (line_length < 0 && !feof (fp))
+ error (0, errno, "cannot read %s", passfile);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", passfile);
- if (current_parsed_root->method != pserver_method)
+ if (found_it)
{
- error (0, 0, "can only call get_cvs_password with pserver method");
- error (1, 0, "CVSROOT: %s", current_parsed_root->original);
+ /* linebuf now contains the line with the password. */
+ char *tmp;
+
+ strtok (linebuf, " ");
+ tmp = strtok (NULL, "\n");
+ if (tmp == NULL)
+ error (1, 0, "bad entry in %s for %s", passfile, CVSroot_original);
+
+ /* Give it permanent storage. */
+ password = xstrdup (tmp);
+ memset (tmp, 0, strlen (password));
}
- return password_entry_operation (password_entry_lookup, current_parsed_root, NULL);
+ if (linebuf)
+ free (linebuf);
+ free (passfile);
+ return password;
}
static const char *const logout_usage[] =
@@ -625,15 +405,29 @@ logout (argc, argv)
int argc;
char **argv;
{
- char *cvsroot_canonical;
+ char *passfile;
+ FILE *fp;
+ char *tmp_name = NULL;
+ FILE *tmp_fp;
+ char *linebuf = (char *) NULL;
+ size_t linebuf_len;
+ int root_len, found = 0;
+ int line_length;
if (argc < 0)
usage (logout_usage);
- if (current_parsed_root->method != pserver_method)
+ if (CVSroot_method != pserver_method)
{
error (0, 0, "can only use pserver method with `logout' command");
- error (1, 0, "CVSROOT: %s", current_parsed_root->original);
+ error (1, 0, "CVSROOT: %s", CVSroot_original);
+ }
+
+ if (! CVSroot_username)
+ {
+ error (0, 0, "CVSROOT \"%s\" is not fully-qualified.",
+ CVSroot_original);
+ error (1, 0, "Please make sure to specify \"user@host\"!");
}
/* Hmm. Do we want a variant of this command which deletes _all_
@@ -644,15 +438,73 @@ logout (argc, argv)
of security, in that it wouldn't delete entries from any
.cvspass files but the current one. */
- if (!quiet)
+ printf ("(Logging out of %s@%s)\n", CVSroot_username, CVSroot_hostname);
+ fflush (stdout);
+
+ /* IF we have a password for this "[user@]host:/path" already
+ * THEN
+ * drop the entry
+ * ELSE
+ * do nothing
+ */
+
+ passfile = construct_cvspass_filename ();
+ /* FIXME: This should not be in /tmp; that is almost surely a security
+ hole. Probably should just keep it in memory. */
+ tmp_name = cvs_temp_name ();
+ if ((tmp_fp = CVS_FOPEN (tmp_name, "w")) == NULL)
{
- cvsroot_canonical = normalize_cvsroot(current_parsed_root);
- printf ("Logging out of %s\n", cvsroot_canonical);
- fflush (stdout);
- free (cvsroot_canonical);
+ error (1, errno, "unable to open temp file %s", tmp_name);
+ return 1;
+ }
+ chmod (tmp_name, 0600);
+
+ root_len = strlen (CVSroot_original);
+
+ fp = CVS_FOPEN (passfile, "r");
+ if (fp == NULL)
+ error (1, errno, "Error opening %s", passfile);
+
+ /* Check each line to see if we have this entry. */
+ /* Copy only those lines that do not match this entry */
+ while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
+ {
+ if (strncmp (CVSroot_original, linebuf, root_len))
+ {
+ if (fprintf (tmp_fp, "%s", linebuf) == EOF)
+ error (0, errno, "cannot write %s", tmp_name);
+ }
+ else
+ found = 1;
+ }
+ if (line_length < 0 && !feof (fp))
+ error (0, errno, "cannot read %s", passfile);
+
+ if (linebuf)
+ free (linebuf);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", passfile);
+ if (fclose (tmp_fp) < 0)
+ error (0, errno, "cannot close %s", tmp_name);
+
+ if (! found)
+ {
+ printf ("Entry not found for %s\n", CVSroot_original);
+ if (unlink_file (tmp_name) < 0)
+ error (0, errno, "cannot remove %s", tmp_name);
+ }
+ else
+ {
+ /* FIXME: rename_file would make more sense (e.g. almost
+ always faster). */
+ copy_file (tmp_name, passfile);
+ if (unlink_file (tmp_name) < 0)
+ error (0, errno, "cannot remove %s", tmp_name);
+ chmod (passfile, 0600);
}
- password_entry_operation (password_entry_delete, current_parsed_root, NULL);
+ if (tmp_name)
+ free (tmp_name);
return 0;
}
diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c
index d2ef806..a5e16b7 100644
--- a/contrib/cvs/src/logmsg.c
+++ b/contrib/cvs/src/logmsg.c
@@ -4,6 +4,8 @@
*
* 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.
+ *
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -190,10 +192,8 @@ do_editor (dir, messagep, repository, changes)
if (strcmp (Editor, "") == 0 && !editinfo_editor)
error(1, 0, "no editor defined, must use -e or -m");
+
/* Create a temporary file */
- /* FIXME - It's possible we should be relying on cvs_temp_file to open
- * the file here - we get race conditions otherwise.
- */
fname = cvs_temp_name ();
again:
if ((fp = CVS_FOPEN (fname, "w+")) == NULL)
@@ -207,6 +207,8 @@ do_editor (dir, messagep, repository, changes)
(*messagep)[strlen (*messagep) - 1] != '\n')
(void) fprintf (fp, "\n");
}
+ else
+ (void) fprintf (fp, "\n");
if (repository != NULL)
/* tack templates on if necessary */
@@ -272,7 +274,7 @@ do_editor (dir, messagep, repository, changes)
free (editinfo_editor);
editinfo_editor = (char *) NULL;
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
; /* nothing, leave editinfo_editor NULL */
else
#endif
@@ -387,16 +389,22 @@ do_editor (dir, messagep, repository, changes)
independant of the running of an editor for getting a message.
*/
void
-do_verify (message, repository)
- char *message;
+do_verify (messagep, repository)
+ char **messagep;
char *repository;
{
FILE *fp;
char *fname;
int retcode = 0;
+ char *line;
+ int line_length;
+ size_t line_chars_allocated;
+ char *p;
+ struct stat stbuf;
+
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
/* The verification will happen on the server. */
return;
#endif
@@ -408,22 +416,25 @@ do_verify (message, repository)
/* If there's no message, then we have nothing to verify. Can this
case happen? And if so why would we print a message? */
- if (message == NULL)
+ if (*messagep == NULL)
{
cvs_output ("No message to verify\n", 0);
return;
}
- /* open a temporary file, write the message to the
+ /* Get a temp filename, open a temporary file, write the message to the
temp file, and close the file. */
- if ((fp = cvs_temp_file (&fname)) == NULL)
+ fname = cvs_temp_name ();
+
+ fp = fopen (fname, "w");
+ if (fp == NULL)
error (1, errno, "cannot create temporary file %s", fname);
else
{
- fprintf (fp, "%s", message);
- if ((message)[0] == '\0' ||
- (message)[strlen (message) - 1] != '\n')
+ fprintf (fp, "%s", *messagep);
+ if ((*messagep)[0] == '\0' ||
+ (*messagep)[strlen (*messagep) - 1] != '\n')
(void) fprintf (fp, "%s", "\n");
if (fclose (fp) == EOF)
error (1, errno, "%s", fname);
@@ -453,6 +464,55 @@ do_verify (message, repository)
}
}
+ /* put the entire message back into the *messagep variable */
+
+ fp = open_file (fname, "r");
+ if (fp == NULL)
+ {
+ error (1, errno, "cannot open temporary file %s", fname);
+ return;
+ }
+
+ if (*messagep)
+ free (*messagep);
+
+ if ( CVS_STAT (fname, &stbuf) != 0)
+ error (1, errno, "cannot find size of temp file %s", fname);
+
+ if (stbuf.st_size == 0)
+ *messagep = NULL;
+ else
+ {
+ /* On NT, we might read less than st_size bytes, but we won't
+ read more. So this works. */
+ *messagep = (char *) xmalloc (stbuf.st_size + 1);
+ *messagep[0] = '\0';
+ }
+
+ line = NULL;
+ line_chars_allocated = 0;
+
+ if (*messagep)
+ {
+ p = *messagep;
+ while (1)
+ {
+ line_length = getline (&line, &line_chars_allocated, fp);
+ if (line_length == -1)
+ {
+ if (ferror (fp))
+ error (0, errno, "warning: cannot read %s", fname);
+ break;
+ }
+ if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
+ continue;
+ (void) strcpy (p, line);
+ p += line_length;
+ }
+ }
+ if (fclose (fp) < 0)
+ error (0, errno, "warning: cannot close %s", fname);
+
/* Delete the temp file */
if (unlink_file (fname) < 0)
@@ -789,16 +849,16 @@ logfile_write (repository, filter, message, logfp, changes)
srepos = Short_Repository (repository);
- prog = cp = xmalloc ((fmt_percent - filter) + 2 * strlen (srepos)
- + 2 * strlen (str_list) + strlen (fmt_continue)
+ prog = xmalloc ((fmt_percent - filter) + strlen (srepos)
+ + strlen (str_list) + strlen (fmt_continue)
+ 10);
- (void) memcpy (cp, filter, fmt_percent - filter);
- cp += fmt_percent - filter;
- *cp++ = '"';
- cp = shell_escape (cp, srepos);
- cp = shell_escape (cp, str_list);
- *cp++ = '"';
- (void) strcpy (cp, fmt_continue);
+ (void) strncpy (prog, filter, fmt_percent - filter);
+ prog[fmt_percent - filter] = '\0';
+ (void) strcat (prog, "'");
+ (void) strcat (prog, srepos);
+ (void) strcat (prog, str_list);
+ (void) strcat (prog, "'");
+ (void) strcat (prog, fmt_continue);
/* To be nice, free up some memory. */
diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c
index 3a21916..cad210b 100644
--- a/contrib/cvs/src/main.c
+++ b/contrib/cvs/src/main.c
@@ -10,10 +10,12 @@
* Credit to Dick Grune, Vrije Universiteit, Amsterdam, for writing
* the shell-script CVS system that this is based on.
*
+ * $FreeBSD$
*/
#include <assert.h>
#include "cvs.h"
+#include "prepend_args.h"
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
@@ -41,6 +43,8 @@ int really_quiet = 0;
int quiet = 0;
int trace = 0;
int noexec = 0;
+int readonlyfs = 0;
+int require_real_user = 0;
int logoff = 0;
/* Set if we should be writing CVSADM directories at top level. At
@@ -64,12 +68,8 @@ char *Editor = EDITOR_DFLT;
List *root_directories = NULL;
/* We step through the above values. This variable is set to reflect
- * the currently active value.
- *
- * Now static. FIXME - this variable should be removable (well, localizable)
- * with a little more work.
- */
-static char *current_root = NULL;
+ the currently active value. */
+char *current_root = NULL;
static const struct cmd
@@ -100,50 +100,47 @@ static const struct cmd
char *nick2;
int (*func) (); /* Function takes (argc, argv) arguments. */
- unsigned long attr; /* Attributes. */
} cmds[] =
{
- { "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 },
- { "checkout", "co", "get", checkout, 0 },
- { "commit", "ci", "com", commit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "diff", "di", "dif", diff, CVS_CMD_USES_WORK_DIR },
- { "edit", NULL, NULL, edit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "editors", NULL, NULL, editors, CVS_CMD_USES_WORK_DIR },
- { "export", "exp", "ex", checkout, CVS_CMD_USES_WORK_DIR },
- { "history", "hi", "his", history, CVS_CMD_USES_WORK_DIR },
- { "import", "im", "imp", import, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR | CVS_CMD_IGNORE_ADMROOT},
- { "init", NULL, NULL, init, CVS_CMD_MODIFIES_REPOSITORY },
+ { "add", "ad", "new", add },
+ { "admin", "adm", "rcs", admin },
+ { "annotate", "ann", NULL, annotate },
+ { "checkout", "co", "get", checkout },
+ { "commit", "ci", "com", commit },
+ { "diff", "di", "dif", diff },
+ { "edit", NULL, NULL, edit },
+ { "editors", NULL, NULL, editors },
+ { "export", "exp", "ex", checkout },
+ { "history", "hi", "his", history },
+ { "import", "im", "imp", import },
+ { "init", NULL, NULL, init },
#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- { "kserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
+ { "kserver", NULL, NULL, server }, /* placeholder */
#endif
- { "log", "lo", NULL, cvslog, CVS_CMD_USES_WORK_DIR },
+ { "log", "lo", "rlog", cvslog },
#ifdef AUTH_CLIENT_SUPPORT
- { "login", "logon", "lgn", login, 0 },
- { "logout", NULL, NULL, logout, 0 },
+ { "login", "logon", "lgn", login },
+ { "logout", NULL, NULL, logout },
#endif /* AUTH_CLIENT_SUPPORT */
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- { "pserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
+ { "pserver", NULL, NULL, server }, /* placeholder */
#endif
- { "rannotate","rann", "ra", annotate, 0 },
- { "rdiff", "patch", "pa", patch, 0 },
- { "release", "re", "rel", release, 0 },
- { "remove", "rm", "delete", cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "rlog", "rl", NULL, cvslog, 0 },
- { "rtag", "rt", "rfreeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY },
+ { "rdiff", "patch", "pa", patch },
+ { "release", "re", "rel", release },
+ { "remove", "rm", "delete", cvsremove },
+ { "rtag", "rt", "rfreeze", rtag },
#ifdef SERVER_SUPPORT
- { "server", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "server", NULL, NULL, server },
#endif
- { "status", "st", "stat", cvsstatus, CVS_CMD_USES_WORK_DIR },
- { "tag", "ta", "freeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "unedit", NULL, NULL, unedit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "update", "up", "upd", update, CVS_CMD_USES_WORK_DIR },
- { "version", "ve", "ver", version, 0 },
- { "watch", NULL, NULL, watch, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "watchers", NULL, NULL, watchers, CVS_CMD_USES_WORK_DIR },
- { NULL, NULL, NULL, NULL, 0 },
+ { "status", "st", "stat", cvsstatus },
+ { "tag", "ta", "freeze", cvstag },
+ { "unedit", NULL, NULL, unedit },
+ { "update", "up", "upd", update },
+ { "version", "ve", "ver", version },
+ { "watch", NULL, NULL, watch },
+ { "watchers", NULL, NULL, watchers },
+ { NULL, NULL, NULL, NULL },
};
static const char *const usg[] =
@@ -218,11 +215,9 @@ static const char *const cmd_usage[] =
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
" pserver Password server mode\n",
#endif
- " rannotate Show last revision where each line of module was modified\n",
" rdiff Create 'patch' format diffs between releases\n",
" release Indicate that a Module is no longer in use\n",
" remove Remove an entry from the repository\n",
- " rlog Print out history information for a module\n",
" rtag Add a symbolic tag to a module\n",
#ifdef SERVER_SUPPORT
" server Server mode\n",
@@ -231,7 +226,6 @@ static const char *const cmd_usage[] =
" tag Add a symbolic tag to checked out version of files\n",
" unedit Undo an edit command\n",
" update Bring work tree in sync with repository\n",
- " version Show current CVS version(s)\n",
" watch Set watches\n",
" watchers See who is watching a file\n",
"(Specify the --help option for a list of other help options)\n",
@@ -247,9 +241,11 @@ static const char *const opt_usage[] =
" -q Cause CVS to be somewhat quiet.\n",
" -r Make checked-out files read-only.\n",
" -w Make checked-out files read-write (default).\n",
+ " -g Force group-write perms on checked-out files.\n",
" -l Turn history logging off.\n",
" -n Do not execute anything that will change the disk.\n",
" -t Show trace of program execution -- try with -n.\n",
+ " -R Assume repository is read-only, such as CDROM\n",
" -v CVS version and copyright.\n",
" -T tmpdir Use 'tmpdir' for temporary files.\n",
" -e editor Use 'editor' for editing log information.\n",
@@ -325,14 +321,51 @@ unsigned long int
lookup_command_attribute (cmd_name)
char *cmd_name;
{
- const struct cmd *cm;
+ unsigned long int ret = 0;
- for (cm = cmds; cm->fullname; cm++)
+ if (strcmp (cmd_name, "import") != 0)
{
- if (strcmp (cmd_name, cm->fullname) == 0)
- break;
+ ret |= CVS_CMD_IGNORE_ADMROOT;
+ }
+
+
+ /* The following commands do not use a checked-out working
+ directory. We conservatively assume that everything else does.
+ Feel free to add to this list if you are _certain_ something
+ something doesn't use the WD. */
+ if ((strcmp (cmd_name, "checkout") != 0) &&
+ (strcmp (cmd_name, "init") != 0) &&
+ (strcmp (cmd_name, "login") != 0) &&
+ (strcmp (cmd_name, "logout") != 0) &&
+ (strcmp (cmd_name, "rdiff") != 0) &&
+ (strcmp (cmd_name, "release") != 0) &&
+ (strcmp (cmd_name, "rtag") != 0))
+ {
+ ret |= CVS_CMD_USES_WORK_DIR;
}
- return cm->attr;
+
+
+ /* The following commands do not modify the repository; we
+ conservatively assume that everything else does. Feel free to
+ add to this list if you are _certain_ something is safe. */
+ if ((strcmp (cmd_name, "annotate") != 0) &&
+ (strcmp (cmd_name, "checkout") != 0) &&
+ (strcmp (cmd_name, "diff") != 0) &&
+ (strcmp (cmd_name, "rdiff") != 0) &&
+ (strcmp (cmd_name, "update") != 0) &&
+ (strcmp (cmd_name, "editors") != 0) &&
+ (strcmp (cmd_name, "export") != 0) &&
+ (strcmp (cmd_name, "history") != 0) &&
+ (strcmp (cmd_name, "log") != 0) &&
+ (strcmp (cmd_name, "noop") != 0) &&
+ (strcmp (cmd_name, "watchers") != 0) &&
+ (strcmp (cmd_name, "release") != 0) &&
+ (strcmp (cmd_name, "status") != 0))
+ {
+ ret |= CVS_CMD_MODIFIES_REPOSITORY;
+ }
+
+ return ret;
}
@@ -405,7 +438,7 @@ main (argc, argv)
int help = 0; /* Has the user asked for help? This
lets us support the `cvs -H cmd'
convention to give help for cmd. */
- static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa";
+ static const char short_options[] = "+QqgrwtnRlvb:T:e:d:Hfz:s:xaU";
static struct option long_options[] =
{
{"help", 0, NULL, 'H'},
@@ -468,6 +501,12 @@ main (argc, argv)
}
if (getenv (CVSREAD_ENV) != NULL)
cvswrite = 0;
+ if (getenv (CVSREADONLYFS_ENV) != NULL) {
+ readonlyfs = 1;
+ logoff = 1;
+ }
+
+ prepend_default_options (getenv ("CVS_OPTIONS"), &argc, &argv);
/* Set this to 0 to force getopt initialization. getopt() sets
this to 1 internally. */
@@ -530,9 +569,20 @@ main (argc, argv)
case 'w':
cvswrite = 1;
break;
+ case 'g':
+ /*
+ * force full group write perms (used for shared checked-out
+ * source trees, see manual page)
+ */
+ umask(umask(077) & 007);
+ break;
case 't':
trace = 1;
break;
+ case 'R':
+ readonlyfs = 1;
+ logoff = 1;
+ break;
case 'n':
noexec = 1;
case 'l': /* Fall through */
@@ -543,7 +593,7 @@ main (argc, argv)
version (0, (char **) NULL);
(void) fputs ("\n", stdout);
(void) fputs ("\
-Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
+Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
Jeff Polk, and other authors\n", stdout);
(void) fputs ("\n", stdout);
(void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
@@ -574,8 +624,6 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
if (CVSroot_cmdline != NULL)
free (CVSroot_cmdline);
CVSroot_cmdline = xstrdup (optarg);
- if (free_CVSroot)
- free (CVSroot);
CVSroot = xstrdup (optarg);
free_CVSroot = 1;
cvs_update_env = 1; /* need to update environment */
@@ -618,6 +666,11 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
We will issue an error later if stream
authentication is not supported. */
break;
+ case 'U':
+#ifdef SERVER_SUPPORT
+ require_real_user = 1;
+#endif
+ break;
case '?':
default:
usage (usg);
@@ -651,6 +704,15 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
else
command_name = cm->fullname; /* Global pointer for later use */
+ /* This should probably remain a warning, rather than an error,
+ for quite a while. For one thing the version of VC distributed
+ with GNU emacs 19.34 invokes 'cvs rlog' instead of 'cvs log'. */
+ if (strcmp (argv[0], "rlog") == 0)
+ {
+ error (0, 0, "warning: the rlog command is deprecated");
+ error (0, 0, "use the synonymous log command instead");
+ }
+
if (help)
{
argc = -1; /* some functions only check for this */
@@ -742,6 +804,12 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
(void) putenv (env);
/* do not free env, as putenv has control of it */
}
+ {
+ char *env;
+ env = xmalloc (sizeof "CVS_PID=" + 32); /* XXX pid < 10^32 */
+ (void) sprintf (env, "CVS_PID=%ld", (long) getpid ());
+ (void) putenv (env);
+ }
#endif
#ifndef DONT_USE_SIGNALS
@@ -799,7 +867,8 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
specify a different repository than the one we are
importing to. */
- if (!(cm->attr & CVS_CMD_IGNORE_ADMROOT)
+ if ((lookup_command_attribute (command_name)
+ & CVS_CMD_IGNORE_ADMROOT)
/* -d overrides CVS/Root, so don't give an error if the
latter points to a nonexistent repository. */
@@ -891,29 +960,25 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
variable. Parse it to see if we're supposed to do
remote accesses or use a special access method. */
- if (current_parsed_root != NULL)
- free_cvsroot_t (current_parsed_root);
- if ((current_parsed_root = parse_cvsroot (current_root)) == NULL)
+ if (parse_cvsroot (current_root))
error (1, 0, "Bad CVSROOT.");
if (trace)
- fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",
- CLIENT_SERVER_STR, current_root);
+ error (0, 0, "notice: main loop with CVSROOT=%s",
+ current_root);
/*
* Check to see if the repository exists.
*/
-#ifdef CLIENT_SUPPORT
- if (!current_parsed_root->isremote)
-#endif /* CLIENT_SUPPORT */
+ if (!client_active)
{
char *path;
int save_errno;
- path = xmalloc (strlen (current_parsed_root->directory)
+ path = xmalloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
- + 2);
- (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
+ + 20);
+ (void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
if (!isaccessible (path, R_OK | X_OK))
{
save_errno = errno;
@@ -958,7 +1023,7 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
&& !server_active
#endif
#ifdef CLIENT_SUPPORT
- && !current_parsed_root->isremote
+ && !client_active
#endif
)
{
@@ -966,15 +1031,14 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
already printed an error. We keep going. Why? Because
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);
+ parse_config (CVSroot_directory);
+
+ /* Now is a convenient time to read CVSROOT/options */
+ parseopts(CVSroot_directory);
}
#ifdef CLIENT_SUPPORT
- /* Need to check for current_parsed_root != NULL here since
- * we could still be in server mode before the server function
- * gets called below and sets the root
- */
- if (current_parsed_root != NULL && current_parsed_root->isremote)
+ if (client_active)
{
/* Create a new list for directory names that we've
sent to the server. */
@@ -1092,55 +1156,31 @@ date_from_time_t (unixtime)
void
date_to_internet (dest, source)
char *dest;
- const char *source;
+ char *source;
{
- struct tm date;
+ int year, month, day, hour, minute, second;
- date_to_tm (&date, source);
- tm_to_internet (dest, &date);
-}
+ /* Just to reiterate, these strings are from RFC822 and do not vary
+ according to locale. */
+ static const char *const month_names[] =
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-void
-date_to_tm (dest, source)
- struct tm *dest;
- const char *source;
-{
if (sscanf (source, SDATEFORM,
- &dest->tm_year, &dest->tm_mon, &dest->tm_mday,
- &dest->tm_hour, &dest->tm_min, &dest->tm_sec)
- != 6)
+ &year, &month, &day, &hour, &minute, &second)
+ != 6)
/* Is there a better way to handle errors here? I made this
non-fatal in case we are called from the code which can't
deal with fatal errors. */
error (0, 0, "internal error: bad date %s", source);
- if (dest->tm_year > 100)
- dest->tm_year -= 1900;
-
- dest->tm_mon -= 1;
-}
-
-/* Convert a date to RFC822/1123 format. This is used in contexts like
- dates to send in the protocol; it should not vary based on locale or
- other such conventions for users. We should have another routine which
- does that kind of thing.
+ /* Always send a four digit year. */
+ if (year < 100)
+ year += 1900;
- The SOURCE date is a pointer to a struct tm. DEST should point to
- storage managed by the caller, at least MAXDATELEN characters. */
-void
-tm_to_internet (dest, source)
- char *dest;
- const struct tm *source;
-{
- /* Just to reiterate, these strings are from RFC822 and do not vary
- according to locale. */
- static const char *const month_names[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", source->tm_mday,
- source->tm_mon < 0 || source->tm_mon > 11 ? "???" : month_names[source->tm_mon],
- source->tm_year + 1900, source->tm_hour, source->tm_min, source->tm_sec);
+ sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", day,
+ month < 1 || month > 12 ? "???" : month_names[month - 1],
+ year, hour, minute, second);
}
void
@@ -1152,3 +1192,61 @@ usage (cpp)
(void) fprintf (stderr, *cpp);
error_exit ();
}
+
+void
+parseopts(root)
+ const char *root;
+{
+ char path[PATH_MAX];
+ int save_errno;
+ char buf[1024];
+ const char *p;
+ char *q;
+ FILE *fp;
+
+ if (root == NULL) {
+ printf("no CVSROOT in parseopts\n");
+ return;
+ }
+ p = strchr (root, ':');
+ if (p)
+ p++;
+ else
+ p = root;
+ if (p == NULL) {
+ printf("mangled CVSROOT in parseopts\n");
+ return;
+ }
+ (void) sprintf (path, "%s/%s/%s", p, CVSROOTADM, CVSROOTADM_OPTIONS);
+ if ((fp = fopen(path, "r")) != NULL) {
+ while (fgets(buf, sizeof buf, fp) != NULL) {
+ if (buf[0] == '#')
+ continue;
+ q = strrchr(buf, '\n');
+ if (q)
+ *q = '\0';
+
+ if (!strncmp(buf, "tag=", 4)) {
+ char *what;
+ char *rcs_localid;
+
+ rcs_localid = buf + 4;
+ RCS_setlocalid(rcs_localid);
+ }
+ if (!strncmp(buf, "tagexpand=", 10)) {
+ char *what;
+ char *rcs_incexc;
+
+ rcs_incexc = buf + 10;
+ RCS_setincexc(rcs_incexc);
+ }
+ /*
+ * OpenBSD has a "umask=" and "dlimit=" command, we silently
+ * ignore them here since they are not much use to us. cvsumask
+ * defaults to 002 already, and the dlimit (data size limit)
+ * should really be handled elsewhere (eg: login.conf).
+ */
+ }
+ fclose(fp);
+ }
+}
diff --git a/contrib/cvs/src/mkmodules.c b/contrib/cvs/src/mkmodules.c
index d1f7ac7..49cda18 100644
--- a/contrib/cvs/src/mkmodules.c
+++ b/contrib/cvs/src/mkmodules.c
@@ -3,7 +3,10 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS kit. */
+ * specified in the README file that comes with the CVS kit.
+ *
+ * $FreeBSD$
+ */
#include "cvs.h"
#include "savecwd.h"
@@ -848,7 +851,7 @@ init (argc, argv)
usage (init_usage);
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
{
start_server ();
@@ -862,10 +865,12 @@ init (argc, argv)
old cvsinit.sh script did. Few utilities do that, and a
non-existent parent directory is as likely to be a typo as something
which needs to be created. */
- mkdir_if_needed (current_parsed_root->directory);
+ mkdir_if_needed (CVSroot_directory);
- adm = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM) + 2);
- sprintf (adm, "%s/%s", current_parsed_root->directory, CVSROOTADM);
+ adm = xmalloc (strlen (CVSroot_directory) + sizeof (CVSROOTADM) + 10);
+ strcpy (adm, CVSroot_directory);
+ strcat (adm, "/");
+ strcat (adm, CVSROOTADM);
mkdir_if_needed (adm);
/* This is needed because we pass "fileptr->filename" not "info"
diff --git a/contrib/cvs/src/prepend_args.c b/contrib/cvs/src/prepend_args.c
new file mode 100644
index 0000000..12322ce
--- /dev/null
+++ b/contrib/cvs/src/prepend_args.c
@@ -0,0 +1,86 @@
+/* prepend_args.c - utilility programs for manpiulating argv[]
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ 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 2, 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "cvs.h"
+#include "prepend_args.h"
+
+
+/* Find the white-space-separated options specified by OPTIONS, and
+ using BUF to store copies of these options, set ARGV[0], ARGV[1],
+ etc. to the option copies. Return the number N of options found.
+ Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0]
+ etc. Backslash can be used to escape whitespace (and backslashes). */
+static int
+prepend_args (options, buf, argv)
+ char const *options;
+ char *buf;
+ char **argv;
+{
+ char const *o = options;
+ char *b = buf;
+ int n = 0;
+
+ for (;;)
+ {
+ while (isspace ((unsigned char) *o))
+ o++;
+ if (!*o)
+ return n;
+ if (argv)
+ argv[n] = b;
+ n++;
+
+ do
+ if ((*b++ = *o++) == '\\' && *o)
+ b[-1] = *o++;
+ while (*o && ! isspace ((unsigned char) *o));
+
+ *b++ = '\0';
+ }
+}
+
+/* Prepend the whitespace-separated options in OPTIONS to the argument
+ vector of a main program with argument count *PARGC and argument
+ vector *PARGV. */
+void
+prepend_default_options (options, pargc, pargv)
+ char const *options;
+ int *pargc;
+ char ***pargv;
+{
+ if (options)
+ {
+ char *buf = xmalloc (strlen (options) + 1);
+ int prepended = prepend_args (options, buf, (char **) NULL);
+ int argc = *pargc;
+ char * const *argv = *pargv;
+ char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
+ *pargc = prepended + argc;
+ *pargv = pp;
+ *pp++ = *argv++;
+ pp += prepend_args (options, buf, pp);
+ while ((*pp++ = *argv++))
+ continue;
+ }
+}
diff --git a/contrib/cvs/src/prepend_args.h b/contrib/cvs/src/prepend_args.h
new file mode 100644
index 0000000..6708442
--- /dev/null
+++ b/contrib/cvs/src/prepend_args.h
@@ -0,0 +1,26 @@
+/* prepend_args.h - utilility programs for manpiulating argv[]
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ 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 2, 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+/* This code, taken from GNU Grep, originally used the "PARAM" macro, as the
+ current GNU coding standards requires. Older GNU code used the "PROTO"
+ macro, before the GNU coding standards replaced it. We use the older
+ form here to keep from having to include another file in cvs/src/main.c. */
+
+void prepend_default_options PROTO ((char const *, int *, char ***));
diff --git a/contrib/cvs/src/rcs.c b/contrib/cvs/src/rcs.c
index 385eaf2..1e9edce 100644
--- a/contrib/cvs/src/rcs.c
+++ b/contrib/cvs/src/rcs.c
@@ -6,6 +6,8 @@
*
* The routines contained in this file do all the rcs file parsing and
* manipulation
+ *
+ * $FreeBSD$
*/
#include <assert.h>
@@ -92,6 +94,11 @@ static void expand_keywords PROTO((RCSNode *, RCSVers *, const char *,
size_t, char **, size_t *));
static void cmp_file_buffer PROTO((void *, const char *, size_t));
+enum rcs_delta_op {RCS_ANNOTATE, RCS_FETCH};
+static void RCS_deltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *, char *,
+ enum rcs_delta_op, char **, size_t *,
+ char **, size_t *));
+
/* Routines for reading, parsing and writing RCS files. */
static RCSVers *getdelta PROTO ((struct rcsbuffer *, char *, char **,
char **));
@@ -120,6 +127,8 @@ static char *rcs_lockfilename PROTO ((char *));
evaluates its arguments multiple times. */
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
+static char * getfullCVSname PROTO ((char *, char **));
+
/*
* We don't want to use isspace() from the C library because:
*
@@ -2121,7 +2130,7 @@ RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
* -- If tag is a branch tag, returns the branch number, not
* the revision of the head of the branch.
* If tag or revision is not valid or does not exist in file,
- * return NULL.
+ * exit with error.
*/
char *
RCS_tag2rev (rcs, tag)
@@ -2200,8 +2209,9 @@ RCS_tag2rev (rcs, tag)
if (rev)
return rev;
- /* Trust the caller to print warnings. */
- return NULL;
+ error (1, 0, "tag `%s' does not exist", tag);
+ /* NOT REACHED -- error (1 ... ) does not return here */
+ return 0;
}
/*
@@ -2383,13 +2393,25 @@ RCS_magicrev (rcs, rev)
char *rev;
{
int rev_num;
- char *xrev, *test_branch;
+ char *xrev, *test_branch, *local_branch_num;
xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */
check_rev = xrev;
+ local_branch_num = getenv("CVS_LOCAL_BRANCH_NUM");
+ if (local_branch_num)
+ {
+ rev_num = atoi(local_branch_num);
+ if (rev_num < 2)
+ rev_num = 2;
+ else
+ rev_num &= ~1;
+ }
+ else
+ rev_num = 2;
+
/* only look at even numbered branches */
- for (rev_num = 2; ; rev_num += 2)
+ for ( ; ; rev_num += 2)
{
/* see if the physical branch exists */
(void) sprintf (xrev, "%s.%d", rev, rev_num);
@@ -2878,8 +2900,10 @@ RCS_getdate (rcs, date, force_tag_match)
p = findnode (rcs->versions, "1.1.1.1");
if (p)
{
+ char *date_1_1 = vers->date;
+
vers = (RCSVers *) p->data;
- if (RCS_datecmp (vers->date, date) != 0)
+ if (RCS_datecmp (vers->date, date_1_1) != 0)
return xstrdup ("1.1");
}
}
@@ -3340,27 +3364,31 @@ struct rcs_keyword
{
const char *string;
size_t len;
+ int expandit;
};
#define KEYWORD_INIT(s) (s), sizeof (s) - 1
-static const struct rcs_keyword keywords[] =
+static struct rcs_keyword keywords[] =
{
- { KEYWORD_INIT ("Author") },
- { KEYWORD_INIT ("Date") },
- { KEYWORD_INIT ("Header") },
- { KEYWORD_INIT ("Id") },
- { KEYWORD_INIT ("Locker") },
- { KEYWORD_INIT ("Log") },
- { KEYWORD_INIT ("Name") },
- { KEYWORD_INIT ("RCSfile") },
- { KEYWORD_INIT ("Revision") },
- { KEYWORD_INIT ("Source") },
- { KEYWORD_INIT ("State") },
- { NULL, 0 }
+ { KEYWORD_INIT ("Author"), 1 },
+ { KEYWORD_INIT ("Date"), 1 },
+ { KEYWORD_INIT ("CVSHeader"), 1 },
+ { KEYWORD_INIT ("Header"), 1 },
+ { KEYWORD_INIT ("Id"), 1 },
+ { KEYWORD_INIT ("Locker"), 1 },
+ { KEYWORD_INIT ("Log"), 1 },
+ { KEYWORD_INIT ("Name"), 1 },
+ { KEYWORD_INIT ("RCSfile"), 1 },
+ { KEYWORD_INIT ("Revision"), 1 },
+ { KEYWORD_INIT ("Source"), 1 },
+ { KEYWORD_INIT ("State"), 1 },
+ { NULL, 0, 0 },
+ { NULL, 0, 0 }
};
enum keyword
{
KEYWORD_AUTHOR = 0,
KEYWORD_DATE,
+ KEYWORD_CVSHEADER,
KEYWORD_HEADER,
KEYWORD_ID,
KEYWORD_LOCKER,
@@ -3369,8 +3397,10 @@ enum keyword
KEYWORD_RCSFILE,
KEYWORD_REVISION,
KEYWORD_SOURCE,
- KEYWORD_STATE
+ KEYWORD_STATE,
+ KEYWORD_LOCALID
};
+enum keyword keyword_local = KEYWORD_ID;
/* Convert an RCS date string into a readable string. This is like
the RCS date2str function. */
@@ -3548,7 +3578,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
slen = s - srch;
for (keyword = keywords; keyword->string != NULL; keyword++)
{
- if (keyword->len == slen
+ if (keyword->expandit
+ && keyword->len == slen
&& strncmp (keyword->string, srch, slen) == 0)
{
break;
@@ -3595,15 +3626,25 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
free_value = 1;
break;
+ case KEYWORD_CVSHEADER:
case KEYWORD_HEADER:
case KEYWORD_ID:
+ case KEYWORD_LOCALID:
{
char *path;
int free_path;
char *date;
+ char *old_path;
- if (kw == KEYWORD_HEADER)
+ old_path = NULL;
+ if (kw == KEYWORD_HEADER ||
+ (kw == KEYWORD_LOCALID &&
+ keyword_local == KEYWORD_HEADER))
path = rcs->path;
+ else if (kw == KEYWORD_CVSHEADER ||
+ (kw == KEYWORD_LOCALID &&
+ keyword_local == KEYWORD_CVSHEADER))
+ path = getfullCVSname(rcs->path, &old_path);
else
path = last_component (rcs->path);
path = escape_keyword_value (path, &free_path);
@@ -3623,6 +3664,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
locker != NULL ? locker : "");
if (free_path)
free (path);
+ if (old_path)
+ free (old_path);
free (date);
free_value = 1;
}
@@ -4141,7 +4184,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
whether it should be considered an error for `dest' to exist
at this point. If so, the unlink call should be removed and
`symlink' should signal the error. -twp) */
- if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
+ if (unlink (dest) < 0 && !existence_error (errno))
error (1, errno, "cannot remove %s", dest);
if (symlink (info->data, dest) < 0)
error (1, errno, "cannot create symbolic link from %s to %s",
@@ -4311,7 +4354,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
/* Unlink `dest', just in case. It's okay if this provokes a
ENOENT error. */
- if (CVS_UNLINK (dest) < 0 && existence_error (errno))
+ if (unlink (dest) < 0 && existence_error (errno))
error (1, errno, "cannot remove %s", dest);
if (mknod (dest, special_file, devnum) < 0)
error (1, errno, "could not create special file %s",
@@ -5254,7 +5297,7 @@ workfile);
memset (commitpt->text, 0, sizeof (Deltatext));
bufsize = 0;
- switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile))
+ switch (diff_exec (workfile, tmpfile, diffopts, changefile))
{
case 0:
case 1:
@@ -5302,7 +5345,7 @@ workfile);
/* This file is not being inserted at the head, but on a side
branch somewhere. Make a diff from the previous revision
to the working file. */
- switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile))
+ switch (diff_exec (tmpfile, workfile, diffopts, changefile))
{
case 0:
case 1:
@@ -5682,7 +5725,7 @@ RCS_setbranch (rcs, rev)
int
RCS_lock (rcs, rev, lock_quiet)
RCSNode *rcs;
- char *rev;
+ const char *rev;
int lock_quiet;
{
List *locks;
@@ -5701,16 +5744,32 @@ RCS_lock (rcs, rev, lock_quiet)
/* A revision number of NULL means lock the head or default branch. */
if (rev == NULL)
xrev = RCS_head (rcs);
- else
- xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
+
+ /* If rev is a branch number, lock the latest revision on that
+ branch. I think that if the branch doesn't exist, it's
+ okay to return 0 -- that just means that the branch is new,
+ so we don't need to lock it anyway. -twp */
+ else if (RCS_nodeisbranch (rcs, rev))
+ {
+ xrev = RCS_getbranch (rcs, (char *) rev, 1);
+ if (xrev == NULL)
+ {
+ if (!lock_quiet)
+ error (0, 0, "%s: branch %s absent", rcs->path, rev);
+ return 1;
+ }
+ }
+
+ if (xrev == NULL)
+ xrev = xstrdup (rev);
/* Make sure that the desired revision exists. Technically,
we can update the locks list without even checking this,
but RCS 5.7 did this. And it can't hurt. */
- if (xrev == NULL || findnode (rcs->versions, xrev) == NULL)
+ if (findnode (rcs->versions, xrev) == NULL)
{
if (!lock_quiet)
- error (0, 0, "%s: revision %s absent", rcs->path, rev);
+ error (0, 0, "%s: revision %s absent", rcs->path, xrev);
free (xrev);
return 1;
}
@@ -5776,7 +5835,7 @@ RCS_lock (rcs, rev, lock_quiet)
int
RCS_unlock (rcs, rev, unlock_quiet)
RCSNode *rcs;
- char *rev;
+ const char *rev;
int unlock_quiet;
{
Node *lock;
@@ -5826,15 +5885,20 @@ RCS_unlock (rcs, rev, unlock_quiet)
return 0; /* no lock found, ergo nothing to do */
xrev = xstrdup (lock->key);
}
- else
+ else if (RCS_nodeisbranch (rcs, rev))
{
- xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
+ /* If rev is a branch number, unlock the latest revision on that
+ branch. */
+ xrev = RCS_getbranch (rcs, (char *) rev, 1);
if (xrev == NULL)
{
- error (0, 0, "%s: revision %s absent", rcs->path, rev);
+ error (0, 0, "%s: branch %s absent", rcs->path, rev);
return 1;
}
}
+ else
+ /* REV is an exact revision number. */
+ xrev = xstrdup (rev);
lock = findnode (RCS_getlocks (rcs), xrev);
if (lock == NULL)
@@ -6356,7 +6420,7 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
goto delrev_done;
outfile = cvs_temp_name();
- status = diff_exec (beforefile, afterfile, NULL, NULL, "-an", outfile);
+ status = diff_exec (beforefile, afterfile, "-an", outfile);
if (status == 2)
{
@@ -6995,7 +7059,7 @@ rcs_change_text (name, textbuf, textlen, diffbuf, difflen, retbuf, retlen)
On error, give a fatal error. */
-void
+static void
RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
RCSNode *rcs;
FILE *fp;
@@ -8354,6 +8418,138 @@ RCS_abandon (rcs)
rcs->flags |= PARTIAL;
}
+
+/* Annotate command. In rcs.c for historical reasons (from back when
+ what is now RCS_deltas was part of annotate_fileproc). */
+
+/* Options from the command line. */
+
+static int force_tag_match = 1;
+static char *tag = NULL;
+static char *date = NULL;
+
+static int annotate_fileproc PROTO ((void *callerdat, struct file_info *));
+
+static int
+annotate_fileproc (callerdat, finfo)
+ void *callerdat;
+ struct file_info *finfo;
+{
+ FILE *fp = NULL;
+ struct rcsbuffer *rcsbufp = NULL;
+ struct rcsbuffer rcsbuf;
+ char *version;
+
+ if (finfo->rcs == NULL)
+ return (1);
+
+ if (finfo->rcs->flags & PARTIAL)
+ {
+ RCS_reparsercsfile (finfo->rcs, &fp, &rcsbuf);
+ rcsbufp = &rcsbuf;
+ }
+
+ version = RCS_getversion (finfo->rcs, tag, date, force_tag_match,
+ (int *) NULL);
+ if (version == NULL)
+ return 0;
+
+ /* Distinguish output for various files if we are processing
+ several files. */
+ cvs_outerr ("Annotations for ", 0);
+ cvs_outerr (finfo->fullname, 0);
+ cvs_outerr ("\n***************\n", 0);
+
+ RCS_deltas (finfo->rcs, fp, rcsbufp, version, RCS_ANNOTATE, NULL,
+ NULL, NULL, NULL);
+ free (version);
+ return 0;
+}
+
+static const char *const annotate_usage[] =
+{
+ "Usage: %s %s [-lRf] [-r rev|-D date] [files...]\n",
+ "\t-l\tLocal directory only, no recursion.\n",
+ "\t-R\tProcess directories recursively.\n",
+ "\t-f\tUse head revision if tag/date not found.\n",
+ "\t-r rev\tAnnotate file as of specified revision/tag.\n",
+ "\t-D date\tAnnotate file as of specified date.\n",
+ "(Specify the --help global option for a list of other help options)\n",
+ NULL
+};
+
+/* Command to show the revision, date, and author where each line of a
+ file was modified. */
+
+int
+annotate (argc, argv)
+ int argc;
+ char **argv;
+{
+ int local = 0;
+ int c;
+
+ if (argc == -1)
+ usage (annotate_usage);
+
+ optind = 0;
+ while ((c = getopt (argc, argv, "+lr:D:fR")) != -1)
+ {
+ switch (c)
+ {
+ case 'l':
+ local = 1;
+ break;
+ case 'R':
+ local = 0;
+ break;
+ case 'r':
+ tag = optarg;
+ break;
+ case 'D':
+ date = Make_Date (optarg);
+ break;
+ case 'f':
+ force_tag_match = 0;
+ break;
+ case '?':
+ default:
+ usage (annotate_usage);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ start_server ();
+ ign_setup ();
+
+ if (local)
+ send_arg ("-l");
+ if (!force_tag_match)
+ send_arg ("-f");
+ option_with_arg ("-r", tag);
+ if (date)
+ client_senddate (date);
+ send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
+ send_to_server ("annotate\012", 0);
+ return get_responses_and_close ();
+ }
+#endif /* CLIENT_SUPPORT */
+
+ if (tag != NULL)
+ tag_check_valid (tag, argc, argv, local, 0, "");
+
+ return start_recursion (annotate_fileproc, (FILESDONEPROC) NULL,
+ (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
+ argc, argv, local, W_LOCAL, 0, 1, (char *)NULL,
+ 1);
+}
+
/*
* For a given file with full pathname PATH and revision number REV,
* produce a file label suitable for passing to diff. The default
@@ -8363,11 +8559,6 @@ RCS_abandon (rcs)
*
* The date and time used are the revision's last checkin date and time.
* If REV is NULL, use the working copy's mtime instead.
- *
- * /dev/null is not statted but assumed to have been created on the Epoch.
- * At least using the POSIX.2 definition of patch, this should cause creation
- * of files on platforms such as Windoze where the null IO device isn't named
- * /dev/null to be parsed by patch properly.
*/
char *
make_file_label (path, rev, rcs)
@@ -8375,47 +8566,141 @@ make_file_label (path, rev, rcs)
char *rev;
RCSNode *rcs;
{
- char datebuf[MAXDATELEN + 1];
+ char datebuf[MAXDATELEN];
char *label;
+ char *file;
+ file = last_component (path);
label = (char *) xmalloc (strlen (path)
- + (rev == NULL ? 0 : strlen (rev) + 1)
- + MAXDATELEN
- + 2);
+ + (rev == NULL ? 0 : strlen (rev))
+ + 50);
if (rev)
{
- char date[MAXDATELEN + 1];
- /* revs cannot be attached to /dev/null ... duh. */
- assert (strcmp(DEVNULL, path));
+ char *date;
RCS_getrevtime (rcs, rev, datebuf, 0);
- (void) date_to_internet (date, datebuf);
+ date = printable_date (datebuf);
(void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
+ free (date);
}
else
{
struct stat sb;
- struct tm *wm = NULL;
+ struct tm *wm;
- if (strcmp(DEVNULL, path))
+ if (CVS_STAT (file, &sb) < 0)
+ error (0, 1, "could not get info for `%s'", path);
+ else
{
- char *file = last_component (path);
- if (CVS_STAT (file, &sb) < 0)
- error (0, 1, "could not get info for `%s'", path);
- else
- wm = gmtime (&sb.st_mtime);
+ wm = gmtime (&sb.st_mtime);
+ (void) sprintf (datebuf, "%04d/%02d/%02d %02d:%02d:%02d",
+ wm->tm_year + 1900, wm->tm_mon + 1,
+ wm->tm_mday, wm->tm_hour,
+ wm->tm_min, wm->tm_sec);
+ (void) sprintf (label, "-L%s\t%s", path, datebuf);
}
+ }
+ return label;
+}
+
+void
+RCS_setlocalid (arg)
+ const char *arg;
+{
+ char *copy, *next, *key;
+
+ copy = xstrdup(arg);
+ next = copy;
+ key = strtok(next, "=");
+
+ keywords[KEYWORD_LOCALID].string = xstrdup(key);
+ keywords[KEYWORD_LOCALID].len = strlen(key);
+ keywords[KEYWORD_LOCALID].expandit = 1;
+
+ /* options? */
+ while (key = strtok(NULL, ",")) {
+ if (!strcmp(key, keywords[KEYWORD_ID].string))
+ keyword_local = KEYWORD_ID;
+ else if (!strcmp(key, keywords[KEYWORD_HEADER].string))
+ keyword_local = KEYWORD_HEADER;
+ else if (!strcmp(key, keywords[KEYWORD_CVSHEADER].string))
+ keyword_local = KEYWORD_CVSHEADER;
else
+ error(1, 0, "Unknown LocalId mode: %s", key);
+ }
+ free(copy);
+}
+
+void
+RCS_setincexc (arg)
+ const char *arg;
+{
+ char *key;
+ char *copy, *next;
+ int include = 0;
+ struct rcs_keyword *keyword;
+
+ copy = xstrdup(arg);
+ next = copy;
+ switch (*next++) {
+ case 'e':
+ include = 0;
+ break;
+ case 'i':
+ include = 1;
+ break;
+ default:
+ free(copy);
+ return;
+ }
+
+ if (include)
+ for (keyword = keywords; keyword->string != NULL; keyword++)
{
- time_t t = 0;
- wm = gmtime(&t);
+ keyword->expandit = 0;
}
- if (wm)
- {
- (void) tm_to_internet (datebuf, wm);
- (void) sprintf (label, "-L%s\t%s", path, datebuf);
+ key = strtok(next, ",");
+ while (key) {
+ for (keyword = keywords; keyword->string != NULL; keyword++) {
+ if (strcmp (keyword->string, key) == 0)
+ keyword->expandit = include;
}
+ key = strtok(NULL, ",");
}
- return label;
+ free(copy);
+ return;
+}
+
+#define ATTIC "/" CVSATTIC
+static char *
+getfullCVSname(CVSname, pathstore)
+ char *CVSname, **pathstore;
+{
+ if (CVSroot_directory) {
+ int rootlen;
+ char *c = NULL;
+ int alen = sizeof(ATTIC) - 1;
+
+ *pathstore = xstrdup(CVSname);
+ if ((c = strrchr(*pathstore, '/')) != NULL) {
+ if (c - *pathstore >= alen) {
+ if (!strncmp(c - alen, ATTIC, alen)) {
+ while (*c != '\0') {
+ *(c - alen) = *c;
+ c++;
+ }
+ *(c - alen) = '\0';
+ }
+ }
+ }
+
+ rootlen = strlen(CVSroot_directory);
+ if (!strncmp(*pathstore, CVSroot_directory, rootlen) &&
+ (*pathstore)[rootlen] == '/')
+ CVSname = (*pathstore + rootlen + 1);
+ else
+ CVSname = (*pathstore);
+ }
+ return CVSname;
}
diff --git a/contrib/cvs/src/rcs.h b/contrib/cvs/src/rcs.h
index 55eed95..397488e 100644
--- a/contrib/cvs/src/rcs.h
+++ b/contrib/cvs/src/rcs.h
@@ -6,6 +6,8 @@
* specified in the README file that comes with the CVS source distribution.
*
* RCS source control definitions needed by rcs.c and friends
+ *
+ * $FreeBSD$
*/
/* Strings which indicate a conflict if they occur at the start of a line. */
@@ -179,9 +181,6 @@ typedef void (*RCSCHECKOUTPROC) PROTO ((void *, const char *, size_t));
struct rcsbuffer;
#endif
-/* What RCS_deltas is supposed to do. */
-enum rcs_delta_op {RCS_ANNOTATE, RCS_FETCH};
-
/*
* exported interfaces
*/
@@ -226,8 +225,8 @@ int RCS_cmp_file PROTO ((RCSNode *, char *, char *, const char *));
int RCS_settag PROTO ((RCSNode *, const char *, const char *));
int RCS_deltag PROTO ((RCSNode *, const char *));
int RCS_setbranch PROTO((RCSNode *, const char *));
-int RCS_lock PROTO ((RCSNode *, char *, int));
-int RCS_unlock PROTO ((RCSNode *, char *, int));
+int RCS_lock PROTO ((RCSNode *, const char *, int));
+int RCS_unlock PROTO ((RCSNode *, const char *, int));
int RCS_delete_revs PROTO ((RCSNode *, char *, char *, int));
void RCS_addaccess PROTO ((RCSNode *, char *));
void RCS_delaccess PROTO ((RCSNode *, char *));
@@ -237,9 +236,9 @@ void RCS_rewrite PROTO ((RCSNode *, Deltatext *, char *));
void RCS_abandon PROTO ((RCSNode *));
int rcs_change_text PROTO ((const char *, char *, size_t, const char *,
size_t, char **, size_t *));
-void RCS_deltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *, char *,
- enum rcs_delta_op, char **, size_t *,
- char **, size_t *));
+void RCS_setincexc PROTO ((const char *arg));
+
+void RCS_setlocalid PROTO ((const char *arg));
char *make_file_label PROTO ((char *, char *, RCSNode *));
extern int preserve_perms;
diff --git a/contrib/cvs/src/rcscmds.c b/contrib/cvs/src/rcscmds.c
index 43be168..bcdffd5 100644
--- a/contrib/cvs/src/rcscmds.c
+++ b/contrib/cvs/src/rcscmds.c
@@ -7,6 +7,8 @@
*
* The functions in this file provide an interface for performing
* operations directly on RCS files.
+ *
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -530,11 +532,9 @@ RCS file: ", 0);
message on stderr. */
int
-diff_exec (file1, file2, label1, label2, options, out)
+diff_exec (file1, file2, options, out)
char *file1;
char *file2;
- char *label1;
- char *label2;
char *options;
char *out;
{
@@ -577,10 +577,6 @@ diff_exec (file1, file2, label1, label2, options, out)
/* The first word in this string is used only for error reporting. */
sprintf (args, "diff %s", options);
call_diff_setup (args);
- if (label1)
- call_diff_arg (label1);
- if (label2)
- call_diff_arg (label2);
call_diff_arg (file1);
call_diff_arg (file2);
free (args);
diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c
index 2235193..09e1cad 100644
--- a/contrib/cvs/src/recurse.c
+++ b/contrib/cvs/src/recurse.c
@@ -6,6 +6,7 @@
*
* General recursion handler
*
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -157,10 +158,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
#ifdef CLIENT_SUPPORT
if (!just_subdirs
&& CVSroot_cmdline == NULL
- && current_parsed_root->isremote)
+ && client_active)
{
char *root = Name_Root (NULL, update_dir);
- if (root && strcmp (root, current_parsed_root->original) != 0)
+ if (root && strcmp (root, current_root) != 0)
/* We're skipping this directory because it is for
a different root. Therefore, we just want to
do the subdirectories only. Processing files would
@@ -204,7 +205,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
program_name);
}
#ifdef CLIENT_SUPPORT
- else if (current_parsed_root->isremote && server_started)
+ else if (client_active && server_started)
{
/* In the the case "cvs update foo bar baz", a call to
send_file_names in update.c will have sent the
@@ -290,7 +291,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
{
if ((which & W_LOCAL) && isdir (CVSADM)
#ifdef CLIENT_SUPPORT
- && !current_parsed_root->isremote
+ && !client_active
#endif
)
{
@@ -363,8 +364,8 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
/* FIXME (njc): in the multiroot case, we don't want to send
argument commands for those top-level directories which do
not contain any subdirectories which have files checked out
- from current_parsed_root->original. If we do, and two repositories
- have a module with the same name, nasty things could happen.
+ from current_root. If we do, and two repositories have a
+ module with the same name, nasty things could happen.
This is hard. Perhaps we should send the Argument commands
later in this procedure, after we've had a chance to notice
@@ -440,7 +441,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
"Directory xxx" command, which forces the server to descend
and serve the files there. client.c (send_file_names) has
also been modified to send only those arguments which are
- appropriate to current_parsed_root->original.
+ appropriate to current_root.
*/
@@ -599,9 +600,8 @@ do_recursion (frame)
}
- process_this_directory =
- (strcmp (current_parsed_root->original, this_root) == 0);
-
+ process_this_directory = (strcmp (current_root, this_root) == 0);
+
free (this_root);
}
}
@@ -711,7 +711,7 @@ do_recursion (frame)
place (server_notify). For local, we can't do them here--we don't
have writelocks in place, and there is no way to get writelocks
here. */
- if (current_parsed_root->isremote)
+ if (client_active)
notify_check (repository, update_dir);
#endif /* CLIENT_SUPPORT */
@@ -1025,8 +1025,7 @@ but CVS uses %s for its own purposes; skipping %s directory",
}
- process_this_directory = (strcmp (current_parsed_root->original, this_root) == 0);
-
+ process_this_directory = (strcmp (current_root, this_root) == 0);
free (this_root);
}
}
diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c
index bb38f4d..a53dc79 100644
--- a/contrib/cvs/src/server.c
+++ b/contrib/cvs/src/server.c
@@ -8,6 +8,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. */
+/*
+ * $FreeBSD$
+ */
+
#include <assert.h>
#include "cvs.h"
#include "watch.h"
@@ -16,19 +20,50 @@
#include "getline.h"
#include "buffer.h"
-#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
-# ifdef HAVE_GSSAPI
-/* This stuff isn't included solely with SERVER_SUPPORT since some of these
- * functions (encryption & the like) get compiled with or without server
- * support.
- *
- * FIXME - They should be in a different file.
- */
-# include <netdb.h>
-# include "xgssapi.h"
+#ifdef SERVER_SUPPORT
+
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_KERBEROS
+# include <netinet/in.h>
+# include <krb.h>
+# ifndef HAVE_KRB_GET_ERR_TEXT
+# define krb_get_err_text(status) krb_err_txt[status]
+# endif
+
+/* Information we need if we are going to use Kerberos encryption. */
+static C_Block kblock;
+static Key_schedule sched;
+
+#endif
+
+#ifdef HAVE_GSSAPI
+
+#include <netdb.h>
+
+#ifdef HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+
+#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif
+
/* We use Kerberos 5 routines to map the GSSAPI credential to a user
name. */
-# include <krb5.h>
+#include <krb5.h>
/* We need this to wrap data. */
static gss_ctx_id_t gcontext;
@@ -38,45 +73,36 @@ static void gserver_authenticate_connection PROTO((void));
/* Whether we are already wrapping GSSAPI communication. */
static int cvs_gssapi_wrapping;
-# ifdef ENCRYPTION
+# ifdef ENCRYPTION
/* Whether to encrypt GSSAPI communication. We use a global variable
like this because we use the same buffer type (gssapi_wrap) to
handle both authentication and encryption, and we don't want
multiple instances of that buffer in the communication stream. */
int cvs_gssapi_encrypt;
-# endif
-# endif /* HAVE_GSSAPI */
-#endif /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */
-
-#ifdef SERVER_SUPPORT
-
-#ifdef HAVE_WINSOCK_H
-#include <winsock.h>
-#endif
+# endif
-#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
-#include <sys/socket.h>
#endif
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
+/* for select */
+#include <sys/types.h>
+#ifdef HAVE_SYS_BSDTYPES_H
+#include <sys/bsdtypes.h>
#endif
-#ifdef HAVE_KERBEROS
-# include <netinet/in.h>
-# include <krb.h>
-# ifndef HAVE_KRB_GET_ERR_TEXT
-# define krb_get_err_text(status) krb_err_txt[status]
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
# endif
-
-/* Information we need if we are going to use Kerberos encryption. */
-static C_Block kblock;
-static Key_schedule sched;
-
#endif
-/* for select */
-#include "xselect.h"
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
#ifndef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
@@ -90,16 +116,18 @@ static Key_schedule sched;
#define blocking_error(err) ((err) == EAGAIN)
#endif
+#ifdef AUTH_SERVER_SUPPORT
+#ifdef HAVE_GETSPNAM
+#include <shadow.h>
+#endif
+#endif /* AUTH_SERVER_SUPPORT */
+
/* For initgroups(). */
#if HAVE_INITGROUPS
#include <grp.h>
#endif /* HAVE_INITGROUPS */
-
-# ifdef AUTH_SERVER_SUPPORT
-
-# ifdef HAVE_GETSPNAM
-# include <shadow.h>
-# endif
+
+#ifdef AUTH_SERVER_SUPPORT
/* The cvs username sent by the client, which might or might not be
the same as the system username the server eventually switches to
@@ -115,7 +143,7 @@ static char *Pserver_Repos = NULL;
CVSROOT/config. */
int system_auth = 1;
-# endif /* AUTH_SERVER_SUPPORT */
+#endif /* AUTH_SERVER_SUPPORT */
/* While processing requests, this buffer accumulates data to be sent to
@@ -396,10 +424,10 @@ create_adm_p (base_dir, dir)
differently. */
char *empty;
- empty = malloc (strlen (current_parsed_root->directory)
+ empty = malloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
+ sizeof (CVSNULLREPOS)
- + 3);
+ + 10);
if (! empty)
{
retval = ENOMEM;
@@ -407,7 +435,7 @@ create_adm_p (base_dir, dir)
}
/* Create the directory name. */
- (void) sprintf (empty, "%s/%s/%s", current_parsed_root->directory,
+ (void) sprintf (empty, "%s/%s/%s", CVSroot_directory,
CVSROOTADM, CVSNULLREPOS);
/* Create the directory if it doesn't exist. */
@@ -573,16 +601,10 @@ print_error (status)
int status;
{
char *msg;
- char tmpstr[80];
-
buf_output0 (buf_to_net, "error ");
msg = strerror (status);
- if (msg == NULL)
- {
- sprintf (tmpstr, "unknown error %d", status);
- msg = tmpstr;
- }
- buf_output0 (buf_to_net, msg);
+ if (msg)
+ buf_output0 (buf_to_net, msg);
buf_append_char (buf_to_net, '\n');
buf_flush (buf_to_net, 0);
@@ -749,7 +771,7 @@ serve_root (arg)
new connection. Doing this would cause interoperability
headaches, so it should be a different request, if there is
any reason why such a feature is needed. */
- if (current_parsed_root != NULL)
+ if (CVSroot_directory != NULL)
{
if (alloc_pending (80 + strlen (arg)))
sprintf (pending_error_text,
@@ -772,24 +794,24 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"",
}
}
#endif
-
- if (current_parsed_root != NULL)
- free_cvsroot_t (current_parsed_root);
- current_parsed_root = local_cvsroot (arg);
+ set_local_cvsroot (arg);
/* For pserver, this will already have happened, and the call will do
nothing. But for rsh, we need to do it now. */
- parse_config (current_parsed_root->directory);
+ parse_config (CVSroot_directory);
- path = malloc (strlen (current_parsed_root->directory)
+ /* Now is a good time to read CVSROOT/options too. */
+ parseopts(CVSroot_directory);
+
+ path = malloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
- + 2);
+ + 10);
if (path == NULL)
{
pending_error = ENOMEM;
return;
}
- (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
+ (void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
if (!isaccessible (path, R_OK | X_OK))
{
int save_errno = errno;
@@ -800,13 +822,13 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"",
free (path);
#ifdef HAVE_PUTENV
- env = malloc (strlen (CVSROOT_ENV) + strlen (current_parsed_root->directory) + 2);
+ env = malloc (strlen (CVSROOT_ENV) + strlen (CVSroot_directory) + 1 + 1);
if (env == NULL)
{
pending_error = ENOMEM;
return;
}
- (void) sprintf (env, "%s=%s", CVSROOT_ENV, current_parsed_root->directory);
+ (void) sprintf (env, "%s=%s", CVSROOT_ENV, CVSroot_directory);
(void) putenv (env);
/* do not free env, as putenv has control of it */
#endif
@@ -849,14 +871,14 @@ server_pathname_check (path)
static int outside_root PROTO ((char *));
/* Is file or directory REPOS an absolute pathname within the
- current_parsed_root->directory? If yes, return 0. If no, set pending_error
+ CVSroot_directory? If yes, return 0. If no, set pending_error
and return 1. */
static int
outside_root (repos)
char *repos;
{
size_t repos_len = strlen (repos);
- size_t root_len = strlen (current_parsed_root->directory);
+ size_t root_len = strlen (CVSroot_directory);
/* I think isabsolute (repos) should always be true, and that
any RELATIVE_REPOS stuff should only be in CVS/Repository
@@ -871,15 +893,15 @@ E protocol error: %s is not absolute", repos);
}
if (repos_len < root_len
- || strncmp (current_parsed_root->directory, repos, root_len) != 0)
+ || strncmp (CVSroot_directory, repos, root_len) != 0)
{
not_within:
- if (alloc_pending (strlen (current_parsed_root->directory)
+ if (alloc_pending (strlen (CVSroot_directory)
+ strlen (repos)
+ 80))
sprintf (pending_error_text, "\
E protocol error: directory '%s' not within root '%s'",
- repos, current_parsed_root->directory);
+ repos, CVSroot_directory);
return 1;
}
if (repos_len > root_len)
@@ -1082,9 +1104,8 @@ dirswitch (dir, repos)
(e.g., an entry like ``world -a .'') by putting /. at the end
of the Repository file, so we do the same. */
if (strcmp (dir, ".") == 0
- && current_parsed_root != NULL
- && current_parsed_root->directory != NULL
- && strcmp (current_parsed_root->directory, repos) == 0)
+ && CVSroot_directory != NULL
+ && strcmp (CVSroot_directory, repos) == 0)
{
if (fprintf (f, "/.") < 0)
{
@@ -2414,9 +2435,6 @@ error ENOMEM Virtual memory exhausted.\n";
/* If this gives an error, not much we could do. syslog() it? */
write (STDOUT_FILENO, msg, sizeof (msg) - 1);
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted");
-#endif
error_exit ();
}
@@ -2474,13 +2492,13 @@ check_command_legal_p (cmd_name)
int found_it = 0;
/* else */
- flen = strlen (current_parsed_root->directory)
+ flen = strlen (CVSroot_directory)
+ strlen (CVSROOTADM)
+ strlen (CVSROOTADM_READERS)
+ 3;
fname = xmalloc (flen);
- (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
+ (void) sprintf (fname, "%s/%s/%s", CVSroot_directory,
CVSROOTADM, CVSROOTADM_READERS);
fp = fopen (fname, "r");
@@ -2526,13 +2544,13 @@ check_command_legal_p (cmd_name)
/* Now check the writers file. */
- flen = strlen (current_parsed_root->directory)
+ flen = strlen (CVSroot_directory)
+ strlen (CVSROOTADM)
+ strlen (CVSROOTADM_WRITERS)
+ 3;
fname = xmalloc (flen);
- (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
+ (void) sprintf (fname, "%s/%s/%s", CVSroot_directory,
CVSROOTADM, CVSROOTADM_WRITERS);
fp = fopen (fname, "r");
@@ -2774,9 +2792,7 @@ error \n");
close (stderr_pipe[0]);
close (stderr_pipe[1]);
close (protocol_pipe[0]);
- close_on_exec (protocol_pipe[1]);
#ifdef SERVER_FLOWCONTROL
- close_on_exec (flowcontrol_pipe[0]);
close (flowcontrol_pipe[1]);
#endif /* SERVER_FLOWCONTROL */
@@ -2793,11 +2809,11 @@ error \n");
exitstatus = (*command) (argument_count, argument_vector);
/* Output any partial lines. If the client doesn't support
- "MT", we go ahead and just tack on a newline since the
- protocol doesn't support anything better. */
- if (! buf_empty_p (saved_output))
+ "MT", we just throw out the partial line, like old versions
+ of CVS did, since the protocol can't support this. */
+ if (supported_response ("MT") && ! buf_empty_p (saved_output))
{
- buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M ");
+ buf_output0 (protocol, "MT text ");
buf_append_buffer (protocol, saved_output);
buf_output (protocol, "\n", 1);
buf_send_counted (protocol);
@@ -2820,7 +2836,7 @@ error \n");
struct buffer *protocol_inbuf;
/* Number of file descriptors to check in select (). */
int num_to_check;
- int count_needed = 1;
+ int count_needed = 0;
#ifdef SERVER_FLOWCONTROL
int have_flowcontrolled = 0;
#endif /* SERVER_FLOWCONTROL */
@@ -2908,16 +2924,13 @@ error \n");
while (stdout_pipe[0] >= 0
|| stderr_pipe[0] >= 0
- || protocol_pipe[0] >= 0
- || count_needed <= 0)
+ || protocol_pipe[0] >= 0)
{
fd_set readfds;
fd_set writefds;
int numfds;
#ifdef SERVER_FLOWCONTROL
int bufmemsize;
- struct timeval *timeout_ptr;
- struct timeval timeout;
/*
* See if we are swamping the remote client and filling our VM.
@@ -2938,24 +2951,8 @@ error \n");
FD_ZERO (&readfds);
FD_ZERO (&writefds);
-
- if (count_needed <= 0)
- {
- /* there is data pending which was read from the protocol pipe
- * so don't block if we don't find any data
- */
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- timeout_ptr = &timeout;
- }
- else
- {
- /* block indefinately */
- timeout_ptr = NULL;
- }
-
if (! buf_empty_p (buf_to_net))
- FD_SET (STDOUT_FILENO, &writefds);
+ FD_SET (STDOUT_FILENO, &writefds);
if (stdout_pipe[0] >= 0)
{
@@ -2971,34 +2968,28 @@ error \n");
}
/* This process of selecting on the three pipes means that
- we might not get output in the same order in which it
- was written, thus producing the well-known
- "out-of-order" bug. If the child process uses
- cvs_output and cvs_outerr, it will send everything on
- the protocol_pipe and avoid this problem, so the
- solution is to use cvs_output and cvs_outerr in the
- child process. */
+ we might not get output in the same order in which it
+ was written, thus producing the well-known
+ "out-of-order" bug. If the child process uses
+ cvs_output and cvs_outerr, it will send everything on
+ the protocol_pipe and avoid this problem, so the
+ solution is to use cvs_output and cvs_outerr in the
+ child process. */
do {
/* This used to select on exceptions too, but as far
as I know there was never any reason to do that and
SCO doesn't let you select on exceptions on pipes. */
numfds = select (num_to_check, &readfds, &writefds,
- (fd_set *)0, timeout_ptr);
+ (fd_set *)0, (struct timeval *)NULL);
if (numfds < 0
- && errno != EINTR)
+ && errno != EINTR)
{
buf_output0 (buf_to_net, "E select failed\n");
print_error (errno);
goto error_exit;
}
} while (numfds < 0);
-
- if (numfds == 0)
- {
- FD_ZERO (&readfds);
- FD_ZERO (&writefds);
- }
-
+
if (FD_ISSET (STDOUT_FILENO, &writefds))
{
/* What should we do with errors? syslog() them? */
@@ -3010,6 +3001,7 @@ error \n");
{
int status;
int count_read;
+ int special;
status = buf_input_data (protocol_inbuf, &count_read);
@@ -3032,49 +3024,29 @@ error \n");
* have.
*/
count_needed -= count_read;
- }
- /* this is still part of the protocol pipe procedure, but it is
- * outside the above conditional so that unprocessed data can be
- * left in the buffer and stderr/stdout can be read when a flush
- * signal is received and control can return here without passing
- * through the select code and maybe blocking
- */
- while (count_needed <= 0)
- {
- int special = 0;
-
- count_needed = buf_copy_counted (buf_to_net,
+ while (count_needed <= 0)
+ {
+ count_needed = buf_copy_counted (buf_to_net,
protocol_inbuf,
&special);
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
+ /* What should we do with errors? syslog() them? */
+ buf_send_output (buf_to_net);
- /* If SPECIAL got set to <0, it means that the child
- * wants us to flush the pipe & maybe stderr or stdout.
- *
- * After that we break to read stderr & stdout again before
- * going back to the protocol pipe
- *
- * Upon breaking, count_needed = 0, so the next pass will only
- * perform a non-blocking select before returning here to finish
- * processing data we already read from the protocol buffer
- */
- if (special == -1)
- {
- cvs_flushout();
- break;
- }
- if (special == -2)
- {
- /* If the client supports the 'F' command, we send it. */
- if (supported_response ("F"))
+ /* If SPECIAL got set to -1, it means that the child
+ wants us to flush the pipe. We don't want to block
+ on the network, but we flush what we can. If the
+ client supports the 'F' command, we send it. */
+ if (special == -1)
{
- buf_append_char (buf_to_net, 'F');
- buf_append_char (buf_to_net, '\n');
+ if (supported_response ("F"))
+ {
+ buf_append_char (buf_to_net, 'F');
+ buf_append_char (buf_to_net, '\n');
+ }
+
+ cvs_flusherr ();
}
- cvs_flusherr ();
- break;
}
}
@@ -3461,11 +3433,6 @@ server_scratch (fname)
* two different cases. Using the last one which happens is almost
* surely correct; I haven't tracked down why they both happen (or
* even verified that they are for the same file).
- *
- * Don't know if this is what whoever wrote the above comment was
- * talking about, but this can happen in the case where a join
- * removes a file - the call to Register puts the '-vers' into the
- * Entries file after the file is removed
*/
if (entries_line != NULL)
{
@@ -3625,15 +3592,6 @@ serve_log (arg)
}
static void
-serve_rlog (arg)
- char *arg;
-{
- /* Tell cvslog() to behave like rlog not log. */
- command_name = "rlog";
- do_cvs_command ("rlog", cvslog);
-}
-
-static void
serve_add (arg)
char *arg;
{
@@ -3672,9 +3630,7 @@ static void
serve_rtag (arg)
char *arg;
{
- /* Tell cvstag() to behave like rtag not tag. */
- command_name = "rtag";
- do_cvs_command ("rtag", cvstag);
+ do_cvs_command ("rtag", rtag);
}
static void
@@ -3798,10 +3754,7 @@ serve_init (arg)
/* Fall through to do_cvs_command which will return the
actual error. */
}
-
- if (current_parsed_root != NULL)
- free_cvsroot_t (current_parsed_root);
- current_parsed_root = local_cvsroot (arg);
+ set_local_cvsroot (arg);
do_cvs_command ("init", init);
}
@@ -3814,17 +3767,6 @@ serve_annotate (arg)
{
do_cvs_command ("annotate", annotate);
}
-
-static void serve_rannotate PROTO ((char *));
-
-static void
-serve_rannotate (arg)
- char *arg;
-{
- /* Tell annotate() to behave like rannotate not annotate. */
- command_name = "rannotate";
- do_cvs_command ("rannotate", annotate);
-}
static void
serve_co (arg)
@@ -4222,23 +4164,6 @@ CVS server internal error: unhandled case in server_updated");
output_dir (finfo->update_dir, finfo->repository);
buf_output0 (protocol, finfo->file);
buf_output (protocol, "\n", 1);
- /* keep the vers structure up to date in case we do a join
- * - if there isn't a file, it can't very well have a version number, can it?
- *
- * we do it here on the assumption that since we just told the client
- * to remove the file/entry, it will, and we want to remember that.
- * If it fails, that's the client's problem, not ours
- */
- if (vers && vers->vn_user != NULL)
- {
- free (vers->vn_user);
- vers->vn_user = NULL;
- }
- if (vers && vers->ts_user != NULL)
- {
- free (vers->ts_user);
- vers->ts_user = NULL;
- }
}
else if (scratched_file == NULL && entries_line == NULL)
{
@@ -4572,7 +4497,7 @@ serve_expand_modules (arg)
for (i = 1; i < argument_count; i++)
err += do_module (db, argument_vector[i],
CHECKOUT, "Updating", expand_proc,
- NULL, 0, 0, 0, 0,
+ NULL, 0, 0, 0,
(char *) NULL);
close_module (db);
server_expanding = 0;
@@ -4773,7 +4698,6 @@ struct request requests[] =
REQ_LINE("update", serve_update, RQ_ESSENTIAL),
REQ_LINE("diff", serve_diff, 0),
REQ_LINE("log", serve_log, 0),
- REQ_LINE("rlog", serve_rlog, 0),
REQ_LINE("add", serve_add, 0),
REQ_LINE("remove", serve_remove, 0),
REQ_LINE("update-patches", serve_ignore, 0),
@@ -4795,7 +4719,6 @@ struct request requests[] =
REQ_LINE("editors", serve_editors, 0),
REQ_LINE("init", serve_init, RQ_ROOTLESS),
REQ_LINE("annotate", serve_annotate, 0),
- REQ_LINE("rannotate", serve_rannotate, 0),
REQ_LINE("noop", serve_noop, RQ_ROOTLESS),
REQ_LINE("version", serve_version, RQ_ROOTLESS),
REQ_LINE(NULL, NULL, 0)
@@ -4829,7 +4752,7 @@ serve_valid_requests (arg)
buf_flush (buf_to_net, 1);
}
-#ifdef SUNOS_KLUDGE
+#ifdef sun
/*
* Delete temporary files. SIG is the signal making this happen, or
* 0 if not called as a result of a signal.
@@ -4843,7 +4766,7 @@ static void wait_sig (sig)
if (r == command_pid)
command_pid_is_dead++;
}
-#endif /* SUNOS_KLUDGE */
+#endif
void
server_cleanup (sig)
@@ -4887,7 +4810,7 @@ server_cleanup (sig)
/* What a bogus kludge. This disgusting code makes all kinds of
assumptions about SunOS, and is only for a bug in that system.
So only enable it on Suns. */
-#ifdef SUNOS_KLUDGE
+#ifdef sun
if (command_pid > 0)
{
/* To avoid crashes on SunOS due to bugs in SunOS tmpfs
@@ -4960,7 +4883,7 @@ server_cleanup (sig)
}
}
}
-#endif /* SUNOS_KLUDGE */
+#endif
CVS_CHDIR (Tmpdir);
/* Temporarily clear noexec, so that we clean up our temp directory
@@ -5098,25 +5021,19 @@ error ENOMEM Virtual memory exhausted.\n");
pending_error = status;
}
#ifndef CHMOD_BROKEN
- else if (chmod (server_temp_dir, S_IRWXU) < 0)
+ else
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
+ if (chmod (server_temp_dir, S_IRWXU) < 0)
+ {
+ int save_errno = errno;
+ if (alloc_pending (80 + strlen (server_temp_dir)))
+ sprintf (pending_error_text,
"E cannot change permissions on temporary directory %s",
- server_temp_dir);
- pending_error = save_errno;
+ server_temp_dir);
+ pending_error = save_errno;
+ }
}
#endif
- else if (CVS_CHDIR (server_temp_dir) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
-"E cannot change to temporary directory %s",
- server_temp_dir);
- pending_error = save_errno;
- }
}
}
@@ -5212,7 +5129,7 @@ error ENOMEM Virtual memory exhausted.\n");
continue;
if (!(rq->flags & RQ_ROOTLESS)
- && current_parsed_root == NULL)
+ && CVSroot_directory == NULL)
{
/* For commands which change the way in which data
is sent and received, for example Gzip-stream,
@@ -5346,10 +5263,10 @@ error 0 %s: no such user\n", username);
#endif
#if HAVE_PUTENV
- /* Set LOGNAME, USER and CVS_USER in the environment, in case they
- are already set to something else. */
+ /* Set LOGNAME and USER in the environment, in case they are
+ already set to something else. */
{
- char *env, *cvs_user;
+ char *env;
env = xmalloc (sizeof "LOGNAME=" + strlen (username));
(void) sprintf (env, "LOGNAME=%s", username);
@@ -5358,11 +5275,6 @@ error 0 %s: no such user\n", username);
env = xmalloc (sizeof "USER=" + strlen (username));
(void) sprintf (env, "USER=%s", username);
(void) putenv (env);
-
- cvs_user = NULL != CVS_Username ? CVS_Username : "";
- env = xmalloc (sizeof "CVS_USER=" + strlen (cvs_user));
- (void) sprintf (env, "CVS_USER=%s", cvs_user);
- (void) putenv (env);
}
#endif /* HAVE_PUTENV */
}
@@ -5397,7 +5309,7 @@ check_repository_password (username, password, repository, host_user_ptr)
int found_it = 0;
int namelen;
- /* We don't use current_parsed_root->directory because it hasn't been set yet
+ /* We don't use CVSroot_directory because it hasn't been set yet
* -- our `repository' argument came from the authentication
* protocol, not the regular CVS protocol.
*/
@@ -5539,7 +5451,10 @@ check_password (username, password, repository)
password file. If so, that's enough to authenticate with. If
not, we'll check /etc/passwd. */
- rc = check_repository_password (username, password, repository,
+ if (require_real_user)
+ rc = 0; /* "not found" */
+ else
+ rc = check_repository_password (username, password, repository,
&host_user);
if (rc == 2)
@@ -5727,13 +5642,8 @@ pserver_authenticate_connection ()
{
int on = 1;
- if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof on) < 0)
- {
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
-#endif
- }
+ (void) setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &on, sizeof on);
}
#endif
@@ -5789,13 +5699,13 @@ pserver_authenticate_connection ()
error (1, 0, "bad auth protocol end: %s", tmp);
}
if (!root_allow_ok (repository))
- {
- printf ("error 0 %s: no such repository\n", repository);
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository);
-#endif
+ /* Just give a generic I HATE YOU. This is because CVS 1.9.10
+ and older clients do not support "error". Once more recent
+ clients are more widespread, probably want to fix this (it is
+ a real pain to track down why it isn't letting you in if it
+ won't say why, and I am not convinced that the potential
+ information disclosure to an attacker outweighs this). */
goto i_hate_you;
- }
/* OK, now parse the config file, so we can use it to control how
to check passwords. If there was an error parsing the config
@@ -5811,13 +5721,6 @@ pserver_authenticate_connection ()
free (descrambled_password);
if (host_user == NULL)
{
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_NOTICE, "login failure (for %s)", repository);
-#ifdef LOG_AUTHPRIV
- syslog (LOG_AUTHPRIV | LOG_NOTICE, "login failure by %s / %s (for %s)",
- username, descrambled_password, repository);
-#endif
-#endif
i_hate_you:
printf ("I HATE YOU\n");
fflush (stdout);
@@ -5899,13 +5802,8 @@ error %s getpeername or getsockname failed\n", strerror (errno));
{
int on = 1;
- if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof on) < 0)
- {
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
-#endif
- }
+ (void) setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &on, sizeof on);
}
#endif
@@ -6501,20 +6399,13 @@ cvs_flusherr ()
#ifdef SERVER_SUPPORT
if (error_use_protocol)
{
- /* skip the actual stderr flush in this case since the parent process
- * on the server should only be writing to stdout anyhow
- */
/* Flush what we can to the network, but don't block. */
buf_flush (buf_to_net, 0);
}
else if (server_active)
{
- /* make sure stderr is flushed before we send the flush count on the
- * protocol pipe
- */
- fflush (stderr);
/* Send a special count to tell the parent to flush. */
- buf_send_special_count (protocol, -2);
+ buf_send_special_count (protocol, -1);
}
else
#endif
@@ -6540,13 +6431,7 @@ cvs_flushout ()
cvs_flushout replaces, setting stdout to line buffering in
main.c, didn't get called in the server child process. But
in the future it is quite plausible that we'll want to make
- this case work analogously to cvs_flusherr.
-
- FIXME - DRP - I tried to implement this and triggered the following
- error: "Protocol error: uncounted data discarded". I don't need
- this feature right now, so I'm not going to bother with it yet.
- */
- buf_send_special_count (protocol, -1);
+ this case work analogously to cvs_flusherr. */
}
else
#endif
diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c
index f4b919f..bec2397 100644
--- a/contrib/cvs/src/update.c
+++ b/contrib/cvs/src/update.c
@@ -31,6 +31,8 @@
* versions, these are updated too. If the -d option was specified, new
* directories added to the repository are automatically created and updated
* as well.
+ *
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -58,7 +60,7 @@ static int patch_file PROTO ((struct file_info *finfo,
static void patch_file_write PROTO ((void *, const char *, size_t));
#endif
static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
-static int scratch_file PROTO((struct file_info *finfo, Vers_TS *vers));
+static int scratch_file PROTO((struct file_info *finfo));
static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir,
char *repository, char *update_dir,
List *entries));
@@ -99,7 +101,6 @@ static int force_tag_match = 1;
static int update_build_dirs = 0;
static int update_prune_dirs = 0;
static int pipeout = 0;
-static int dotemplate = 0;
#ifdef SERVER_SUPPORT
static int patches = 0;
static int rcs_diff_patches = 0;
@@ -108,7 +109,7 @@ static List *ignlist = (List *) NULL;
static time_t last_register_time;
static const char *const update_usage[] =
{
- "Usage: %s %s [-APCdflRp] [-k kopt] [-r rev] [-D date] [-j rev]\n",
+ "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n",
" [-I ign] [-W spec] [files...]\n",
"\t-A\tReset any sticky tags/date/kopts.\n",
"\t-P\tPrune empty directories.\n",
@@ -118,7 +119,7 @@ static const char *const update_usage[] =
"\t-l\tLocal directory only, no recursion.\n",
"\t-R\tProcess directories recursively.\n",
"\t-p\tSend updates to standard output (avoids stickiness).\n",
- "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
+ "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
"\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
"\t-D date\tSet date to update from (is sticky).\n",
"\t-j rev\tMerge in changes made between current revision and rev.\n",
@@ -234,7 +235,7 @@ update (argc, argv)
argv += optind;
#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
+ if (client_active)
{
int pass;
@@ -410,7 +411,7 @@ update (argc, argv)
/* call the command line interface */
err = do_update (argc, argv, options, tag, date, force_tag_match,
local, update_build_dirs, aflag, update_prune_dirs,
- pipeout, which, join_rev1, join_rev2, (char *) NULL, 1);
+ pipeout, which, join_rev1, join_rev2, (char *) NULL);
/* free the space Make_Date allocated if necessary */
if (date != NULL)
@@ -424,8 +425,7 @@ update (argc, argv)
*/
int
do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
- xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir,
- xdotemplate)
+ xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir)
int argc;
char **argv;
char *xoptions;
@@ -441,7 +441,6 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
char *xjoin_rev1;
char *xjoin_rev2;
char *preload_update_dir;
- int xdotemplate;
{
int err = 0;
char *cp;
@@ -455,7 +454,6 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
aflag = xaflag;
update_prune_dirs = xprune;
pipeout = xpipeout;
- dotemplate = xdotemplate;
/* setup the join support */
join_rev1 = xjoin_rev1;
@@ -507,15 +505,11 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
argc, argv, local, which, aflag, 1,
preload_update_dir, 1);
-#ifdef SERVER_SUPPORT
- if (server_active)
- return err;
-#endif
-
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- sleep_past (last_register_time);
+ while (time ((time_t *) NULL) == last_register_time)
+ sleep (1);
}
return (err);
@@ -583,6 +577,9 @@ update_fileproc (callerdat, finfo)
int retval;
Ctype status;
Vers_TS *vers;
+ int resurrecting;
+
+ resurrecting = 0;
status = Classify_File (finfo, tag, date, options, force_tag_match,
aflag, &vers, pipeout);
@@ -595,7 +592,7 @@ update_fileproc (callerdat, finfo)
&& tag != NULL
&& finfo->rcs != NULL)
{
- char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
+ char *rev = RCS_getversion (finfo->rcs, tag, date, 1, NULL);
if (rev != NULL
&& !RCS_nodeisbranch (finfo->rcs, tag))
nonbranch = 1;
@@ -628,7 +625,9 @@ update_fileproc (callerdat, finfo)
case T_MODIFIED: /* locally modified */
case T_REMOVED: /* removed but not committed */
case T_CHECKOUT: /* needs checkout */
+#ifdef SERVER_SUPPORT
case T_PATCH: /* needs patch */
+#endif
retval = checkout_file (finfo, vers, 0, 0, 0);
break;
@@ -653,12 +652,8 @@ update_fileproc (callerdat, finfo)
write_letter (finfo, 'C');
break;
case T_NEEDS_MERGE: /* needs merging */
- if (! toss_local_changes)
- {
- retval = merge_file (finfo, vers);
- break;
- }
- /* else FALL THROUGH */
+ retval = merge_file (finfo, vers);
+ break;
case T_MODIFIED: /* locally modified */
retval = 0;
if (toss_local_changes)
@@ -738,8 +733,8 @@ update_fileproc (callerdat, finfo)
}
}
break;
- case T_PATCH: /* needs patch */
#ifdef SERVER_SUPPORT
+ case T_PATCH: /* needs patch */
if (patches)
{
int docheckout;
@@ -761,11 +756,11 @@ update_fileproc (callerdat, finfo)
break;
}
}
-#endif
/* If we're not running as a server, just check the
file out. It's simpler and faster than producing
and applying patches. */
/* Fall through. */
+#endif
case T_CHECKOUT: /* needs checkout */
retval = checkout_file (finfo, vers, 0, 0, 1);
break;
@@ -778,7 +773,18 @@ update_fileproc (callerdat, finfo)
retval = 0;
break;
case T_REMOVE_ENTRY: /* needs to be un-registered */
- retval = scratch_file (finfo, vers);
+ retval = scratch_file (finfo);
+#ifdef SERVER_SUPPORT
+ if (server_active && retval == 0)
+ {
+ if (vers->ts_user == NULL)
+ server_scratch_entry_only ();
+ server_updated (finfo, vers,
+ SERVER_UPDATED, (mode_t) -1,
+ (unsigned char *) NULL,
+ (struct buffer *) NULL);
+ }
+#endif
break;
default: /* can't ever happen :-) */
error (0, 0,
@@ -793,7 +799,7 @@ update_fileproc (callerdat, finfo)
join_file (finfo, vers);
/* if this directory has an ignore list, add this file to it */
- if (ignlist && (status != T_UNKNOWN || vers->ts_user == NULL))
+ if (ignlist)
{
Node *p;
@@ -873,7 +879,7 @@ update_filesdone_proc (callerdat, err, repository, update_dir, entries)
{
/* If there is no CVS/Root file, add one */
if (!isfile (CVSADM_ROOT))
- Create_Root ((char *) NULL, current_parsed_root->original);
+ Create_Root ((char *) NULL, CVSroot_original);
}
return (err);
@@ -966,7 +972,7 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
via WriteTag. */
0,
0,
- dotemplate);
+ 1);
rewrite_tag = 1;
nonbranch = 0;
Subdir_Register (entries, (char *) NULL, dir);
@@ -1169,7 +1175,7 @@ isemptydir (dir, might_not_exist)
return (0);
}
errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
+ while ((dp = readdir (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") != 0
&& strcmp (dp->d_name, "..") != 0)
@@ -1178,7 +1184,7 @@ isemptydir (dir, might_not_exist)
{
/* An entry other than the CVS directory. The directory
is certainly not empty. */
- (void) CVS_CLOSEDIR (dirp);
+ (void) closedir (dirp);
return (0);
}
else
@@ -1209,7 +1215,7 @@ isemptydir (dir, might_not_exist)
{
/* There are files that have been removed, but not
committed! Do not consider the directory empty. */
- (void) CVS_CLOSEDIR (dirp);
+ (void) closedir (dirp);
return (0);
}
}
@@ -1219,10 +1225,10 @@ isemptydir (dir, might_not_exist)
if (errno != 0)
{
error (0, errno, "cannot read directory %s", dir);
- (void) CVS_CLOSEDIR (dirp);
+ (void) closedir (dirp);
return (0);
}
- (void) CVS_CLOSEDIR (dirp);
+ (void) closedir (dirp);
return (1);
}
@@ -1230,46 +1236,13 @@ isemptydir (dir, might_not_exist)
* scratch the Entries file entry associated with a file
*/
static int
-scratch_file (finfo, vers)
+scratch_file (finfo)
struct file_info *finfo;
- Vers_TS *vers;
{
history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
Scratch_Entry (finfo->entries, finfo->file);
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- if (vers->ts_user == NULL)
- server_scratch_entry_only ();
- server_updated (finfo, vers,
- SERVER_UPDATED, (mode_t) -1,
- (unsigned char *) NULL,
- (struct buffer *) NULL);
- }
-#endif
if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
error (0, errno, "unable to remove %s", finfo->fullname);
- else
-#ifdef SERVER_SUPPORT
- /* skip this step when the server is running since
- * server_updated should have handled it */
- if (!server_active)
-#endif
- {
- /* keep the vers structure up to date in case we do a join
- * - if there isn't a file, it can't very well have a version number, can it?
- */
- if (vers->vn_user != NULL)
- {
- free (vers->vn_user);
- vers->vn_user = NULL;
- }
- if (vers->ts_user != NULL)
- {
- free (vers->ts_user);
- vers->ts_user = NULL;
- }
- }
return (0);
}
@@ -1769,7 +1742,7 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
diff_options = "-n";
}
- retcode = diff_exec (file1, file2, NULL, NULL, diff_options, finfo->file);
+ retcode = diff_exec (file1, file2, diff_options, finfo->file);
/* A retcode of 0 means no differences. 1 means some differences. */
if (retcode != 0
@@ -2135,17 +2108,6 @@ join_file (finfo, vers)
char *jdate1;
char *jdate2;
- if (trace)
- fprintf (stderr, "%s-> join_file(%s, %s%s%s%s, %s, %s)\n",
- CLIENT_SERVER_STR,
- finfo->file,
- vers->tag ? vers->tag : "",
- vers->tag ? " (" : "",
- vers->vn_rcs ? vers->vn_rcs : "",
- vers->tag ? ")" : "",
- join_rev1 ? join_rev1 : "",
- join_rev2 ? join_rev2 : "");
-
jrev1 = join_rev1;
jrev2 = join_rev2;
jdate1 = date_rev1;
@@ -2314,14 +2276,7 @@ join_file (finfo, vers)
for removal. FIXME: If we are doing a checkout, this has
the effect of first checking out the file, and then
removing it. It would be better to just register the
- removal.
-
- The same goes for a removal then an add. e.g.
- cvs up -rbr -jbr2 could remove and readd the same file
- */
- /* save the rev since server_updated might invalidate it */
- mrev = xmalloc (strlen (vers->vn_user) + 2);
- sprintf (mrev, "-%s", vers->vn_user);
+ removal. */
#ifdef SERVER_SUPPORT
if (server_active)
{
@@ -2330,6 +2285,8 @@ join_file (finfo, vers)
(unsigned char *) NULL, (struct buffer *) NULL);
}
#endif
+ mrev = xmalloc (strlen (vers->vn_user) + 2);
+ sprintf (mrev, "-%s", vers->vn_user);
Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
vers->options, vers->tag, vers->date, vers->ts_conflict);
free (mrev);
@@ -2372,7 +2329,6 @@ join_file (finfo, vers)
addition. */
if (vers->vn_user == NULL)
{
- char *saved_options = options;
Vers_TS *xvers;
xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
@@ -2387,7 +2343,6 @@ join_file (finfo, vers)
/* FIXME: If checkout_file fails, we should arrange to
return a non-zero exit status. */
status = checkout_file (finfo, xvers, 1, 0, 1);
- options = saved_options;
freevers_ts (&xvers);
OpenPOWER on IntegriCloud