Merge cvs-1.9.xx -> 1.10 changes onto mainline.

Changes of significance include the top level CVS directory being optional
and defaulting to off..
This commit is contained in:
Peter Wemm 1999-03-18 09:32:46 +00:00
parent b791882da9
commit 46a2066259
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=44856
14 changed files with 1388 additions and 455 deletions

View file

@ -146,7 +146,16 @@ if ($dostatus != 0) {
}
last;
}
open(RCS, "-|") || exec 'cvs', '-nQq', 'status', '-v', $file;
$pid = open(RCS, "-|");
if ( !defined $pid )
{
die "fork failed: $!";
}
if ($pid == 0)
{
exec 'cvs', '-nQq', 'status', '-v', $file;
die "cvs exec failed: $!";
}
while (<RCS>) {
print OUT;
if (MAIL) {

View file

@ -35,19 +35,15 @@ described in the SEE ALSO section of this manpage).
.IX "release control system" "cvs command" "" "\fLcvs\fP \- concurrent versions system"
.IX "source control system" "cvs command" "" "\fLcvs\fP \- concurrent versions system"
.IX revisions "cvs command" "" "\fLcvs\fP \- source control"
.B cvs
is a front end to the
.BR rcs ( 1 )
revision control system which extends
the notion of revision control from a collection of files in a single
directory to a hierarchical collection of directories consisting of
revision controlled files.
These directories and files can be combined together to form a software
release.
.B cvs
provides the functions necessary to manage these software releases and to
control the concurrent editing of source files among multiple software
developers.
CVS is a version control system, which allows you to keep old versions
of files (usually source code), keep a log of who, when, and why
changes occurred, etc., like RCS or SCCS. Unlike the simpler systems,
CVS does not just operate on one file at a time or one directory at a
time, but operates on hierarchical collections of directories
consisting of version controlled files. CVS helps to manage releases
and to control the concurrent editing of source files among multiple
authors. CVS allows triggers to enable/log/control various
operations and works well over a wide area network.
.SP
.B cvs
keeps a single copy of the master sources.
@ -175,7 +171,7 @@ Use
.I bindir
as the directory where
.SM RCS
programs are located.
programs are located (CVS 1.9 and older).
Overrides the setting of the
.SM RCSBIN
environment variable.
@ -185,7 +181,6 @@ This value should be specified as an absolute pathname.
Use
.I CVS_root_directory
as the root directory pathname of the master
.SM RCS
source repository.
Overrides the setting of the
.SM CVSROOT
@ -337,7 +332,6 @@ working directory.)
.TP
.B admin
Execute
.SM RCS
control functions on the source repository. (Changes
repository directly; uses working directory without changing it.)
.TP
@ -385,7 +379,6 @@ as a ``vendor branch''. (Changes repository.)
.TP
.B log
Display
.SM RCS
log information.
(Does not change repository or working directory.)
.TP
@ -454,11 +447,8 @@ even with these standard options.
\fB\-D\fP \fIdate_spec\fP
Use the most recent revision no later than \fIdate_spec\fP (a single
argument, date description specifying a date in the
past). A wide variety of date formats are supported by the underlying
.SM RCS
facilities, similar to those described in
.BR co ( 1 ),
but not exactly the same.
past). A wide variety of date formats are supported, in particular
ISO ("1972-09-24 20:05") or Internet ("24 Sep 1972 20:05").
The \fIdate_spec\fP is interpreted as being in the local timezone, unless a
specific timezone is specified.
The specification is ``sticky'' when you use it to make a
@ -511,12 +501,8 @@ commands.
.TP
\fB\-k\fP \fIkflag\fP
Alter the default
.SM RCS
processing of keywords; all the
.B \-k
options described in
.BR co ( 1 )
are available. The \fB\-k\fP option is available with the
processing of keywords.
The \fB\-k\fP option is available with the
.BR add ", " checkout ", " diff ", " export ", "
.BR rdiff ", and " update
commands. Your \fIkflag\fP specification is ``sticky'' when you use
@ -526,10 +512,8 @@ this option with the \fBcheckout\fP or \fBupdate\fP commands,
continues to use it with future \fBupdate\fP commands on the same file
until you specify otherwise.
.SP
Some of the more useful \fIkflag\fPs are \-ko and \-kb (for binary files,
only compatible with
.SM RCS
version 5.7 or later), and \-kv which is useful for an
Some of the more useful \fIkflag\fPs are \-ko and \-kb (for binary files),
and \-kv which is useful for an
.B export
where you wish to retain keyword information after an
.B import
@ -619,9 +603,7 @@ make your own copy of a file: \fBcvs\fP remembers the \fItag\fP and
continues to use it on future \fBupdate\fP commands, until you specify
otherwise.
.I tag
can be either a symbolic or numeric tag, in
.SM RCS
fashion.
can be either a symbolic or numeric tag.
Specifying the
.B \-q
global option along with the
@ -678,7 +660,6 @@ working directory.
Use the
.B add
command to create a new file or directory in the
.SM RCS
source repository.
The files or directories specified with
.B add
@ -695,7 +676,6 @@ If the argument to
.` "cvs add"
refers to an immediate sub-directory, the directory is
created at the correct place in the
.SM RCS
source repository, and the necessary
.B cvs
administration files are created in your working directory.
@ -738,7 +718,6 @@ or
.` "cvs update -d".)
.SP
The added files are not placed in the
.SM RCS
source repository until you use
.` "cvs commit"
to make the change permanent.
@ -776,9 +755,8 @@ file and can be changed with
Specifying
.` "-ko"
is useful for checking in binaries that
shouldn't have the
.SM RCS
id strings expanded.
shouldn't have
keywords expanded.
.TP
\fBadmin\fP [\fIrcs-options\fP] \fIfiles.\|.\|.\fP
.I Requires:
@ -793,14 +771,9 @@ repository.
This is the
.B cvs
interface to assorted administrative
.SM RCS
facilities, documented in
facilities, similar to
.BR rcs ( 1 ).
.` "cvs admin"
simply passes all its options and arguments to the
.B rcs
command; it does no filtering or other processing.
This command does work recursively, however, so extreme care should be
This command works recursively, so extreme care should be
used.
.TP
\fBcheckout\fP [\fBoptions\fP] \fImodules\fP.\|.\|.
@ -839,7 +812,6 @@ You can then edit these source files at any time (regardless of whether
other software developers are editing their own copies of the sources);
update them to include new changes applied by others to the source
repository; or commit your work as a permanent change to the
.SM RCS
repository.
.SP
Note that
@ -1006,7 +978,6 @@ the time is right.
.SP
When all is well, an editor is invoked to allow you to enter a log
message that will be written to one or more logging programs and placed in the
.SM RCS
source repository file.
You can instead specify the log message on the command line with the
.B \-m
@ -1016,12 +987,8 @@ option to specify that the argument \fIfile\fP contains the log message.
.SP
The
.B \-r
option can be used to commit to a particular symbolic or numeric revision
within the
.SM RCS
file.
option can be used to commit to a particular symbolic or numeric revision.
For example, to bring all your files up to the
.SM RCS
revision ``3.0'' (including those that haven't changed), you might do:
.SP
.in +1i
@ -1173,7 +1140,6 @@ option is useful when
.B export
is used.
This causes any
.SM RCS
keywords to be expanded such that an
.B import
done at some other site will not lose the keyword revision information.
@ -1349,7 +1315,6 @@ For an up to date list of ignored file names, see the Cederqvist manual (as
described in the SEE ALSO section of this manpage).
.SP
The outside source is saved in a first-level
.SM RCS
branch, by default
.` "1.1.1".
Updates are leaves of this
@ -1409,13 +1374,7 @@ nothing.
.B rlog
.br
Display log information for \fIfiles\fP.
.` "cvs log"
calls
the
.SM RCS
utility \fBrlog\fP; all the options described in
.BR rlog ( 1 )
are available. Among the more useful \fBrlog\fP options are \fB\-h\fP
Among the more useful options are \fB\-h\fP
to display only the header (including tag definitions, but omitting
most of the full log); \fB\-r\fP to select logs on particular
revisions or ranges of revisions; and \fB\-d\fP to select particular
@ -1463,14 +1422,6 @@ command when patching the old sources, so that
.B patch
is able to find the files that are located in other directories.
.SP
If you use the option \fB\-V\fP \fIvn\fP,
.SM RCS
keywords are expanded according to the rules current in
.SM RCS
version \fIvn\fP (the expansion format changed with
.SM RCS
version 5).
.SP
The standard option \fIflags\fP \fB\-f\fP, and \fB\-l\fP
are available with this command. There are also several
special options flags:
@ -1788,7 +1739,6 @@ recent versions available in the repository.
\fBA\fP \fIfile\fP
The file has been \fIadded\fP to your private copy of the sources, and
will be added to the
.SM RCS
source repository when you run
.` "cvs commit"
on the file.
@ -1797,7 +1747,6 @@ This is a reminder to you that the file needs to be committed.
\fBR\fP \fIfile\fP
The file has been \fIremoved\fP from your private copy of the sources, and
will be removed from the
.SM RCS
source repository when you run
.` "cvs commit"
on the file.
@ -1816,14 +1765,12 @@ directory.
\fBC\fP \fIfile\fP
A \fIconflict\fP was detected while trying to merge your changes to
\fIfile\fP with changes from the source repository. \fIfile\fP (the
copy in your working directory) is now the output of the
.BR rcsmerge ( 1 )
command on the two versions; an unmodified copy of your file is also
copy in your working directory) is now the result of merging
the two versions; an unmodified copy of your file is also
in your working directory, with the name `\fB.#\fP\fIfile\fP\fB.\fP\fIversion\fP',
where
.I version
is the
.SM RCS
revision that your modified file started from.
(Note that some systems automatically purge files that begin with
\&
@ -2056,7 +2003,6 @@ Directory for removed source files.
A lock directory created by
.B cvs
when doing sensitive changes to the
.SM RCS
source repository.
.TP
#cvs.tfl.\fIpid\fP
@ -2099,9 +2045,8 @@ Specifies the full pathname where to find
programs, such as
.BR co ( 1 )
and
.BR ci ( 1 ).
If not set, a compiled-in value is used; see the display from
.` "cvs \-v".
.BR ci ( 1 )
(CVS 1.9 and older).
.TP
.SM CVSEDITOR
Specifies the program to use for recording log messages during
@ -2167,6 +2112,8 @@ module and vendor branch support and author of the
.BR checkin ( 1 )
shell script (the ancestor of
.` "cvs import").
.TP
And many others too numerous to mention here.
.SH "SEE ALSO"
The most comprehensive manual for CVS is
Version Management with CVS by Per Cederqvist et al. Depending on

