Merge changes from 1.10.7 -> 1.11 into mainline. Note that the old

anoncvs no-password hack is gone and is replaced by the official version.
This commit is contained in:
peter 2000-10-02 06:43:58 +00:00
parent e0aa09eb34
commit a152a7ef82
21 changed files with 1263 additions and 1147 deletions

View File

@ -54,7 +54,6 @@ Current local changes:
- CVSREADONLYFS environment variable and global option -R to enable
no-locking readonly mode (eg: cvs repo is a cdrom or mirror)
- the verify message script can edit the submitted log message.
- if pserver username is "anoncvs", implicitly use a password of "anoncvs".
- CVSROOT/options file
- Variable keyword expansion controls including custom keywords.
- $ CVSHeader$ keyword - like Header, but with $CVSROOT stripped off.

View File

@ -7,9 +7,10 @@
#
# $FreeBSD$
# Usage: log.pl [[-m user] ...] [-s] -f logfile 'dirname file ...'
# Usage: log.pl [-u user] [[-m mailto] ...] [-s] -f logfile 'dirname file ...'
#
# -m user - for each user to receive cvs log reports
# -u user - $USER passed from loginfo
# -m mailto - for each user to receive cvs log reports
# (multiple -m's permitted)
# -s - to prevent "cvs status -v" messages
# -f logfile - for the logfile to append to (mandatory,
@ -67,6 +68,8 @@ while (@ARGV) {
if ($arg eq '-m') {
$users = "$users " . shift @ARGV;
} elsif ($arg eq '-u') {
$login = shift @ARGV;
} elsif ($arg eq '-f') {
($logfile) && die "Too many '-f' args";
$logfile = shift @ARGV;
@ -96,7 +99,9 @@ $year += 1900;
# get a login name for the guy doing the commit....
#
$login = getlogin || (getpwuid($<))[0] || "nobody";
if ($login eq '') {
$login = getlogin || (getpwuid($<))[0] || "nobody";
}
# open log file for appending
#

View File

@ -178,7 +178,12 @@ foreach sfile (SCCS/s.*)
if ($status != 0) goto ERROR
# get file into current dir and get stats
set date = `sccs prs -r$rev $file | grep "^D " | awk '{y=$3; if($3 < 100) {y+=1900};printf("%s %s", y, $4);exit;}'`
set year = `echo $date | cut -c3-4`
if ($year < 70) then
# Y2K Bug, change century to 20
set date = `echo $date | sed -e s/19/20/`
endif
set date = `sccs prs -r$rev $file | grep "^D " | awk '{printf("19%s %s", $3, $4); exit}'`
set author = `sccs prs -r$rev $file | grep "^D " | awk '{print $5; exit}'`
echo ""
echo "==> file $file, rev=$rev, date=$date, author=$author"

View File

@ -44,6 +44,8 @@ void printf_output PARAMS((char const *, ...))
;
void flush_output PARAMS((void));
char * cvs_temp_name PARAMS((void));
/*
* Internal data structures and macros for the diff3 program; includes
* data structures for both diff3 diffs and normal diffs.
@ -478,8 +480,6 @@ diff3_run (argc, argv, out, callbacks_arg)
free(content0);
free(content1);
free_diff_blocks(thread0);
free_diff_blocks(thread1);
free_diff3_blocks(diff3);
if (! callbacks || ! callbacks->write_output)
@ -679,7 +679,7 @@ make_3way_diff (thread0, thread1)
struct diff3_block const *last_diff3;
static struct diff3_block const zero_diff3;
static struct diff3_block const zero_diff3 = { 0 };
/* Initialization */
result = 0;
@ -768,6 +768,8 @@ make_3way_diff (thread0, thread1)
tmpblock = using_to_diff3_block (using, last_using,
base_water_thread, high_water_thread,
last_diff3);
free_diff_blocks(using[0]);
free_diff_blocks(using[1]);
if (!tmpblock)
diff3_fatal ("internal error: screwup in format of diff blocks");
@ -1277,7 +1279,7 @@ read_diff (filea, fileb, output_placement)
*ap++ = fileb;
*ap = 0;
diffout = (char *)cvs_temp_name();
diffout = cvs_temp_name ();
outfile_hold = outfile;
callbacks_hold = callbacks;

View File

@ -193,8 +193,10 @@ Use
.I editor
to enter revision log information.
Overrides the setting of the
.SM CVSEDITOR
and the
.SM CVSEDITOR\c
,
.SM VISUAL\c
, and
.SM EDITOR
environment variables.
.TP
@ -397,6 +399,11 @@ file; see
Incorporate a set of updates from off-site into the source repository,
as a ``vendor branch''. (Changes repository.)
.TP
.B init
Initialize a repository by adding the CVSROOT subdirectory and some default
control files. You must use this command or initialize the repository in
some other way before you can use it.
.TP
.B log
Display
log information.
@ -512,13 +519,6 @@ is available with these commands:
.BR checkout ", " export ", "
.BR rdiff ", " rtag ", and " update .
.TP
.B \-H
Help; describe the options available for this command. This is the
only option supported for
.I all
.B cvs
commands.
.TP
\fB\-k\fP \fIkflag\fP
Alter the default
processing of keywords.
@ -1723,7 +1723,7 @@ executes recursively through subdirectories; you can prevent this by
using the standard \fB\-l\fP option, or specify the recursion
explicitly by using \fB\-R\fP.
.TP
\fBupdate\fP [\fB\-Adf\|lPpQqR\fP] [\fB\-d\fP] [\fB\-r\fP \fItag\fP|\fB\-D\fP \fIdate\fP] \fIfiles\|.\|.\|.\fP
\fBupdate\fP [\fB\-ACdf\|lPpQqR\fP] [\fB\-d\fP] [\fB\-r\fP \fItag\fP|\fB\-D\fP \fIdate\fP] \fIfiles\|.\|.\|.\fP
.I Requires:
repository, working directory.
.br
@ -1880,6 +1880,12 @@ Use
.` "\-I !"
to avoid ignoring any files at all.
.SP
Use the
.` "\-C"
option to overwrite locally modified files with clean copies from
the repository (the modified file is saved in
`\fB.#\fP\fIfile\fP\fB.\fP\fIrevision\fP', however).
.SP
The standard \fBcvs\fP command options \fB\-f\fP, \fB\-k\fP,
\fB\-l\fP, \fB\-P\fP, \fB\-p\fP, and \fB\-r\fP
are also available with \fBupdate\fP.
@ -2079,12 +2085,13 @@ and
Specifies the program to use for recording log messages during
.BR commit .
If not set, the
.SM VISUAL
and
.SM EDITOR
environment variable is used instead.
If
.SM EDITOR
is not set either, the default is
.BR /usr/ucb/vi .
environment variables are tried (in that order).
If neither is set, a system-dependent default editor (e.g.,
.BR vi )
is used.
.TP
.SM CVS_IGNORE_REMOTE_ROOT
If this variable is set then

View File

@ -17,8 +17,9 @@
.\" General Public License for more details.
.\"
.\" ---------------------------------------------------------------------------
.\" $FreeBSD$
.nh
.TH CVSBUG 1 xVERSIONx "February 1993"
.TH CVSBUG 8 xVERSIONx "February 1993"
.SH NAME
cvsbug \- send problem report (PR) about CVS to a central support site
.SH SYNOPSIS

View File

@ -1,3 +1,5 @@
/* JT thinks BeOS is worth the trouble. */
/* CVS client-related stuff.
This program is free software; you can redistribute it and/or modify
@ -64,7 +66,6 @@ extern char *strerror ();
#if HAVE_KERBEROS
#define CVS_PORT 1999
#if HAVE_KERBEROS
#include <krb.h>
extern char *krb_realmofhost ();
@ -78,8 +79,6 @@ static Key_schedule sched;
#endif /* HAVE_KERBEROS */
#endif /* HAVE_KERBEROS */
#ifdef HAVE_GSSAPI
#ifdef HAVE_GSSAPI_H
@ -1119,7 +1118,7 @@ call_in_directory (pathname, func, data)
strcpy (r, "/.");
Create_Admin (".", ".", repo, (char *) NULL,
(char *) NULL, 0, 1);
(char *) NULL, 0, 1, 1);
free (repo);
}
@ -1256,7 +1255,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);
(char *)NULL, (char *)NULL, 0, 0, 1);
free (repo);
b = strrchr (dir, '/');
@ -1764,6 +1763,7 @@ 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
@ -1851,7 +1851,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (use_gzip)
{
if (gunzip_and_write (fd, short_pathname, buf, size))
if (gunzip_and_write (fd, short_pathname,
(unsigned char *) buf, size))
error (1, 0, "aborting due to compression error");
}
else if (write (fd, buf, size) != size)
@ -2029,6 +2030,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
free (mode_string);
free (buf);
free (scratch_entries);
free (entries_line);
return;
}
@ -2127,8 +2130,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);
}
@ -2494,7 +2497,11 @@ 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);
@ -2509,7 +2516,11 @@ 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);
@ -2687,7 +2698,7 @@ send_repository (dir, repos, update_dir)
{
Node *n;
n = getnode ();
n->type = UNKNOWN;
n->type = NT_UNKNOWN;
n->key = xstrdup (update_dir);
n->data = NULL;
@ -3598,19 +3609,15 @@ 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 */
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
time_t now;
for (;;)
{
(void) time (&now);
if (now != last_register_time) break;
sleep (1); /* to avoid time-stamp races */
}
while (time ((time_t *) NULL) == last_register_time)
sleep (1);
}
return errs;
@ -3778,6 +3785,7 @@ 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)
@ -3822,6 +3830,14 @@ 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)
@ -3845,8 +3861,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));
}
{
@ -3939,20 +3955,28 @@ 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,
"authorization failed: server %s rejected access",
CVSroot_hostname);
error (1, 0,
error (0, 0,
"shutdown() failed (server %s): %s",
CVSroot_hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
error (1, 0,
"authorization failed: server %s rejected access",
CVSroot_hostname);
error_exit();
}
#endif /* AUTH_CLIENT_SUPPORT */
@ -4115,9 +4139,16 @@ 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 (&stat_min, stat_maj, GSS_C_GSS_CODE,
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_C_NULL_OID, &message_context, &tok_out);
error (1, 0, "GSSAPI authentication failed: %s",
(char *) tok_out.value);
@ -4141,7 +4172,29 @@ connect_to_gserver (sock, hostinfo)
recv_bytes (sock, cbuf, 2);
need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
assert (need <= sizeof buf);
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);
}
recv_bytes (sock, buf, need);
tok_in.length = need;
}
@ -4175,7 +4228,7 @@ send_variable_proc (node, closure)
void
start_server ()
{
int tofd, fromfd;
int tofd, fromfd, rootless;
char *log = getenv ("CVS_CLIENT_LOG");
@ -4354,7 +4407,8 @@ the :server: access method is not supported by this port of CVS");
stored_mode = NULL;
}
if (strcmp (command_name, "init") != 0)
rootless = (strcmp (command_name, "init") == 0);
if (!rootless)
{
send_to_server ("Root ", 0);
send_to_server (CVSroot_directory, 0);
@ -4478,7 +4532,7 @@ the :server: access method is not supported by this port of CVS");
}
}
if (cvsencrypt)
if (cvsencrypt && !rootless)
{
#ifdef ENCRYPTION
/* Turn on encryption before turning on compression. We do
@ -4525,7 +4579,7 @@ the :server: access method is not supported by this port of CVS");
#endif /* ! ENCRYPTION */
}
if (gzip_level)
if (gzip_level && !rootless)
{
if (supported_request ("Gzip-stream"))
{
@ -4567,7 +4621,7 @@ the :server: access method is not supported by this port of CVS");
}
}
if (cvsauthenticate && ! cvsencrypt)
if (cvsauthenticate && ! cvsencrypt && !rootless)
{
/* Turn on authentication after turning on compression, so
that we can compress the authentication information. We
@ -4598,7 +4652,7 @@ the :server: access method is not supported by this port of CVS");
}
#ifdef FILENAMES_CASE_INSENSITIVE
if (supported_request ("Case"))
if (supported_request ("Case") && !rootless)
send_to_server ("Case\012", 0);
#endif
@ -4968,6 +5022,7 @@ 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));
@ -5089,6 +5144,18 @@ 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
{
@ -5197,9 +5264,6 @@ 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.
@ -5215,6 +5279,9 @@ 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
{
@ -5239,6 +5306,29 @@ 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
@ -5430,9 +5520,10 @@ 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, (DIRLEAVEPROC)NULL, (void *) &args,
send_dirent_proc, send_dirleave_proc, (void *) &args,
argc, argv, local, W_LOCAL, aflag, 0, (char *)NULL, 0);
if (err)
error_exit ();

View File

@ -264,6 +264,7 @@ 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,6 +286,7 @@ 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;
}
@ -422,28 +424,12 @@ commit (argc, argv)
/* some checks related to the "-F logfile" option */
if (logfile)
{
int n, logfd;
struct stat statbuf;
size_t size = 0, len;
if (saved_message)
error (1, 0, "cannot specify both a message and a log file");
/* 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';
get_file (logfile, logfile, "r", &saved_message, &size, &len);
}
#ifdef CLIENT_SUPPORT
@ -474,11 +460,14 @@ 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.
@ -584,6 +573,8 @@ 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 ();
@ -673,16 +664,11 @@ commit (argc, argv)
Lock_Cleanup ();
dellist (&mulist);
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
time_t now;
for (;;)
{
(void) time (&now);
if (now != last_register_time) break;
sleep (1); /* to avoid time-stamp races */
}
while (time ((time_t *) NULL) == last_register_time)
sleep (1);
}
return (err);
@ -795,6 +781,12 @@ 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,
@ -1291,6 +1283,8 @@ 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);
@ -1401,6 +1395,8 @@ commit_fileproc (callerdat, finfo)
}
}
}
if (SIG_inCrSect ())
SIG_endCrSect ();
return (err);
}
@ -1501,6 +1497,7 @@ 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);
}
@ -1583,8 +1580,10 @@ 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, Name_Repository (dir, update_dir));
update_dir, repos);
free (repos);
}
return (err);
@ -1752,6 +1751,9 @@ 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);
@ -1963,6 +1965,11 @@ 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;
@ -2045,74 +2052,76 @@ checkaddfile (file, repository, tag, options, rcsnode)
newfile = 1;
if (desc != NULL)
free (desc);
}
/* 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 && 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);
/* 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);
/* 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;
}
}
/* 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 (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);
/* 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);
/* 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;
/* and lock it once again. */
if (lock_RCS (file, rcsfile, NULL, repository))
{
error (0, 0, "cannot lock `%s'.", rcs);
retval = 1;
goto out;
}
}
/* when adding with a tag, we need to stub a branch, if it
doesn't already exist. */
@ -2197,6 +2206,8 @@ checkaddfile (file, repository, tag, options, rcsnode)
retval = 0;
out:
if (retval != 0 && SIG_inCrSect ())
SIG_endCrSect ();
free (rcs);
return retval;
}

