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.c173
-rw-r--r--contrib/cvs/src/commit.c188
-rw-r--r--contrib/cvs/src/cvs.h26
-rw-r--r--contrib/cvs/src/diff.c8
-rw-r--r--contrib/cvs/src/filesubr.c45
-rw-r--r--contrib/cvs/src/import.c82
-rw-r--r--contrib/cvs/src/lock.c21
-rw-r--r--contrib/cvs/src/login.c66
-rw-r--r--contrib/cvs/src/logmsg.c85
-rw-r--r--contrib/cvs/src/main.c189
-rw-r--r--contrib/cvs/src/mkmodules.c43
-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.c1024
-rw-r--r--contrib/cvs/src/rcs.h13
-rw-r--r--contrib/cvs/src/rcscmds.c2
-rw-r--r--contrib/cvs/src/recurse.c14
-rw-r--r--contrib/cvs/src/server.c544
-rw-r--r--contrib/cvs/src/update.c256
21 files changed, 1635 insertions, 1347 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 c451b28..eafe916 100644
--- a/contrib/cvs/src/client.c
+++ b/contrib/cvs/src/client.c
@@ -1,5 +1,3 @@
-/* JT thinks BeOS is worth the trouble. */
-
/* CVS client-related stuff.
This program is free software; you can redistribute it and/or modify
@@ -12,6 +10,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 */
@@ -62,6 +64,7 @@ extern char *strerror ();
#if HAVE_KERBEROS
#define CVS_PORT 1999
+#if HAVE_KERBEROS
#include <krb.h>
extern char *krb_realmofhost ();
@@ -75,6 +78,8 @@ static Key_schedule sched;
#endif /* HAVE_KERBEROS */
+#endif /* HAVE_KERBEROS */
+
#ifdef HAVE_GSSAPI
#ifdef HAVE_GSSAPI_H
@@ -263,7 +268,7 @@ arg_should_not_be_sent_to_server (arg)
}
/* Now check the value for root. */
- if (this_root && current_root
+ if (CVSroot_cmdline == NULL && this_root && current_root
&& (strcmp (this_root, current_root) != 0))
{
/* Don't send this, since the CVSROOTs don't match. */
@@ -1114,7 +1119,7 @@ call_in_directory (pathname, func, data)
strcpy (r, "/.");
Create_Admin (".", ".", repo, (char *) NULL,
- (char *) NULL, 0, 1, 1);
+ (char *) NULL, 0, 1);
free (repo);
}
@@ -1251,7 +1256,7 @@ warning: server is not creating directories one at a time");
strcpy (r, reposdirname);
Create_Admin (dir, dir, repo,
- (char *)NULL, (char *)NULL, 0, 0, 1);
+ (char *)NULL, (char *)NULL, 0, 0);
free (repo);
b = strrchr (dir, '/');
@@ -1759,7 +1764,6 @@ update_entries (data_arg, ent_list, short_pathname, filename)
}
free (mode_string);
- free (scratch_entries);
free (entries_line);
/* The Mode, Mod-time, and Checksum responses should not carry
@@ -1847,8 +1851,7 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (use_gzip)
{
- if (gunzip_and_write (fd, short_pathname,
- (unsigned char *) buf, size))
+ if (gunzip_and_write (fd, short_pathname, buf, size))
error (1, 0, "aborting due to compression error");
}
else if (write (fd, buf, size) != size)
@@ -2026,8 +2029,6 @@ update_entries (data_arg, ent_list, short_pathname, filename)
free (mode_string);
free (buf);
- free (scratch_entries);
- free (entries_line);
return;
}
@@ -2126,8 +2127,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (file_timestamp)
free (file_timestamp);
+ free (scratch_entries);
}
- free (scratch_entries);
free (entries_line);
}
@@ -2493,11 +2494,7 @@ handle_set_checkin_prog (args, len)
{
char *prog;
struct save_prog *p;
-
read_line (&prog);
- if (strcmp (command_name, "export") == 0)
- return;
-
p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
p->next = checkin_progs;
p->dir = xstrdup (args);
@@ -2512,11 +2509,7 @@ handle_set_update_prog (args, len)
{
char *prog;
struct save_prog *p;
-
read_line (&prog);
- if (strcmp (command_name, "export") == 0)
- return;
-
p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
p->next = update_progs;
p->dir = xstrdup (args);
@@ -2694,7 +2687,7 @@ send_repository (dir, repos, update_dir)
{
Node *n;
n = getnode ();
- n->type = NT_UNKNOWN;
+ n->type = UNKNOWN;
n->key = xstrdup (update_dir);
n->data = NULL;
@@ -3605,15 +3598,19 @@ get_responses_and_close ()
&& waitpid (rsh_pid, (int *) 0, 0) == -1)
error (1, errno, "waiting for process %d", rsh_pid);
- buf_free (to_server);
- buf_free (from_server);
server_started = 0;
- /* see if we need to sleep before returning to avoid time-stamp races */
+ /* see if we need to sleep before returning */
if (last_register_time)
{
- while (time ((time_t *) NULL) == last_register_time)
- sleep (1);
+ time_t now;
+
+ for (;;)
+ {
+ (void) time (&now);
+ if (now != last_register_time) break;
+ sleep (1); /* to avoid time-stamp races */
+ }
}
return errs;
@@ -3781,7 +3778,6 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
int port_number;
struct sockaddr_in client_sai;
struct hostent *hostinfo;
- char no_passwd = 0; /* gets set if no password found */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == -1)
@@ -3826,14 +3822,6 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
/* Get the password, probably from ~/.cvspass. */
password = get_cvs_password ();
-
- /* Send the empty string by default. This is so anonymous CVS
- access doesn't require client to have done "cvs login". */
- if (password == NULL)
- {
- no_passwd = 1;
- password = scramble ("");
- }
/* Announce that we're starting the authorization protocol. */
if (send (sock, begin, strlen (begin), 0) < 0)
@@ -3857,8 +3845,8 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
if (send (sock, end, strlen (end), 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
- /* Paranoia. */
- memset (password, 0, strlen (password));
+ /* Paranoia. */
+ memset (password, 0, strlen (password));
}
{
@@ -3951,28 +3939,20 @@ 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,
+ error (0, 0,
+ "authorization failed: server %s rejected access",
+ CVSroot_hostname);
+ error (1, 0,
"shutdown() failed (server %s): %s",
CVSroot_hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
- error_exit();
+ error (1, 0,
+ "authorization failed: server %s rejected access",
+ CVSroot_hostname);
}
#endif /* AUTH_CLIENT_SUPPORT */
@@ -4135,16 +4115,9 @@ connect_to_gserver (sock, hostinfo)
if (stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
{
OM_uint32 message_context;
- OM_uint32 new_stat_min;
message_context = 0;
- gss_display_status (&new_stat_min, stat_maj, GSS_C_GSS_CODE,
- GSS_C_NULL_OID, &message_context, &tok_out);
- error (0, 0, "GSSAPI authentication failed: %s",
- (char *) tok_out.value);
-
- message_context = 0;
- gss_display_status (&new_stat_min, stat_min, GSS_C_MECH_CODE,
+ gss_display_status (&stat_min, stat_maj, GSS_C_GSS_CODE,
GSS_C_NULL_OID, &message_context, &tok_out);
error (1, 0, "GSSAPI authentication failed: %s",
(char *) tok_out.value);
@@ -4168,29 +4141,7 @@ connect_to_gserver (sock, hostinfo)
recv_bytes (sock, cbuf, 2);
need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
-
- if (need > sizeof buf)
- {
- int got;
-
- /* This usually means that the server sent us an error
- message. Read it byte by byte and print it out.
- FIXME: This is a terrible error handling strategy.
- However, even if we fix the server, we will still
- want to do this to work with older servers. */
- buf[0] = cbuf[0];
- buf[1] = cbuf[1];
- got = recv (sock, buf + 2, sizeof buf - 2, 0);
- if (got < 0)
- error (1, 0, "recv() from server %s: %s",
- 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", CVSroot_hostname,
- buf);
- }
-
+ assert (need <= sizeof buf);
recv_bytes (sock, buf, need);
tok_in.length = need;
}
@@ -4224,7 +4175,7 @@ send_variable_proc (node, closure)
void
start_server ()
{
- int tofd, fromfd, rootless;
+ int tofd, fromfd;
char *log = getenv ("CVS_CLIENT_LOG");
@@ -4403,8 +4354,7 @@ the :server: access method is not supported by this port of CVS");
stored_mode = NULL;
}
- rootless = (strcmp (command_name, "init") == 0);
- if (!rootless)
+ if (strcmp (command_name, "init") != 0)
{
send_to_server ("Root ", 0);
send_to_server (CVSroot_directory, 0);
@@ -4528,7 +4478,7 @@ the :server: access method is not supported by this port of CVS");
}
}
- if (cvsencrypt && !rootless)
+ if (cvsencrypt)
{
#ifdef ENCRYPTION
/* Turn on encryption before turning on compression. We do
@@ -4575,7 +4525,7 @@ the :server: access method is not supported by this port of CVS");
#endif /* ! ENCRYPTION */
}
- if (gzip_level && !rootless)
+ if (gzip_level)
{
if (supported_request ("Gzip-stream"))
{
@@ -4617,7 +4567,7 @@ the :server: access method is not supported by this port of CVS");
}
}
- if (cvsauthenticate && ! cvsencrypt && !rootless)
+ if (cvsauthenticate && ! cvsencrypt)
{
/* Turn on authentication after turning on compression, so
that we can compress the authentication information. We
@@ -4648,7 +4598,7 @@ the :server: access method is not supported by this port of CVS");
}
#ifdef FILENAMES_CASE_INSENSITIVE
- if (supported_request ("Case") && !rootless)
+ if (supported_request ("Case"))
send_to_server ("Case\012", 0);
#endif
@@ -5018,7 +4968,6 @@ struct send_data
int build_dirs;
int force;
int no_contents;
- int backup_modified;
};
static int send_fileproc PROTO ((void *callerdat, struct file_info *finfo));
@@ -5140,18 +5089,6 @@ warning: ignoring -k options due to server limitations");
}
else
send_modified (filename, finfo->fullname, vers);
-
- if (args->backup_modified)
- {
- char *bakname;
- bakname = backup_file (filename, vers->vn_user);
- /* This behavior is sufficiently unexpected to
- justify overinformativeness, I think. */
- if (! really_quiet)
- printf ("(Locally modified %s moved to %s)\n",
- filename, bakname);
- free (bakname);
- }
}
else
{
@@ -5260,6 +5197,9 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
dir_exists = isdir (cvsadm_name);
free (cvsadm_name);
+ /* initialize the ignore list for this directory */
+ ignlist = getlist ();
+
/*
* If there is an empty directory (e.g. we are doing `cvs add' on a
* newly-created directory), the server still needs to know about it.
@@ -5275,9 +5215,6 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
char *repos = Name_Repository (dir, update_dir);
send_a_repository (dir, repos, update_dir);
free (repos);
-
- /* initialize the ignore list for this directory */
- ignlist = getlist ();
}
else
{
@@ -5302,29 +5239,6 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
return (dir_exists ? R_PROCESS : R_SKIP_ALL);
}
-static int send_dirleave_proc PROTO ((void *, char *, int, char *, List *));
-
-/*
- * send_dirleave_proc () is called back by the recursion code upon leaving
- * a directory. All it does is delete the ignore list if it hasn't already
- * been done (by send_filesdone_proc).
- */
-/* ARGSUSED */
-static int
-send_dirleave_proc (callerdat, dir, err, update_dir, entries)
- void *callerdat;
- char *dir;
- int err;
- char *update_dir;
- List *entries;
-{
-
- /* Delete the ignore list if it hasn't already been done. */
- if (ignlist)
- dellist (&ignlist);
- return err;
-}
-
/*
* Send each option in a string to the server, one by one.
* This assumes that the options are separated by spaces, for example
@@ -5516,10 +5430,9 @@ send_files (argc, argv, local, aflag, flags)
args.build_dirs = flags & SEND_BUILD_DIRS;
args.force = flags & SEND_FORCE;
args.no_contents = flags & SEND_NO_CONTENTS;
- args.backup_modified = flags & BACKUP_MODIFIED_FILES;
err = start_recursion
(send_fileproc, send_filesdoneproc,
- send_dirent_proc, send_dirleave_proc, (void *) &args,
+ send_dirent_proc, (DIRLEAVEPROC)NULL, (void *) &args,
argc, argv, local, W_LOCAL, aflag, 0, (char *)NULL, 0);
if (err)
error_exit ();
diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c
index 1c1f71c..6dfd4a8 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>
@@ -263,7 +264,6 @@ find_fileproc (callerdat, finfo)
else
error (0, 0, "use `%s add' to create an entry for %s",
program_name, finfo->fullname);
- freevers_ts (&vers);
return 1;
}
else if (vers->ts_user != NULL
@@ -285,7 +285,6 @@ find_fileproc (callerdat, finfo)
cases. FIXME: we probably should be printing a message and
returning 1 for many of those cases (but I'm not sure
exactly which ones). */
- freevers_ts (&vers);
return 0;
}
@@ -423,12 +422,28 @@ commit (argc, argv)
/* some checks related to the "-F logfile" option */
if (logfile)
{
- size_t size = 0, len;
+ int n, logfd;
+ struct stat statbuf;
if (saved_message)
error (1, 0, "cannot specify both a message and a log file");
- get_file (logfile, logfile, "r", &saved_message, &size, &len);
+ /* FIXME: Why is this binary? Needs more investigation. */
+ if ((logfd = CVS_OPEN (logfile, O_RDONLY | OPEN_BINARY)) < 0)
+ error (1, errno, "cannot open log file %s", logfile);
+
+ if (fstat(logfd, &statbuf) < 0)
+ error (1, errno, "cannot find size of log file %s", logfile);
+
+ saved_message = xmalloc (statbuf.st_size + 1);
+
+ /* FIXME: Should keep reading until EOF, rather than assuming the
+ first read gets the whole thing. */
+ if ((n = read (logfd, saved_message, statbuf.st_size + 1)) < 0)
+ error (1, errno, "cannot read log message from %s", logfile);
+
+ (void) close (logfd);
+ saved_message[n] = '\0';
}
#ifdef CLIENT_SUPPORT
@@ -459,14 +474,11 @@ commit (argc, argv)
error (1, 0, "correct above errors first!");
if (find_args.argc == 0)
- {
/* Nothing to commit. Exit now without contacting the
server (note that this means that we won't print "?
foo" for files which merit it, because we don't know
what is in the CVSROOT/cvsignore file). */
- dellist (&find_args.ulist);
return 0;
- }
/* Now we keep track of which files we actually are going to
operate on, and only work with those files in the future.
@@ -498,7 +510,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
@@ -572,8 +584,6 @@ commit (argc, argv)
previous versions of client/server CVS, but it probably is a Good
Thing, or at least Not Such A Bad Thing. */
send_file_names (find_args.argc, find_args.argv, 0);
- free (find_args.argv);
- dellist (&find_args.ulist);
send_to_server ("ci\012", 0);
err = get_responses_and_close ();
@@ -663,11 +673,16 @@ commit (argc, argv)
Lock_Cleanup ();
dellist (&mulist);
- /* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- while (time ((time_t *) NULL) == last_register_time)
- sleep (1);
+ time_t now;
+
+ for (;;)
+ {
+ (void) time (&now);
+ if (now != last_register_time) break;
+ sleep (1); /* to avoid time-stamp races */
+ }
}
return (err);
@@ -780,12 +795,6 @@ check_fileproc (callerdat, finfo)
size_t cvsroot_len = strlen (CVSroot_directory);
- if (!finfo->repository)
- {
- error (0, 0, "nothing known about `%s'", finfo->fullname);
- return (1);
- }
-
if (strncmp (finfo->repository, CVSroot_directory, cvsroot_len) == 0
&& ISDIRSEP (finfo->repository[cvsroot_len])
&& strncmp (finfo->repository + cvsroot_len + 1,
@@ -1240,7 +1249,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);
@@ -1282,8 +1291,6 @@ commit_fileproc (callerdat, finfo)
{
if (finfo->rcs == NULL)
error (1, 0, "internal error: no parsed RCS file");
- if (ci->rev)
- free (ci->rev);
ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
err = Checkin ('A', finfo, finfo->rcs->path, ci->rev,
ci->tag, ci->options, saved_message);
@@ -1394,8 +1401,6 @@ out:
}
}
}
- if (SIG_inCrSect ())
- SIG_endCrSect ();
return (err);
}
@@ -1496,7 +1501,6 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
cvs_output (": Executing '", 0);
run_print (stdout);
cvs_output ("'\n", 0);
- cvs_flushout ();
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
free (repos);
}
@@ -1556,7 +1560,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);
}
@@ -1579,10 +1583,8 @@ commit_dirleaveproc (callerdat, dir, err, update_dir, entries)
this being a confusing feature! */
if (err == 0 && write_dirtag != NULL)
{
- char *repos = Name_Repository (dir, update_dir);
WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
- update_dir, repos);
- free (repos);
+ update_dir, Name_Repository (dir, update_dir));
}
return (err);
@@ -1750,9 +1752,6 @@ remove_file (finfo, tag, message)
"failed to commit dead revision for `%s'", finfo->fullname);
return (1);
}
- /* At this point, the file has been committed as removed. We should
- probably tell the history file about it */
- history_write ('R', NULL, finfo->rcs->head, finfo->file, finfo->repository);
if (rev != NULL)
free (rev);
@@ -1964,11 +1963,6 @@ checkaddfile (file, repository, tag, options, rcsnode)
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
- /* Begin a critical section around the code that spans the
- first commit on the trunk of a file that's already been
- committed on a branch. */
- SIG_beginCrSect ();
-
if (RCS_setattic (rcsfile, 0))
{
retval = 1;
@@ -2051,76 +2045,74 @@ checkaddfile (file, repository, tag, options, rcsnode)
newfile = 1;
if (desc != NULL)
free (desc);
- if (rcsnode != NULL)
- {
- assert (*rcsnode == NULL);
- *rcsnode = rcsfile;
- }
}
/* when adding a file for the first time, and using a tag, we need
to create a dead revision on the trunk. */
- if (adding_on_branch)
+ if (adding_on_branch && newfile)
{
- if (newfile)
- {
- char *tmp;
- FILE *fp;
-
- /* move the new file out of the way. */
- fname = xmalloc (strlen (file) + sizeof (CVSADM)
- + sizeof (CVSPREFIX) + 10);
- (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
- rename_file (file, fname);
+ char *tmp;
+ FILE *fp;
- /* Create empty FILE. Can't use copy_file with a DEVNULL
- argument -- copy_file now ignores device files. */
- fp = fopen (file, "w");
- if (fp == NULL)
- error (1, errno, "cannot open %s for writing", file);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", file);
-
- tmp = xmalloc (strlen (file) + strlen (tag) + 80);
- /* commit a dead revision. */
- (void) sprintf (tmp, "file %s was initially added on branch %s.",
- file, tag);
- retcode = RCS_checkin (rcsfile, NULL, tmp, NULL,
- RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
- free (tmp);
- if (retcode != 0)
- {
- error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
- "could not create initial dead revision %s", rcs);
- retval = 1;
- goto out;
- }
+ /* move the new file out of the way. */
+ fname = xmalloc (strlen (file) + sizeof (CVSADM)
+ + sizeof (CVSPREFIX) + 10);
+ (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
+ rename_file (file, fname);
+
+ /* Create empty FILE. Can't use copy_file with a DEVNULL
+ argument -- copy_file now ignores device files. */
+ fp = fopen (file, "w");
+ if (fp == NULL)
+ error (1, errno, "cannot open %s for writing", file);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", file);
+
+ tmp = xmalloc (strlen (file) + strlen (tag) + 80);
+ /* commit a dead revision. */
+ (void) sprintf (tmp, "file %s was initially added on branch %s.",
+ file, tag);
+ retcode = RCS_checkin (rcsfile, NULL, tmp, NULL,
+ RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
+ free (tmp);
+ if (retcode != 0)
+ {
+ error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
+ "could not create initial dead revision %s", rcs);
+ retval = 1;
+ goto out;
+ }
- /* put the new file back where it was */
- rename_file (fname, file);
- free (fname);
+ /* put the new file back where it was */
+ rename_file (fname, file);
+ free (fname);
- /* double-check that the file was written correctly */
- freercsnode (&rcsfile);
- rcsfile = RCS_parse (file, repository);
- if (rcsfile == NULL)
- {
- error (0, 0, "could not read %s", rcs);
- retval = 1;
- goto out;
- }
- if (rcsnode != NULL)
- *rcsnode = rcsfile;
+ /* double-check that the file was written correctly */
+ freercsnode (&rcsfile);
+ rcsfile = RCS_parse (file, repository);
+ if (rcsfile == NULL)
+ {
+ error (0, 0, "could not read %s", rcs);
+ retval = 1;
+ goto out;
+ }
+ if (rcsnode != NULL)
+ {
+ assert (*rcsnode == NULL);
+ *rcsnode = rcsfile;
+ }
- /* and lock it once again. */
- if (lock_RCS (file, rcsfile, NULL, repository))
- {
- error (0, 0, "cannot lock `%s'.", rcs);
- retval = 1;
- goto out;
- }
+ /* and lock it once again. */
+ if (lock_RCS (file, rcsfile, NULL, repository))
+ {
+ error (0, 0, "cannot lock `%s'.", rcs);
+ retval = 1;
+ goto out;
}
+ }
+ if (adding_on_branch)
+ {
/* when adding with a tag, we need to stub a branch, if it
doesn't already exist. */
@@ -2146,6 +2138,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);
@@ -2203,8 +2197,6 @@ checkaddfile (file, repository, tag, options, rcsnode)
retval = 0;
out:
- if (retval != 0 && SIG_inCrSect ())
- SIG_endCrSect ();
free (rcs);
return retval;
}
diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h
index 0277c86..b889c9a 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 */
@@ -363,6 +367,7 @@ 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 {
@@ -390,11 +395,12 @@ extern List *root_directories;
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;
@@ -487,6 +493,7 @@ char *xreadlink PROTO((const char *link));
char *last_component PROTO((char *path));
char *get_homedir PROTO ((void));
char *cvs_temp_name PROTO ((void));
+void parseopts PROTO ((const char *root));
int numdots PROTO((const char *s));
char *increment_revnum PROTO ((const char *));
@@ -500,7 +507,7 @@ void *valloc PROTO((size_t bytes));
time_t get_date PROTO((char *date, struct timeb *now));
extern int Create_Admin PROTO ((char *dir, char *update_dir,
char *repository, char *tag, char *date,
- int nonbranch, int warn, int dotemplate));
+ int nonbranch, int warn));
extern int expand_at_signs PROTO ((char *, off_t, FILE *));
/* Locking subsystem (implemented in lock.c). */
@@ -526,7 +533,7 @@ void cat_module PROTO((int status));
void check_entries PROTO((char *dir));
void close_module PROTO((DBM * db));
void copy_file PROTO((const char *from, const char *to));
-void fperrmsg PROTO((FILE * fp, int status, int errnum, char *message,...));
+void fperror PROTO((FILE * fp, int status, int errnum, char *message,...));
void free_names PROTO((int *pargc, char *argv[]));
extern int ign_name PROTO ((char *name));
@@ -547,7 +554,6 @@ 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
@@ -577,9 +583,9 @@ 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,
+typedef int (*CALLBACKPROC) PROTO((int *pargc, char *argv[], char *where,
char *mwhere, char *mfile, int shorten, int local_specified,
char *omodule, char *msg));
@@ -638,7 +644,6 @@ int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
int dosrcs));
void SIG_beginCrSect PROTO((void));
void SIG_endCrSect PROTO((void));
-int SIG_inCrSect PROTO((void));
void read_cvsrc PROTO((int *argc, char ***argv, char *cmdname));
char *make_message_rcslegal PROTO((char *message));
@@ -856,7 +861,6 @@ extern int cvsremove PROTO((int argc, char **argv));
extern int rtag PROTO((int argc, char **argv));
extern int cvsstatus PROTO((int argc, char **argv));
extern int cvstag PROTO((int argc, char **argv));
-extern int version PROTO((int argc, char **argv));
extern unsigned long int lookup_command_attribute PROTO((char *));
@@ -873,8 +877,6 @@ extern void tag_check_valid PROTO ((char *, int, char **, int, int, char *));
extern void tag_check_valid_join PROTO ((char *, int, char **, int, int,
char *));
-#include "server.h"
-
/* From server.c and documented there. */
extern void cvs_output PROTO ((const char *, size_t));
extern void cvs_output_binary PROTO ((char *, size_t));
@@ -882,3 +884,7 @@ extern void cvs_outerr PROTO ((const char *, size_t));
extern void cvs_flusherr PROTO ((void));
extern void cvs_flushout PROTO ((void));
extern void cvs_output_tagged PROTO ((char *, char *));
+
+#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
+#include "server.h"
+#endif
diff --git a/contrib/cvs/src/diff.c b/contrib/cvs/src/diff.c
index e98938d..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"
@@ -457,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);
}
@@ -467,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)
diff --git a/contrib/cvs/src/filesubr.c b/contrib/cvs/src/filesubr.c
index 3a800a9..7572558 100644
--- a/contrib/cvs/src/filesubr.c
+++ b/contrib/cvs/src/filesubr.c
@@ -17,6 +17,10 @@
definitions under operating systems (like, say, Windows NT) with different
file system semantics. */
+/*
+ * $FreeBSD$
+ */
+
#include "cvs.h"
static int deep_remove_dir PROTO((const char *path));
@@ -51,13 +55,9 @@ copy_file (from, to)
if (isdevice (from))
{
-#if defined(HAVE_MKNOD) && defined(HAVE_ST_RDEV)
if (stat (from, &sb) < 0)
error (1, errno, "cannot stat %s", from);
mknod (to, sb.st_mode, sb.st_rdev);
-#else
- error (1, 0, "cannot copy device files on this system (%s)", from);
-#endif
}
else
{
@@ -624,15 +624,10 @@ xcmp (file1, file2)
numbers match. */
if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
{
-#ifdef HAVE_ST_RDEV
if (sb1.st_rdev == sb2.st_rdev)
return 0;
else
return 1;
-#else
- error (1, 0, "cannot compare device files on this system (%s and %s)",
- file1, file2);
-#endif
}
if ((fd1 = open (file1, O_RDONLY)) < 0)
@@ -691,6 +686,23 @@ xcmp (file1, file2)
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 *value;
+ int retval;
+
+ value = xmalloc (strlen (Tmpdir) + 40);
+ sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXXXXXX");
+ retval = mkstemp (value);
+
+ if (retval == -1)
+ error (1, errno, "cannot generate temporary filename");
+ close (retval);
+ return value;
+}
+#else
#ifdef HAVE_TEMPNAM
char *
cvs_temp_name ()
@@ -730,6 +742,7 @@ cvs_temp_name ()
# endif
}
#endif
+#endif
/* Return non-zero iff FILENAME is absolute.
Trivial under Unix, but more complicated under other systems. */
@@ -750,8 +763,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;
@@ -762,15 +775,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);
diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c
index e1fb460..a449842 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"
@@ -220,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')
{
@@ -266,22 +268,12 @@ import (argc, argv)
client_import_setup (repository);
err = import_descend (message, argv[1], argc - 2, argv + 2);
client_import_done ();
- if (message)
- free (message);
- free (repository);
- free (vbranch);
- free (vhead);
send_to_server ("import\012", 0);
err += get_responses_and_close ();
return err;
}
#endif
- if (!safe_location ())
- {
- error (1, 0, "attempt to import the repository");
- }
-
/*
* Make all newly created directories writable. Should really use a more
* sophisticated security mechanism here.
@@ -463,12 +455,9 @@ import_descend (message, vtag, targc, targv)
}
else if (
#ifdef DT_DIR
- dp->d_type == DT_LNK
- || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
-#else
- islink (dp->d_name)
+ dp->d_type == DT_LNK || dp->d_type == DT_UNKNOWN &&
#endif
- )
+ islink (dp->d_name))
{
add_log ('L', dp->d_name);
err++;
@@ -738,8 +727,8 @@ add_rev (message, rcs, vfile, vers)
{
if (!noexec)
{
- fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
- "ERROR: Check-in of %s failed", rcs->path);
+ fperror (logfp, 0, status == -1 ? ierrno : 0,
+ "ERROR: Check-in of %s failed", rcs->path);
error (0, status == -1 ? ierrno : 0,
"ERROR: Check-in of %s failed", rcs->path);
}
@@ -778,8 +767,8 @@ add_tags (rcs, vfile, vtag, targc, targv)
if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
{
ierrno = errno;
- fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
- "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
+ fperror (logfp, 0, retcode == -1 ? ierrno : 0,
+ "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
error (0, retcode == -1 ? ierrno : 0,
"ERROR: Failed to set tag %s in %s", vtag, rcs->path);
return (1);
@@ -802,9 +791,9 @@ add_tags (rcs, vfile, vtag, targc, targv)
else
{
ierrno = errno;
- fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
- "WARNING: Couldn't add tag %s to %s", targv[i],
- rcs->path);
+ fperror (logfp, 0, retcode == -1 ? ierrno : 0,
+ "WARNING: Couldn't add tag %s to %s", targv[i],
+ rcs->path);
error (0, retcode == -1 ? ierrno : 0,
"WARNING: Couldn't add tag %s to %s", targv[i],
rcs->path);
@@ -1067,14 +1056,7 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
stat the file before opening it. -twp */
if (CVS_LSTAT (userfile, &sb) < 0)
- {
- /* not fatal, continue import */
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, errno,
- "ERROR: cannot lstat file %s", userfile);
- error (0, errno, "cannot lstat file %s", userfile);
- goto read_error;
- }
+ error (1, errno, "cannot lstat %s", user);
file_type = sb.st_mode & S_IFMT;
fpuser = NULL;
@@ -1089,8 +1071,8 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
{
/* not fatal, continue import */
if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, errno,
- "ERROR: cannot read file %s", userfile);
+ fperror (add_logfp, 0, errno,
+ "ERROR: cannot read file %s", userfile);
error (0, errno, "ERROR: cannot read file %s", userfile);
goto read_error;
}
@@ -1222,18 +1204,12 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
case S_IFREG: break;
case S_IFCHR:
case S_IFBLK:
-#ifdef HAVE_ST_RDEV
if (fprintf (fprcs, "special\t%s %lu;\012",
(file_type == S_IFCHR
? "character"
: "block"),
(unsigned long) sb.st_rdev) < 0)
goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
break;
default:
error (0, 0,
@@ -1279,18 +1255,12 @@ userfile);
case S_IFREG: break;
case S_IFCHR:
case S_IFBLK:
-#ifdef HAVE_ST_RDEV
if (fprintf (fprcs, "special\t%s %lu;\012",
(file_type == S_IFCHR
? "character"
: "block"),
(unsigned long) sb.st_rdev) < 0)
goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
break;
default:
error (0, 0,
@@ -1409,8 +1379,8 @@ userfile);
{
ierrno = errno;
if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, ierrno,
- "WARNING: cannot change mode of file %s", rcs);
+ fperror (add_logfp, 0, ierrno,
+ "WARNING: cannot change mode of file %s", rcs);
error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
err++;
}
@@ -1429,14 +1399,14 @@ write_error_noclose:
if (fclose (fpuser) < 0)
error (0, errno, "cannot close %s", user);
if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
+ fperror (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
error (0, ierrno, "ERROR: cannot write file %s", rcs);
if (ierrno == ENOSPC)
{
if (CVS_UNLINK (rcs) < 0)
error (0, errno, "cannot remove %s", rcs);
if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
+ fperror (add_logfp, 0, 0, "ERROR: out of space - aborting");
error (1, 0, "ERROR: out of space - aborting");
}
read_error:
@@ -1545,7 +1515,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
return (0);
if (save_cwd (&cwd))
{
- fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
+ fperror (logfp, 0, 0, "ERROR: cannot get working directory");
return (1);
}
@@ -1576,7 +1546,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
if ( CVS_CHDIR (dir) < 0)
{
ierrno = errno;
- fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
+ fperror (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
error (0, ierrno, "ERROR: cannot chdir to %s", repository);
err = 1;
goto out;
@@ -1591,9 +1561,9 @@ import_descend_dir (message, dir, vtag, targc, targv)
(void) sprintf (rcs, "%s%s", repository, RCSEXT);
if (isfile (repository) || isfile(rcs))
{
- fperrmsg (logfp, 0, 0,
- "ERROR: %s is a file, should be a directory!",
- repository);
+ fperror (logfp, 0, 0,
+ "ERROR: %s is a file, should be a directory!",
+ repository);
error (0, 0, "ERROR: %s is a file, should be a directory!",
repository);
err = 1;
@@ -1602,8 +1572,8 @@ import_descend_dir (message, dir, vtag, targc, targv)
if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
{
ierrno = errno;
- fperrmsg (logfp, 0, ierrno,
- "ERROR: cannot mkdir %s -- not added", repository);
+ fperror (logfp, 0, ierrno,
+ "ERROR: cannot mkdir %s -- not added", repository);
error (0, ierrno,
"ERROR: cannot mkdir %s -- not added", repository);
err = 1;
diff --git a/contrib/cvs/src/lock.c b/contrib/cvs/src/lock.c
index 1b98180..a0c0a34 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
@@ -175,12 +177,8 @@ lock_name (repository, name)
assert (CVSroot_directory != NULL);
assert (strncmp (repository, CVSroot_directory,
strlen (CVSroot_directory)) == 0);
- short_repos = repository + strlen (CVSroot_directory) + 1;
-
- if (strcmp (repository, CVSroot_directory) == 0)
- short_repos = ".";
- else
- assert (short_repos[-1] == '/');
+ short_repos = repository + strlen (CVSroot_directory);
+ assert (*short_repos++ == '/');
retval = xmalloc (strlen (lock_dir)
+ strlen (short_repos)
@@ -395,7 +393,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! */
@@ -470,6 +468,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)
{
@@ -759,8 +762,8 @@ set_lock (lock, will_wait)
if (errno != EEXIST)
{
error (0, errno,
- "failed to create lock directory for `%s' (%s)",
- lock->repository, masterlock);
+ "failed to create lock directory in repository `%s'",
+ lock->repository);
return (L_ERROR);
}
diff --git a/contrib/cvs/src/login.c b/contrib/cvs/src/login.c
index 1a774e0..708dfc8 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"
@@ -12,12 +14,6 @@
#ifdef AUTH_CLIENT_SUPPORT /* This covers the rest of the file. */
-#ifdef HAVE_GETPASSPHRASE
-#define GETPASS getpassphrase
-#else
-#define GETPASS getpass
-#endif
-
/* There seems to be very little agreement on which system header
getpass is declared in. With a lot of fancy autoconfiscation,
we could perhaps detect this, but for now we'll just rely on
@@ -26,7 +22,7 @@
varadic, believe it or not). On Cray, getpass will be declared
in either stdlib.h or unistd.h. */
#ifndef _CRAY
-extern char *GETPASS ();
+extern char *getpass ();
#endif
#ifndef CVS_PASSWORD_FILE
@@ -148,7 +144,7 @@ login (argc, argv)
fflush (stdout);
passfile = construct_cvspass_filename ();
- typed_password = GETPASS ("CVS password: ");
+ typed_password = getpass ("CVS password: ");
typed_password = scramble (typed_password);
/* Force get_cvs_password() to use this one (when the client
@@ -295,19 +291,21 @@ login (argc, argv)
}
/* 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. */
+ before hashing and comparing. */
char *
get_cvs_password ()
{
int found_it = 0;
int root_len;
- char *password = NULL;
- char *linebuf = NULL;
+ char *password;
+ char *linebuf = (char *) NULL;
size_t linebuf_len;
FILE *fp;
char *passfile;
int line_length;
+ int anoncvs;
+
+ anoncvs = (strcmp(CVSroot_username, "anoncvs") == 0);
/* If someone (i.e., login()) is calling connect_to_pserver() out of
context, then assume they have supplied the correct, scrambled
@@ -346,10 +344,15 @@ get_cvs_password ()
passfile = construct_cvspass_filename ();
fp = CVS_FOPEN (passfile, "r");
- if (fp == NULL)
+ if (fp == NULL)
{
+ if (anoncvs) {
+ free (passfile);
+ return strdup("Ay=0=h<Z"); /* scrambled "anoncvs" */
+ }
+ error (0, errno, "could not open %s", passfile);
free (passfile);
- return NULL;
+ error (1, 0, "use \"cvs login\" to log in first");
}
root_len = strlen (CVSroot_original);
@@ -368,6 +371,7 @@ get_cvs_password ()
error (0, errno, "cannot read %s", passfile);
if (fclose (fp) < 0)
error (0, errno, "cannot close %s", passfile);
+ free (passfile);
if (found_it)
{
@@ -375,19 +379,25 @@ get_cvs_password ()
char *tmp;
strtok (linebuf, " ");
- tmp = strtok (NULL, "\n");
- if (tmp == NULL)
- error (1, 0, "bad entry in %s for %s", passfile, CVSroot_original);
+ password = strtok (NULL, "\n");
/* Give it permanent storage. */
- password = xstrdup (tmp);
- memset (tmp, 0, strlen (password));
+ tmp = xstrdup (password);
+ memset (password, 0, strlen (password));
+ free (linebuf);
+ return tmp;
}
-
- if (linebuf)
- free (linebuf);
- free (passfile);
- return password;
+ else
+ {
+ if (linebuf)
+ free (linebuf);
+ if (anoncvs)
+ return strdup("Ay=0=h<Z"); /* scrambled "anoncvs" */
+ error (0, 0, "cannot find password");
+ error (1, 0, "use \"cvs login\" to log in first");
+ }
+ /* NOTREACHED */
+ return NULL;
}
static const char *const logout_usage[] =
@@ -397,7 +407,7 @@ static const char *const logout_usage[] =
NULL
};
-/* Remove any entry for the CVSRoot repository found in .cvspass. */
+/* Remove any entry for the CVSRoot repository found in "CVS/.cvspass". */
int
logout (argc, argv)
int argc;
@@ -405,7 +415,7 @@ logout (argc, argv)
{
char *passfile;
FILE *fp;
- char *tmp_name = NULL;
+ char *tmp_name;
FILE *tmp_fp;
char *linebuf = (char *) NULL;
size_t linebuf_len;
@@ -500,10 +510,6 @@ logout (argc, argv)
error (0, errno, "cannot remove %s", tmp_name);
chmod (passfile, 0600);
}
-
- if (tmp_name)
- free (tmp_name);
-
return 0;
}
diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c
index cb08cdf..e1b8ed0 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"
@@ -182,6 +184,7 @@ do_editor (dir, messagep, repository, changes)
char *fname;
struct stat pre_stbuf, post_stbuf;
int retcode = 0;
+ char *p;
if (noexec || reuse_log_message)
return;
@@ -215,6 +218,7 @@ do_editor (dir, messagep, repository, changes)
{
FILE *tfp;
char buf[1024];
+ char *p;
size_t n;
size_t nwrite;
@@ -229,9 +233,9 @@ do_editor (dir, messagep, repository, changes)
{
while (!feof (tfp))
{
- char *p = buf;
n = fread (buf, 1, sizeof buf, tfp);
nwrite = n;
+ p = buf;
while (nwrite > 0)
{
n = fwrite (p, 1, nwrite, fp);
@@ -313,8 +317,7 @@ do_editor (dir, messagep, repository, changes)
if (*messagep)
{
- size_t message_len = post_stbuf.st_size + 1;
- size_t offset = 0;
+ p = *messagep;
while (1)
{
line_length = getline (&line, &line_chars_allocated, fp);
@@ -326,11 +329,8 @@ do_editor (dir, messagep, repository, changes)
}
if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
continue;
- if (offset + line_length >= message_len)
- expand_string (messagep, &message_len,
- offset + line_length + 1);
- (void) strcpy (*messagep + offset, line);
- offset += line_length;
+ (void) strcpy (p, line);
+ p += line_length;
}
}
if (fclose (fp) < 0)
@@ -387,14 +387,20 @@ 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 (client_active)
/* The verification will happen on the server. */
@@ -408,7 +414,7 @@ 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;
@@ -424,9 +430,9 @@ do_verify (message, repository)
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);
@@ -456,6 +462,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)
@@ -761,7 +816,7 @@ logfile_write (repository, filter, message, logfp, changes)
}
len = fmt_end - fmt_begin;
- str_list_format = xmalloc (len + 1);
+ str_list_format = xmalloc (sizeof (char) * (len + 1));
strncpy (str_list_format, fmt_begin, len);
str_list_format[len] = '\0';
diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c
index 86913e1..39bfaa2 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
@@ -111,31 +115,30 @@ static const struct cmd
{ "history", "hi", "his", history },
{ "import", "im", "imp", import },
{ "init", NULL, NULL, init },
-#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
+#ifdef SERVER_SUPPORT
{ "kserver", NULL, NULL, server }, /* placeholder */
#endif
{ "log", "lo", "rlog", cvslog },
#ifdef AUTH_CLIENT_SUPPORT
{ "login", "logon", "lgn", login },
{ "logout", NULL, NULL, logout },
-#endif /* AUTH_CLIENT_SUPPORT */
-#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
+#ifdef SERVER_SUPPORT
{ "pserver", NULL, NULL, server }, /* placeholder */
#endif
+#endif /* AUTH_CLIENT_SUPPORT */
{ "rdiff", "patch", "pa", patch },
{ "release", "re", "rel", release },
{ "remove", "rm", "delete", cvsremove },
- { "rtag", "rt", "rfreeze", rtag },
-#ifdef SERVER_SUPPORT
- { "server", NULL, NULL, server },
-#endif
{ "status", "st", "stat", cvsstatus },
+ { "rtag", "rt", "rfreeze", rtag },
{ "tag", "ta", "freeze", cvstag },
{ "unedit", NULL, NULL, unedit },
{ "update", "up", "upd", update },
- { "version", "ve", "ver", version },
{ "watch", NULL, NULL, watch },
{ "watchers", NULL, NULL, watchers },
+#ifdef SERVER_SUPPORT
+ { "server", NULL, NULL, server },
+#endif
{ NULL, NULL, NULL, NULL },
};
@@ -180,7 +183,7 @@ static const char *const usg[] =
version control means. */
"For CVS updates and additional information, see\n",
- " the CVS home page at http://www.cvshome.org/ or\n",
+ " Cyclic Software at http://www.cyclic.com/ or\n",
" Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n",
NULL,
};
@@ -200,24 +203,15 @@ static const char *const cmd_usage[] =
" history Show repository access history\n",
" import Import sources into CVS, using vendor branches\n",
" init Create a CVS repository if it doesn't exist\n",
-#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- " kserver Kerberos server mode\n",
-#endif
" log Print out history information for files\n",
#ifdef AUTH_CLIENT_SUPPORT
- " login Prompt for password for authenticating server\n",
- " logout Removes entry in .cvspass for remote repository\n",
+ " login Prompt for password for authenticating server.\n",
+ " logout Removes entry in .cvspass for remote repository.\n",
#endif /* AUTH_CLIENT_SUPPORT */
-#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- " pserver Password server mode\n",
-#endif
" 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",
" rtag Add a symbolic tag to a module\n",
-#ifdef SERVER_SUPPORT
- " server Server mode\n",
-#endif
" status Display status information on checked out files\n",
" tag Add a symbolic tag to checked out version of files\n",
" unedit Undo an edit command\n",
@@ -237,9 +231,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",
@@ -353,7 +349,6 @@ lookup_command_attribute (cmd_name)
(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;
@@ -373,11 +368,6 @@ main_cleanup (sig)
switch (sig)
{
-#ifdef SIGABRT
- case SIGABRT:
- name = "abort";
- break;
-#endif
#ifdef SIGHUP
case SIGHUP:
name = "hangup";
@@ -421,6 +411,8 @@ main (argc, argv)
char **argv;
{
char *CVSroot = CVSROOT_DFLT;
+ extern char *version_string;
+ extern char *config_string;
char *cp, *end;
const struct cmd *cm;
int c, err = 0;
@@ -432,7 +424,6 @@ 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 struct option long_options[] =
{
{"help", 0, NULL, 'H'},
@@ -495,6 +486,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. */
@@ -507,7 +504,7 @@ main (argc, argv)
opterr = 0;
while ((c = getopt_long
- (argc, argv, short_options, long_options, &option_index))
+ (argc, argv, "+f", NULL, NULL))
!= EOF)
{
if (c == 'f')
@@ -524,7 +521,7 @@ main (argc, argv)
opterr = 1;
while ((c = getopt_long
- (argc, argv, short_options, long_options, &option_index))
+ (argc, argv, "+QqgrwtnRlvb:T:e:d:Hfz:s:xaU", long_options, &option_index))
!= EOF)
{
switch (c)
@@ -557,20 +554,34 @@ 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 */
logoff = 1;
break;
case 'v':
- (void) fputs ("\n", stdout);
- version (0, (char **) NULL);
+ /* Having the year here is a good idea, so people have
+ some idea of how long ago their version of CVS was
+ released. */
+ (void) fputs (version_string, stdout);
+ (void) fputs (config_string, stdout);
(void) fputs ("\n", stdout);
(void) fputs ("\
-Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
+Copyright (c) 1989-1998 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);
@@ -614,9 +625,9 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
case 'z':
#ifdef CLIENT_SUPPORT
gzip_level = atoi (optarg);
- if (gzip_level < 0 || gzip_level > 9)
+ if (gzip_level <= 0 || gzip_level > 9)
error (1, 0,
- "gzip compression level must be between 0 and 9");
+ "gzip compression level must be between 1 and 9");
#endif
/* If no CLIENT_SUPPORT, we just silently ignore the gzip
level, so that users can have it in their .cvsrc and not
@@ -643,6 +654,11 @@ Copyright (c) 1989-2000 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);
@@ -669,10 +685,7 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
}
if (!cm->fullname)
- {
- fprintf (stderr, "Unknown command: `%s'\n\n", command_name);
- usage (cmd_usage);
- }
+ usage (cmd_usage); /* no match */
else
command_name = cm->fullname; /* Global pointer for later use */
@@ -776,27 +789,35 @@ Copyright (c) 1989-2000 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
/* make sure we clean up on error */
-#ifdef SIGABRT
- (void) SIG_register (SIGABRT, main_cleanup);
-#endif
#ifdef SIGHUP
(void) SIG_register (SIGHUP, main_cleanup);
+ (void) SIG_register (SIGHUP, Lock_Cleanup);
#endif
#ifdef SIGINT
(void) SIG_register (SIGINT, main_cleanup);
+ (void) SIG_register (SIGINT, Lock_Cleanup);
#endif
#ifdef SIGQUIT
(void) SIG_register (SIGQUIT, main_cleanup);
+ (void) SIG_register (SIGQUIT, Lock_Cleanup);
#endif
#ifdef SIGPIPE
(void) SIG_register (SIGPIPE, main_cleanup);
+ (void) SIG_register (SIGPIPE, Lock_Cleanup);
#endif
#ifdef SIGTERM
(void) SIG_register (SIGTERM, main_cleanup);
+ (void) SIG_register (SIGTERM, Lock_Cleanup);
#endif
#endif /* !DONT_USE_SIGNALS */
@@ -891,7 +912,7 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
{
Node *n;
n = getnode ();
- n->type = NT_UNKNOWN;
+ n->type = UNKNOWN;
n->key = xstrdup (CVSroot);
n->data = NULL;
@@ -934,8 +955,11 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
current_root);
/*
- * Check to see if the repository exists.
+ * Check to see if we can write into the history file. If not,
+ * we assume that we can't work in the repository.
+ * BUT, only if the history file exists.
*/
+
if (!client_active)
{
char *path;
@@ -943,7 +967,8 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
path = xmalloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
- + 20);
+ + 20
+ + sizeof (CVSROOTADM_HISTORY));
(void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
if (!isaccessible (path, R_OK | X_OK))
{
@@ -954,6 +979,14 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
error (1, save_errno, "%s", path);
}
}
+ (void) strcat (path, "/");
+ (void) strcat (path, CVSROOTADM_HISTORY);
+ if (readonlyfs == 0 && isfile (path) && !isaccessible (path, R_OK | W_OK))
+ {
+ save_errno = errno;
+ error (0, 0, "Sorry, you don't have read/write access to the history file");
+ error (1, save_errno, "%s", path);
+ }
free (path);
}
@@ -962,17 +995,12 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
/* FIXME (njc): should we always set this with the CVSROOT from the command line? */
if (cvs_update_env)
{
- static char *prev;
char *env;
env = xmalloc (strlen (CVSROOT_ENV) + strlen (CVSroot)
+ 1 + 1);
(void) sprintf (env, "%s=%s", CVSROOT_ENV, CVSroot);
(void) putenv (env);
- /* do not free env yet, as putenv has control of it */
- /* but do free the previous value, if any */
- if (prev != NULL)
- free (prev);
- prev = env;
+ /* do not free env, as putenv has control of it */
}
#endif
}
@@ -998,6 +1026,9 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
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 (CVSroot_directory);
+
+ /* Now is a convenient time to read CVSROOT/options */
+ parseopts(CVSroot_directory);
}
#ifdef CLIENT_SUPPORT
@@ -1155,3 +1186,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 4e4b5d0..966fb328 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"
@@ -280,23 +283,14 @@ static const char *const config_contents[] = {
"# Set this to \"no\" if pserver shouldn't check system users/passwords\n",
"#SystemAuth=no\n",
"\n",
- "# Put CVS lock files in this directory rather than directly in the repository.\n",
- "#LockDir=/var/lock/cvs\n",
- "\n",
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
"# Set `PreservePermissions' to `yes' to save file status information\n",
"# in the repository.\n",
"#PreservePermissions=no\n",
"\n",
-#endif
"# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top\n",
"# level of the new working directory when using the `cvs checkout'\n",
"# command.\n",
"#TopLevelAdmin=no\n",
- "\n",
- "# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the\n",
- "# history file, or a subset as needed (ie `TMAR' logs all write operations)\n",
- "#LogHistory=TOFEWGCMAR\n",
NULL
};
@@ -381,9 +375,6 @@ mkmodules (dir)
size_t line_allocated = 0;
const struct admin_file *fileptr;
- if (noexec)
- return 0;
-
if (save_cwd (&cwd))
error_exit ();
@@ -877,9 +868,6 @@ init (argc, argv)
if ( CVS_CHDIR (adm) < 0)
error (1, errno, "cannot change to directory %s", adm);
- /* Make Emptydir so it's there if we need it */
- mkdir_if_needed (CVSNULLREPOS);
-
/* 80 is long enough for all the administrative file names, plus
"/" and so on. */
info = xmalloc (strlen (adm) + 80);
@@ -941,29 +929,6 @@ init (argc, argv)
fp = open_file (info, "w");
if (fclose (fp) < 0)
error (1, errno, "cannot close %s", info);
-
- /* Make the new history file world-writeable, since every CVS
- user will need to be able to write to it. We use chmod()
- because xchmod() is too shy. */
- chmod (info, 0666);
- }
-
- /* Make an empty val-tags file to prevent problems creating it later. */
- strcpy (info, adm);
- strcat (info, "/");
- strcat (info, CVSROOTADM_VALTAGS);
- if (!isfile (info))
- {
- FILE *fp;
-
- fp = open_file (info, "w");
- if (fclose (fp) < 0)
- error (1, errno, "cannot close %s", info);
-
- /* Make the new val-tags file world-writeable, since every CVS
- user will need to be able to write to it. We use chmod()
- because xchmod() is too shy. */
- chmod (info, 0666);
}
free (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 b28572c..48be8e5 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>
@@ -60,7 +62,6 @@ static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,
char **valp));
-static int rcsbuf_valcmp PROTO ((struct rcsbuffer *));
static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish,
size_t *lenp));
static void rcsbuf_valpolish PROTO ((struct rcsbuffer *, char *val, int polish,
@@ -125,6 +126,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:
*
@@ -155,7 +158,6 @@ static const char spacetab[] = {
#define whitespace(c) (spacetab[(unsigned char)c] != 0)
static char *rcs_lockfile;
-static int rcs_lockfd = -1;
/* A few generic thoughts on error handling, in particular the
printing of unexpected characters that we find in the RCS file
@@ -544,10 +546,9 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
if (rdata->other == NULL)
rdata->other = getlist ();
kv = getnode ();
- kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
+ kv->type = RCSFIELD;
kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
- (size_t *) NULL);
+ kv->data = rcsbuf_valcopy (&rcsbuf, value, 1, (size_t *) NULL);
if (addnode (rdata->other, kv) != 0)
{
error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
@@ -593,7 +594,9 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
key, rcsfile);
free (rdata->desc);
}
- rdata->desc = rcsbuf_valcopy (&rcsbuf, value, 1, (size_t *) NULL);
+ /* Don't need to rcsbuf_valcopy `value' because
+ getdelta already did that. */
+ rdata->desc = xstrdup (value);
}
rdata->delta_pos = rcsbuf_ftell (&rcsbuf);
@@ -749,10 +752,9 @@ RCS_fully_parse (rcs)
if (vnode->other == NULL)
vnode->other = getlist ();
kv = getnode ();
- kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
+ kv->type = RCSFIELD;
kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
- (size_t *) NULL);
+ kv->data = rcsbuf_valcopy (&rcsbuf, value, 1, (size_t *) NULL);
if (addnode (vnode->other, kv) != 0)
{
error (0, 0,
@@ -1030,9 +1032,6 @@ rcsbuf_close (rcsbuf)
characters. Call rcsbuf_valcopy or rcsbuf_valpolish to do
appropriate massaging. */
-/* Note that the extreme hair in rcsbuf_getkey is because profiling
- statistics show that it was worth it. */
-
static int
rcsbuf_getkey (rcsbuf, keyp, valp)
struct rcsbuffer *rcsbuf;
@@ -1288,10 +1287,13 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
}
/* The value extends past the '@' string. We need to undo the
- '@' stripping done in the default case above. This
+ closing of the '@' done in the default case above. This
case never happens in a plain RCS file, but it can happen
if user defined phrases are used. */
- ((*valp)--)[rcsbuf->vlen++] = '@';
+ if (rcsbuf->vlen != 0)
+ (*valp)[rcsbuf->vlen] = ' ';
+ else
+ *valp = ptr;
}
/* Here we have a value which is not a simple '@' string. We need
@@ -1348,8 +1350,8 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
return 1;
}
- /* We found an '@' string in the value. We set RCSBUF->AT_STRING
- and RCSBUF->EMBEDDED_AT to indicate that we won't be able to
+ /* We found an '@' string in the value. We set
+ RCSBUF->AT_STRING, which means that we won't be able to
compress whitespace correctly for this type of value.
Since this type of value never arises in a normal RCS file,
this should not be a big deal. It means that if anybody
@@ -1358,7 +1360,8 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
themselves. */
rcsbuf->at_string = 1;
- rcsbuf->embedded_at = -1;
+
+ *pat = ' ';
ptr = pat + 1;
@@ -1393,16 +1396,495 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
break;
/* We found an '@' pair in the string. Keep looking. */
+ ++rcsbuf->embedded_at;
ptr = pat + 2;
}
/* Here PAT points to the final '@' in the string. */
+
+ *pat = ' ';
+
ptr = pat + 1;
}
#undef my_whitespace
}
+/* TODO: Eliminate redundant code in rcsbuf_getkey, rcsbuf_getid,
+ rcsbuf_getstring, rcsbuf_getword. These last three functions were
+ all created by hacking monstrous swaths of code from rcsbuf_getkey,
+ and some engineering would make the code easier to read and
+ maintain.
+
+ Note that the extreme hair in rcsbuf_getkey is because profiling
+ statistics show that it was worth it.
+
+ We probably could be processing "hardlinks" by first calling
+ rcsbuf_getkey, and breaking up the value afterwards; the code to
+ break it up would not need to be hacked for speed. This would
+ remove the need for rcsbuf_getword, rcsbuf_getid, and
+ rcsbuf_getstring, as the other calls are easy to remove. */
+
+/* Read an `id' (in the sense of rcsfile(5)) from RCSBUF, and store in
+ IDP. */
+
+static int
+rcsbuf_getid (rcsbuf, idp)
+ struct rcsbuffer *rcsbuf;
+ char **idp;
+{
+ register const char * const my_spacetab = spacetab;
+ register char *ptr, *ptrend;
+ char c;
+
+#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
+
+ rcsbuf->vlen = 0;
+ rcsbuf->at_string = 0;
+ rcsbuf->embedded_at = 0;
+
+ ptr = rcsbuf->ptr;
+ ptrend = rcsbuf->ptrend;
+
+ /* Sanity check. */
+ if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
+ abort ();
+
+ /* If the pointer is more than RCSBUF_BUFSIZE bytes into the
+ buffer, move back to the start of the buffer. This keeps the
+ buffer from growing indefinitely. */
+ if (ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE)
+ {
+ int len;
+
+ len = ptrend - ptr;
+
+ /* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
+ at a time, so we can't have more bytes than that past PTR. */
+ if (len > RCSBUF_BUFSIZE)
+ abort ();
+
+ /* Update the POS field, which holds the file offset of the
+ first byte in the RCSBUF_BUFFER buffer. */
+ rcsbuf->pos += ptr - rcsbuf_buffer;
+
+ memcpy (rcsbuf_buffer, ptr, len);
+ ptr = rcsbuf_buffer;
+ ptrend = ptr + len;
+ rcsbuf->ptrend = ptrend;
+ }
+
+ /* Skip leading whitespace. */
+
+ while (1)
+ {
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
+ if (ptr == NULL)
+ return 0;
+ ptrend = rcsbuf->ptrend;
+ }
+
+ c = *ptr;
+ if (! my_whitespace (c))
+ break;
+
+ ++ptr;
+ }
+
+ /* We've found the start of the key. */
+
+ *idp = ptr;
+
+ if (c != ';')
+ {
+ while (1)
+ {
+ ++ptr;
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, idp, (char **) NULL);
+ if (ptr == NULL)
+ error (1, 0, "EOF in key in RCS file %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+ c = *ptr;
+ if (c == ';' || my_whitespace (c))
+ break;
+ }
+ }
+
+ /* Here *IDP points to the id in the buffer, C is the character
+ we found at the end of the key, and PTR points to the location in
+ the buffer where we found C. We may not set *PTR to \0, because
+ it may overwrite a terminating semicolon. The calling function
+ must copy and terminate the id on its own. */
+
+ rcsbuf->ptr = ptr;
+ return 1;
+
+#undef my_whitespace
+}
+
+/* Read an RCS @-delimited string. Store the result in STRP. */
+
+static int
+rcsbuf_getstring (rcsbuf, strp)
+ struct rcsbuffer *rcsbuf;
+ char **strp;
+{
+ register const char * const my_spacetab = spacetab;
+ register char *ptr, *ptrend;
+ char *pat;
+ size_t vlen;
+ char c;
+
+#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
+
+ rcsbuf->vlen = 0;
+ rcsbuf->at_string = 0;
+ rcsbuf->embedded_at = 0;
+
+ ptr = rcsbuf->ptr;
+ ptrend = rcsbuf->ptrend;
+
+ /* Sanity check. */
+ if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
+ abort ();
+
+ /* If the pointer is more than RCSBUF_BUFSIZE bytes into the
+ buffer, move back to the start of the buffer. This keeps the
+ buffer from growing indefinitely. */
+ if (ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE)
+ {
+ int len;
+
+ len = ptrend - ptr;
+
+ /* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
+ at a time, so we can't have more bytes than that past PTR. */
+ if (len > RCSBUF_BUFSIZE)
+ abort ();
+
+ /* Update the POS field, which holds the file offset of the
+ first byte in the RCSBUF_BUFFER buffer. */
+ rcsbuf->pos += ptr - rcsbuf_buffer;
+
+ memcpy (rcsbuf_buffer, ptr, len);
+ ptr = rcsbuf_buffer;
+ ptrend = ptr + len;
+ rcsbuf->ptrend = ptrend;
+ }
+
+ /* Skip leading whitespace. */
+
+ while (1)
+ {
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
+ if (ptr == NULL)
+ error (1, 0, "unexpected end of file reading %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ c = *ptr;
+ if (! my_whitespace (c))
+ break;
+
+ ++ptr;
+ }
+
+ /* PTR should now point to the start of a string. */
+ if (c != '@')
+ error (1, 0, "expected @-string at '\\x%x' in %s",
+ c, rcsbuf->filename);
+
+ /* Optimize the common case of a value composed of a single
+ '@' string. */
+
+ rcsbuf->at_string = 1;
+
+ ++ptr;
+
+ *strp = ptr;
+
+ while (1)
+ {
+ while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
+ {
+ /* Note that we pass PTREND as the PTR value to
+ rcsbuf_fill, so that we will wind up setting PTR to
+ the location corresponding to the old PTREND, so
+ that we don't search the same bytes again. */
+ ptr = rcsbuf_fill (rcsbuf, ptrend, NULL, strp);
+ if (ptr == NULL)
+ error (1, 0,
+ "EOF while looking for end of string in RCS file %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ /* Handle the special case of an '@' right at the end of
+ the known bytes. */
+ if (pat + 1 >= ptrend)
+ {
+ /* Note that we pass PAT, not PTR, here. */
+ pat = rcsbuf_fill (rcsbuf, pat, NULL, strp);
+ if (pat == NULL)
+ {
+ /* EOF here is OK; it just means that the last
+ character of the file was an '@' terminating a
+ value for a key type which does not require a
+ trailing ';'. */
+ pat = rcsbuf->ptrend - 1;
+
+ }
+ ptrend = rcsbuf->ptrend;
+
+ /* Note that the value of PTR is bogus here. This is
+ OK, because we don't use it. */
+ }
+
+ if (pat + 1 >= ptrend || pat[1] != '@')
+ break;
+
+ /* We found an '@' pair in the string. Keep looking. */
+ ++rcsbuf->embedded_at;
+ ptr = pat + 2;
+ }
+
+ /* Here PAT points to the final '@' in the string. */
+
+ *pat = '\0';
+
+ vlen = pat - *strp;
+ if (vlen == 0)
+ *strp = NULL;
+ rcsbuf->vlen = vlen;
+ rcsbuf->ptr = pat + 1;
+
+ return 1;
+
+#undef my_whitespace
+}
+
+/* Read an RCS `word', in the sense of rcsfile(5) (an id, a num, a
+ @-delimited string, or `:'). Store the result in WORDP. If a
+ `;' is reached without reading any text, the result is NULL. */
+
+static int
+rcsbuf_getword (rcsbuf, wordp)
+ struct rcsbuffer *rcsbuf;
+ char **wordp;
+{
+ register const char * const my_spacetab = spacetab;
+ register char *ptr, *ptrend;
+ char c;
+
+#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
+
+ rcsbuf->vlen = 0;
+ rcsbuf->at_string = 0;
+ rcsbuf->embedded_at = 0;
+
+ ptr = rcsbuf->ptr;
+ ptrend = rcsbuf->ptrend;
+
+ /* Sanity check. */
+ if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
+ abort ();
+
+ /* If the pointer is more than RCSBUF_BUFSIZE bytes into the
+ buffer, move back to the start of the buffer. This keeps the
+ buffer from growing indefinitely. */
+ if (ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE)
+ {
+ int len;
+
+ len = ptrend - ptr;
+
+ /* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
+ at a time, so we can't have more bytes than that past PTR. */
+ if (len > RCSBUF_BUFSIZE)
+ abort ();
+
+ /* Update the POS field, which holds the file offset of the
+ first byte in the RCSBUF_BUFFER buffer. */
+ rcsbuf->pos += ptr - rcsbuf_buffer;
+
+ memcpy (rcsbuf_buffer, ptr, len);
+ ptr = rcsbuf_buffer;
+ ptrend = ptr + len;
+ rcsbuf->ptrend = ptrend;
+ }
+
+ /* Skip leading whitespace. */
+
+ while (1)
+ {
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
+ if (ptr == NULL)
+ error (1, 0, "unexpected end of file reading %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ c = *ptr;
+ if (! my_whitespace (c))
+ break;
+
+ ++ptr;
+ }
+
+ /* If we have reached `;', there is no value. */
+ if (c == ';')
+ {
+ *wordp = NULL;
+ *ptr++ = '\0';
+ rcsbuf->ptr = ptr;
+ rcsbuf->vlen = 0;
+ return 1;
+ }
+
+ /* PTR now points to the start of a value. Find out whether it is
+ a num, an id, a string or a colon. */
+ if (c == ':')
+ {
+ *wordp = ptr++;
+ rcsbuf->ptr = ptr;
+ rcsbuf->vlen = 1;
+ return 1;
+ }
+
+ if (c == '@')
+ {
+ char *pat;
+ size_t vlen;
+
+ /* Optimize the common case of a value composed of a single
+ '@' string. */
+
+ rcsbuf->at_string = 1;
+
+ ++ptr;
+
+ *wordp = ptr;
+
+ while (1)
+ {
+ while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
+ {
+ /* Note that we pass PTREND as the PTR value to
+ rcsbuf_fill, so that we will wind up setting PTR to
+ the location corresponding to the old PTREND, so
+ that we don't search the same bytes again. */
+ ptr = rcsbuf_fill (rcsbuf, ptrend, NULL, wordp);
+ if (ptr == NULL)
+ error (1, 0,
+ "EOF while looking for end of string in RCS file %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ /* Handle the special case of an '@' right at the end of
+ the known bytes. */
+ if (pat + 1 >= ptrend)
+ {
+ /* Note that we pass PAT, not PTR, here. */
+ pat = rcsbuf_fill (rcsbuf, pat, NULL, wordp);
+ if (pat == NULL)
+ {
+ /* EOF here is OK; it just means that the last
+ character of the file was an '@' terminating a
+ value for a key type which does not require a
+ trailing ';'. */
+ pat = rcsbuf->ptrend - 1;
+
+ }
+ ptrend = rcsbuf->ptrend;
+
+ /* Note that the value of PTR is bogus here. This is
+ OK, because we don't use it. */
+ }
+
+ if (pat + 1 >= ptrend || pat[1] != '@')
+ break;
+
+ /* We found an '@' pair in the string. Keep looking. */
+ ++rcsbuf->embedded_at;
+ ptr = pat + 2;
+ }
+
+ /* Here PAT points to the final '@' in the string. */
+
+ *pat = '\0';
+
+ vlen = pat - *wordp;
+ if (vlen == 0)
+ *wordp = NULL;
+ rcsbuf->vlen = vlen;
+ rcsbuf->ptr = pat + 1;
+
+ return 1;
+ }
+
+ /* C is neither `:', `;' nor `@', so it should be the start of a num
+ or an id. Make sure it is not another special character. */
+ if (c == '$' || c == '.' || c == ',')
+ {
+ error (1, 0, "illegal special character in RCS field in %s",
+ rcsbuf->filename);
+ }
+
+ *wordp = ptr;
+ while (1)
+ {
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, wordp);
+ if (ptr == NULL)
+ error (1, 0, "unexpected end of file reading %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ /* Legitimate ID characters are digits, dots and any `graphic
+ printing character that is not a special.' This test ought
+ to do the trick. */
+ c = *ptr;
+ if (isprint ((unsigned char) c) &&
+ c != ';' && c != '$' && c != ',' && c != '@' && c != ':')
+ {
+ ++ptr;
+ continue;
+ }
+ break;
+ }
+
+ /* PTR points to the last non-id character in this word, and C is
+ the character in its memory cell. Check to make sure that it
+ is a legitimate word delimiter -- whitespace or semicolon. */
+ if (c == ';' || my_whitespace (c))
+ {
+ rcsbuf->vlen = ptr - *wordp;
+ rcsbuf->ptr = ptr;
+ return 1;
+ }
+
+ error (1, 0, "illegal special character in RCS field in %s",
+ rcsbuf->filename);
+ /* Shut up compiler warnings. */
+ return 0;
+
+#undef my_whitespace
+}
+
/* Read an RCS revision number from an RCS file. This sets *REVP to
point to the revision number; it will point to space that is
managed by the rcsbuf functions, and is only good until the next
@@ -1506,8 +1988,6 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp)
koff = *keyp - rcsbuf_buffer;
if (valp != NULL && *valp != NULL)
voff = *valp - rcsbuf_buffer;
- koff = keyp == NULL ? 0 : *keyp - rcsbuf_buffer;
- voff = valp == NULL ? 0 : *valp - rcsbuf_buffer;
expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size,
rcsbuf_buffer_size + RCSBUF_BUFSIZE);
@@ -1533,16 +2013,6 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp)
return ptr;
}
-/* Test whether the last value returned by rcsbuf_getkey is a composite
- value or not. */
-
-static int
-rcsbuf_valcmp (rcsbuf)
- struct rcsbuffer *rcsbuf;
-{
- return rcsbuf->at_string && rcsbuf->embedded_at < 0;
-}
-
/* Copy the value VAL returned by rcsbuf_getkey into a memory buffer,
returning the memory buffer. Polish the value like
rcsbuf_valpolish, q.v. */
@@ -1566,7 +2036,7 @@ rcsbuf_valcopy (rcsbuf, val, polish, lenp)
}
vlen = rcsbuf->vlen;
- embedded_at = rcsbuf->embedded_at < 0 ? 0 : rcsbuf->embedded_at;
+ embedded_at = rcsbuf->embedded_at;
ret = xmalloc (vlen - embedded_at + 1);
@@ -1673,7 +2143,6 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
orig_to = to;
embedded_at = rcsbuf->embedded_at;
- assert (embedded_at > 0);
if (lenp != NULL)
*lenp = len - embedded_at;
@@ -1722,112 +2191,6 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
}
}
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-
-/* Copy the next word from the value VALP returned by rcsbuf_getkey into a
- memory buffer, updating VALP and returning the memory buffer. Return
- NULL when there are no more words. */
-
-static char *
-rcsbuf_valword (rcsbuf, valp)
- struct rcsbuffer *rcsbuf;
- char **valp;
-{
- register const char * const my_spacetab = spacetab;
- register char *ptr, *pat;
- char c;
-
-#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
-
- if (*valp == NULL)
- return NULL;
-
- for (ptr = *valp; my_whitespace (*ptr); ++ptr) ;
- if (*ptr == '\0')
- {
- assert (ptr - *valp == rcsbuf->vlen);
- *valp = NULL;
- rcsbuf->vlen = 0;
- return NULL;
- }
-
- /* PTR now points to the start of a value. Find out whether it is
- a num, an id, a string or a colon. */
- c = *ptr;
- if (c == ':')
- {
- rcsbuf->vlen -= ++ptr - *valp;
- *valp = ptr;
- return xstrdup (":");
- }
-
- if (c == '@')
- {
- int embedded_at = 0;
- size_t vlen;
-
- pat = ++ptr;
- while ((pat = strchr (pat, '@')) != NULL)
- {
- if (pat[1] != '@')
- break;
- ++embedded_at;
- pat += 2;
- }
-
- /* Here PAT points to the final '@' in the string. */
- *pat++ = '\0';
- assert (rcsbuf->at_string);
- vlen = rcsbuf->vlen - (pat - *valp);
- rcsbuf->vlen = pat - ptr - 1;
- rcsbuf->embedded_at = embedded_at;
- ptr = rcsbuf_valcopy (rcsbuf, ptr, 0, (size_t *) NULL);
- *valp = pat;
- rcsbuf->vlen = vlen;
- if (strchr (pat, '@') == NULL)
- rcsbuf->at_string = 0;
- else
- rcsbuf->embedded_at = -1;
- return ptr;
- }
-
- /* *PTR is neither `:', `;' nor `@', so it should be the start of a num
- or an id. Make sure it is not another special character. */
- if (c == '$' || c == '.' || c == ',')
- {
- error (1, 0, "illegal special character in RCS field in %s",
- rcsbuf->filename);
- }
-
- pat = ptr;
- while (1)
- {
- /* Legitimate ID characters are digits, dots and any `graphic
- printing character that is not a special.' This test ought
- to do the trick. */
- c = *++pat;
- if (!isprint ((unsigned char) c) ||
- c == ';' || c == '$' || c == ',' || c == '@' || c == ':')
- break;
- }
-
- /* PAT points to the last non-id character in this word, and C is
- the character in its memory cell. Check to make sure that it
- is a legitimate word delimiter -- whitespace or end. */
- if (c != '\0' && !my_whitespace (c))
- error (1, 0, "illegal special character in RCS field in %s",
- rcsbuf->filename);
-
- *pat = '\0';
- rcsbuf->vlen -= pat - *valp;
- *valp = pat;
- return xstrdup (ptr);
-
-#undef my_whitespace
-}
-
-#endif
-
/* Return the current position of an rcsbuf. */
static unsigned long
@@ -2389,13 +2752,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);
@@ -2505,8 +2880,8 @@ RCS_nodeisbranch (rcs, rev)
return (1);
}
free (magic);
+ free (version);
}
- free (version);
return (0);
}
@@ -2555,8 +2930,8 @@ RCS_whatbranch (rcs, rev)
return (magic);
}
free (magic);
+ free (version);
}
- free (version);
return ((char *) NULL);
}
@@ -3346,27 +3721,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,
@@ -3375,8 +3754,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. */
@@ -3554,7 +3935,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;
@@ -3601,15 +3983,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);
@@ -3629,6 +4021,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;
}
@@ -3708,7 +4102,6 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
uses for ci -k. */
if (kw == KEYWORD_LOG
&& (sizeof "checked in with -k by " <= loglen
- || log == NULL
|| strncmp (log, "checked in with -k by ",
sizeof "checked in with -k by " - 1) != 0))
{
@@ -3727,10 +4120,6 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
if (expand != KFLAG_V)
++s;
- /* CVS never has empty log messages, but old RCS files might. */
- if (log == NULL)
- log = "";
-
/* Find the start of the line. */
start = srch;
while (start > buf && start[-1] != '\n')
@@ -4301,7 +4690,6 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
#ifdef PRESERVE_PERMISSIONS_SUPPORT
else if (special_file)
{
-#ifdef HAVE_MKNOD
char *dest;
/* Can send either to WORKFILE or to SOUT, as long as SOUT is
@@ -4322,11 +4710,6 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
if (mknod (dest, special_file, devnum) < 0)
error (1, errno, "could not create special file %s",
dest);
-#else
- error (1, 0,
-"cannot create %s: unable to create special files on this system",
-workfile);
-#endif
}
#endif
else
@@ -4690,10 +5073,8 @@ RCS_addbranch (rcs, branch)
if (nodep == NULL)
{
error (0, 0, "%s: can't find branch point %s", rcs->path, branchpoint);
- free (branchpoint);
return NULL;
}
- free (branchpoint);
branchnode = (RCSVers *) nodep->data;
/* If BRANCH was a full branch number, make sure it is higher than MAX. */
@@ -4895,7 +5276,6 @@ RCS_checkin (rcs, workfile, message, rev, flags)
if (S_ISLNK (sb.st_mode))
{
np = getnode();
- np->type = RCSFIELD;
np->key = xstrdup ("symlink");
np->data = xreadlink (workfile);
addnode (delta->other_delta, np);
@@ -4904,21 +5284,18 @@ RCS_checkin (rcs, workfile, message, rev, flags)
{
(void) sprintf (buf, "%u", sb.st_uid);
np = getnode();
- np->type = RCSFIELD;
np->key = xstrdup ("owner");
np->data = xstrdup (buf);
addnode (delta->other_delta, np);
(void) sprintf (buf, "%u", sb.st_gid);
np = getnode();
- np->type = RCSFIELD;
np->key = xstrdup ("group");
np->data = xstrdup (buf);
addnode (delta->other_delta, np);
(void) sprintf (buf, "%o", sb.st_mode & 07777);
np = getnode();
- np->type = RCSFIELD;
np->key = xstrdup ("permissions");
np->data = xstrdup (buf);
addnode (delta->other_delta, np);
@@ -4929,9 +5306,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
case S_IFREG: break;
case S_IFCHR:
case S_IFBLK:
-#ifdef HAVE_ST_RDEV
np = getnode();
- np->type = RCSFIELD;
np->key = xstrdup ("special");
sprintf (buf, "%s %lu",
((sb.st_mode & S_IFMT) == S_IFCHR
@@ -4939,11 +5314,6 @@ RCS_checkin (rcs, workfile, message, rev, flags)
(unsigned long) sb.st_rdev);
np->data = xstrdup (buf);
addnode (delta->other_delta, np);
-#else
- error (0, 0,
-"can't preserve %s: unable to save device files on this system",
-workfile);
-#endif
break;
default:
@@ -4988,9 +5358,8 @@ workfile);
delta->version = xstrdup (newrev);
nodep = getnode();
nodep->type = RCSVERS;
- nodep->delproc = rcsvers_delproc;
+ nodep->key = xstrdup (newrev);
nodep->data = (char *) delta;
- nodep->key = delta->version;
(void) addnode (rcs->versions, nodep);
dtext->version = xstrdup (newrev);
@@ -5024,6 +5393,7 @@ workfile);
error (1, errno, "cannot ftell for %s", rcs->path);
putdeltatext (fout, dtext);
rcs_internal_unlockfile (fout, rcs->path);
+ freedeltatext (dtext);
if ((flags & RCS_FLAGS_KEEPFILE) == 0)
{
@@ -5035,8 +5405,7 @@ workfile);
if (!checkin_quiet)
cvs_output ("done\n", 5);
- status = 0;
- goto checkin_done;
+ return 0;
}
/* Derive a new revision number. From the `ci' man page:
@@ -5132,13 +5501,6 @@ workfile);
goto checkin_done;
}
delta->version = RCS_addbranch (rcs, branch);
- if (!delta->version)
- {
- free (branch);
- free (newrev);
- status = 1;
- goto checkin_done;
- }
adding_branch = 1;
p = strrchr (branch, '.');
*p = '\0';
@@ -5363,9 +5725,8 @@ workfile);
rcs->versions = getlist();
nodep = getnode();
nodep->type = RCSVERS;
- nodep->delproc = rcsvers_delproc;
+ nodep->key = xstrdup (delta->version);
nodep->data = (char *) delta;
- nodep->key = delta->version;
(void) addnode (rcs->versions, nodep);
/* Write the new RCS file, inserting the new delta at COMMITPT. */
@@ -5388,10 +5749,8 @@ workfile);
}
if (unlink_file (tmpfile) < 0)
error (0, errno, "cannot remove %s", tmpfile);
- free (tmpfile);
if (unlink_file (changefile) < 0)
error (0, errno, "cannot remove %s", changefile);
- free (changefile);
if (!checkin_quiet)
cvs_output ("done\n", 5);
@@ -5474,7 +5833,6 @@ RCS_cmp_file (rcs, rev, options, filename)
retcode = xcmp (tmp, filename);
if (CVS_UNLINK (tmp) < 0)
error (0, errno, "cannot remove %s", tmp);
- free (tmp);
return retcode;
}
else
@@ -5835,14 +6193,17 @@ RCS_unlock (rcs, rev, unlock_quiet)
lock = NULL;
for (p = locks->list->next; p != locks->list; p = p->next)
{
- if (lock != NULL)
+ if (STREQ (p->data, user))
{
- if (!unlock_quiet)
- error (0, 0, "\
+ if (lock != NULL)
+ {
+ if (!unlock_quiet)
+ error (0, 0, "\
%s: multiple revisions locked by %s; please specify one", rcs->path, user);
- return 1;
+ return 1;
+ }
+ lock = p;
}
- lock = p;
}
if (lock == NULL)
return 0; /* no lock found, ergo nothing to do */
@@ -5922,7 +6283,6 @@ RCS_addaccess (rcs, user)
return;
}
}
- free (access);
rcs->access = (char *) xrealloc
(rcs->access, strlen (rcs->access) + strlen (user) + 2);
strcat (rcs->access, " ");
@@ -5946,19 +6306,13 @@ RCS_delaccess (rcs, user)
if (rcs->access == NULL)
return;
- if (user == NULL)
- {
- free (rcs->access);
- rcs->access = NULL;
- return;
- }
-
p = rcs->access;
ulen = strlen (user);
while (p != NULL)
{
- if (strncmp (p, user, ulen) == 0 && (p[ulen] == '\0' || p[ulen] == ' '))
- break;
+ if (p[ulen] == '\0' || p[ulen] == ' ')
+ if (strncmp (p, user, ulen) == 0)
+ break;
p = strchr (p, ' ');
if (p != NULL)
++p;
@@ -7357,7 +7711,7 @@ getdelta (rcsbuf, rcsfile, keyp, valp)
char **valp;
{
RCSVers *vnode;
- char *key, *value, *cp;
+ char *key, *value, *keybuf, *valbuf, *cp;
Node *kv;
/* Get revision number if it wasn't passed in. This uses
@@ -7475,32 +7829,81 @@ unable to parse %s; `state' not in the expected place", rcsfile);
*/
while (1)
{
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
+ int len;
+ size_t valbuflen;
+
+ key = NULL;
+
+ if (! rcsbuf_getid (rcsbuf, &keybuf))
error (1, 0, "unexpected end of file reading %s", rcsfile);
- /* The `desc' keyword is the end of the deltas. */
- if (strcmp (key, RCSDESC) == 0)
+ /* rcsbuf_getid did not terminate the key, so copy it to new space. */
+ len = rcsbuf->ptr - keybuf;
+ key = (char *) xmalloc (sizeof(char) * (len + 1));
+ strncpy (key, keybuf, len);
+ key[len] = '\0';
+
+ /* The `desc' keyword has only a single string value, with no
+ trailing semicolon, so it must be handled specially. */
+ if (STREQ (key, RCSDESC))
+ {
+ (void) rcsbuf_getstring (rcsbuf, &valbuf);
+ value = rcsbuf_valcopy (rcsbuf, valbuf, 1, &valbuflen);
break;
+ }
#ifdef PRESERVE_PERMISSIONS_SUPPORT
-
/* The `hardlinks' value is a group of words, which must
be parsed separately and added as a list to vnode->hardlinks. */
- if (strcmp (key, "hardlinks") == 0)
+ if (STREQ (key, "hardlinks"))
{
- char *word;
+ Node *n;
vnode->hardlinks = getlist();
- while ((word = rcsbuf_valword (rcsbuf, &value)) != NULL)
+ while (1)
{
- Node *n = getnode();
- n->key = word;
+ if (! rcsbuf_getword (rcsbuf, &valbuf))
+ error (1, 0, "unexpected end of file reading %s", rcsfile);
+ if (valbuf == NULL)
+ break;
+ n = getnode();
+ n->key = rcsbuf_valcopy (rcsbuf, valbuf, 1, NULL);
addnode (vnode->hardlinks, n);
}
continue;
}
#endif
+ /* Get the value. */
+ value = NULL;
+ while (1)
+ {
+ if (! rcsbuf_getword (rcsbuf, &valbuf))
+ error (1, 0, "unexpected end of file reading %s", rcsfile);
+ if (valbuf == NULL)
+ break;
+
+ /* Copy valbuf to new space so we can polish it, then
+ append it to value. */
+
+ if (value == NULL)
+ {
+ value = rcsbuf_valcopy (rcsbuf, valbuf, 1, &valbuflen);
+ }
+ else
+ {
+ char *temp_value;
+
+ temp_value = rcsbuf_valcopy (rcsbuf, valbuf, 1, &valbuflen);
+ len = strlen (value);
+ value = (char *) xrealloc
+ (value, sizeof(char) * (len + valbuflen + 2));
+ value[len] = ' ';
+ strcpy (value + len + 1, temp_value);
+ free (temp_value);
+ }
+ }
+
/* Enable use of repositories created by certain obsolete
versions of CVS. This code should remain indefinately;
there is no procedure for converting old repositories, and
@@ -7529,10 +7932,9 @@ unable to parse %s; `state' not in the expected place", rcsfile);
if (vnode->other_delta == NULL)
vnode->other_delta = getlist ();
kv = getnode ();
- kv->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
- kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (rcsbuf, value, kv->type == RCSFIELD,
- (size_t *) NULL);
+ kv->type = RCSFIELD;
+ kv->key = key;
+ kv->data = value;
if (addnode (vnode->other_delta, kv) != 0)
{
/* Complaining about duplicate keys in newphrases seems
@@ -7617,10 +8019,9 @@ RCS_getdeltatext (rcs, fp, rcsbuf)
break;
p = getnode();
- p->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
+ p->type = RCSFIELD;
p->key = xstrdup (key);
- p->data = rcsbuf_valcopy (rcsbuf, value, p->type == RCSFIELD,
- (size_t *) NULL);
+ p->data = rcsbuf_valcopy (rcsbuf, value, 1, (size_t *) NULL);
if (addnode (d->other, p) < 0)
{
error (0, 0, "warning: %s, delta %s: duplicate field `%s'",
@@ -7701,8 +8102,8 @@ putrcsfield_proc (node, vfp)
A case where we are wrong in a much more clear-cut way is that
we let through non-graphic characters such as whitespace and
control characters. */
-
- if (node->type == RCSCMPFLD || strpbrk (node->data, "$,.:;@") == NULL)
+ int n = strcspn (node->data, "$,.:;@");
+ if (node->data[n] == 0)
fputs (node->data, fp);
else
{
@@ -7863,13 +8264,7 @@ RCS_putdtree (rcs, rev, fp)
/* Find the delta node for this revision. */
p = findnode (rcs->versions, rev);
- if (p == NULL)
- {
- error (1, 0,
- "error parsing repository file %s, file may be corrupt.",
- rcs->path);
- }
-
+ assert (p != NULL);
versp = (RCSVers *) p->data;
/* Print the delta node and recurse on its `next' node. This prints
@@ -7990,7 +8385,6 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
/* If this revision has been outdated, just skip it. */
if (dadmin->outdated)
{
- freedeltatext (dtext);
--actions;
continue;
}
@@ -8110,7 +8504,7 @@ count_delta_actions (np, ignore)
/*
* Clean up temporary files
*/
-RETSIGTYPE
+static RETSIGTYPE
rcs_cleanup ()
{
/* Note that the checks for existence_error are because we are
@@ -8124,18 +8518,11 @@ rcs_cleanup ()
of a just-created file) reentrancy won't be an issue. */
if (rcs_lockfile != NULL)
{
- char *tmp = rcs_lockfile;
- rcs_lockfile = NULL;
- if (rcs_lockfd >= 0)
- {
- if (close (rcs_lockfd) != 0)
- error (0, errno, "error closing lock file %s", tmp);
- rcs_lockfd = -1;
- }
- if (unlink_file (tmp) < 0
+ if (unlink_file (rcs_lockfile) < 0
&& !existence_error (errno))
- error (0, errno, "cannot remove %s", tmp);
+ error (0, errno, "cannot remove %s", rcs_lockfile);
}
+ rcs_lockfile = NULL;
}
/* RCS_internal_lockfile and RCS_internal_unlockfile perform RCS-style
@@ -8169,6 +8556,7 @@ static FILE *
rcs_internal_lockfile (rcsfile)
char *rcsfile;
{
+ int fd;
struct stat rstat;
FILE *fp;
static int first_call = 1;
@@ -8177,9 +8565,6 @@ rcs_internal_lockfile (rcsfile)
{
first_call = 0;
/* clean up if we get a signal */
-#ifdef SIGABRT
- (void) SIG_register (SIGABRT, rcs_cleanup);
-#endif
#ifdef SIGHUP
(void) SIG_register (SIGHUP, rcs_cleanup);
#endif
@@ -8199,7 +8584,6 @@ rcs_internal_lockfile (rcsfile)
/* Get the lock file name: `,file,' for RCS file `file,v'. */
assert (rcs_lockfile == NULL);
- assert (rcs_lockfd < 0);
rcs_lockfile = rcs_lockfilename (rcsfile);
/* Use the existing RCS file mode, or read-only if this is a new
@@ -8226,11 +8610,11 @@ rcs_internal_lockfile (rcsfile)
rely on O_EXCL these days. This might be true for unix (I
don't really know), but I am still pretty skeptical in the case
of the non-unix systems. */
- rcs_lockfd = open (rcs_lockfile,
- OPEN_BINARY | O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
- S_IRUSR | S_IRGRP | S_IROTH);
+ fd = open (rcs_lockfile,
+ OPEN_BINARY | O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
+ S_IRUSR | S_IRGRP | S_IROTH);
- if (rcs_lockfd < 0)
+ if (fd < 0)
{
error (1, errno, "could not open lock file `%s'", rcs_lockfile);
}
@@ -8239,10 +8623,10 @@ rcs_internal_lockfile (rcsfile)
/* Because we change the modes later, we don't worry about
this in the non-HAVE_FCHMOD case. */
#ifdef HAVE_FCHMOD
- if (fchmod (rcs_lockfd, rstat.st_mode) < 0)
+ if (fchmod (fd, rstat.st_mode) < 0)
error (1, errno, "cannot change mode for %s", rcs_lockfile);
#endif
- fp = fdopen (rcs_lockfd, FOPEN_BINARY_WRITE);
+ fp = fdopen (fd, FOPEN_BINARY_WRITE);
if (fp == NULL)
error (1, errno, "cannot fdopen %s", rcs_lockfile);
@@ -8255,7 +8639,6 @@ rcs_internal_unlockfile (fp, rcsfile)
char *rcsfile;
{
assert (rcs_lockfile != NULL);
- assert (rcs_lockfd >= 0);
/* Abort if we could not write everything successfully to LOCKFILE.
This is not a great error-handling mechanism, but should prevent
@@ -8271,7 +8654,6 @@ rcs_internal_unlockfile (fp, rcsfile)
error (1, 0, "error writing to lock file %s", rcs_lockfile);
if (fclose (fp) == EOF)
error (1, errno, "error closing lock file %s", rcs_lockfile);
- rcs_lockfd = -1;
rename_file (rcs_lockfile, rcsfile);
@@ -8365,22 +8747,6 @@ RCS_rewrite (rcs, newdtext, insertpt)
rcs_internal_unlockfile (fout, rcs->path);
}
-/* Abandon changes to an RCS file. */
-
-void
-RCS_abandon (rcs)
- RCSNode *rcs;
-{
- free_rcsnode_contents (rcs);
- rcs->symbols_data = NULL;
- rcs->expand = NULL;
- rcs->access = NULL;
- rcs->locks_data = NULL;
- rcs->comment = NULL;
- rcs->desc = NULL;
- rcs->flags |= PARTIAL;
-}
-
/* Annotate command. In rcs.c for historical reasons (from back when
what is now RCS_deltas was part of annotate_fileproc). */
@@ -8565,3 +8931,105 @@ make_file_label (path, rev, rcs)
}
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++)
+ {
+ keyword->expandit = 0;
+ }
+
+ key = strtok(next, ",");
+ while (key) {
+ for (keyword = keywords; keyword->string != NULL; keyword++) {
+ if (strcmp (keyword->string, key) == 0)
+ keyword->expandit = include;
+ }
+ key = strtok(NULL, ",");
+ }
+ 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 3466398..7aee90a 100644
--- a/contrib/cvs/src/rcs.h
+++ b/contrib/cvs/src/rcs.h
@@ -6,12 +6,12 @@
* 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. */
-#define RCS_MERGE_PAT_1 "<<<<<<< "
-#define RCS_MERGE_PAT_2 "=======\n"
-#define RCS_MERGE_PAT_3 ">>>>>>> "
+/* String which indicates a conflict if it occurs at the start of a line. */
+#define RCS_MERGE_PAT ">>>>>>> "
#define RCSEXT ",v"
#define RCSPAT "*,v"
@@ -229,11 +229,12 @@ int RCS_delete_revs PROTO ((RCSNode *, char *, char *, int));
void RCS_addaccess PROTO ((RCSNode *, char *));
void RCS_delaccess PROTO ((RCSNode *, char *));
char *RCS_getaccess PROTO ((RCSNode *));
-RETSIGTYPE rcs_cleanup PROTO ((void));
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_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 ab94e40..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"
diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c
index 1cb2fbb..209d324 100644
--- a/contrib/cvs/src/recurse.c
+++ b/contrib/cvs/src/recurse.c
@@ -6,6 +6,7 @@
*
* General recursion handler
*
+ * $FreeBSD$
*/
#include "cvs.h"
@@ -173,7 +174,6 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
seems to be handled somewhere (else) but why should
it be a separate case? Needs investigation... */
just_subdirs = 1;
- free (root);
}
#endif
@@ -591,7 +591,7 @@ do_recursion (frame)
/* Add it to our list. */
Node *n = getnode ();
- n->type = NT_UNKNOWN;
+ n->type = UNKNOWN;
n->key = xstrdup (this_root);
if (addnode (root_directories, n))
@@ -1016,7 +1016,7 @@ but CVS uses %s for its own purposes; skipping %s directory",
/* Add it to our list. */
Node *n = getnode ();
- n->type = NT_UNKNOWN;
+ n->type = UNKNOWN;
n->key = xstrdup (this_root);
if (addnode (root_directories, n))
@@ -1133,7 +1133,6 @@ addfile (listp, dir, file)
char *file;
{
Node *n;
- List *fl;
/* add this dir. */
addlist (listp, dir);
@@ -1146,9 +1145,7 @@ addfile (listp, dir, file)
}
n->type = DIRS;
- fl = (List *) n->data;
- addlist (&fl, file);
- n->data = (char *) fl;
+ addlist ((List **) &n->data, file);
return;
}
@@ -1208,7 +1205,6 @@ unroll_files_proc (p, closure)
}
dirlist = save_dirlist;
- if (filelist)
- dellist (&filelist);
+ filelist = NULL;
return(err);
}
diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c
index e1af5e4..63fef8c 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"
@@ -183,7 +187,6 @@ static int fd_buffer_input PROTO((void *, char *, int, int, int *));
static int fd_buffer_output PROTO((void *, const char *, int, int *));
static int fd_buffer_flush PROTO((void *));
static int fd_buffer_block PROTO((void *, int));
-static int fd_buffer_shutdown PROTO((void *));
/* Initialize a buffer built on a file descriptor. FD is the file
descriptor. INPUT is nonzero if this is for input, zero if this is
@@ -205,7 +208,7 @@ fd_buffer_initialize (fd, input, memory)
input ? NULL : fd_buffer_output,
input ? NULL : fd_buffer_flush,
fd_buffer_block,
- fd_buffer_shutdown,
+ (int (*) PROTO((void *))) NULL,
memory,
n);
}
@@ -342,16 +345,6 @@ fd_buffer_block (closure, block)
return 0;
}
-/* The buffer shutdown function for a buffer built on a file descriptor. */
-
-static int
-fd_buffer_shutdown (closure)
- void *closure;
-{
- free (closure);
- return 0;
-}
-
/* Populate all of the directories between BASE_DIR and its relative
subdirectory DIR with CVSADM directories. Return 0 for success or
errno value. */
@@ -749,6 +742,8 @@ serve_root (arg)
{
char *env;
char *path;
+ int save_errno;
+ char *arg_dup;
if (error_pending()) return;
@@ -790,14 +785,25 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"",
}
}
#endif
- set_local_cvsroot (arg);
+ arg_dup = malloc (strlen (arg) + 1);
+ if (arg_dup == NULL)
+ {
+ pending_error = ENOMEM;
+ return;
+ }
+ strcpy (arg_dup, arg);
+ set_local_cvsroot (arg_dup);
/* For pserver, this will already have happened, and the call will do
nothing. But for rsh, we need to do it now. */
parse_config (CVSroot_directory);
+ /* Now is a good time to read CVSROOT/options too. */
+ parseopts(CVSroot_directory);
+
path = malloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
+ + sizeof (CVSROOTADM_HISTORY)
+ 10);
if (path == NULL)
{
@@ -807,11 +813,23 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"",
(void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
if (!isaccessible (path, R_OK | X_OK))
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (path)))
+ save_errno = errno;
+ pending_error_text = malloc (80 + strlen (path));
+ if (pending_error_text != NULL)
sprintf (pending_error_text, "E Cannot access %s", path);
pending_error = save_errno;
}
+ (void) strcat (path, "/");
+ (void) strcat (path, CVSROOTADM_HISTORY);
+ if (readonlyfs == 0 && isfile (path) && !isaccessible (path, R_OK | W_OK))
+ {
+ save_errno = errno;
+ pending_error_text = malloc (80 + strlen (path));
+ if (pending_error_text != NULL)
+ sprintf (pending_error_text, "E \
+Sorry, you don't have read/write access to the history file %s", path);
+ pending_error = save_errno;
+ }
free (path);
#ifdef HAVE_PUTENV
@@ -1025,9 +1043,9 @@ dirswitch (dir, repos)
if (status != 0
&& status != EEXIST)
{
+ pending_error = status;
if (alloc_pending (80 + strlen (dir_name)))
sprintf (pending_error_text, "E cannot mkdir %s", dir_name);
- pending_error = status;
return;
}
@@ -1040,18 +1058,17 @@ dirswitch (dir, repos)
status = create_adm_p (server_temp_dir, dir);
if (status != 0)
{
+ pending_error = status;
if (alloc_pending (80 + strlen (dir_name)))
sprintf (pending_error_text, "E cannot create_adm_p %s", dir_name);
- pending_error = status;
return;
}
if ( CVS_CHDIR (dir_name) < 0)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (dir_name)))
sprintf (pending_error_text, "E cannot change to %s", dir_name);
- pending_error = save_errno;
return;
}
/*
@@ -1060,14 +1077,10 @@ dirswitch (dir, repos)
*/
if ((CVS_MKDIR (CVSADM, 0777) < 0) && (errno != EEXIST))
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM)))
- sprintf (pending_error_text,
- "E cannot mkdir %s/%s", dir_name, CVSADM);
- pending_error = save_errno;
+ pending_error = errno;
return;
}
-
+
/* The following will overwrite the contents of CVSADM_REP. This
is the correct behavior -- mkdir_p may have written a
placeholder value to this file and we need to insert the
@@ -1076,20 +1089,12 @@ dirswitch (dir, repos)
f = CVS_FOPEN (CVSADM_REP, "w");
if (f == NULL)
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E cannot open %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
+ pending_error = errno;
return;
}
if (fprintf (f, "%s", repos) < 0)
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error writing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
+ pending_error = errno;
fclose (f);
return;
}
@@ -1102,32 +1107,20 @@ dirswitch (dir, repos)
{
if (fprintf (f, "/.") < 0)
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error writing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
+ pending_error = errno;
fclose (f);
return;
}
}
if (fprintf (f, "\n") < 0)
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error writing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
+ pending_error = errno;
fclose (f);
return;
}
if (fclose (f) == EOF)
{
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error closing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
+ pending_error = errno;
return;
}
/* We open in append mode because we don't want to clobber an
@@ -1135,18 +1128,16 @@ dirswitch (dir, repos)
f = CVS_FOPEN (CVSADM_ENT, "a");
if (f == NULL)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_ENT)))
sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
- pending_error = save_errno;
return;
}
if (fclose (f) == EOF)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_ENT)))
sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
- pending_error = save_errno;
return;
}
}
@@ -1155,7 +1146,10 @@ static void
serve_repository (arg)
char *arg;
{
- if (alloc_pending (80))
+ pending_error_text = malloc (80);
+ if (pending_error_text == NULL)
+ pending_error = ENOMEM;
+ else
strcpy (pending_error_text,
"E Repository request is obsolete; aborted");
return;
@@ -1171,8 +1165,9 @@ serve_directory (arg)
status = buf_read_line (buf_from_net, &repos, (int *) NULL);
if (status == 0)
{
- if (!outside_root (repos))
- dirswitch (arg, repos);
+ if (outside_root (repos))
+ return;
+ dirswitch (arg, repos);
free (repos);
}
else if (status == -2)
@@ -1211,18 +1206,16 @@ serve_static_directory (arg)
f = CVS_FOPEN (CVSADM_ENTSTAT, "w+");
if (f == NULL)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
sprintf (pending_error_text, "E cannot open %s", CVSADM_ENTSTAT);
- pending_error = save_errno;
return;
}
if (fclose (f) == EOF)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
sprintf (pending_error_text, "E cannot close %s", CVSADM_ENTSTAT);
- pending_error = save_errno;
return;
}
}
@@ -1238,26 +1231,23 @@ serve_sticky (arg)
f = CVS_FOPEN (CVSADM_TAG, "w+");
if (f == NULL)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_TAG)))
sprintf (pending_error_text, "E cannot open %s", CVSADM_TAG);
- pending_error = save_errno;
return;
}
if (fprintf (f, "%s\n", arg) < 0)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_TAG)))
sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG);
- pending_error = save_errno;
return;
}
if (fclose (f) == EOF)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_TAG)))
sprintf (pending_error_text, "E cannot close %s", CVSADM_TAG);
- pending_error = save_errno;
return;
}
}
@@ -1316,10 +1306,10 @@ receive_partial_file (size, file)
nwrote = write (file, data, nread);
if (nwrote < 0)
{
- int save_errno = errno;
- if (alloc_pending (40))
- strcpy (pending_error_text, "E unable to write");
- pending_error = save_errno;
+ pending_error_text = malloc (40);
+ if (pending_error_text != NULL)
+ sprintf (pending_error_text, "E unable to write");
+ pending_error = errno;
/* Read and discard the file data. */
while (size > 0)
@@ -1355,10 +1345,10 @@ receive_file (size, file, gzipped)
fd = CVS_OPEN (arg, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
{
- int save_errno = errno;
- if (alloc_pending (40 + strlen (arg)))
+ pending_error_text = malloc (40 + strlen (arg));
+ if (pending_error_text)
sprintf (pending_error_text, "E cannot open %s", arg);
- pending_error = save_errno;
+ pending_error = errno;
return;
}
@@ -1424,7 +1414,7 @@ receive_file (size, file, gzipped)
goto out;
}
- if (gunzip_and_write (fd, file, (unsigned char *) filebuf, size))
+ if (gunzip_and_write (fd, file, filebuf, size))
{
if (alloc_pending (80))
sprintf (pending_error_text,
@@ -1450,10 +1440,10 @@ receive_file (size, file, gzipped)
out:
if (close (fd) < 0 && !error_pending ())
{
- int save_errno = errno;
- if (alloc_pending (40 + strlen (arg)))
+ pending_error_text = malloc (40 + strlen (arg));
+ if (pending_error_text)
sprintf (pending_error_text, "E cannot close %s", arg);
- pending_error = save_errno;
+ pending_error = errno;
return;
}
}
@@ -1532,11 +1522,10 @@ serve_modified (arg)
{
sprintf (pending_error_text,
"E error reading size for %s", arg);
- pending_error = status;
+ pending_error = errno;
}
}
}
- free (mode_text);
return;
}
if (size_text[0] == 'z')
@@ -1561,24 +1550,16 @@ serve_modified (arg)
return;
size -= nread;
}
- free (mode_text);
return;
}
if (outside_dir (arg))
- {
- free (mode_text);
return;
- }
if (size >= 0)
{
receive_file (size, arg, gzipped);
- if (error_pending ())
- {
- free (mode_text);
- return;
- }
+ if (error_pending ()) return;
}
if (checkin_time_valid)
@@ -1589,11 +1570,9 @@ serve_modified (arg)
t.modtime = t.actime = checkin_time;
if (utime (arg, &t) < 0)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (arg)))
sprintf (pending_error_text, "E cannot utime %s", arg);
- pending_error = save_errno;
- free (mode_text);
return;
}
checkin_time_valid = 0;
@@ -1604,7 +1583,8 @@ serve_modified (arg)
free (mode_text);
if (status)
{
- if (alloc_pending (40 + strlen (arg)))
+ pending_error_text = malloc (40 + strlen (arg));
+ if (pending_error_text)
sprintf (pending_error_text,
"E cannot change mode for %s", arg);
pending_error = status;
@@ -1879,10 +1859,9 @@ server_write_entries ()
f = CVS_FOPEN (CVSADM_ENT, "a");
if (f == NULL)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_ENT)))
sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
- pending_error = save_errno;
}
}
for (p = entries; p != NULL;)
@@ -1891,11 +1870,10 @@ server_write_entries ()
{
if (fprintf (f, "%s\n", p->entry) < 0)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen(CVSADM_ENT)))
sprintf (pending_error_text,
"E cannot write to %s", CVSADM_ENT);
- pending_error = save_errno;
}
}
free (p->entry);
@@ -1906,10 +1884,9 @@ server_write_entries ()
entries = NULL;
if (f != NULL && fclose (f) == EOF && !error_pending ())
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_ENT)))
sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
- pending_error = save_errno;
}
}
@@ -1941,8 +1918,8 @@ static void
serve_notify (arg)
char *arg;
{
- struct notify_note *new = NULL;
- char *data = NULL;
+ struct notify_note *new;
+ char *data;
int status;
if (error_pending ()) return;
@@ -1950,26 +1927,27 @@ serve_notify (arg)
if (outside_dir (arg))
return;
- if (dir_name == NULL)
- goto error;
-
new = (struct notify_note *) malloc (sizeof (struct notify_note));
if (new == NULL)
{
pending_error = ENOMEM;
return;
}
+ if (dir_name == NULL)
+ goto error;
new->dir = malloc (strlen (dir_name) + 1);
- new->filename = malloc (strlen (arg) + 1);
- if (new->dir == NULL || new->filename == NULL)
+ if (new->dir == NULL)
{
pending_error = ENOMEM;
- if (new->dir != NULL)
- free (new->dir);
- free (new);
return;
}
strcpy (new->dir, dir_name);
+ new->filename = malloc (strlen (arg) + 1);
+ if (new->filename == NULL)
+ {
+ pending_error = ENOMEM;
+ return;
+ }
strcpy (new->filename, arg);
status = buf_read_line (buf_from_net, &data, (int *) NULL);
@@ -1995,9 +1973,6 @@ serve_notify (arg)
}
}
}
- free (new->filename);
- free (new->dir);
- free (new);
}
else
{
@@ -2045,18 +2020,11 @@ serve_notify (arg)
}
return;
error:
- pending_error = 0;
- if (alloc_pending (80))
+ pending_error_text = malloc (80);
+ if (pending_error_text)
strcpy (pending_error_text,
"E Protocol error; misformed Notify request");
- if (data != NULL)
- free (data);
- if (new != NULL)
- {
- free (new->filename);
- free (new->dir);
- free (new);
- }
+ pending_error = 0;
return;
}
@@ -2099,7 +2067,6 @@ server_notify ()
buf_append_char (buf_to_net, '/');
buf_output0 (buf_to_net, notify_list->filename);
buf_append_char (buf_to_net, '\n');
- free (repos);
p = notify_list->next;
free (notify_list->filename);
@@ -2687,26 +2654,22 @@ error \n");
if (pipe (stdout_pipe) < 0)
{
- buf_output0 (buf_to_net, "E pipe failed\n");
print_error (errno);
goto error_exit;
}
if (pipe (stderr_pipe) < 0)
{
- buf_output0 (buf_to_net, "E pipe failed\n");
print_error (errno);
goto error_exit;
}
if (pipe (protocol_pipe) < 0)
{
- buf_output0 (buf_to_net, "E pipe failed\n");
print_error (errno);
goto error_exit;
}
#ifdef SERVER_FLOWCONTROL
if (pipe (flowcontrol_pipe) < 0)
{
- buf_output0 (buf_to_net, "E pipe failed\n");
print_error (errno);
goto error_exit;
}
@@ -2717,7 +2680,6 @@ error \n");
dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY);
if (dev_null_fd < 0)
{
- buf_output0 (buf_to_net, "E open /dev/null failed\n");
print_error (errno);
goto error_exit;
}
@@ -2745,7 +2707,6 @@ error \n");
command_pid = fork ();
if (command_pid < 0)
{
- buf_output0 (buf_to_net, "E fork failed\n");
print_error (errno);
goto error_exit;
}
@@ -2779,11 +2740,8 @@ error \n");
error (1, errno, "can't set up pipes");
if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
error (1, errno, "can't set up pipes");
- close (dev_null_fd);
close (stdout_pipe[0]);
- close (stdout_pipe[1]);
close (stderr_pipe[0]);
- close (stderr_pipe[1]);
close (protocol_pipe[0]);
#ifdef SERVER_FLOWCONTROL
close (flowcontrol_pipe[1]);
@@ -2818,7 +2776,6 @@ error \n");
* When we exit, that will close the pipes, giving an EOF to
* the parent.
*/
- buf_free (protocol);
exit (exitstatus);
}
@@ -2875,7 +2832,6 @@ error \n");
if (close (stdout_pipe[1]) < 0)
{
- buf_output0 (buf_to_net, "E close failed\n");
print_error (errno);
goto error_exit;
}
@@ -2883,7 +2839,6 @@ error \n");
if (close (stderr_pipe[1]) < 0)
{
- buf_output0 (buf_to_net, "E close failed\n");
print_error (errno);
goto error_exit;
}
@@ -2891,7 +2846,6 @@ error \n");
if (close (protocol_pipe[1]) < 0)
{
- buf_output0 (buf_to_net, "E close failed\n");
print_error (errno);
goto error_exit;
}
@@ -2900,7 +2854,6 @@ error \n");
#ifdef SERVER_FLOWCONTROL
if (close (flowcontrol_pipe[0]) < 0)
{
- buf_output0 (buf_to_net, "E close failed\n");
print_error (errno);
goto error_exit;
}
@@ -2909,7 +2862,6 @@ error \n");
if (close (dev_null_fd) < 0)
{
- buf_output0 (buf_to_net, "E close failed\n");
print_error (errno);
goto error_exit;
}
@@ -2977,7 +2929,6 @@ error \n");
if (numfds < 0
&& errno != EINTR)
{
- buf_output0 (buf_to_net, "E select failed\n");
print_error (errno);
goto error_exit;
}
@@ -2989,6 +2940,48 @@ error \n");
buf_send_output (buf_to_net);
}
+ if (stdout_pipe[0] >= 0
+ && (FD_ISSET (stdout_pipe[0], &readfds)))
+ {
+ int status;
+
+ status = buf_input_data (stdoutbuf, (int *) NULL);
+
+ buf_copy_lines (buf_to_net, stdoutbuf, 'M');
+
+ if (status == -1)
+ stdout_pipe[0] = -1;
+ else if (status > 0)
+ {
+ print_error (status);
+ goto error_exit;
+ }
+
+ /* What should we do with errors? syslog() them? */
+ buf_send_output (buf_to_net);
+ }
+
+ if (stderr_pipe[0] >= 0
+ && (FD_ISSET (stderr_pipe[0], &readfds)))
+ {
+ int status;
+
+ status = buf_input_data (stderrbuf, (int *) NULL);
+
+ buf_copy_lines (buf_to_net, stderrbuf, 'E');
+
+ if (status == -1)
+ stderr_pipe[0] = -1;
+ else if (status > 0)
+ {
+ print_error (status);
+ goto error_exit;
+ }
+
+ /* What should we do with errors? syslog() them? */
+ buf_send_output (buf_to_net);
+ }
+
if (protocol_pipe[0] >= 0
&& (FD_ISSET (protocol_pipe[0], &readfds)))
{
@@ -2999,13 +2992,9 @@ error \n");
status = buf_input_data (protocol_inbuf, &count_read);
if (status == -1)
- {
- close (protocol_pipe[0]);
protocol_pipe[0] = -1;
- }
else if (status > 0)
{
- buf_output0 (buf_to_net, "E buf_input_data failed\n");
print_error (status);
goto error_exit;
}
@@ -3042,56 +3031,6 @@ error \n");
}
}
}
-
- if (stdout_pipe[0] >= 0
- && (FD_ISSET (stdout_pipe[0], &readfds)))
- {
- int status;
-
- status = buf_input_data (stdoutbuf, (int *) NULL);
-
- buf_copy_lines (buf_to_net, stdoutbuf, 'M');
-
- if (status == -1)
- {
- close (stdout_pipe[0]);
- stdout_pipe[0] = -1;
- }
- else if (status > 0)
- {
- buf_output0 (buf_to_net, "E buf_input_data failed\n");
- print_error (status);
- goto error_exit;
- }
-
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
- }
-
- if (stderr_pipe[0] >= 0
- && (FD_ISSET (stderr_pipe[0], &readfds)))
- {
- int status;
-
- status = buf_input_data (stderrbuf, (int *) NULL);
-
- buf_copy_lines (buf_to_net, stderrbuf, 'E');
-
- if (status == -1)
- {
- close (stderr_pipe[0]);
- stderr_pipe[0] = -1;
- }
- else if (status > 0)
- {
- buf_output0 (buf_to_net, "E buf_input_data failed\n");
- print_error (status);
- goto error_exit;
- }
-
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
- }
}
/*
@@ -3113,11 +3052,6 @@ error \n");
buf_output0 (buf_to_net,
"E Protocol error: uncounted data discarded\n");
-#ifdef SERVER_FLOWCONTROL
- close (flowcontrol_pipe[1]);
- flowcontrol_pipe[1] = -1;
-#endif /* SERVER_FLOWCONTROL */
-
errs = 0;
while (command_pid > 0)
@@ -3172,12 +3106,6 @@ E CVS locks may need cleaning up.\n");
*/
set_block (buf_to_net);
buf_flush (buf_to_net, 1);
- buf_shutdown (protocol_inbuf);
- buf_free (protocol_inbuf);
- buf_shutdown (stderrbuf);
- buf_free (stderrbuf);
- buf_shutdown (stdoutbuf);
- buf_free (stdoutbuf);
}
if (errs)
@@ -3208,10 +3136,6 @@ E CVS locks may need cleaning up.\n");
close (stderr_pipe[1]);
close (stdout_pipe[0]);
close (stdout_pipe[1]);
-#ifdef SERVER_FLOWCONTROL
- close (flowcontrol_pipe[0]);
- close (flowcontrol_pipe[1]);
-#endif /* SERVER_FLOWCONTROL */
free_args_and_return:
/* Now free the arguments. */
@@ -3267,7 +3191,6 @@ server_pause_check()
if (numfds < 0
&& errno != EINTR)
{
- buf_output0 (buf_to_net, "E select failed\n");
print_error (errno);
return;
}
@@ -3708,29 +3631,23 @@ serve_editors (arg)
do_cvs_command ("editors", editors);
}
-static void serve_noop PROTO ((char *));
+static int noop PROTO ((int, char **));
-static void
-serve_noop (arg)
- char *arg;
+static int
+noop (argc, argv)
+ int argc;
+ char **argv;
{
-
- server_write_entries ();
- if (!print_pending_error ())
- {
- (void) server_notify ();
- buf_output0 (buf_to_net, "ok\n");
- }
- buf_flush (buf_to_net, 1);
+ return 0;
}
-static void serve_version PROTO ((char *));
+static void serve_noop PROTO ((char *));
static void
-serve_version (arg)
+serve_noop (arg)
char *arg;
{
- do_cvs_command ("version", version);
+ do_cvs_command ("noop", noop);
}
static void serve_init PROTO ((char *));
@@ -4107,7 +4024,7 @@ CVS server internal error: unhandled case in server_updated");
if (file != NULL)
{
- buf_output (protocol, (char *) file, file_used);
+ buf_output (protocol, file, file_used);
free (file);
file = NULL;
}
@@ -4404,9 +4321,9 @@ serve_ignore (arg)
}
static int
-expand_proc (argc, argv, where, mwhere, mfile, shorten,
+expand_proc (pargc, argv, where, mwhere, mfile, shorten,
local_specified, omodule, msg)
- int argc;
+ int *pargc;
char **argv;
char *where;
char *mwhere;
@@ -4445,7 +4362,7 @@ expand_proc (argc, argv, where, mwhere, mfile, shorten,
{
/* We may not need to do this anymore -- check the definition
of aliases before removing */
- if (argc == 1)
+ if (*pargc == 1)
{
buf_output0 (buf_to_net, "Module-expansion ");
if (server_dir != NULL)
@@ -4458,7 +4375,7 @@ expand_proc (argc, argv, where, mwhere, mfile, shorten,
}
else
{
- for (i = 1; i < argc; ++i)
+ for (i = 1; i < *pargc; ++i)
{
buf_output0 (buf_to_net, "Module-expansion ");
if (server_dir != NULL)
@@ -4550,27 +4467,24 @@ serve_checkin_prog (arg)
f = CVS_FOPEN (CVSADM_CIPROG, "w+");
if (f == NULL)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
sprintf (pending_error_text, "E cannot open %s", CVSADM_CIPROG);
- pending_error = save_errno;
return;
}
if (fprintf (f, "%s\n", arg) < 0)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
sprintf (pending_error_text,
"E cannot write to %s", CVSADM_CIPROG);
- pending_error = save_errno;
return;
}
if (fclose (f) == EOF)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
sprintf (pending_error_text, "E cannot close %s", CVSADM_CIPROG);
- pending_error = save_errno;
return;
}
}
@@ -4596,26 +4510,23 @@ E Flag -u in modules not allowed in readonly mode");
f = CVS_FOPEN (CVSADM_UPROG, "w+");
if (f == NULL)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_UPROG)))
sprintf (pending_error_text, "E cannot open %s", CVSADM_UPROG);
- pending_error = save_errno;
return;
}
if (fprintf (f, "%s\n", arg) < 0)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_UPROG)))
sprintf (pending_error_text, "E cannot write to %s", CVSADM_UPROG);
- pending_error = save_errno;
return;
}
if (fclose (f) == EOF)
{
- int save_errno = errno;
+ pending_error = errno;
if (alloc_pending (80 + strlen (CVSADM_UPROG)))
sprintf (pending_error_text, "E cannot close %s", CVSADM_UPROG);
- pending_error = save_errno;
return;
}
}
@@ -4668,7 +4579,7 @@ struct request requests[] =
REQ_LINE("Case", serve_case, 0),
REQ_LINE("Argument", serve_argument, RQ_ESSENTIAL),
REQ_LINE("Argumentx", serve_argumentx, RQ_ESSENTIAL),
- REQ_LINE("Global_option", serve_global_option, RQ_ROOTLESS),
+ REQ_LINE("Global_option", serve_global_option, 0),
REQ_LINE("Gzip-stream", serve_gzip_stream, 0),
REQ_LINE("wrapper-sendme-rcsOptions",
serve_wrapper_sendme_rcs_options,
@@ -4712,8 +4623,7 @@ struct request requests[] =
REQ_LINE("editors", serve_editors, 0),
REQ_LINE("init", serve_init, RQ_ROOTLESS),
REQ_LINE("annotate", serve_annotate, 0),
- REQ_LINE("noop", serve_noop, RQ_ROOTLESS),
- REQ_LINE("version", serve_version, RQ_ROOTLESS),
+ REQ_LINE("noop", serve_noop, 0),
REQ_LINE(NULL, NULL, 0)
#undef REQ_LINE
@@ -4937,10 +4847,16 @@ server (argc, argv)
for that case. */
if (!isabsolute (Tmpdir))
{
- if (alloc_pending (80 + strlen (Tmpdir)))
+ pending_error_text = malloc (80 + strlen (Tmpdir));
+ if (pending_error_text == NULL)
+ {
+ pending_error = ENOMEM;
+ }
+ else
+ {
sprintf (pending_error_text,
"E Value of %s for TMPDIR is not absolute", Tmpdir);
-
+ }
/* FIXME: we would like this error to be persistent, that
is, not cleared by print_pending_error. The current client
will exit as soon as it gets an error, but the protocol spec
@@ -4949,7 +4865,6 @@ server (argc, argv)
else
{
int status;
- int i = 0;
server_temp_dir = malloc (strlen (Tmpdir) + 80);
if (server_temp_dir == NULL)
@@ -4996,21 +4911,12 @@ error ENOMEM Virtual memory exhausted.\n");
/* Create the temporary directory, and set the mode to
700, to discourage random people from tampering with
it. */
- while ((status = mkdir_p (server_temp_dir)) == EEXIST)
+ status = mkdir_p (server_temp_dir);
+ if (status != 0 && status != EEXIST)
{
- static const char suffix[] = "abcdefghijklmnopqrstuvwxyz";
-
- if (i >= sizeof suffix - 1) break;
- if (i == 0) p = server_temp_dir + strlen (server_temp_dir);
- p[0] = suffix[i++];
- p[1] = '\0';
- }
- if (status != 0)
- {
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
- "E can't create temporary directory %s",
- server_temp_dir);
+ if (alloc_pending (80))
+ strcpy (pending_error_text,
+ "E can't create temporary directory");
pending_error = status;
}
#ifndef CHMOD_BROKEN
@@ -5019,10 +4925,9 @@ error ENOMEM Virtual memory exhausted.\n");
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);
+ if (alloc_pending (80))
+ strcpy (pending_error_text, "\
+E cannot change permissions on temporary directory");
pending_error = save_errno;
}
}
@@ -5030,9 +4935,6 @@ error ENOMEM Virtual memory exhausted.\n");
}
}
-#ifdef SIGABRT
- (void) SIG_register (SIGABRT, server_cleanup);
-#endif
#ifdef SIGHUP
(void) SIG_register (SIGHUP, server_cleanup);
#endif
@@ -5212,7 +5114,7 @@ error 0 %s: no such user\n", username);
if (setgid (getegid ()) < 0)
{
/* See comments at setuid call below for more discussion. */
- printf ("error 0 setgid failed: %s\n", strerror (errno));
+ printf ("error 0 setuid failed: %s\n", strerror (errno));
/* Don't worry about server_cleanup;
server_active isn't set yet. */
error_exit ();
@@ -5224,7 +5126,7 @@ error 0 %s: no such user\n", username);
if (setgid (pw->pw_gid) < 0)
{
/* See comments at setuid call below for more discussion. */
- printf ("error 0 setgid failed: %s\n", strerror (errno));
+ printf ("error 0 setuid failed: %s\n", strerror (errno));
/* Don't worry about server_cleanup;
server_active isn't set yet. */
error_exit ();
@@ -5249,12 +5151,6 @@ error 0 %s: no such user\n", username);
the client. */
umask (0);
-#ifdef AUTH_SERVER_SUPPORT
- /* Make sure our CVS_Username has been set. */
- if (CVS_Username == NULL)
- CVS_Username = xstrdup (username);
-#endif
-
#if HAVE_PUTENV
/* Set LOGNAME and USER in the environment, in case they are
already set to something else. */
@@ -5280,15 +5176,14 @@ extern char *crypt PROTO((const char *, const char *));
/*
* 0 means no entry found for this user.
- * 1 means entry found and password matches (or found password is empty)
+ * 1 means entry found and password matches.
* 2 means entry found, but password does not match.
*
- * If 1, host_user_ptr will be set to point at the system
+ * If success, host_user_ptr will be set to point at the system
* username (i.e., the "real" identity, which may or may not be the
* CVS username) of this user; caller may free this. Global
* CVS_Username will point at an allocated copy of cvs username (i.e.,
* the username argument below).
- * kff todo: FIXME: last sentence is not true, it applies to caller.
*/
static int
check_repository_password (username, password, repository, host_user_ptr)
@@ -5341,72 +5236,21 @@ check_repository_password (username, password, repository, host_user_ptr)
if (fclose (fp) < 0)
error (0, errno, "cannot close %s", filename);
- /* If found_it, then linebuf contains the information we need. */
+ /* If found_it != 0, then linebuf contains the information we need. */
if (found_it)
{
- char *found_password, *host_user_tmp;
- char *non_cvsuser_portion;
+ char *found_password, *host_user_tmp = NULL;
+ char *linebufp = linebuf;
- /* We need to make sure lines such as
- *
- * "username::sysuser\n"
- * "username:\n"
- * "username: \n"
- *
- * all result in a found_password of NULL, but we also need to
- * make sure that
- *
- * "username: :sysuser\n"
- * "username: <whatever>:sysuser\n"
- *
- * continues to result in an impossible password. That way,
- * an admin would be on safe ground by going in and tacking a
- * space onto the front of a password to disable the account
- * (a technique some people use to close accounts
- * temporarily).
- */
-
- /* Make `non_cvsuser_portion' contain everything after the CVS
- username, but null out any final newline. */
- non_cvsuser_portion = linebuf + namelen;
- strtok (non_cvsuser_portion, "\n");
-
- /* If there's a colon now, we just want to inch past it. */
- if (strchr (non_cvsuser_portion, ':') == non_cvsuser_portion)
- non_cvsuser_portion++;
-
- /* Okay, after this conditional chain, found_password and
- host_user_tmp will have useful values: */
-
- if ((non_cvsuser_portion == NULL)
- || (strlen (non_cvsuser_portion) == 0)
- || ((strspn (non_cvsuser_portion, " \t"))
- == strlen (non_cvsuser_portion)))
- {
- found_password = NULL;
- host_user_tmp = NULL;
- }
- else if (strncmp (non_cvsuser_portion, ":", 1) == 0)
- {
- found_password = NULL;
- host_user_tmp = non_cvsuser_portion + 1;
- if (strlen (host_user_tmp) == 0)
- host_user_tmp = NULL;
- }
- else
- {
- found_password = strtok (non_cvsuser_portion, ":");
- host_user_tmp = strtok (NULL, ":");
- }
-
- /* Of course, maybe there was no system user portion... */
+ strsep (&linebufp, ":");
+ found_password = strsep (&linebufp, ": \n");
+ if (found_password)
+ host_user_tmp = strsep (&linebufp, ": \n");
if (host_user_tmp == NULL)
host_user_tmp = username;
- /* Verify blank passwords directly, otherwise use crypt(). */
- if ((found_password == NULL)
- || ((strcmp (found_password, crypt (password, found_password))
- == 0)))
+ if (found_password == NULL || *found_password == '\0' ||
+ strcmp (found_password, crypt (password, found_password)) == 0)
{
/* Give host_user_ptr permanent storage. */
*host_user_ptr = xstrdup (host_user_tmp);
@@ -5418,7 +5262,7 @@ check_repository_password (username, password, repository, host_user_ptr)
retval = 2;
}
}
- else /* Didn't find this user, so deny access. */
+ else
{
*host_user_ptr = NULL;
retval = 0;
@@ -5444,7 +5288,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)
@@ -5501,14 +5348,14 @@ error 0 %s: no such user\n", username);
/* user exists and has a password */
host_user = ((! strcmp (found_passwd,
crypt (password, found_passwd)))
- ? xstrdup (username) : NULL);
+ ? username : NULL);
goto handle_return;
}
else if (password && *password)
{
/* user exists and has no system password, but we got
one as parameter */
- host_user = xstrdup (username);
+ host_user = username;
goto handle_return;
}
else
@@ -5638,7 +5485,7 @@ pserver_authenticate_connection ()
#endif
/* Make sure the protocol starts off on the right foot... */
- if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0)
+ if (getline (&tmp, &tmp_allocated, stdin) < 0)
/* FIXME: what? We could try writing error/eof, but chances
are the network connection is dead bidirectionally. log it
somewhere? */
@@ -5669,9 +5516,9 @@ pserver_authenticate_connection ()
/* Get the three important pieces of information in order. */
/* See above comment about error handling. */
- getline_safe (&repository, &repository_allocated, stdin, PATH_MAX);
- getline_safe (&username, &username_allocated, stdin, PATH_MAX);
- getline_safe (&password, &password_allocated, stdin, PATH_MAX);
+ getline (&repository, &repository_allocated, stdin);
+ getline (&username, &username_allocated, stdin);
+ getline (&password, &password_allocated, stdin);
/* Make them pure. */
strip_trailing_newlines (repository);
@@ -5680,7 +5527,7 @@ pserver_authenticate_connection ()
/* ... and make sure the protocol ends on the right foot. */
/* See above comment about error handling. */
- getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX);
+ getline (&tmp, &tmp_allocated, stdin);
if (strcmp (tmp,
verify_and_exit ?
"END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n")
@@ -5742,7 +5589,6 @@ pserver_authenticate_connection ()
/* Switch to run as this user. */
switch_to_user (host_user);
- free (host_user);
free (tmp);
free (repository);
free (username);
diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c
index 81d4fea..89e8323 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"
@@ -94,7 +96,6 @@ static char *tag_update_dir;
static char *join_rev1, *date_rev1;
static char *join_rev2, *date_rev2;
static int aflag = 0;
-static int toss_local_changes = 0;
static int force_tag_match = 1;
static int update_build_dirs = 0;
static int update_prune_dirs = 0;
@@ -111,7 +112,6 @@ static const char *const update_usage[] =
" [-I ign] [-W spec] [files...]\n",
"\t-A\tReset any sticky tags/date/kopts.\n",
"\t-P\tPrune empty directories.\n",
- "\t-C\tOverwrite locally modified files with clean repository copies.\n",
"\t-d\tBuild directories, like checkout does.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, no recursion.\n",
@@ -147,16 +147,13 @@ update (argc, argv)
/* parse the args */
optind = 0;
- while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1)
+ while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1)
{
switch (c)
{
case 'A':
aflag = 1;
break;
- case 'C':
- toss_local_changes = 1;
- break;
case 'I':
ign_add (optarg, 0);
break;
@@ -257,8 +254,6 @@ update (argc, argv)
send_arg("-f");
if (aflag)
send_arg("-A");
- if (toss_local_changes)
- send_arg("-C");
if (update_prune_dirs)
send_arg("-P");
client_prune_dirs = update_prune_dirs;
@@ -273,35 +268,28 @@ update (argc, argv)
option_with_arg ("-j", join_rev2);
wrap_send ();
- if (failed_patches_count == 0)
+ /* If the server supports the command "update-patches", that means
+ that it knows how to handle the -u argument to update, which
+ means to send patches instead of complete files.
+
+ We don't send -u if failed_patches != NULL, so that the
+ server doesn't try to send patches which will just fail
+ again. At least currently, the client also clobbers the
+ file and tells the server it is lost, which also will get
+ a full file instead of a patch, but it seems clean to omit
+ -u. */
+ if (failed_patches == NULL)
{
- unsigned int flags = 0;
-
- /* If the server supports the command "update-patches", that
- means that it knows how to handle the -u argument to update,
- which means to send patches instead of complete files.
-
- We don't send -u if failed_patches != NULL, so that the
- server doesn't try to send patches which will just fail
- again. At least currently, the client also clobbers the
- file and tells the server it is lost, which also will get
- a full file instead of a patch, but it seems clean to omit
- -u. */
if (supported_request ("update-patches"))
send_arg ("-u");
+ }
- if (update_build_dirs)
- flags |= SEND_BUILD_DIRS;
-
- if (toss_local_changes) {
- flags |= SEND_NO_CONTENTS;
- flags |= BACKUP_MODIFIED_FILES;
- }
-
+ if (failed_patches == NULL)
+ {
/* If noexec, probably could be setting SEND_NO_CONTENTS.
Same caveats as for "cvs status" apply. */
-
- send_files (argc, argv, local, aflag, flags);
+ send_files (argc, argv, local, aflag,
+ update_build_dirs ? SEND_BUILD_DIRS : 0);
send_file_names (argc, argv, SEND_EXPAND_WILD);
}
else
@@ -325,9 +313,11 @@ update (argc, argv)
send_files (failed_patches_count, failed_patches, local,
aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
send_file_names (failed_patches_count, failed_patches, 0);
- free_names (&failed_patches_count, failed_patches);
}
+ failed_patches = NULL;
+ failed_patches_count = 0;
+
send_to_server ("update\012", 0);
status = get_responses_and_close ();
@@ -346,15 +336,13 @@ update (argc, argv)
conflict-and-patch-failed case. */
if (status != 0
- && (failed_patches_count == 0 || pass > 1))
+ && (failed_patches == NULL || pass > 1))
{
- if (failed_patches_count > 0)
- free_names (&failed_patches_count, failed_patches);
return status;
}
++pass;
- } while (failed_patches_count > 0);
+ } while (failed_patches != NULL);
return 0;
}
@@ -380,20 +368,15 @@ update (argc, argv)
error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
#ifdef SERVER_SUPPORT
if (server_active)
- {
- char *repos = Name_Repository (NULL, NULL);
- server_clear_entstat (".", repos);
- free (repos);
- }
+ server_clear_entstat (".", Name_Repository (NULL, NULL));
#endif
}
/* keep the CVS/Tag file current with the specified arguments */
if (aflag || tag || date)
{
- char *repos = Name_Repository (NULL, NULL);
- WriteTag ((char *) NULL, tag, date, 0, ".", repos);
- free (repos);
+ WriteTag ((char *) NULL, tag, date, 0,
+ ".", Name_Repository (NULL, NULL));
rewrite_tag = 1;
nonbranch = 0;
}
@@ -503,11 +486,17 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
argc, argv, local, which, aflag, 1,
preload_update_dir, 1);
- /* see if we need to sleep before returning to avoid time-stamp races */
+ /* see if we need to sleep before returning */
if (last_register_time)
{
- while (time ((time_t *) NULL) == last_register_time)
- sleep (1);
+ time_t now;
+
+ for (;;)
+ {
+ (void) time (&now);
+ if (now != last_register_time) break;
+ sleep (1); /* to avoid time-stamp races */
+ }
}
return (err);
@@ -590,7 +579,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;
@@ -654,82 +643,54 @@ update_fileproc (callerdat, finfo)
break;
case T_MODIFIED: /* locally modified */
retval = 0;
- if (toss_local_changes)
- {
- char *bakname;
- bakname = backup_file (finfo->file, vers->vn_user);
- /* This behavior is sufficiently unexpected to
- justify overinformativeness, I think. */
-#ifdef SERVER_SUPPORT
- if ((! really_quiet) && (! server_active))
-#else /* ! SERVER_SUPPORT */
- if (! really_quiet)
-#endif /* SERVER_SUPPORT */
- (void) printf ("(Locally modified %s moved to %s)\n",
- finfo->file, bakname);
- free (bakname);
-
- /* The locally modified file is still present, but
- it will be overwritten by the repository copy
- after this. */
- status = T_CHECKOUT;
- retval = checkout_file (finfo, vers, 0, 0, 1);
- }
- else
- {
- if (vers->ts_conflict)
- {
- char *filestamp;
- int retcode;
-
- /*
- * If the timestamp has changed and no
- * conflict indicators are found, it isn't a
- * 'C' any more.
- */
+ if (vers->ts_conflict)
+ {
+ char *filestamp;
+ int retcode;
+ /*
+ * If the timestamp has changed and no conflict indicators
+ * are found, it isn't a 'C' any more.
+ */
#ifdef SERVER_SUPPORT
- if (server_active)
- retcode = vers->ts_conflict[0] != '=';
- else
- {
- filestamp = time_stamp (finfo->file);
- retcode = strcmp (vers->ts_conflict, filestamp);
- free (filestamp);
- }
+ if (server_active)
+ retcode = vers->ts_conflict[0] != '=';
+ else {
+ filestamp = time_stamp (finfo->file);
+ retcode = strcmp (vers->ts_conflict, filestamp);
+ free (filestamp);
+ }
#else
- filestamp = time_stamp (finfo->file);
- retcode = strcmp (vers->ts_conflict, filestamp);
- free (filestamp);
+ filestamp = time_stamp (finfo->file);
+ retcode = strcmp (vers->ts_conflict, filestamp);
+ free (filestamp);
#endif
- if (retcode)
- {
- /* The timestamps differ. But if there
- are conflict markers print 'C' anyway. */
- retcode = !file_has_markers (finfo);
- }
-
- if (!retcode)
- {
- write_letter (finfo, 'C');
- retval = 1;
- }
- else
- {
- /* Reregister to clear conflict flag. */
- Register (finfo->entries, finfo->file,
- vers->vn_rcs, vers->ts_rcs,
- vers->options, vers->tag,
- vers->date, (char *)0);
- }
- }
- if (!retval)
- {
- write_letter (finfo, 'M');
- retval = 0;
- }
- }
+ if (retcode)
+ {
+ /* The timestamps differ. But if there are conflict
+ markers print 'C' anyway. */
+ retcode = !file_has_markers (finfo);
+ }
+
+ if (!retcode)
+ {
+ write_letter (finfo, 'C');
+ retval = 1;
+ }
+ else
+ {
+ /* Reregister to clear conflict flag. */
+ Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs,
+ vers->options, vers->tag,
+ vers->date, (char *)0);
+ }
+ }
+ if (!retval)
+ {
+ write_letter (finfo, 'M');
+ retval = 0;
+ }
break;
#ifdef SERVER_SUPPORT
case T_PATCH: /* needs patch */
@@ -969,8 +930,7 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
/* This is a guess. We will rewrite it later
via WriteTag. */
0,
- 0,
- 1);
+ 0);
rewrite_tag = 1;
nonbranch = 0;
Subdir_Register (entries, (char *) NULL, dir);
@@ -1056,10 +1016,6 @@ update_dirleave_proc (callerdat, dir, err, update_dir, entries)
{
FILE *fp;
- /* Delete the ignore list if it hasn't already been done. */
- if (ignlist)
- dellist (&ignlist);
-
/* If we set the tag or date for a new subdirectory in
update_dirent_proc, and we're now done with that subdirectory,
undo the tag/date setting. Note that we know that the tag and
@@ -1105,7 +1061,6 @@ update_dirleave_proc (callerdat, dir, err, update_dir, entries)
cvs_output (": Executing '", 0);
run_print (stdout);
cvs_output ("'\n", 0);
- cvs_flushout ();
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
}
else if (ferror (fp))
@@ -2096,7 +2051,7 @@ join_file (finfo, vers)
Vers_TS *vers;
{
char *backup;
- char *t_options;
+ char *options;
int status;
char *rev1;
@@ -2331,13 +2286,6 @@ join_file (finfo, vers)
xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
- /* Reset any keyword expansion option. Otherwise, when a
- command like `cvs update -kk -jT1 -jT2' creates a new file
- (because a file had the T2 tag, but not T1), the subsequent
- commit of that just-added file effectively would set the
- admin `-kk' option for that file in the repository. */
- options = NULL;
-
/* FIXME: If checkout_file fails, we should arrange to
return a non-zero exit status. */
status = checkout_file (finfo, xvers, 1, 0, 1);
@@ -2380,11 +2328,11 @@ join_file (finfo, vers)
if (jdate2 != NULL)
error (0, 0,
- "file %s does not exist, but is present in revision %s as of %s",
+ "file %s is present in revision %s as of %s",
finfo->fullname, jrev2, jdate2);
else
error (0, 0,
- "file %s does not exist, but is present in revision %s",
+ "file %s is present in revision %s",
finfo->fullname, jrev2);
/* FIXME: Should we arrange to return a non-zero exit status? */
@@ -2426,10 +2374,10 @@ join_file (finfo, vers)
copy_file (finfo->file, backup);
xchmod (finfo->file, 1);
- t_options = vers->options;
+ options = vers->options;
#if 0
- if (*t_options == '\0')
- t_options = "-kk"; /* to ignore keyword expansions */
+ if (*options == '\0')
+ options = "-kk"; /* to ignore keyword expansions */
#endif
/* If the source of the merge is the same as the working file
@@ -2447,12 +2395,12 @@ join_file (finfo, vers)
/* This is because of the worry below about $Name. If that
isn't a problem, I suspect this code probably works for
text files too. */
- && (strcmp (t_options, "-kb") == 0
+ && (strcmp (options, "-kb") == 0
|| wrap_merge_is_copy (finfo->file)))
{
/* FIXME: what about nametag? What does RCS_merge do with
$Name? */
- if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
+ if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
status = 2;
else
@@ -2476,7 +2424,7 @@ join_file (finfo, vers)
print. */
write_letter (finfo, 'U');
}
- else if (strcmp (t_options, "-kb") == 0
+ else if (strcmp (options, "-kb") == 0
|| wrap_merge_is_copy (finfo->file)
|| special_file_mismatch (finfo, rev1, rev2))
{
@@ -2486,7 +2434,7 @@ join_file (finfo, vers)
the two files, and let them resolve it. It is possible
that we should require a "touch foo" or similar step before
we allow a checkin. */
- if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
+ if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
status = 2;
else
@@ -2517,7 +2465,7 @@ join_file (finfo, vers)
}
else
status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
- t_options, rev1, rev2);
+ options, rev1, rev2);
if (status != 0 && status != 1)
{
@@ -2548,9 +2496,9 @@ join_file (finfo, vers)
(void) time (&last_register_time);
cp = time_stamp (finfo->file);
}
- Register (finfo->entries, finfo->file,
- vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge",
- vers->options, vers->tag, vers->date, cp);
+ Register (finfo->entries, finfo->file, vers->vn_rcs,
+ "Result of merge", vers->options, vers->tag,
+ vers->date, cp);
if (cp)
free(cp);
}
@@ -2598,8 +2546,8 @@ special_file_mismatch (finfo, rev1, rev2)
dev_t rev1_dev, rev2_dev;
char *rev1_symlink = NULL;
char *rev2_symlink = NULL;
- List *rev1_hardlinks = NULL;
- List *rev2_hardlinks = NULL;
+ List *rev1_hardlinks;
+ List *rev2_hardlinks;
int check_uids, check_gids, check_modes;
int result;
@@ -2628,7 +2576,6 @@ special_file_mismatch (finfo, rev1, rev2)
rev1_symlink = xreadlink (finfo->file);
else
{
-#ifdef HAVE_ST_RDEV
if (CVS_LSTAT (finfo->file, &sb) < 0)
error (1, errno, "could not get file information for %s",
finfo->file);
@@ -2637,10 +2584,6 @@ special_file_mismatch (finfo, rev1, rev2)
rev1_mode = sb.st_mode;
if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
rev1_dev = sb.st_rdev;
-#else
- error (1, 0, "cannot handle device files on this system (%s)",
- finfo->file);
-#endif
}
rev1_hardlinks = list_linked_files_on_disk (finfo->file);
}
@@ -2706,7 +2649,6 @@ special_file_mismatch (finfo, rev1, rev2)
rev2_symlink = xreadlink (finfo->file);
else
{
-#ifdef HAVE_ST_RDEV
if (CVS_LSTAT (finfo->file, &sb) < 0)
error (1, errno, "could not get file information for %s",
finfo->file);
@@ -2715,10 +2657,6 @@ special_file_mismatch (finfo, rev1, rev2)
rev2_mode = sb.st_mode;
if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
rev2_dev = sb.st_rdev;
-#else
- error (1, 0, "cannot handle device files on this system (%s)",
- finfo->file);
-#endif
}
rev2_hardlinks = list_linked_files_on_disk (finfo->file);
}
OpenPOWER on IntegriCloud