View file

@ -1,17 +1,17 @@
/*
* Copyright (c) 1992, Brian Berliner and Jeff Polk
* 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 source distribution.
*
*
* Commit Files
*
*
* "commit" commits the present version to the RCS repository, AFTER
* having done a test on conflicts.
*
* The call is: cvs commit [options] files...
*
*
*/
#include <assert.h>
@ -29,7 +29,7 @@ static int check_filesdoneproc PROTO ((void *callerdat, int err,
char *repos, char *update_dir,
List *entries));
static int checkaddfile PROTO((char *file, char *repository, char *tag,
char *options, RCSNode **rcsnode));
char *options, RCSNode **rcsnode));
static Dtype commit_direntproc PROTO ((void *callerdat, char *dir,
char *repos, char *update_dir,
List *entries));
@ -74,12 +74,13 @@ static int force_ci = 0;
static int got_message;
static int run_module_prog = 1;
static int aflag;
static char *tag;
static char *saved_tag;
static char *write_dirtag;
static int write_dirnonbranch;
static char *logfile;
static List *mulist;
static char *message;
static List *saved_ulist;
static char *saved_message;
static time_t last_register_time;
static const char *const commit_usage[] =
@ -247,7 +248,7 @@ find_fileproc (callerdat, finfo)
xfinfo.repository = NULL;
xfinfo.rcs = NULL;
vers = Version_TS (&xfinfo, NULL, tag, NULL, 0, 0);
vers = Version_TS (&xfinfo, NULL, saved_tag, NULL, 0, 0);
if (vers->ts_user == NULL
&& vers->vn_user != NULL
&& vers->vn_user[0] == '-')
@ -364,18 +365,18 @@ commit (argc, argv)
#else
use_editor = 0;
#endif
if (message)
if (saved_message)
{
free (message);
message = NULL;
free (saved_message);
saved_message = NULL;
}
message = xstrdup(optarg);
saved_message = xstrdup(optarg);
break;
case 'r':
if (tag)
free (tag);
tag = xstrdup (optarg);
if (saved_tag)
free (saved_tag);
saved_tag = xstrdup (optarg);
break;
case 'l':
local = 1;
@ -405,12 +406,12 @@ commit (argc, argv)
argv += optind;
/* numeric specified revision means we ignore sticky tags... */
if (tag && isdigit (*tag))
if (saved_tag && isdigit (*saved_tag))
{
aflag = 1;
/* strip trailing dots */
while (tag[strlen (tag) - 1] == '.')
tag[strlen (tag) - 1] = '\0';
while (saved_tag[strlen (saved_tag) - 1] == '.')
saved_tag[strlen (saved_tag) - 1] = '\0';
}
/* some checks related to the "-F logfile" option */
@ -419,7 +420,7 @@ commit (argc, argv)
int n, logfd;
struct stat statbuf;
if (message)
if (saved_message)
error (1, 0, "cannot specify both a message and a log file");
/* FIXME: Why is this binary? Needs more investigation. */
@ -429,21 +430,20 @@ commit (argc, argv)
if (fstat(logfd, &statbuf) < 0)
error (1, errno, "cannot find size of log file %s", logfile);
message = xmalloc (statbuf.st_size + 1);
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, message, statbuf.st_size + 1)) < 0)
if ((n = read (logfd, saved_message, statbuf.st_size + 1)) < 0)
error (1, errno, "cannot read log message from %s", logfile);
(void) close (logfd);
message[n] = '\0';
saved_message[n] = '\0';
}
#ifdef CLIENT_SUPPORT
if (client_active)
if (client_active)
{
int err;
struct find_data find_args;
ign_setup ();
@ -458,7 +458,7 @@ commit (argc, argv)
I haven't really thought about it much.
Anyway, I suspect that setting it unnecessarily only causes
a little unneeded network traffic. */
find_args.force = force_ci || tag != NULL;
find_args.force = force_ci || saved_tag != NULL;
err = start_recursion (find_fileproc, find_filesdoneproc,
find_dirent_proc, (DIRLEAVEPROC) NULL,
@ -500,17 +500,17 @@ commit (argc, argv)
* The protocol is designed this way. This is a feature.
*/
if (use_editor)
do_editor (".", &message, (char *)NULL, find_args.ulist);
do_editor (".", &saved_message, (char *)NULL, find_args.ulist);
/* Run the user-defined script to verify/check information in
*the log message
*/
do_verify (&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
which can leave the message NULL. */
option_with_arg ("-m", message);
option_with_arg ("-m", saved_message);
/* OK, now process all the questionable files we have been saving
up. */
@ -559,7 +559,7 @@ commit (argc, argv)
send_arg("-f");
if (!run_module_prog)
send_arg("-n");
option_with_arg ("-r", tag);
option_with_arg ("-r", saved_tag);
/* Sending only the names of the files which were modified, added,
or removed means that the server will only do an up-to-date
@ -582,7 +582,7 @@ commit (argc, argv)
send_to_server ("ci\012", 0);
err = get_responses_and_close ();
if (err != 0 && use_editor && message != NULL)
if (err != 0 && use_editor && saved_message != NULL)
{
/* If there was an error, don't nuke the user's carefully
constructed prose. This is something of a kludge; a better
@ -600,7 +600,8 @@ commit (argc, argv)
fp = CVS_FOPEN (fname, "w+");
if (fp == NULL)
error (1, 0, "cannot create temporary file %s", fname);
if (fwrite (message, 1, strlen (message), fp) != strlen (message))
if (fwrite (saved_message, 1, strlen (saved_message), fp)
!= strlen (saved_message))
error (1, errno, "cannot write temporary file %s", fname);
if (fclose (fp) < 0)
error (0, errno, "cannot close temporary file %s", fname);
@ -610,12 +611,12 @@ commit (argc, argv)
}
#endif
if (tag != NULL)
tag_check_valid (tag, argc, argv, local, aflag, "");
if (saved_tag != NULL)
tag_check_valid (saved_tag, argc, argv, local, aflag, "");
/* XXX - this is not the perfect check for this */
if (argc <= 0)
write_dirtag = tag;
write_dirtag = saved_tag;
wrap_setup ();
@ -651,17 +652,6 @@ commit (argc, argv)
error (1, 0, "correct above errors first!");
}
#ifdef PRESERVE_PERMISSIONS_SUPPORT
if (preserve_perms)
{
/* hardlist now includes a complete index of the files
to be committed, indexed by inode. For each inode,
compile a list of the files that are linked to it,
and save this list in each file's hardlink_info node. */
(void) walklist (hardlist, cache_hardlinks_proc, NULL);
}
#endif
/*
* Run the recursion processor to commit the files
*/
@ -683,7 +673,7 @@ commit (argc, argv)
time_t now;
(void) time (&now);
if (now == last_register_time)
if (now == last_register_time)
{
sleep (1); /* to avoid time-stamp races */
}
@ -713,10 +703,10 @@ classify_file_internal (finfo, vers)
noexec = quiet = really_quiet = 1;
/* handle specified numeric revision specially */
if (tag && isdigit (*tag))
if (saved_tag && isdigit (*saved_tag))
{
/* If the tag is for the trunk, make sure we're at the head */
if (numdots (tag) < 2)
if (numdots (saved_tag) < 2)
{
status = Classify_File (finfo, (char *) NULL, (char *) NULL,
(char *) NULL, 1, aflag, vers, 0);
@ -726,7 +716,7 @@ classify_file_internal (finfo, vers)
Ctype xstatus;
freevers_ts (vers);
xstatus = Classify_File (finfo, tag, (char *) NULL,
xstatus = Classify_File (finfo, saved_tag, (char *) NULL,
(char *) NULL, 1, aflag, vers, 0);
if (xstatus == T_REMOVE_ENTRY)
status = T_MODIFIED;
@ -744,7 +734,7 @@ classify_file_internal (finfo, vers)
* The revision is off the main trunk; make sure we're
* up-to-date with the head of the specified branch.
*/
xtag = xstrdup (tag);
xtag = xstrdup (saved_tag);
if ((numdots (xtag) & 1) != 0)
{
cp = strrchr (xtag, '.');
@ -765,12 +755,12 @@ classify_file_internal (finfo, vers)
}
/* now, muck with vers to make the tag correct */
free ((*vers)->tag);
(*vers)->tag = xstrdup (tag);
(*vers)->tag = xstrdup (saved_tag);
free (xtag);
}
}
else
status = Classify_File (finfo, tag, (char *) NULL, (char *) NULL,
status = Classify_File (finfo, saved_tag, (char *) NULL, (char *) NULL,
1, 0, vers, 0);
noexec = save_noexec;
quiet = save_quiet;
@ -796,7 +786,7 @@ check_fileproc (callerdat, finfo)
Vers_TS *vers;
struct commit_info *ci;
struct logfile_info *li;
status = classify_file_internal (finfo, &vers);
/*
@ -835,7 +825,7 @@ check_fileproc (callerdat, finfo)
* allow the commit if timestamp is identical or if we find
* an RCS_MERGE_PAT in the file.
*/
if (!tag || !isdigit (*tag))
if (!saved_tag || !isdigit (*saved_tag))
{
if (vers->date)
{
@ -1047,7 +1037,6 @@ warning: file `%s' seems to still contain conflict indicators",
hlinfo = (struct hardlink_info *)
xmalloc (sizeof (struct hardlink_info));
hlinfo->status = status;
hlinfo->links = NULL;
linkp->data = (char *) hlinfo;
}
}
@ -1114,7 +1103,6 @@ precommit_list_proc (p, closure)
/*
* Callback proc for pre-commit checking
*/
static List *ulist;
static int
precommit_proc (repository, filter)
char *repository;
@ -1124,7 +1112,7 @@ precommit_proc (repository, filter)
if (isabsolute (filter))
{
char *s, *cp;
s = xstrdup (filter);
for (cp = s; *cp; cp++)
if (isspace (*cp))
@ -1143,7 +1131,7 @@ precommit_proc (repository, filter)
run_setup (filter);
run_arg (repository);
(void) walklist (ulist, precommit_list_proc, NULL);
(void) walklist (saved_ulist, precommit_list_proc, NULL);
return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
}
@ -1165,12 +1153,12 @@ check_filesdoneproc (callerdat, err, repos, update_dir, entries)
/* find the update list for this dir */
p = findnode (mulist, update_dir);
if (p != NULL)
ulist = ((struct master_lists *) p->data)->ulist;
saved_ulist = ((struct master_lists *) p->data)->ulist;
else
ulist = (List *) NULL;
saved_ulist = (List *) NULL;
/* skip the checks if there's nothing to do */
if (ulist == NULL || ulist->list->next == ulist->list)
if (saved_ulist == NULL || saved_ulist->list->next == saved_ulist->list)
return (err);
/* run any pre-commit checks */
@ -1238,8 +1226,9 @@ commit_fileproc (callerdat, finfo)
{
got_message = 1;
if (use_editor)
do_editor (finfo->update_dir, &message, finfo->repository, ulist);
do_verify (&message, finfo->repository);
do_editor (finfo->update_dir, &saved_message,
finfo->repository, ulist);
do_verify (&saved_message, finfo->repository);
}
p = findnode (cilist, finfo->file);
@ -1279,7 +1268,7 @@ commit_fileproc (callerdat, finfo)
error (1, 0, "internal error: no parsed RCS file");
ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
err = Checkin ('A', finfo, finfo->rcs->path, ci->rev,
ci->tag, ci->options, message);
ci->tag, ci->options, saved_message);
if (err != 0)
{
unlockrcs (finfo->rcs);
@ -1319,7 +1308,7 @@ commit_fileproc (callerdat, finfo)
{
err = Checkin ('M', finfo,
finfo->rcs->path, ci->rev, ci->tag,
ci->options, message);
ci->options, saved_message);
(void) time (&last_register_time);
@ -1331,7 +1320,7 @@ commit_fileproc (callerdat, finfo)
}
else if (ci->status == T_REMOVED)
{
err = remove_file (finfo, ci->tag, message);
err = remove_file (finfo, ci->tag, saved_message);
#ifdef SERVER_SUPPORT
if (server_active) {
server_scratch_entry_only ();
@ -1371,7 +1360,7 @@ commit_fileproc (callerdat, finfo)
been removed from the archive, which is not the behavior we
want for our commitlog messages; we want the old version
number and then "NONE." */
if (ci->status != T_REMOVED)
{
p = findnode (ulist, finfo->file);
@ -1379,7 +1368,7 @@ commit_fileproc (callerdat, finfo)
{
Vers_TS *vers;
struct logfile_info *li;
(void) classify_file_internal (finfo, &vers);
li = (struct logfile_info *) p->data;
li->rev_new = xstrdup (vers->vn_rcs);
@ -1415,7 +1404,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
got_message = 0;
Update_Logfile (repository, message, (FILE *) 0, ulist);
Update_Logfile (repository, saved_message, (FILE *) 0, ulist);
/* Build the administrative files if necessary. */
{
@ -1423,11 +1412,17 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
if (strncmp (CVSroot_directory, repository,
strlen (CVSroot_directory)) != 0)
error (0, 0, "internal error: repository (%s) doesn't begin with root (%s)", repository, CVSroot_directory);
error (0, 0,
"internal error: repository (%s) doesn't begin with root (%s)",
repository, CVSroot_directory);
p = repository + strlen (CVSroot_directory);
if (*p == '/')
++p;
if (strcmp ("CVSROOT", p) == 0)
if (strcmp ("CVSROOT", p) == 0
/* Check for subdirectories because people may want to create
subdirectories and list files therein in checkoutlist. */
|| strncmp ("CVSROOT/", p, strlen ("CVSROOT/")) == 0
)
{
/* "Database" might a little bit grandiose and/or vague,
but "checked-out copies of administrative files, unless
@ -1435,11 +1430,21 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
case modules.{pag,dir,db}" is verbose and excessively
focused on how the database is implemented. */
/* mkmodules requires the absolute name of the CVSROOT directory.
Remove anything after the `CVSROOT' component -- this is
necessary when committing in a subdirectory of CVSROOT. */
char *admin_dir = xstrdup (repository);
int cvsrootlen = strlen ("CVSROOT");
assert (admin_dir[p - repository + cvsrootlen] == '\0'
|| admin_dir[p - repository + cvsrootlen] == '/');
admin_dir[p - repository + cvsrootlen] = '\0';
cvs_output (program_name, 0);
cvs_output (" ", 1);
cvs_output (command_name, 0);
cvs_output (": Rebuilding administrative file database\n", 0);
mkmodules (repository);
mkmodules (admin_dir);
free (admin_dir);
}
}
@ -1452,7 +1457,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
char *line;
int line_length;
size_t line_chars_allocated;
char *repository;
char *repos;
line = NULL;
line_chars_allocated = 0;
@ -1462,9 +1467,9 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
/* Remove any trailing newline. */
if (line[line_length - 1] == '\n')
line[--line_length] = '\0';
repository = Name_Repository ((char *) NULL, update_dir);
repos = Name_Repository ((char *) NULL, update_dir);
run_setup (line);
run_arg (repository);
run_arg (repos);
cvs_output (program_name, 0);
cvs_output (" ", 1);
cvs_output (command_name, 0);
@ -1472,7 +1477,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
run_print (stdout);
cvs_output ("'\n", 0);
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
free (repository);
free (repos);
}
else
{
@ -1529,8 +1534,8 @@ commit_direntproc (callerdat, dir, repos, update_dir, entries)
real_repos = Name_Repository (dir, update_dir);
got_message = 1;
if (use_editor)
do_editor (update_dir, &message, real_repos, ulist);
do_verify (&message, real_repos);
do_editor (update_dir, &saved_message, real_repos, ulist);
do_verify (&saved_message, real_repos);
free (real_repos);
return (R_PROCESS);
}
@ -1622,7 +1627,7 @@ remove_file (finfo, tag, message)
if (tag && !(branch = RCS_nodeisbranch (finfo->rcs, tag)))
{
/* a symbolic tag is specified; just remove the tag from the file */
if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
@ -1655,7 +1660,7 @@ remove_file (finfo, tag, message)
error (0, 0, "cannot find branch \"%s\".", tag);
return (1);
}
branchname = RCS_getbranch (finfo->rcs, rev, 1);
if (branchname == NULL)
{
@ -1676,12 +1681,12 @@ remove_file (finfo, tag, message)
/* Get current head revision of file. */
prev_rev = RCS_head (finfo->rcs);
}
/* if removing without a tag or a branch, then make sure the default
branch is the trunk. */
if (!tag && !branch)
{
if (RCS_setbranch (finfo->rcs, NULL) != 0)
if (RCS_setbranch (finfo->rcs, NULL) != 0)
{
error (0, 0, "cannot change branch to default for %s",
finfo->fullname);
@ -1740,7 +1745,7 @@ remove_file (finfo, tag, message)
if (!branch)
{
/* this was the head; really move it into the Attic */
tmp = xmalloc(strlen(finfo->repository) +
tmp = xmalloc(strlen(finfo->repository) +
sizeof('/') +
sizeof(CVSATTIC) +
sizeof('/') +
@ -1750,8 +1755,9 @@ remove_file (finfo, tag, message)
omask = umask (cvsumask);
(void) CVS_MKDIR (tmp, 0777);
(void) umask (omask);
(void) sprintf (tmp, "%s/%s/%s%s", finfo->repository, CVSATTIC, finfo->file, RCSEXT);
(void) sprintf (tmp, "%s/%s/%s%s", finfo->repository, CVSATTIC,
finfo->file, RCSEXT);
if (strcmp (finfo->rcs->path, tmp) != 0
&& CVS_RENAME (finfo->rcs->path, tmp) == -1
&& (isreadable (finfo->rcs->path) || !isreadable (tmp)))
@ -1794,7 +1800,7 @@ finaladd (finfo, rev, tag, options)
char *rcs;
rcs = locate_rcs (finfo->file, finfo->repository);
ret = Checkin ('A', finfo, rcs, rev, tag, options, message);
ret = Checkin ('A', finfo, rcs, rev, tag, options, saved_message);
if (ret == 0)
{
char *tmp = xmalloc (strlen (finfo->file) + sizeof (CVSADM)
@ -1931,7 +1937,7 @@ checkaddfile (file, repository, tag, options, rcsnode)
Attic. */
oldfile = xstrdup (rcs);
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
if (strcmp (oldfile, rcs) == 0)
{
error (0, 0, "internal error: confused about attic for %s",
@ -2156,7 +2162,7 @@ internal error: `%s' didn't move out of the attic",
retval = 1;
goto out;
}
}
}
if (rcsnode && *rcsnode != rcsfile)
{
@ -2202,7 +2208,7 @@ lock_RCS (user, rcs, rev, repository)
* For a specified, numeric revision of the form "1" or "1.1", (or when
* no revision is specified ""), definitely move the branch to the trunk
* before locking the RCS file.
*
*
* The assumption is that if there is more than one revision on the trunk,
* the head points to the trunk, not a branch... and as such, it's not
* necessary to move the head in this case.

View file

@ -391,6 +391,8 @@ 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;
#ifdef AUTH_SERVER_SUPPORT
extern char *Pserver_Repos; /* used to check that same repos is
transmitted in pserver auth and in
@ -435,6 +437,8 @@ void Subdir_Register PROTO((List *, const char *, const char *));
void Subdir_Deregister PROTO((List *, const char *, const char *));
char *Make_Date PROTO((char *rawdate));
char *date_from_time_t PROTO ((time_t));
char *Name_Repository PROTO((char *dir, char *update_dir));
char *Short_Repository PROTO((char *repository));
void Sanitize_Repository_Name PROTO((char *repository));
@ -483,7 +487,6 @@ int numdots PROTO((const char *s));
char *increment_revnum PROTO ((const char *));
int compare_revnums PROTO ((const char *, const char *));
int unlink_file PROTO((const char *f));
int link_file PROTO ((const char *from, const char *to));
int unlink_file_dir PROTO((const char *f));
int update PROTO((int argc, char *argv[]));
int xcmp PROTO((const char *file1, const char *file2));
@ -841,7 +844,7 @@ extern int patch PROTO((int argc, char **argv));
extern int release PROTO((int argc, char **argv));
extern int cvsremove PROTO((int argc, char **argv));
extern int rtag PROTO((int argc, char **argv));
extern int status PROTO((int argc, char **argv));
extern int cvsstatus PROTO((int argc, char **argv));
extern int cvstag PROTO((int argc, char **argv));
extern unsigned long int lookup_command_attribute PROTO((char *));

View file

@ -414,29 +414,6 @@ rename_file (from, to)
error (1, errno, "cannot rename file %s to %s", from, to);
}
/*
* link a file, if possible. Warning: the Windows NT version of this
* function just copies the file, so only use this function in ways
* that can deal with either a link or a copy.
*/
int
link_file (from, to)
const char *from;
const char *to;
{
if (trace)
#ifdef SERVER_SUPPORT
(void) fprintf (stderr, "%c-> link(%s,%s)\n",
(server_active) ? 'S' : ' ', from, to);
#else
(void) fprintf (stderr, "-> link(%s,%s)\n", from, to);
#endif
if (noexec)
return (0);
return (link (from, to));
}
/*
* unlink a file, if possible.
*/
@ -770,6 +747,7 @@ xreadlink (link)
const char *link;
{
char *file = NULL;
char *tfile;
int buflen = BUFSIZ;
int linklen;
@ -792,9 +770,11 @@ xreadlink (link)
error (1, errno, "cannot readlink %s", link);
file[linklen] = '\0';
return file;
}
tfile = xstrdup (file);
free (file);
return tfile;
}
/* Return a pointer into PATH's last component. */

View file

@ -20,8 +20,6 @@
#include "savecwd.h"
#include <assert.h>
#define FILE_HOLDER ".#cvsxxx"
static char *get_comment PROTO((char *user));
static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile,
char *vers));
@ -655,39 +653,15 @@ add_rev (message, rcs, vfile, vers)
RCS_rewrite (rcs, NULL, NULL);
}
tocvsPath = wrap_tocvs_process_file (vfile);
if (tocvsPath == NULL)
{
/* We play with hard links rather than passing -u to ci to avoid
expanding RCS keywords (see test 106.5 in sanity.sh). */
if (link_file (vfile, FILE_HOLDER) < 0)
{
if (errno == EEXIST)
{
(void) unlink_file (FILE_HOLDER);
(void) link_file (vfile, FILE_HOLDER);
}
else
{
ierrno = errno;
fperror (logfp, 0, ierrno,
"ERROR: cannot create link to %s", vfile);
error (0, ierrno, "ERROR: cannot create link to %s", vfile);
return (1);
}
}
}
status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
message, vbranch,
(RCS_FLAGS_QUIET
(RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
| (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
ierrno = errno;
if (tocvsPath == NULL)
rename_file (FILE_HOLDER, vfile);
else
if (unlink_file_dir (tocvsPath) < 0)
error (0, errno, "cannot remove %s", tocvsPath);
if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
error (0, errno, "cannot remove %s", tocvsPath);
if (status)
{

View file

@ -43,6 +43,12 @@ 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
least for now we'll make the default be off (the CVS 1.9, not CVS
1.9.2, behavior). */
int top_level_admin = 0;
mode_t cvsumask = UMASK_DFLT;
char *CurDir;
@ -110,7 +116,7 @@ static const struct cmd
{ "rdiff", "patch", "pa", patch },
{ "release", "re", "rel", release },
{ "remove", "rm", "delete", cvsremove },
{ "status", "st", "stat", status },
{ "status", "st", "stat", cvsstatus },
{ "rtag", "rt", "rfreeze", rtag },
{ "tag", "ta", "freeze", cvstag },
{ "unedit", NULL, NULL, unedit },
@ -285,6 +291,10 @@ lookup_command_attribute (cmd_name)
}
/* The following commands do not use a checked-out working
directory. We conservatively assume that everything else does.
Feel free to add to this list if you are _certain_ something
something doesn't use the WD. */
if ((strcmp (cmd_name, "checkout") != 0) &&
(strcmp (cmd_name, "init") != 0) &&
(strcmp (cmd_name, "login") != 0) &&
@ -300,8 +310,10 @@ lookup_command_attribute (cmd_name)
/* The following commands do not modify the repository; we
conservatively assume that everything else does. Feel free to
add to this list if you are _certain_ something is safe. */
if ((strcmp (cmd_name, "checkout") != 0) &&
if ((strcmp (cmd_name, "annotate") != 0) &&
(strcmp (cmd_name, "checkout") != 0) &&
(strcmp (cmd_name, "diff") != 0) &&
(strcmp (cmd_name, "rdiff") != 0) &&
(strcmp (cmd_name, "update") != 0) &&
(strcmp (cmd_name, "history") != 0) &&
(strcmp (cmd_name, "editors") != 0) &&
@ -1000,20 +1012,37 @@ char *
Make_Date (rawdate)
char *rawdate;
{
struct tm *ftm;
time_t unixtime;
char date[MAXDATELEN];
char *ret;
unixtime = get_date (rawdate, (struct timeb *) NULL);
if (unixtime == (time_t) - 1)
error (1, 0, "Can't parse date/time: %s", rawdate);
return date_from_time_t (unixtime);
}
/* Convert a time_t to an RCS format date. This is mainly for the
use of "cvs history", because the CVSROOT/history file contains
time_t format dates; most parts of CVS will want to avoid using
time_t's directly, and instead use RCS_datecmp, Make_Date, &c.
Assuming that the time_t is in GMT (as it generally should be),
then the result will be in GMT too.
Returns a newly malloc'd string. */
char *
date_from_time_t (unixtime)
time_t unixtime;
{
struct tm *ftm;
char date[MAXDATELEN];
char *ret;
ftm = gmtime (&unixtime);
if (ftm == NULL)
/* This is a system, like VMS, where the system clock is in local
time. Hopefully using localtime here matches the "zero timezone"
hack I added to get_date. */
hack I added to get_date (get_date of course being the relevant
issue for Make_Date, and for history.c too I think). */
ftm = localtime (&unixtime);
(void) sprintf (date, DATEFORM,

View file

@ -283,6 +283,11 @@ static const char *const config_contents[] = {
"# Set `PreservePermissions' to `yes' to save file status information\n",
"# in the repository.\n",
"#PreservePermissions=no\n",
"\n",
"# 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",
NULL
};

File diff suppressed because it is too large Load diff

View file

@ -154,6 +154,10 @@ struct rcsversnode
List *other;
/* Newphrase fields from delta nodes. */
List *other_delta;
#ifdef PRESERVE_PERMISSIONS_SUPPORT
/* Hard link information for each revision. */
List *hardlinks;
#endif
};
typedef struct rcsversnode RCSVers;
@ -185,6 +189,9 @@ char *RCS_check_kflag PROTO((const char *arg));
char *RCS_getdate PROTO((RCSNode * rcs, char *date, int force_tag_match));
char *RCS_gettag PROTO((RCSNode * rcs, char *symtag, int force_tag_match,
int *simple_tag));
int RCS_exist_rev PROTO((RCSNode *rcs, char *rev));
int RCS_exist_tag PROTO((RCSNode *rcs, char *tag));
char *RCS_tag2rev PROTO((RCSNode *rcs, char *tag));
char *RCS_getversion PROTO((RCSNode * rcs, char *tag, char *date,
int force_tag_match, int *simple_tag));
char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
@ -196,9 +203,11 @@ int RCS_datecmp PROTO((char *date1, char *date2));
time_t RCS_getrevtime PROTO((RCSNode * rcs, char *rev, char *date, int fudge));
List *RCS_symbols PROTO((RCSNode *rcs));
void RCS_check_tag PROTO((const char *tag));
int RCS_valid_rev PROTO ((char *rev));
List *RCS_getlocks PROTO((RCSNode *rcs));
void freercsnode PROTO((RCSNode ** rnodep));
char *RCS_getbranch PROTO((RCSNode * rcs, char *tag, int force_tag_match));
char *RCS_branch_head PROTO ((RCSNode *rcs, char *rev));
int RCS_isdead PROTO((RCSNode *, const char *));
char *RCS_getexpand PROTO ((RCSNode *));

View file

@ -11,6 +11,8 @@
#include "cvs.h"
#include <assert.h>
#include <stdio.h>
#include "diffrun.h"
/* This file, rcs.h, and rcs.c, together sometimes known as the "RCS
library", are intended to define our interface to RCS files.
@ -75,6 +77,11 @@ static void call_diff_setup PROTO ((const char *prog));
static int call_diff PROTO ((char *out));
static int call_diff3 PROTO ((char *out));
static void call_diff_write_output PROTO((const char *, size_t));
static void call_diff_flush_output PROTO((void));
static void call_diff_write_stdout PROTO((const char *));
static void call_diff_error PROTO((const char *, const char *, const char *));
/* VARARGS */
static void
call_diff_setup (prog)
@ -132,59 +139,92 @@ call_diff_add_arg (s)
call_diff_argv[call_diff_argc] = (char *) 0;
}
/* diff_run is imported from libdiff.a. */
extern int diff_run PROTO ((int argc, char **argv, char *out));
/* Callback function for the diff library to write data to the output
file. This is used when we are producing output to stdout. */
static void
call_diff_write_output (text, len)
const char *text;
size_t len;
{
cvs_output (text, len);
}
/* Call back function for the diff library to flush the output file.
This is used when we are producing output to stdout. */
static void
call_diff_flush_output ()
{
cvs_flushout ();
}
/* Call back function for the diff library to write to stdout. */
static void
call_diff_write_stdout (text)
const char *text;
{
cvs_output (text, 0);
}
/* Call back function for the diff library to write to stderr. */
static void
call_diff_error (format, a1, a2)
const char *format;
const char *a1;
const char *a2;
{
/* FIXME: Should we somehow indicate that this error is coming from
the diff library? */
error (0, 0, format, a1, a2);
}
/* This set of callback functions is used if we are sending the diff
to stdout. */
static struct diff_callbacks call_diff_stdout_callbacks =
{
call_diff_write_output,
call_diff_flush_output,
call_diff_write_stdout,
call_diff_error
};
/* This set of callback functions is used if we are sending the diff
to a file. */
static struct diff_callbacks call_diff_file_callbacks =
{
(void (*) PROTO((const char *, size_t))) NULL,
(void (*) PROTO((void))) NULL,
call_diff_write_stdout,
call_diff_error
};
static int
call_diff (out)
char *out;
{
/* Try to keep the out-of-order bugs at bay (protocol_pipe for cvs_output
with has "Index: foo" and such; stdout and/or stderr for diff's
output). I think the only reason that this used to not be such
a problem is that the time spent on the fork() and exec() of diff
slowed us down enough to let the "Index:" make it through first.
The real fix, of course, will be to have the diff library do all
its output through callbacks (which CVS will supply as cvs_output
and cvs_outerr). */
#if defined(SERVER_SUPPORT)
/* only do this on the server if it's in protocol mode */
if (error_use_protocol || server_active)
usleep (50);
#endif
if (out == RUN_TTY)
return diff_run (call_diff_argc, call_diff_argv, NULL);
return diff_run (call_diff_argc, call_diff_argv, NULL,
&call_diff_stdout_callbacks);
else
return diff_run (call_diff_argc, call_diff_argv, out);
return diff_run (call_diff_argc, call_diff_argv, out,
&call_diff_file_callbacks);
}
extern int diff3_run PROTO ((int argc, char **argv, char *out));
static int
call_diff3 (out)
char *out;
{
/* Try to keep the out-of-order bugs at bay (protocol_pipe for cvs_output
with has "Index: foo" and such; stdout and/or stderr for diff's
output). I think the only reason that this used to not be such
a problem is that the time spent on the fork() and exec() of diff
slowed us down enough to let the "Index:" make it through first.
The real fix, of course, will be to have the diff library do all
its output through callbacks (which CVS will supply as cvs_output
and cvs_outerr). */
#if defined(SERVER_SUPPORT)
/* only do this on the server if it's in protocol mode */
if (error_use_protocol || server_active)
usleep (50);
#endif
if (out == RUN_TTY)
return diff3_run (call_diff_argc, call_diff_argv, NULL);
return diff3_run (call_diff_argc, call_diff_argv, NULL,
&call_diff_stdout_callbacks);
else
return diff3_run (call_diff_argc, call_diff_argv, out);
return diff3_run (call_diff_argc, call_diff_argv, out,
&call_diff_file_callbacks);
}

View file

@ -13,6 +13,9 @@
#include "fileattr.h"
#include "edit.h"
#ifdef CLIENT_SUPPORT
static int do_argument_proc PROTO((Node * p, void *closure));
#endif
static int do_dir_proc PROTO((Node * p, void *closure));
static int do_file_proc PROTO((Node * p, void *closure));
static void addlist PROTO((List ** listp, char *key));
@ -58,6 +61,24 @@ struct frame_and_entries {
List *entries;
};
#ifdef CLIENT_SUPPORT
/* This is a callback to send "Argument" commands to the server in the
case we've done a "cvs update" or "cvs commit" in a top-level
directory where there is no CVSADM directory. */
static int
do_argument_proc (p, closure)
Node *p;
void *closure;
{
char *dir = p->key;
send_to_server ("Argument ", 0);
send_to_server (dir, 0);
send_to_server ("\012", 1);
return 0;
}
#endif
/* Start a recursive command.
Command line arguments (ARGC, ARGV) dictate the directories and
@ -175,6 +196,19 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
"there is no version here; run '%s checkout' first",
program_name);
}
#ifdef CLIENT_SUPPORT
else if (client_active && server_started)
{
/* In the the case "cvs update foo bar baz", a call to
send_file_names in update.c will have sent the
appropriate "Argument" commands to the server. In
this case, that won't have happened, so we need to
do it here. While this example uses "update", this
generalizes to other commands. */
err += walklist (dirlist, do_argument_proc, NULL);
}
#endif
}
else
addlist (&dirlist, ".");
@ -586,7 +620,6 @@ do_dir_proc (p, closure)
char *newrepos;
List *sdirlist;
char *srepository;
char *cp;
Dtype dir_return = R_PROCESS;
int stripped_dot = 0;
int err = 0;
@ -790,25 +823,8 @@ but CVS uses %s for its own purposes; skipping %s directory",
repository = srepository;
}
#if 0
/* Put back update_dir. I think this is the same as just setting
update_dir back to saved_update_dir, but there are a few cases I'm
not sure about (in particular, if DIR is "." and update_dir is
not ""), so for conservatism I'm leaving this here. */
cp = last_component (update_dir);
if (cp > update_dir)
cp[-1] = '\0';
else
update_dir[0] = '\0';
free (saved_update_dir);
#else
/* The above code is cactus!!! - it doesn't handle descending
multiple directories at once! ie: it recurses down several
dirs and then back up one. This breaks 'diff', 'update',
'commit', etc. */
free (update_dir);
update_dir = saved_update_dir;
#endif
return (err);
}

View file

@ -42,8 +42,20 @@ static Key_schedule sched;
#ifdef HAVE_GSSAPI
#include <netdb.h>
#ifdef HAVE_GSSAPI_H
#include <gssapi.h>
#endif
#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
#endif
#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
#endif
#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
#endif
/* We use Kerberos 5 routines to map the GSSAPI credential to a user
name. */
@ -366,7 +378,8 @@ mkdir_p (dir)
int saved_errno = errno;
if (saved_errno != EEXIST
&& (saved_errno != EACCES || !isdir (q)))
&& ((saved_errno != EACCES && saved_errno != EROFS)
|| !isdir (q)))
{
retval = saved_errno;
goto done;
@ -638,6 +651,18 @@ server_pathname_check (path)
and is unlikely to do us any good here. It also is probably capable
of being a security hole in the anonymous readonly case. */
if (isabsolute (path))
/* Giving an error is actually kind of a cop-out, in the sense
that it would be nice for "cvs co -d /foo/bar/baz" to work.
A quick fix in the server would be requiring Max-dotdot of
at least one if pathnames are absolute, and then putting
/abs/foo/bar/baz in the temp dir beside the /d/d/d stuff.
A cleaner fix in the server might be to decouple the
pathnames we pass back to the client from pathnames in our
temp directory (this would also probably remove the need
for Max-dotdot). A fix in the client would have the client
turn it into "cd /foo/bar; cvs co -d baz" (more or less).
This probably has some problems with pathnames which appear
in messages. */
error (1, 0, "absolute pathname `%s' illegal for server", path);
if (pathname_levels (path) > max_dotdot_limit)
{
@ -2259,6 +2284,9 @@ error \n");
/* We shouldn't have any partial lines from cvs_output and
cvs_outerr, but we handle them here in case there is a bug. */
/* FIXME: appending a newline, rather than using "MT" as we
do in the child process, is probably not really a very good
way to "handle" them. */
if (! buf_empty_p (saved_output))
{
buf_append_char (saved_output, '\n');
@ -2329,6 +2357,19 @@ error \n");
exitstatus = (*command) (argument_count, argument_vector);
/* Output any partial lines. If the client doesn't support
"MT", we just throw out the partial line, like old versions
of CVS did, since the protocol can't support this. */
if (supported_response ("MT") && ! buf_empty_p (saved_output))
{
buf_output0 (protocol, "MT text ");
buf_append_buffer (protocol, saved_output);
buf_output (protocol, "\n", 1);
buf_send_counted (protocol);
}
/* For now we just discard partial lines on stderr. I suspect
that CVS can't write such lines unless there is a bug. */
/*
* When we exit, that will close the pipes, giving an EOF to
* the parent.
@ -2843,8 +2884,9 @@ server_register (name, version, timestamp, options, tag, date, conflict)
(void) fprintf (stderr,
"%c-> server_register(%s, %s, %s, %s, %s, %s, %s)\n",
(server_active) ? 'S' : ' ', /* silly */
name, version, timestamp, options, tag ? tag : "",
date ? date : "", conflict ? conflict : "");
name, version, timestamp ? timestamp : "", options,
tag ? tag : "", date ? date : "",
conflict ? conflict : "");
}
if (entries_line != NULL)
@ -3074,21 +3116,21 @@ static void
serve_remove (arg)
char *arg;
{
do_cvs_command ("cvsremove", cvsremove);
do_cvs_command ("remove", cvsremove);
}
static void
serve_status (arg)
char *arg;
{
do_cvs_command ("status", status);
do_cvs_command ("status", cvsstatus);
}
static void
serve_rdiff (arg)
char *arg;
{
do_cvs_command ("patch", patch);
do_cvs_command ("rdiff", patch);
}
static void
@ -3357,6 +3399,17 @@ server_modtime (finfo, vers_ts)
/* See server.h for description. */
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
/* Need to prototype because mode_t might be smaller than int. */
void
server_updated (
struct file_info *finfo,
Vers_TS *vers,
enum server_updated_arg4 updated,
mode_t mode,
unsigned char *checksum,
struct buffer *filebuf)
#else
void
server_updated (finfo, vers, updated, mode, checksum, filebuf)
struct file_info *finfo;
@ -3365,6 +3418,7 @@ server_updated (finfo, vers, updated, mode, checksum, filebuf)
mode_t mode;
unsigned char *checksum;
struct buffer *filebuf;
#endif
{
if (noexec)
{
@ -3583,7 +3637,7 @@ CVS server internal error: unhandled case in server_updated");
if ((updated == SERVER_UPDATED
|| updated == SERVER_PATCHED
|| updated == SERVER_RCS_DIFF)
&& filebuf != NULL
&& filebuf == NULL
/* But if we are joining, we'll need the file when we call
join_file. */
&& !joining ())
@ -4788,25 +4842,23 @@ check_password (username, password, repository)
/* No cvs password found, so try /etc/passwd. */
const char *found_passwd = NULL;
#ifdef HAVE_GETSPNAM
struct spwd *pw;
pw = getspnam (username);
if (pw != NULL)
{
found_passwd = pw->sp_pwdp;
}
#else
struct passwd *pw;
#ifdef HAVE_GETSPNAM
struct spwd *spw;
pw = getpwnam (username);
if (pw != NULL)
spw = getspnam (username);
if (spw != NULL)
{
found_passwd = spw->sp_pwdp;
}
#endif
if (found_passwd == NULL && (pw = getpwnam (username)) != NULL)
{
found_passwd = pw->pw_passwd;
}
#endif
if (pw == NULL)
if (found_passwd == NULL)
{
printf ("E Fatal error, aborting.\n\
error 0 %s: no such user\n", username);
@ -4824,8 +4876,9 @@ error 0 %s: no such user\n", username);
exit (EXIT_FAILURE);
}
if (found_passwd && *found_passwd)
if (*found_passwd)
{
/* user exists and has a password */
host_user = ((! strcmp (found_passwd,
crypt (password, found_passwd)))
? username : NULL);
@ -4833,11 +4886,14 @@ error 0 %s: no such user\n", username);
}
else if (password && *password)
{
/* user exists and has no system password, but we got
one as parameter */
host_user = username;
goto handle_return;
}
else
{
/* user exists but has no password at all */
host_user = NULL;
goto handle_return;
}
@ -5195,7 +5251,7 @@ gserver_authenticate_connection ()
tok_in.value = buf;
tok_in.length = strlen (buf);
if (gss_import_name (&stat_min, &tok_in, gss_nt_service_name,
if (gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
&server_name) != GSS_S_COMPLETE)
error (1, 0, "could not import GSSAPI service name %s", buf);
@ -5596,7 +5652,7 @@ cvs_output_binary (str, len)
if (error_use_protocol)
buf = buf_to_net;
else if (server_active)
else
buf = protocol;
if (!supported_response ("Mbinary"))

View file

@ -530,7 +530,6 @@ get_linkinfo_proc (callerdat, finfo)
hlinfo->status = (Ctype) 0; /* is this dumb? */
hlinfo->checked_out = 0;
hlinfo->links = NULL;
linkp->data = (char *) hlinfo;
@ -1639,8 +1638,6 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
{
char *diff_options;
/* FIXME: It might be better to come up with a diff library
which can be shared with the diffutils. */
/* If the client does not support the Rcs-diff command, we
send a context diff, and the client must invoke patch.
That approach was problematical for various reasons. The
@ -1649,8 +1646,10 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
program. */
if (! rcs_diff_patches)
{
/* We use -c, not -u, because we have no way of knowing
which DIFF is in use. */
/* We use -c, not -u, because that is what CVS has
traditionally used. Kind of a moot point, now that
Rcs-diff is preferred, so there is no point in making
the compatibility issues worse. */
diff_options = "-c";
}
else
@ -1922,14 +1921,21 @@ merge_file (finfo, vers)
if (strcmp (vers->options, "-V4") == 0)
vers->options[0] = '\0';
(void) time (&last_register_time);
/* This file is the result of a merge, which means that it has
been modified. We use a special timestamp string which will
not compare equal to any actual timestamp. */
{
char *cp = 0;
if (status)
{
(void) time (&last_register_time);
cp = time_stamp (finfo->file);
Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, 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);
}
@ -2428,25 +2434,27 @@ join_file (finfo, vers)
free (rev1);
free (rev2);
#ifdef SERVER_SUPPORT
/*
* If we're in server mode, then we need to re-register the file
* even if there were no conflicts (status == 0).
* This tells server_updated() to send the modified file back to
* the client.
*/
if (status == 1 || (status == 0 && server_active))
#else
if (status == 1)
#endif
/* The file has changed, but if we just checked it out it may
still have the same timestamp it did when it was first
registered above in checkout_file. We register it again with a
dummy timestamp to make sure that later runs of CVS will
recognize that it has changed.
We don't actually need to register again if we called
RCS_checkout above, and we aren't running as the server.
However, that is not the normal case, and calling Register
again won't cost much in that case. */
{
char *cp = 0;
if (status)
{
(void) time (&last_register_time);
cp = time_stamp (finfo->file);
Register (finfo->entries, finfo->file,
vers->vn_rcs, vers->ts_rcs, 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);
}
@ -2494,8 +2502,8 @@ special_file_mismatch (finfo, rev1, rev2)
dev_t rev1_dev, rev2_dev;
char *rev1_symlink = NULL;
char *rev2_symlink = NULL;
char *rev1_hardlinks = NULL;
char *rev2_hardlinks = NULL;
List *rev1_hardlinks;
List *rev2_hardlinks;
int check_uids, check_gids, check_modes;
int result;
@ -2533,7 +2541,7 @@ special_file_mismatch (finfo, rev1, rev2)
if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
rev1_dev = sb.st_rdev;
}
rev1_hardlinks = list_files_linked_to (finfo->file);
rev1_hardlinks = list_linked_files_on_disk (finfo->file);
}
else
{
@ -2584,11 +2592,9 @@ special_file_mismatch (finfo, rev1, rev2)
finfo->file, rev1, ftype);
}
n = findnode (vp->other_delta, "hardlinks");
if (n == NULL)
rev1_hardlinks = xstrdup ("");
else
rev1_hardlinks = xstrdup (n->data);
rev1_hardlinks = vp->hardlinks;
if (rev1_hardlinks == NULL)
rev1_hardlinks = getlist();
}
}
@ -2608,7 +2614,7 @@ special_file_mismatch (finfo, rev1, rev2)
if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
rev2_dev = sb.st_rdev;
}
rev2_hardlinks = list_files_linked_to (finfo->file);
rev2_hardlinks = list_linked_files_on_disk (finfo->file);
}
else
{
@ -2659,11 +2665,9 @@ special_file_mismatch (finfo, rev1, rev2)
finfo->file, rev2, ftype);
}
n = findnode (vp->other_delta, "hardlinks");
if (n == NULL)
rev2_hardlinks = xstrdup ("");
else
rev2_hardlinks = xstrdup (n->data);
rev2_hardlinks = vp->hardlinks;
if (rev2_hardlinks == NULL)
rev2_hardlinks = getlist();
}
}
@ -2744,7 +2748,7 @@ special_file_mismatch (finfo, rev1, rev2)
}
/* Compare hard links. */
if (strcmp (rev1_hardlinks, rev2_hardlinks) != 0)
if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0)
{
error (0, 0, "%s: hard linkage of %s and %s do not match",
finfo->file,
@ -2759,9 +2763,9 @@ special_file_mismatch (finfo, rev1, rev2)
if (rev2_symlink != NULL)
free (rev2_symlink);
if (rev1_hardlinks != NULL)
free (rev1_hardlinks);
dellist (&rev1_hardlinks);
if (rev2_hardlinks != NULL)
free (rev2_hardlinks);
dellist (&rev2_hardlinks);
return result;
#else