View File

@ -395,6 +395,7 @@ 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 */
@ -507,7 +508,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 nonbranch, int warn, int dotemplate));
extern int expand_at_signs PROTO ((char *, off_t, FILE *));
/* Locking subsystem (implemented in lock.c). */
@ -533,7 +534,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 fperror PROTO((FILE * fp, int status, int errnum, char *message,...));
void fperrmsg PROTO((FILE * fp, int status, int errnum, char *message,...));
void free_names PROTO((int *pargc, char *argv[]));
extern int ign_name PROTO ((char *name));
@ -554,6 +555,7 @@ void make_directories PROTO((const char *name));
void make_directory PROTO((const char *name));
extern int mkdir_if_needed PROTO ((char *name));
void rename_file PROTO((const char *from, const char *to));
char *backup_file PROTO((const char *file, const char *suffix));
/* Expand wildcards in each element of (ARGC,ARGV). This is according to the
files which exist in the current directory, and accordingly to OS-specific
conventions regarding wildcard syntax. It might be desirable to change the
@ -585,7 +587,7 @@ void do_editor PROTO((char *dir, char **messagep,
void do_verify PROTO((char **messagep, char *repository));
typedef int (*CALLBACKPROC) PROTO((int *pargc, char *argv[], char *where,
typedef int (*CALLBACKPROC) PROTO((int argc, char *argv[], char *where,
char *mwhere, char *mfile, int shorten, int local_specified,
char *omodule, char *msg));
@ -644,6 +646,7 @@ 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));
@ -861,6 +864,7 @@ 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 *));
@ -877,6 +881,8 @@ 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));
@ -884,7 +890,3 @@ 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

View File

@ -55,9 +55,13 @@ 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,10 +628,15 @@ 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)

View File

@ -268,12 +268,22 @@ 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.
@ -455,9 +465,12 @@ import_descend (message, vtag, targc, targv)
}
else if (
#ifdef DT_DIR
dp->d_type == DT_LNK || dp->d_type == DT_UNKNOWN &&
dp->d_type == DT_LNK
|| (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
#else
islink (dp->d_name)
#endif
islink (dp->d_name))
)
{
add_log ('L', dp->d_name);
err++;
@ -727,8 +740,8 @@ add_rev (message, rcs, vfile, vers)
{
if (!noexec)
{
fperror (logfp, 0, status == -1 ? ierrno : 0,
"ERROR: Check-in of %s failed", rcs->path);
fperrmsg (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);
}
@ -767,8 +780,8 @@ add_tags (rcs, vfile, vtag, targc, targv)
if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
{
ierrno = errno;
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
"ERROR: Failed to set tag %s in %s", vtag, rcs->path);
fperrmsg (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);
@ -791,9 +804,9 @@ add_tags (rcs, vfile, vtag, targc, targv)
else
{
ierrno = errno;
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
"WARNING: Couldn't add tag %s to %s", targv[i],
rcs->path);
fperrmsg (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);
@ -1056,7 +1069,14 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
stat the file before opening it. -twp */
if (CVS_LSTAT (userfile, &sb) < 0)
error (1, errno, "cannot lstat %s", user);
{
/* 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;
}
file_type = sb.st_mode & S_IFMT;
fpuser = NULL;
@ -1071,8 +1091,8 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
{
/* not fatal, continue import */
if (add_logfp != NULL)
fperror (add_logfp, 0, errno,
"ERROR: cannot read file %s", userfile);
fperrmsg (add_logfp, 0, errno,
"ERROR: cannot read file %s", userfile);
error (0, errno, "ERROR: cannot read file %s", userfile);
goto read_error;
}
@ -1204,12 +1224,18 @@ 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,
@ -1255,12 +1281,18 @@ 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,
@ -1379,8 +1411,8 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
{
ierrno = errno;
if (add_logfp != NULL)
fperror (add_logfp, 0, ierrno,
"WARNING: cannot change mode of file %s", rcs);
fperrmsg (add_logfp, 0, ierrno,
"WARNING: cannot change mode of file %s", rcs);
error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
err++;
}
@ -1399,14 +1431,14 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
if (fclose (fpuser) < 0)
error (0, errno, "cannot close %s", user);
if (add_logfp != NULL)
fperror (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
fperrmsg (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)
fperror (add_logfp, 0, 0, "ERROR: out of space - aborting");
fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
error (1, 0, "ERROR: out of space - aborting");
}
read_error:
@ -1515,7 +1547,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
return (0);
if (save_cwd (&cwd))
{
fperror (logfp, 0, 0, "ERROR: cannot get working directory");
fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
return (1);
}
@ -1546,7 +1578,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
if ( CVS_CHDIR (dir) < 0)
{
ierrno = errno;
fperror (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
error (0, ierrno, "ERROR: cannot chdir to %s", repository);
err = 1;
goto out;
@ -1561,9 +1593,9 @@ import_descend_dir (message, dir, vtag, targc, targv)
(void) sprintf (rcs, "%s%s", repository, RCSEXT);
if (isfile (repository) || isfile(rcs))
{
fperror (logfp, 0, 0,
"ERROR: %s is a file, should be a directory!",
repository);
fperrmsg (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;
@ -1572,8 +1604,8 @@ import_descend_dir (message, dir, vtag, targc, targv)
if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
{
ierrno = errno;
fperror (logfp, 0, ierrno,
"ERROR: cannot mkdir %s -- not added", repository);
fperrmsg (logfp, 0, ierrno,
"ERROR: cannot mkdir %s -- not added", repository);
error (0, ierrno,
"ERROR: cannot mkdir %s -- not added", repository);
err = 1;

View File

@ -177,8 +177,12 @@ lock_name (repository, name)
assert (CVSroot_directory != NULL);
assert (strncmp (repository, CVSroot_directory,
strlen (CVSroot_directory)) == 0);
short_repos = repository + strlen (CVSroot_directory);
assert (*short_repos++ == '/');
short_repos = repository + strlen (CVSroot_directory) + 1;
if (strcmp (repository, CVSroot_directory) == 0)
short_repos = ".";
else
assert (short_repos[-1] == '/');
retval = xmalloc (strlen (lock_dir)
+ strlen (short_repos)
@ -762,8 +766,8 @@ set_lock (lock, will_wait)
if (errno != EEXIST)
{
error (0, errno,
"failed to create lock directory in repository `%s'",
lock->repository);
"failed to create lock directory for `%s' (%s)",
lock->repository, masterlock);
return (L_ERROR);
}

View File

@ -14,6 +14,12 @@
#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
@ -22,7 +28,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
@ -144,7 +150,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
@ -291,21 +297,19 @@ login (argc, argv)
}
/* Returns the _scrambled_ password. The server must descramble
before hashing and comparing. */
before hashing and comparing. If password file not found, or
password not found in the file, just return NULL. */
char *
get_cvs_password ()
{
int found_it = 0;
int root_len;
char *password;
char *linebuf = (char *) NULL;
char *password = NULL;
char *linebuf = 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
@ -344,15 +348,10 @@ 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);
error (1, 0, "use \"cvs login\" to log in first");
return NULL;
}
root_len = strlen (CVSroot_original);
@ -371,7 +370,6 @@ 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)
{
@ -379,25 +377,19 @@ get_cvs_password ()
char *tmp;
strtok (linebuf, " ");
password = strtok (NULL, "\n");
tmp = strtok (NULL, "\n");
if (tmp == NULL)
error (1, 0, "bad entry in %s for %s", passfile, CVSroot_original);
/* Give it permanent storage. */
tmp = xstrdup (password);
memset (password, 0, strlen (password));
free (linebuf);
return tmp;
password = xstrdup (tmp);
memset (tmp, 0, strlen (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;
if (linebuf)
free (linebuf);
free (passfile);
return password;
}
static const char *const logout_usage[] =
@ -407,7 +399,7 @@ static const char *const logout_usage[] =
NULL
};
/* Remove any entry for the CVSRoot repository found in "CVS/.cvspass". */
/* Remove any entry for the CVSRoot repository found in .cvspass. */
int
logout (argc, argv)
int argc;
@ -415,7 +407,7 @@ logout (argc, argv)
{
char *passfile;
FILE *fp;
char *tmp_name;
char *tmp_name = NULL;
FILE *tmp_fp;
char *linebuf = (char *) NULL;
size_t linebuf_len;
@ -510,6 +502,10 @@ logout (argc, argv)
error (0, errno, "cannot remove %s", tmp_name);
chmod (passfile, 0600);
}
if (tmp_name)
free (tmp_name);
return 0;
}

View File

@ -184,7 +184,6 @@ 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;
@ -218,7 +217,6 @@ do_editor (dir, messagep, repository, changes)
{
FILE *tfp;
char buf[1024];
char *p;
size_t n;
size_t nwrite;
@ -233,9 +231,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);
@ -317,7 +315,8 @@ do_editor (dir, messagep, repository, changes)
if (*messagep)
{
p = *messagep;
size_t message_len = post_stbuf.st_size + 1;
size_t offset = 0;
while (1)
{
line_length = getline (&line, &line_chars_allocated, fp);
@ -329,8 +328,11 @@ do_editor (dir, messagep, repository, changes)
}
if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
continue;
(void) strcpy (p, line);
p += line_length;
if (offset + line_length >= message_len)
expand_string (messagep, &message_len,
offset + line_length + 1);
(void) strcpy (*messagep + offset, line);
offset += line_length;
}
}
if (fclose (fp) < 0)
@ -816,7 +818,7 @@ logfile_write (repository, filter, message, logfp, changes)
}
len = fmt_end - fmt_begin;
str_list_format = xmalloc (sizeof (char) * (len + 1));
str_list_format = xmalloc (len + 1);
strncpy (str_list_format, fmt_begin, len);
str_list_format[len] = '\0';

View File

@ -115,30 +115,31 @@ static const struct cmd
{ "history", "hi", "his", history },
{ "import", "im", "imp", import },
{ "init", NULL, NULL, init },
#ifdef SERVER_SUPPORT
#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
{ "kserver", NULL, NULL, server }, /* placeholder */
#endif
{ "log", "lo", "rlog", cvslog },
#ifdef AUTH_CLIENT_SUPPORT
{ "login", "logon", "lgn", login },
{ "logout", NULL, NULL, logout },
#ifdef SERVER_SUPPORT
#endif /* AUTH_CLIENT_SUPPORT */
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
{ "pserver", NULL, NULL, server }, /* placeholder */
#endif
#endif /* AUTH_CLIENT_SUPPORT */
{ "rdiff", "patch", "pa", patch },
{ "release", "re", "rel", release },
{ "remove", "rm", "delete", cvsremove },
{ "status", "st", "stat", cvsstatus },
{ "rtag", "rt", "rfreeze", rtag },
{ "tag", "ta", "freeze", cvstag },
{ "unedit", NULL, NULL, unedit },
{ "update", "up", "upd", update },
{ "watch", NULL, NULL, watch },
{ "watchers", NULL, NULL, watchers },
#ifdef SERVER_SUPPORT
{ "server", NULL, NULL, server },
#endif
{ "status", "st", "stat", cvsstatus },
{ "tag", "ta", "freeze", cvstag },
{ "unedit", NULL, NULL, unedit },
{ "update", "up", "upd", update },
{ "version", "ve", "ver", version },
{ "watch", NULL, NULL, watch },
{ "watchers", NULL, NULL, watchers },
{ NULL, NULL, NULL, NULL },
};
@ -183,7 +184,7 @@ static const char *const usg[] =
version control means. */
"For CVS updates and additional information, see\n",
" Cyclic Software at http://www.cyclic.com/ or\n",
" the CVS home page at http://www.cvshome.org/ or\n",
" Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n",
NULL,
};
@ -203,15 +204,24 @@ 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",
@ -349,6 +359,7 @@ 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;
@ -368,6 +379,11 @@ main_cleanup (sig)
switch (sig)
{
#ifdef SIGABRT
case SIGABRT:
name = "abort";
break;
#endif
#ifdef SIGHUP
case SIGHUP:
name = "hangup";
@ -411,8 +427,6 @@ 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;
@ -424,6 +438,7 @@ main (argc, argv)
int help = 0; /* Has the user asked for help? This
lets us support the `cvs -H cmd'
convention to give help for cmd. */
static const char short_options[] = "+QqgrwtnRlvb:T:e:d:Hfz:s:xaU";
static struct option long_options[] =
{
{"help", 0, NULL, 'H'},
@ -504,7 +519,7 @@ main (argc, argv)
opterr = 0;
while ((c = getopt_long
(argc, argv, "+f", NULL, NULL))
(argc, argv, short_options, long_options, &option_index))
!= EOF)
{
if (c == 'f')
@ -521,7 +536,7 @@ main (argc, argv)
opterr = 1;
while ((c = getopt_long
(argc, argv, "+QqgrwtnRlvb:T:e:d:Hfz:s:xaU", long_options, &option_index))
(argc, argv, short_options, long_options, &option_index))
!= EOF)
{
switch (c)
@ -574,14 +589,11 @@ main (argc, argv)
logoff = 1;
break;
case 'v':
/* 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);
version (0, (char **) NULL);
(void) fputs ("\n", stdout);
(void) fputs ("\
Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
Jeff Polk, and other authors\n", stdout);
(void) fputs ("\n", stdout);
(void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
@ -625,9 +637,9 @@ Copyright (c) 1989-1998 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 1 and 9");
"gzip compression level must be between 0 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
@ -685,7 +697,10 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
}
if (!cm->fullname)
usage (cmd_usage); /* no match */
{
fprintf (stderr, "Unknown command: `%s'\n\n", command_name);
usage (cmd_usage);
}
else
command_name = cm->fullname; /* Global pointer for later use */
@ -799,25 +814,23 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
#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 */
@ -912,7 +925,7 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
{
Node *n;
n = getnode ();
n->type = UNKNOWN;
n->type = NT_UNKNOWN;
n->key = xstrdup (CVSroot);
n->data = NULL;
@ -955,11 +968,8 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
current_root);
/*
* 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.
* Check to see if the repository exists.
*/
if (!client_active)
{
char *path;
@ -967,8 +977,7 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
path = xmalloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
+ 20
+ sizeof (CVSROOTADM_HISTORY));
+ 20);
(void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
if (!isaccessible (path, R_OK | X_OK))
{
@ -979,14 +988,6 @@ Copyright (c) 1989-1998 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);
}
@ -995,12 +996,17 @@ Copyright (c) 1989-1998 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, as putenv has control of it */
/* 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;
}
#endif
}

View File

@ -283,14 +283,23 @@ 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
};
@ -375,6 +384,9 @@ mkmodules (dir)
size_t line_allocated = 0;
const struct admin_file *fileptr;
if (noexec)
return 0;
if (save_cwd (&cwd))
error_exit ();
@ -868,6 +880,9 @@ 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);
@ -929,6 +944,29 @@ 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);

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,10 @@
* $FreeBSD$
*/
/* String which indicates a conflict if it occurs at the start of a line. */
#define RCS_MERGE_PAT ">>>>>>> "
/* 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 ">>>>>>> "
#define RCSEXT ",v"
#define RCSPAT "*,v"
@ -229,7 +231,9 @@ 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));

View File

@ -174,6 +174,7 @@ 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 +592,7 @@ do_recursion (frame)
/* Add it to our list. */
Node *n = getnode ();
n->type = UNKNOWN;
n->type = NT_UNKNOWN;
n->key = xstrdup (this_root);
if (addnode (root_directories, n))
@ -1016,7 +1017,7 @@ but CVS uses %s for its own purposes; skipping %s directory",
/* Add it to our list. */
Node *n = getnode ();
n->type = UNKNOWN;
n->type = NT_UNKNOWN;
n->key = xstrdup (this_root);
if (addnode (root_directories, n))
@ -1133,6 +1134,7 @@ addfile (listp, dir, file)
char *file;
{
Node *n;
List *fl;
/* add this dir. */
addlist (listp, dir);
@ -1145,7 +1147,9 @@ addfile (listp, dir, file)
}
n->type = DIRS;
addlist ((List **) &n->data, file);
fl = (List *) n->data;
addlist (&fl, file);
n->data = (char *) fl;
return;
}
@ -1205,6 +1209,7 @@ unroll_files_proc (p, closure)
}
dirlist = save_dirlist;
filelist = NULL;
if (filelist)
dellist (&filelist);
return(err);
}

File diff suppressed because it is too large Load Diff

View File

@ -96,6 +96,7 @@ 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;
@ -112,6 +113,7 @@ 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,13 +149,16 @@ update (argc, argv)
/* parse the args */
optind = 0;
while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1)
while ((c = getopt (argc, argv, "+ApCPflRQqduk: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;
@ -254,6 +259,8 @@ 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;
@ -268,28 +275,35 @@ update (argc, argv)
option_with_arg ("-j", join_rev2);
wrap_send ();
/* 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)
if (failed_patches_count == 0)
{
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 (failed_patches == NULL)
{
if (update_build_dirs)
flags |= SEND_BUILD_DIRS;
if (toss_local_changes) {
flags |= SEND_NO_CONTENTS;
flags |= BACKUP_MODIFIED_FILES;
}
/* If noexec, probably could be setting SEND_NO_CONTENTS.
Same caveats as for "cvs status" apply. */
send_files (argc, argv, local, aflag,
update_build_dirs ? SEND_BUILD_DIRS : 0);
send_files (argc, argv, local, aflag, flags);
send_file_names (argc, argv, SEND_EXPAND_WILD);
}
else
@ -313,11 +327,9 @@ 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 ();
@ -336,13 +348,15 @@ update (argc, argv)
conflict-and-patch-failed case. */
if (status != 0
&& (failed_patches == NULL || pass > 1))
&& (failed_patches_count == 0 || pass > 1))
{
if (failed_patches_count > 0)
free_names (&failed_patches_count, failed_patches);
return status;
}
++pass;
} while (failed_patches != NULL);
} while (failed_patches_count > 0);
return 0;
}
@ -368,15 +382,20 @@ update (argc, argv)
error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
#ifdef SERVER_SUPPORT
if (server_active)
server_clear_entstat (".", Name_Repository (NULL, NULL));
{
char *repos = Name_Repository (NULL, NULL);
server_clear_entstat (".", repos);
free (repos);
}
#endif
}
/* keep the CVS/Tag file current with the specified arguments */
if (aflag || tag || date)
{
WriteTag ((char *) NULL, tag, date, 0,
".", Name_Repository (NULL, NULL));
char *repos = Name_Repository (NULL, NULL);
WriteTag ((char *) NULL, tag, date, 0, ".", repos);
free (repos);
rewrite_tag = 1;
nonbranch = 0;
}
@ -486,17 +505,11 @@ 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 */
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
time_t now;
for (;;)
{
(void) time (&now);
if (now != last_register_time) break;
sleep (1); /* to avoid time-stamp races */
}
while (time ((time_t *) NULL) == last_register_time)
sleep (1);
}
return (err);
@ -643,54 +656,82 @@ update_fileproc (callerdat, finfo)
break;
case T_MODIFIED: /* locally modified */
retval = 0;
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 (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 (server_active)
retcode = vers->ts_conflict[0] != '=';
else {
filestamp = time_stamp (finfo->file);
retcode = strcmp (vers->ts_conflict, filestamp);
free (filestamp);
}
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.
*/
#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);
}
#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)
{
/* 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)
{
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 */
@ -930,7 +971,8 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
/* This is a guess. We will rewrite it later
via WriteTag. */
0,
0);
0,
1);
rewrite_tag = 1;
nonbranch = 0;
Subdir_Register (entries, (char *) NULL, dir);
@ -1016,6 +1058,10 @@ 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
@ -1061,6 +1107,7 @@ 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))
@ -2051,7 +2098,7 @@ join_file (finfo, vers)
Vers_TS *vers;
{
char *backup;
char *options;
char *t_options;
int status;
char *rev1;
@ -2286,6 +2333,13 @@ 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);
@ -2328,11 +2382,11 @@ join_file (finfo, vers)
if (jdate2 != NULL)
error (0, 0,
"file %s is present in revision %s as of %s",
"file %s does not exist, but is present in revision %s as of %s",
finfo->fullname, jrev2, jdate2);
else
error (0, 0,
"file %s is present in revision %s",
"file %s does not exist, but is present in revision %s",
finfo->fullname, jrev2);
/* FIXME: Should we arrange to return a non-zero exit status? */
@ -2374,10 +2428,10 @@ join_file (finfo, vers)
copy_file (finfo->file, backup);
xchmod (finfo->file, 1);
options = vers->options;
t_options = vers->options;
#if 0
if (*options == '\0')
options = "-kk"; /* to ignore keyword expansions */
if (*t_options == '\0')
t_options = "-kk"; /* to ignore keyword expansions */
#endif
/* If the source of the merge is the same as the working file
@ -2395,12 +2449,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 (options, "-kb") == 0
&& (strcmp (t_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, options,
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
status = 2;
else
@ -2424,7 +2478,7 @@ join_file (finfo, vers)
print. */
write_letter (finfo, 'U');
}
else if (strcmp (options, "-kb") == 0
else if (strcmp (t_options, "-kb") == 0
|| wrap_merge_is_copy (finfo->file)
|| special_file_mismatch (finfo, rev1, rev2))
{
@ -2434,7 +2488,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, options,
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
status = 2;
else
@ -2465,7 +2519,7 @@ join_file (finfo, vers)
}
else
status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
options, rev1, rev2);
t_options, rev1, rev2);
if (status != 0 && status != 1)
{
@ -2496,9 +2550,9 @@ join_file (finfo, vers)
(void) time (&last_register_time);
cp = time_stamp (finfo->file);
}
Register (finfo->entries, finfo->file, vers->vn_rcs,
"Result of merge", vers->options, vers->tag,
vers->date, cp);
Register (finfo->entries, finfo->file,
vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge",
vers->options, vers->tag, vers->date, cp);
if (cp)
free(cp);
}
@ -2546,8 +2600,8 @@ special_file_mismatch (finfo, rev1, rev2)
dev_t rev1_dev, rev2_dev;
char *rev1_symlink = NULL;
char *rev2_symlink = NULL;
List *rev1_hardlinks;
List *rev2_hardlinks;
List *rev1_hardlinks = NULL;
List *rev2_hardlinks = NULL;
int check_uids, check_gids, check_modes;
int result;
@ -2576,6 +2630,7 @@ 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);
@ -2584,6 +2639,10 @@ 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);
}
@ -2649,6 +2708,7 @@ 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);
@ -2657,6 +2717,10 @@ 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);
}