Initial merge of 1.11.1p1 -> 1.11.2 changes onto mainline

This commit is contained in:
Peter Wemm 2002-09-02 05:57:14 +00:00
parent 0471b259a4
commit 8df8fc83d5
19 changed files with 1082 additions and 700 deletions

View File

@ -178,13 +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 '{printf("19%s %s", $3, $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 author = `sccs prs -r$rev $file | grep "^D " | awk '{print $5; exit}'`
# Is the substr stuff and the +0 in the following awk script really
# necessary? It seems to me that if we didn't find the date format
# we expected in the output we have other problems.
set date = `sccs prs -r$rev $file | awk '/^D / {print (substr($3,0,2)+0<70?20:19) $3, $4; exit}'`
set author = `sccs prs -r$rev $file | awk '/^D / {print $5; exit}'`
echo ""
echo "==> file $file, rev=$rev, date=$date, author=$author"
sccs edit -r$rev $file >>& $logfile

View File

@ -447,7 +447,7 @@ diff3_run (argc, argv, out, callbacks_arg)
outfile = fopen (out, "w");
if (outfile == NULL)
{
perror_with_name ("could not open output file");
perror_with_name (out);
return 2;
}
opened_file = 1;
@ -1850,10 +1850,10 @@ myread (fd, ptr, size)
char *ptr;
size_t size;
{
size_t result = read (fd, ptr, size);
ssize_t result = read (fd, ptr, size);
if (result == -1)
diff3_perror_with_exit ("read failed");
return result;
return (size_t)result;
}
static void

View File

@ -27,8 +27,12 @@ cvs \- Concurrent Versions System
.SH "NOTE"
This manpage is a summary of some of the features of
.B cvs
but for more in-depth documentation, consult the Cederqvist manual (as
described in the SEE ALSO section of this manpage).
but it may no longer be kept up-to-date.
For more current and in-depth documentation, please consult the
Cederqvist manual (via the
.B info cvs
command or otherwise,
as described in the SEE ALSO section of this manpage).
.SH "DESCRIPTION"
.IX "revision control system" "\fLcvs\fR"
.IX cvs "" "\fLcvs\fP \- concurrent versions system"
@ -958,7 +962,7 @@ the
.B \-s
option within the modules file.
.TP
\fBcommit\fP [\fB\-lnR\fP] [\fB\-m\fP '\fIlog_message\fP' | \fB\-f\fP \fIfile\fP] [\fB\-r\fP \fIrevision\fP] [\fIfiles.\|.\|.\fP]
\fBcommit\fP [\fB\-lnR\fP] [\fB\-m\fP '\fIlog_message\fP' | \fB\-F\fP \fIfile\fP] [\fB\-r\fP \fIrevision\fP] [\fIfiles.\|.\|.\fP]
.I Requires:
working directory, repository.
.br
@ -1494,7 +1498,7 @@ Working directory.
Working directory, history log.
.br
This command is meant to safely cancel the effect of
.` "cvs checkout'.
.` "cvs checkout".
Since
.B cvs
doesn't lock files, it isn't strictly necessary to use this command.
@ -1677,6 +1681,13 @@ Use this command to assign symbolic tags to the nearest repository
versions to your working sources. The tags are applied immediately to
the repository, as with \fBrtag\fP.
.SP
One potentially surprising aspect of the fact that \fBcvs tag\fP
operates on the repository is that you are tagging the checked-in
revisions, which may differ from locally modified files in your working
directory. If you want to avoid doing this by mistake, specify the
\fB-c\fP option to \fBcvs tag\fP. If there are any locally modified files, CVS
will abort with an error before it tags any files.
.SP
One use for tags is to record a ``snapshot'' of the current sources
when the software freeze date of a project arrives. As bugs are fixed
after the freeze date, only those changed sources that are to be part
@ -1762,7 +1773,7 @@ or
.B update
keeps you informed of its progress by printing a line for each file,
prefaced with one of the characters
.` "U A R M C ?"
.` "U P A R M C ?"
to indicate the status of the file:
.TP 1i
\fBU\fP \fIfile\fP
@ -1771,6 +1782,10 @@ This is done for any file that exists in the repository but not in
your source, and for files that you haven't changed but are not the most
recent versions available in the repository.
.TP 1i
\fBP\fP \fIfile\fP
Like \fBU\fP, but the CVS server sends a patch instead of an entire file.
This accomplishes the same thing as \fBU\fP using less bandwidth.
.TP 1i
\fBA\fP \fIfile\fP
The file has been \fIadded\fP to your private copy of the sources, and
will be added to the
@ -2180,7 +2195,7 @@ command or it may be available as cvs.ps (postscript), cvs.texinfo
For CVS updates, more information on documentation, software related
to CVS, development of CVS, and more, see:
.in +1i
.B http://www.cyclic.com
.B http://cvshome.org
.B http://www.loria.fr/~molli/cvs-index.html
.in -1i
.SP

View File

@ -87,19 +87,19 @@ static const char *const export_usage[] =
};
static int checkout_prune_dirs;
static int force_tag_match = 1;
static int force_tag_match;
static int pipeout;
static int aflag;
static char *options = NULL;
static char *tag = NULL;
static int tag_validated = 0;
static char *date = NULL;
static char *join_rev1 = NULL;
static char *join_rev2 = NULL;
static int join_tags_validated = 0;
static int pull_template = 0;
static char *preload_update_dir = NULL;
static char *history_name = NULL;
static char *options;
static char *tag;
static int tag_validated;
static char *date;
static char *join_rev1;
static char *join_rev2;
static int join_tags_validated;
static int pull_template;
static char *preload_update_dir;
static char *history_name;
static enum mtype m_type;
int
@ -118,6 +118,18 @@ checkout (argc, argv)
char *valid_options;
const char *const *valid_usage;
/* initialize static options */
force_tag_match = 1;
if (options)
{
free (options);
options = NULL;
}
tag = date = join_rev1 = join_rev2 = preload_update_dir = NULL;
history_name = NULL;
tag_validated = join_tags_validated = 0;
/*
* A smaller subset of options are allowed for the export command, which
* is essentially like checkout, except that it hard-codes certain
@ -257,7 +269,7 @@ checkout (argc, argv)
}
#endif
if (!cat && !safe_location()) {
if (!cat && !pipeout && !safe_location( where )) {
error(1, 0, "Cannot check out files into the repository itself");
}
@ -342,7 +354,10 @@ checkout (argc, argv)
{
cat_module (status);
if (options)
{
free (options);
options = NULL;
}
return (0);
}
db = open_module ();
@ -360,17 +375,17 @@ checkout (argc, argv)
/* If we will be calling history_write, work out the name to pass
it. */
if (m_type == CHECKOUT && !pipeout)
if (!pipeout)
{
if (tag && date)
if (!date)
history_name = tag;
else if (!tag)
history_name = date;
else
{
history_name = xmalloc (strlen (tag) + strlen (date) + 2);
sprintf (history_name, "%s:%s", tag, date);
}
else if (tag)
history_name = tag;
else
history_name = date;
}
@ -380,7 +395,12 @@ checkout (argc, argv)
(char *) NULL);
close_module (db);
if (options)
{
free (options);
options = NULL;
}
if (history_name != tag && history_name != date && history_name != NULL)
free (history_name);
return (err);
}
@ -388,9 +408,11 @@ checkout (argc, argv)
reasons, probably want to move them. */
int
safe_location ()
safe_location (where)
char *where;
{
char *current;
char *where_location;
char hardpath[PATH_MAX+5];
size_t hardpath_len;
int x;
@ -412,9 +434,68 @@ safe_location ()
{
hardpath[x] = '\0';
}
/* set current - even if where is set we'll need to cd back... */
current = xgetwd ();
if (current == NULL)
error (1, errno, "could not get working directory");
/* if where is set, set current to where, where - last_component( where ),
* or fail, depending on whether the directories exist or not.
*/
if( where != NULL )
{
if( chdir( where ) != -1 )
{
/* where */
where_location = xgetwd();
if( where_location == NULL )
error( 1, errno, "could not get working directory" );
if( chdir( current ) == -1 )
error( 1, errno, "could not change directory to `%s'", current );
free( current );
current = where_location;
}
else if( errno == ENOENT )
{
if ( last_component( where ) != where )
{
/* where - last_component( where ) */
char *parent;
/* strip the last_component */
where_location = strdup( where );
parent = last_component( where_location );
parent[-1] = '\0';
if( chdir( where_location ) != -1 )
{
where_location = xgetwd();
if( where_location == NULL )
error( 1, errno, "could not get working directory (nominally `%s')", where_location );
if( chdir( current ) == -1 )
error( 1, errno, "could not change directory to `%s'", current );
free( current );
current = where_location;
}
else
/* fail */
error( 1, errno, "could not change directory to requested checkout directory `%s'", where_location );
}
/* else: ERRNO == ENOENT & last_component(where) == where
* for example, 'cvs co -d newdir module', where newdir hasn't
* been created yet, so leave current set to '.' and check that
*/
}
else
/* fail */
error( 1, errno, "could not change directory to requested checkout directory `%s'", where );
}
hardpath_len = strlen (hardpath);
if (strlen (current) >= hardpath_len
&& strncmp (current, hardpath, hardpath_len) == 0)
@ -860,7 +941,7 @@ internal error: %s doesn't start with %s in checkout_proc",
build_one_dir whenever the -d command option was specified
to checkout. */
if (! where_is_absolute && top_level_admin)
if (! where_is_absolute && top_level_admin && m_type == CHECKOUT)
{
/* It may be argued that we shouldn't set any sticky
bits for the top-level repository. FIXME? */
@ -1007,12 +1088,9 @@ internal error: %s doesn't start with %s in checkout_proc",
*/
if (!(local_specified || argc > 1))
{
if (m_type == CHECKOUT && !pipeout)
history_write ('O', preload_update_dir, history_name, where,
repository);
else if (m_type == EXPORT && !pipeout)
history_write ('E', preload_update_dir, tag ? tag : date, where,
repository);
if (!pipeout)
history_write (m_type == CHECKOUT ? 'O' : 'E', preload_update_dir,
history_name, where, repository);
err += do_update (0, (char **) NULL, options, tag, date,
force_tag_match, 0 /* !local */ ,
1 /* update -d */ , aflag, checkout_prune_dirs,

File diff suppressed because it is too large Load Diff

View File

@ -352,9 +352,10 @@ commit (argc, argv)
struct passwd *pw;
if ((pw = (struct passwd *) getpwnam (getcaller ())) == NULL)
error (1, 0, "you are unknown to this system");
error (1, 0, "your apparent username (%s) is unknown to this system",
getcaller ());
if (pw->pw_uid == (uid_t) 0)
error (1, 0, "cannot commit files as 'root'");
error (1, 0, "'root' is not allowed to commit files");
}
#endif /* CVS_BADROOT */
@ -496,11 +497,6 @@ commit (argc, argv)
if (use_editor)
do_editor (".", &saved_message, (char *)NULL, find_args.ulist);
/* Run the user-defined script to verify/check information in
*the log message
*/
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. */
@ -1576,7 +1572,7 @@ 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);
char *repos = Name_Repository (NULL, update_dir);
WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
update_dir, repos);
free (repos);
@ -1810,7 +1806,7 @@ unlockrcs (rcs)
{
int retcode;
if ((retcode = RCS_unlock (rcs, NULL, 0)) != 0)
if ((retcode = RCS_unlock (rcs, NULL, 1)) != 0)
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
"could not unlock %s", rcs->path);
else

View File

@ -82,8 +82,11 @@ extern int errno;
#include "system.h"
#include "hash.h"
#include "root.h"
#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
#include "client.h"
# include "client.h"
#endif
#ifdef MY_NDBM
@ -369,26 +372,7 @@ extern int cvswrite;
extern mode_t cvsumask;
extern char *RCS_citag;
/* Access method specified in CVSroot. */
typedef enum {
null_method, local_method, server_method, pserver_method, kserver_method, gserver_method,
ext_method, fork_method
} CVSmethod;
extern char *method_names[]; /* change this in root.c if you change
the enum above */
typedef struct cvsroot_s {
char *original; /* the complete source CVSroot string */
CVSmethod method; /* one of the enum values above */
char *username; /* the username or NULL if method == local */
char *password; /* the username or NULL if method == local */
char *hostname; /* the hostname or NULL if method == local */
int port; /* the port or zero if method == local */
char *directory; /* the directory name */
#ifdef CLIENT_SUPPORT
unsigned char isremote; /* nonzero if we are doing remote access */
#endif /* CLIENT_SUPPORT */
} cvsroot_t;
/* This global variable holds the global -d option. It is NULL if -d
was not used, which means that we must get the CVSroot information
@ -401,7 +385,7 @@ extern List *root_directories;
extern cvsroot_t *current_parsed_root;
extern char *emptydir_name PROTO ((void));
extern int safe_location PROTO ((void));
extern int safe_location PROTO ((char *));
extern int trace; /* Show all commands */
extern int noexec; /* Don't modify disk anywhere */
@ -411,6 +395,12 @@ extern int require_real_user; /* skip CVSROOT/passwd, /etc/passwd users only*/
extern int top_level_admin;
#define LOGMSG_REREAD_NEVER 0 /* do_verify - never reread message */
#define LOGMSG_REREAD_ALWAYS 1 /* do_verify - always reread message */
#define LOGMSG_REREAD_STAT 2 /* do_verify - reread message if changed */
extern int RereadLogAfterVerify;
#ifdef CLIENT_SUPPORT
extern List *dirs_sent_to_server; /* used to decide which "Argument
xxx" commands to send to each
@ -482,7 +472,7 @@ char *time_stamp PROTO((char *file));
void *xmalloc PROTO((size_t bytes));
void *xrealloc PROTO((void *ptr, size_t bytes));
void expand_string PROTO ((char **, size_t *, size_t));
void allocate_and_strcat PROTO ((char **, size_t *, const char *));
void xrealloc_and_strcat PROTO ((char **, size_t *, const char *));
char *xstrdup PROTO((const char *str));
void strip_trailing_newlines PROTO((char *str));
int pathname_levels PROTO ((char *path));

View File

@ -64,24 +64,71 @@ static size_t opts_allocated = 1;
static int diff_errors;
static int empty_files = 0;
/* FIXME: should be documenting all the options here. They don't
perfectly match rcsdiff options (for example, we always support
--ifdef and --context, but rcsdiff only does if diff does). */
static const char *const diff_usage[] =
{
"Usage: %s %s [-lNR] [rcsdiff-options]\n",
"Usage: %s %s [-lR] [-k kopt] [format_options]\n",
" [[-r rev1 | -D date1] [-r rev2 | -D date2]] [files...] \n",
"\t-l\tLocal directory only, not recursive\n",
"\t-R\tProcess directories recursively.\n",
"\t-k kopt\tSpecify keyword expansion mode.\n",
"\t-D d1\tDiff revision for date against working file.\n",
"\t-D d2\tDiff rev1/date1 against date2.\n",
"\t-N\tinclude diffs for added and removed files.\n",
"\t-r rev1\tDiff revision for rev1 against working file.\n",
"\t-r rev2\tDiff rev1/date1 against rev2.\n",
"\t--ifdef=arg\tOutput diffs in ifdef format.\n",
"(consult the documentation for your diff program for rcsdiff-options.\n",
"The most popular is -c for context diffs but there are many more).\n",
"(Specify the --help global option for a list of other help options)\n",
"\nformat_options:\n",
" -i --ignore-case Consider upper- and lower-case to be the same.\n",
" -w --ignore-all-space Ignore all white space.\n",
" -b --ignore-space-change Ignore changes in the amount of white space.\n",
" -B --ignore-blank-lines Ignore changes whose lines are all blank.\n",
" -I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.\n",
" --binary Read and write data in binary mode.\n",
" -a --text Treat all files as text.\n\n",
" -c -C NUM --context[=NUM] Output NUM (default 2) lines of copied context.\n",
" -u -U NUM --unified[=NUM] Output NUM (default 2) lines of unified context.\n",
" -NUM Use NUM context lines.\n",
" -L LABEL --label LABEL Use LABEL instead of file name.\n",
" -p --show-c-function Show which C function each change is in.\n",
" -F RE --show-function-line=RE Show the most recent line matching RE.\n",
" --brief Output only whether files differ.\n",
" -e --ed Output an ed script.\n",
" -f --forward-ed Output something like an ed script in forward order.\n",
" -n --rcs Output an RCS format diff.\n",
" -y --side-by-side Output in two columns.\n",
" -W NUM --width=NUM Output at most NUM (default 130) characters per line.\n",
" --left-column Output only the left column of common lines.\n",
" --suppress-common-lines Do not output common lines.\n",
" --ifdef=NAME Output merged file to show `#ifdef NAME' diffs.\n",
" --GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT.\n",
" --line-format=LFMT Similar, but format all input lines with LFMT.\n",
" --LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT.\n",
" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'.\n",
" GFMT may contain:\n",
" %%< lines from FILE1\n",
" %%> lines from FILE2\n",
" %%= lines common to FILE1 and FILE2\n",
" %%[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER\n",
" LETTERs are as follows for new group, lower case for old group:\n",
" F first line number\n",
" L last line number\n",
" N number of lines = L-F+1\n",
" E F-1\n",
" M L+1\n",
" LFMT may contain:\n",
" %%L contents of line\n",
" %%l contents of line, excluding any trailing newline\n",
" %%[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number\n",
" Either GFMT or LFMT may contain:\n",
" %%%% %%\n",
" %%c'C' the single character C\n",
" %%c'\\OOO' the character with octal code OOO\n\n",
" -t --expand-tabs Expand tabs to spaces in output.\n",
" -T --initial-tab Make tabs line up by prepending a tab.\n\n",
" -N --new-file Treat absent files as empty.\n",
" -s --report-identical-files Report when two files are the same.\n",
" --horizon-lines=NUM Keep NUM lines of the common prefix and suffix.\n",
" -d --minimal Try hard to find a smaller set of changes.\n",
" -H --speed-large-files Assume large files and many scattered small changes.\n",
"\n(Specify the --help global option for a list of other help options)\n",
NULL
};
@ -89,19 +136,20 @@ static const char *const diff_usage[] =
removing the following entries, none of which seem relevant to use
with CVS:
--help
--version
--recursive
--unidirectional-new-file
--starting-file
--exclude
--exclude-from
--version (-v)
--recursive (-r)
--unidirectional-new-file (-P)
--starting-file (-S)
--exclude (-x)
--exclude-from (-X)
--sdiff-merge-assist
--paginate (-l) (doesn't work with library callbacks)
I changed the options which take optional arguments (--context and
--unified) to return a number rather than a letter, so that the
optional argument could be handled more easily. I changed the
--paginate and --brief options to return a number, since -l and -q
mean something else to cvs diff.
--brief and --ifdef options to return numbers, since -q and -D mean
something else to cvs diff.
The numbers 129- that appear in the fourth element of some entries
tell the big switch in `diff' how to process those options. -- Ian
@ -128,7 +176,6 @@ static struct option const longopts[] =
{"ed", 0, 0, 'e'},
{"forward-ed", 0, 0, 'f'},
{"ignore-case", 0, 0, 'i'},
{"paginate", 0, 0, 144},
{"rcs", 0, 0, 'n'},
{"show-c-function", 0, 0, 'p'},
@ -229,19 +276,22 @@ diff (argc, argv)
optind = 0;
while ((c = getopt_long (argc, argv,
"+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:j:",
"+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:j:",
longopts, &option_index)) != -1)
{
switch (c)
{
case 'y':
xrealloc_and_strcat (&opts, &opts_allocated, " --side-by-side");
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'h': case 'i': case 'n': case 'p': case 's': case 't':
case 'u': case 'w': case 'y':
case 'u': case 'w':
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
case 'B': case 'H': case 'T':
(void) sprintf (tmp, " -%c", (char) c);
allocate_and_strcat (&opts, &opts_allocated, tmp);
xrealloc_and_strcat (&opts, &opts_allocated, tmp);
break;
case 'L':
if (have_rev1_label++)
@ -251,31 +301,31 @@ diff (argc, argv)
break;
}
allocate_and_strcat (&opts, &opts_allocated, " -L");
allocate_and_strcat (&opts, &opts_allocated, optarg);
xrealloc_and_strcat (&opts, &opts_allocated, " -L");
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
break;
case 'C': case 'F': case 'I': case 'U': case 'V': case 'W':
case 'C': case 'F': case 'I': case 'U': case 'W':
(void) sprintf (tmp, " -%c", (char) c);
allocate_and_strcat (&opts, &opts_allocated, tmp);
allocate_and_strcat (&opts, &opts_allocated, optarg);
xrealloc_and_strcat (&opts, &opts_allocated, tmp);
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
break;
case 131:
/* --ifdef. */
allocate_and_strcat (&opts, &opts_allocated, " --ifdef=");
allocate_and_strcat (&opts, &opts_allocated, optarg);
xrealloc_and_strcat (&opts, &opts_allocated, " --ifdef=");
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
break;
case 129: case 130: case 132: case 133: case 134:
case 135: case 136: case 137: case 138: case 139: case 140:
case 141: case 142: case 143: case 144: case 145: case 146:
allocate_and_strcat (&opts, &opts_allocated, " --");
allocate_and_strcat (&opts, &opts_allocated,
case 141: case 142: case 143: case 145: case 146:
xrealloc_and_strcat (&opts, &opts_allocated, " --");
xrealloc_and_strcat (&opts, &opts_allocated,
longopts[option_index].name);
if (longopts[option_index].has_arg == 1
|| (longopts[option_index].has_arg == 2
&& optarg != NULL))
{
allocate_and_strcat (&opts, &opts_allocated, "=");
allocate_and_strcat (&opts, &opts_allocated, optarg);
xrealloc_and_strcat (&opts, &opts_allocated, "=");
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
}
break;
case 'R':
@ -470,8 +520,7 @@ diff_fileproc (callerdat, finfo)
(vers->vn_rcs == NULL
? NULL
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
exists = (head != NULL
&& !RCS_isdead (vers->srcfile, head));
exists = head != NULL && !RCS_isdead(vers->srcfile, head);
if (head != NULL)
free (head);
}
@ -481,8 +530,7 @@ diff_fileproc (callerdat, finfo)
xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1,
1, 0);
exists = (xvers->vn_rcs != NULL
&& !RCS_isdead (xvers->srcfile, xvers->vn_rcs));
exists = xvers->vn_rcs != NULL && !RCS_isdead(xvers->srcfile, xvers->vn_rcs);
freevers_ts (&xvers);
}
if (exists)

View File

@ -335,8 +335,7 @@ mkdir_if_needed (name)
{
if (mkdir (name, 0777) < 0)
{
if (!(errno == EEXIST
|| (errno == EACCES && isdir (name))))
if (errno != EEXIST && !isdir (name))
error (1, errno, "cannot make directory %s", name);
return 1;
}

View File

@ -220,7 +220,11 @@ import (argc, argv)
if (use_editor)
{
do_editor ((char *) NULL, &message, repository,
do_editor ((char *) NULL, &message,
#ifdef CLIENT_SUPPORT
current_parsed_root->isremote ? (char *) NULL :
#endif
repository,
(List *) NULL);
}
do_verify (&message, repository);
@ -280,7 +284,7 @@ import (argc, argv)
}
#endif
if (!safe_location ())
if (!safe_location ( NULL ))
{
error (1, 0, "attempt to import the repository");
}
@ -313,7 +317,6 @@ import (argc, argv)
if (!really_quiet)
{
char buf[20];
char *buf2;
cvs_output_tagged ("+importmergecmd", NULL);
cvs_output_tagged ("newline", NULL);
@ -333,12 +336,9 @@ import (argc, argv)
cvs_output_tagged ("text", CVSroot_cmdline);
}
cvs_output_tagged ("text", " checkout -j");
buf2 = xmalloc (strlen (argv[1]) + 20);
sprintf (buf2, "%s:yesterday", argv[1]);
cvs_output_tagged ("mergetag1", buf2);
free (buf2);
cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
cvs_output_tagged ("text", " -j");
cvs_output_tagged ("mergetag2", argv[1]);
cvs_output_tagged ("mergetag2", argv[2]);
cvs_output_tagged ("text", " ");
cvs_output_tagged ("repository", argv[0]);
cvs_output_tagged ("newline", NULL);
@ -620,6 +620,7 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
Vers_TS *vers;
int letter;
char *tocvsPath;
char *expand;
struct file_info finfo;
memset (&finfo, 0, sizeof finfo);
@ -649,7 +650,9 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
tocvsPath = wrap_tocvs_process_file (vfile);
/* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
not NULL? */
different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, "-ko", vfile);
expand = vers->srcfile->expand != NULL &&
vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, expand, vfile);
if (tocvsPath)
if (unlink_file_dir (tocvsPath) < 0)
error (0, errno, "cannot remove %s", tocvsPath);
@ -1153,7 +1156,7 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
goto write_error;
}
if (local_opt != NULL)
if (local_opt != NULL && strcmp (local_opt, "kv") != 0)
{
if (fprintf (fprcs, "expand @%s@;\012", local_opt) < 0)
{

View File

@ -293,6 +293,9 @@ Lock_Cleanup ()
/* FIXME-reentrancy: the workaround isn't reentrant. */
static int in_lock_cleanup = 0;
if (trace)
(void) fprintf (stderr, "%s-> Lock_Cleanup()\n", CLIENT_SERVER_STR);
if (in_lock_cleanup)
return;
in_lock_cleanup = 1;
@ -398,6 +401,10 @@ Reader_Lock (xrepository)
FILE *fp;
char *tmp;
if (trace)
(void) fprintf (stderr, "%s-> Reader_Lock(%s)\n", CLIENT_SERVER_STR,
xrepository);
if (noexec || readonlyfs)
return (0);
@ -561,6 +568,10 @@ write_lock (lock)
FILE *fp;
char *tmp;
if (trace)
(void) fprintf (stderr, "%s-> write_lock(%s)\n",
CLIENT_SERVER_STR, lock->repository);
if (writelock == NULL)
{
writelock = xmalloc (strlen (hostname) + sizeof (CVSWFL) + 40);

View File

@ -324,8 +324,8 @@ password_entry_operation (operation, root, newpassword)
fp = CVS_FOPEN (passfile, "r");
if (fp == NULL)
{
error (0, errno, "failed to open %s for reading", passfile);
goto error_exit;
error (0, errno, "warning: failed to open %s for reading", passfile);
goto process;
}
cvsroot_canonical = normalize_cvsroot (root);
@ -363,6 +363,8 @@ password_entry_operation (operation, root, newpassword)
password = xstrdup (password);
}
process:
/* might as well return now */
if (operation == password_entry_lookup)
goto out;
@ -552,6 +554,12 @@ login (argc, argv)
{
char *tmp;
tmp = GETPASS ("CVS password: ");
/* Must deal with a NULL return value here. I haven't managed to
* disconnect the CVS process from the tty and force a NULL return
* in sanity.sh, but the Linux version of getpass is documented
* to return NULL when it can't open /dev/tty...
*/
if (!tmp) error (1, errno, "login: Failed to read password.");
typed_password = scramble (tmp);
memset (tmp, 0, strlen (tmp));
}
@ -562,7 +570,7 @@ login (argc, argv)
* will get zeroed by connect_to_server(). */
cvs_password = xstrdup (typed_password);
connect_to_pserver (NULL, NULL, 1, 0);
connect_to_pserver (current_parsed_root, NULL, NULL, 1, 0);
password_entry_operation (password_entry_add, current_parsed_root, typed_password);

View File

@ -8,6 +8,8 @@
* $FreeBSD$
*/
#include <assert.h>
#include "cvs.h"
#include "getline.h"
@ -29,6 +31,15 @@ static char *editinfo_editor;
static char *verifymsg_script;
static Ctype type;
/*
* Should the logmsg be re-read during the do_verify phase?
* RereadLogAfterVerify=no|stat|yes
* LOGMSG_REREAD_NEVER - never re-read the logmsg
* LOGMSG_REREAD_STAT - re-read the logmsg only if it has changed
* LOGMSG_REREAD_ALWAYS - always re-read the logmsg
*/
int RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS;
/*
* Puts a standard header on the output which is either being prepared for an
* editor session, or being sent to a logfile program. The modified, added,
@ -168,7 +179,8 @@ fmt_proc (p, closure)
* stripped and the log message is stored in the "message" argument.
*
* If REPOSITORY is non-NULL, process rcsinfo for that repository; if it
* is NULL, use the CVSADM_TEMPLATE file instead.
* is NULL, use the CVSADM_TEMPLATE file instead. REPOSITORY should be
* NULL when running in client mode.
*/
void
do_editor (dir, messagep, repository, changes)
@ -185,6 +197,9 @@ do_editor (dir, messagep, repository, changes)
struct stat pre_stbuf, post_stbuf;
int retcode = 0;
assert (current_parsed_root->isremote && !repository
|| !current_parsed_root->isremote && repository);
if (noexec || reuse_log_message)
return;
@ -309,7 +324,7 @@ do_editor (dir, messagep, repository, changes)
/* On NT, we might read less than st_size bytes, but we won't
read more. So this works. */
*messagep = (char *) xmalloc (post_stbuf.st_size + 1);
*messagep[0] = '\0';
(*messagep)[0] = '\0';
}
line = NULL;
@ -342,8 +357,14 @@ do_editor (dir, messagep, repository, changes)
if (pre_stbuf.st_mtime == post_stbuf.st_mtime ||
*messagep == NULL ||
(*messagep)[0] == '\0' ||
strcmp (*messagep, "\n") == 0)
{
if (*messagep)
{
free (*messagep);
*messagep = NULL;
}
for (;;)
{
(void) printf ("\nLog message unchanged or not specified\n");
@ -399,11 +420,7 @@ do_verify (messagep, repository)
char *fname;
int retcode = 0;
char *line;
int line_length;
size_t line_chars_allocated;
char *p;
struct stat stbuf;
struct stat pre_stbuf, post_stbuf;
#ifdef CLIENT_SUPPORT
if (current_parsed_root->isremote)
@ -429,78 +446,104 @@ do_verify (messagep, repository)
if ((fp = cvs_temp_file (&fname)) == NULL)
error (1, errno, "cannot create temporary file %s", fname);
else
fprintf (fp, "%s", *messagep);
if ((*messagep)[0] == '\0' ||
(*messagep)[strlen (*messagep) - 1] != '\n')
(void) fprintf (fp, "%s", "\n");
if (fclose (fp) == EOF)
error (1, errno, "%s", fname);
if (RereadLogAfterVerify == LOGMSG_REREAD_STAT)
{
fprintf (fp, "%s", *messagep);
if ((*messagep)[0] == '\0' ||
(*messagep)[strlen (*messagep) - 1] != '\n')
(void) fprintf (fp, "%s", "\n");
if (fclose (fp) == EOF)
error (1, errno, "%s", fname);
/* Remember the status of the temp file for later */
if ( CVS_STAT (fname, &pre_stbuf) != 0 )
error (1, errno, "cannot stat temp file %s", fname);
/* Get the name of the verification script to run */
/*
* See if we need to sleep before running the verification
* script to avoid time-stamp races.
*/
sleep_past (pre_stbuf.st_mtime);
}
if (repository != NULL)
(void) Parse_Info (CVSROOTADM_VERIFYMSG, repository,
verifymsg_proc, 0);
/* Get the name of the verification script to run */
/* Run the verification script */
if (repository != NULL)
(void) Parse_Info (CVSROOTADM_VERIFYMSG, repository,
verifymsg_proc, 0);
if (verifymsg_script)
/* Run the verification script */
if (verifymsg_script)
{
run_setup (verifymsg_script);
run_arg (fname);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
RUN_NORMAL | RUN_SIGIGNORE)) != 0)
{
run_setup (verifymsg_script);
run_arg (fname);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
RUN_NORMAL | RUN_SIGIGNORE)) != 0)
{
/* Since following error() exits, delete the temp file
now. */
if (unlink_file (fname) < 0)
error (0, errno, "cannot remove %s", fname);
/* Since following error() exits, delete the temp file now. */
if (unlink_file (fname) < 0)
error (0, errno, "cannot remove %s", fname);
error (1, retcode == -1 ? errno : 0,
"Message verification failed");
}
error (1, retcode == -1 ? errno : 0,
"Message verification failed");
}
}
/* Get the mod time and size of the possibly new log message
* in always and stat modes.
*/
if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
RereadLogAfterVerify == LOGMSG_REREAD_STAT)
{
if ( CVS_STAT (fname, &post_stbuf) != 0 )
error (1, errno, "cannot find size of temp file %s", fname);
}
/* And reread the log message in `always' mode or in `stat' mode when it's
* changed
*/
if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
(RereadLogAfterVerify == LOGMSG_REREAD_STAT &&
(pre_stbuf.st_mtime != post_stbuf.st_mtime ||
pre_stbuf.st_size != post_stbuf.st_size)))
{
/* put the entire message back into the *messagep variable */
fp = open_file (fname, "r");
if (fp == NULL)
{
if ( (fp = open_file (fname, "r")) == NULL )
error (1, errno, "cannot open temporary file %s", fname);
return;
}
if (*messagep)
free (*messagep);
if (*messagep) free (*messagep);
if ( CVS_STAT (fname, &stbuf) != 0)
error (1, errno, "cannot find size of temp file %s", fname);
if (stbuf.st_size == 0)
if (post_stbuf.st_size == 0)
*messagep = NULL;
else
{
/* On NT, we might read less than st_size bytes, but we won't
read more. So this works. */
*messagep = (char *) xmalloc (stbuf.st_size + 1);
/* On NT, we might read less than st_size bytes,
but we won't read more. So this works. */
*messagep = (char *) xmalloc (post_stbuf.st_size + 1);
*messagep[0] = '\0';
}
line = NULL;
line_chars_allocated = 0;
if (*messagep)
{
p = *messagep;
char *line = NULL;
int line_length;
size_t line_chars_allocated = 0;
char *p = *messagep;
while (1)
{
line_length = getline (&line, &line_chars_allocated, fp);
line_length = getline (&line,
&line_chars_allocated,
fp);
if (line_length == -1)
{
if (ferror (fp))
error (0, errno, "warning: cannot read %s", fname);
/* Fail in this case because otherwise we will have no
* log message
*/
error (1, errno, "cannot read %s", fname);
break;
}
if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
@ -508,16 +551,17 @@ do_verify (messagep, repository)
(void) strcpy (p, line);
p += line_length;
}
if (line) free (line);
}
if (fclose (fp) < 0)
error (0, errno, "warning: cannot close %s", fname);
/* Delete the temp file */
if (unlink_file (fname) < 0)
error (0, errno, "cannot remove %s", fname);
free (fname);
}
/* Delete the temp file */
if (unlink_file (fname) < 0)
error (0, errno, "cannot remove %s", fname);
free (fname);
}
/*

View File

@ -156,7 +156,7 @@ static const char *const usg[] =
putting metavariables in uppercase. I don't know whether that
is a good convention or not, but if it changes it would have to
change in all the usage messages. For now, they consistently
use lowercase, as far as I know. Puncutation is pretty funky,
use lowercase, as far as I know. Punctuation is pretty funky,
though. Sometimes they use none, as here. Sometimes they use
single quotes (not the TeX-ish `' stuff), as in --help-options.
Sometimes they use double quotes, as in cvs -H add.
@ -338,6 +338,8 @@ lookup_command_attribute (cmd_name)
if (strcmp (cmd_name, cm->fullname) == 0)
break;
}
if (!cm->fullname)
error (1, 0, "unknown command: %s", cmd_name);
return cm->attr;
}
@ -868,7 +870,7 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
error (0, 0,
"CVSROOT is set but empty! Make sure that the");
error (0, 0,
"specification of CVSROOT is legal, either via the");
"specification of CVSROOT is valid, either via the");
error (0, 0,
"`-d' option, the %s environment variable, or the",
CVSROOT_ENV);
@ -928,7 +930,7 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
if (current_parsed_root != NULL)
free_cvsroot_t (current_parsed_root);
if ((current_parsed_root = parse_cvsroot (current_root)) == NULL)
error (1, 0, "Bad CVSROOT.");
error (1, 0, "Bad CVSROOT: `%s'.", current_root);
if (trace)
fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",

View File

@ -209,10 +209,12 @@ static const char *const checkoutlist_contents[] = {
static const char *const cvswrappers_contents[] = {
"# This file affects handling of files based on their names.\n",
"#\n",
#if 0 /* see comments in wrap_add in wrapper.c */
"# The -t/-f options allow one to treat directories of files\n",
"# as a single file, or to transform a file in other ways on\n",
"# its way in and out of CVS.\n",
"#\n",
#endif
"# The -m option specifies whether CVS attempts to merge files.\n",
"#\n",
"# The -k option specifies keyword expansion (e.g. -kb for binary).\n",
@ -245,7 +247,7 @@ static const char *const notify_contents[] = {
"# \"ALL\" or \"DEFAULT\" can be used in place of the regular expression.\n",
"#\n",
"# For example:\n",
"#ALL mail %s -s \"CVS notification\"\n",
"#ALL mail -s \"CVS notification\" %s\n",
NULL
};
@ -300,6 +302,14 @@ static const char *const config_contents[] = {
"# 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",
"\n",
"# Set `RereadLogAfterVerify' to `always' (the default) to allow the verifymsg\n",
"# script to change the log message. Set it to `stat' to force CVS to verify",
"# that the file has changed before reading it (this can take up to an extra\n",
"# second per directory being committed, so it is not recommended for large\n",
"# repositories. Set it to `never' (the previous CVS behavior) to prevent\n",
"# verifymsg scripts from changing the log message.\n",
"#RereadLogAfterVerify=always\n",
NULL
};

View File

@ -15,6 +15,14 @@
#include "edit.h"
#include "hardlink.h"
/* These need to be source after cvs.h or HAVE_MMAP won't be set... */
#ifdef HAVE_MMAP
# include <sys/mman.h>
# ifndef HAVE_GETPAGESIZE
# include "getpagesize.h"
# endif
#endif
int preserve_perms = 0;
/* The RCS -k options, and a set of enums that must match the array.
@ -60,8 +68,10 @@ static void rcsbuf_close PROTO ((struct rcsbuffer *));
static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
char **valp));
static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
#ifndef HAVE_MMAP
static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,
char **valp));
#endif
static int rcsbuf_valcmp PROTO ((struct rcsbuffer *));
static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish,
size_t *lenp));
@ -734,8 +744,8 @@ RCS_fully_parse (rcs)
vers = findnode (rcs->versions, key);
if (vers == NULL)
error (1, 0,
"mismatch in rcs file %s between deltas and deltatexts",
rcs->path);
"mismatch in rcs file %s between deltas and deltatexts (%s)",
rcs->path, key);
vnode = (RCSVers *) vers->data;
@ -793,12 +803,12 @@ unrecognized operation '\\x%x' in %s",
op, rcs->path);
(void) strtoul (cp, (char **) &cp, 10);
if (*cp++ != ' ')
error (1, 0, "space expected in %s",
rcs->path);
error (1, 0, "space expected in %s revision %s",
rcs->path, vnode->version);
count = strtoul (cp, (char **) &cp, 10);
if (*cp++ != '\012')
error (1, 0, "linefeed expected in %s",
rcs->path);
error (1, 0, "linefeed expected in %s revision %s",
rcs->path, vnode->version);
if (op == 'd')
del += count;
@ -813,8 +823,8 @@ unrecognized operation '\\x%x' in %s",
{
if (count != 1)
error (1, 0, "\
invalid rcs file %s: premature end of value",
rcs->path);
premature end of value in %s revision %s",
rcs->path, vnode->version);
else
break;
}
@ -991,14 +1001,45 @@ rcsbuf_open (rcsbuf, fp, filename, pos)
error (1, 0, "rcsbuf_open: internal error");
rcsbuf_inuse = 1;
#ifdef HAVE_MMAP
{
/* When we have mmap, it is much more efficient to let the system do the
* buffering and caching for us
*/
struct stat fs;
size_t mmap_off = 0;
if ( fstat (fileno(fp), &fs) < 0 )
error ( 1, errno, "Could not stat RCS archive %s for mapping", filename );
if (pos)
{
size_t ps = getpagesize ();
mmap_off = ( pos / ps ) * ps;
}
/* Map private here since this particular buffer is read only */
rcsbuf_buffer = mmap ( NULL, fs.st_size - mmap_off,
PROT_READ | PROT_WRITE,
MAP_PRIVATE, fileno(fp), mmap_off );
if ( rcsbuf_buffer == NULL || rcsbuf_buffer == MAP_FAILED )
error ( 1, errno, "Could not map memory to RCS archive %s", filename );
rcsbuf_buffer_size = fs.st_size - mmap_off;
rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off;
rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off;
rcsbuf->pos = mmap_off;
}
#else /* HAVE_MMAP */
if (rcsbuf_buffer_size < RCSBUF_BUFSIZE)
expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE);
rcsbuf->ptr = rcsbuf_buffer;
rcsbuf->ptrend = rcsbuf_buffer;
rcsbuf->pos = pos;
#endif /* HAVE_MMAP */
rcsbuf->fp = fp;
rcsbuf->filename = filename;
rcsbuf->pos = pos;
rcsbuf->vlen = 0;
rcsbuf->at_string = 0;
rcsbuf->embedded_at = 0;
@ -1012,6 +1053,9 @@ rcsbuf_close (rcsbuf)
{
if (! rcsbuf_inuse)
error (1, 0, "rcsbuf_close: internal error");
#ifdef HAVE_MMAP
munmap ( rcsbuf_buffer, rcsbuf_buffer_size );
#endif
rcsbuf_inuse = 0;
}
@ -1052,9 +1096,9 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
ptrend = rcsbuf->ptrend;
/* Sanity check. */
if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
abort ();
assert (ptr >= rcsbuf_buffer && ptr < rcsbuf_buffer + rcsbuf_buffer_size);
#ifndef HAVE_MMAP
/* If the pointer is more than RCSBUF_BUFSIZE bytes into the
buffer, move back to the start of the buffer. This keeps the
buffer from growing indefinitely. */
@ -1066,8 +1110,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
/* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
at a time, so we can't have more bytes than that past PTR. */
if (len > RCSBUF_BUFSIZE)
abort ();
assert (len <= RCSBUF_BUFSIZE);
/* Update the POS field, which holds the file offset of the
first byte in the RCSBUF_BUFFER buffer. */
@ -1078,18 +1121,23 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
ptrend = ptr + len;
rcsbuf->ptrend = ptrend;
}
#endif /* ndef HAVE_MMAP */
/* Skip leading whitespace. */
while (1)
{
if (ptr >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
if (ptr == NULL)
#endif
return 0;
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
c = *ptr;
if (! my_whitespace (c))
@ -1108,13 +1156,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
{
++ptr;
if (ptr >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
if (ptr == NULL)
#endif
error (1, 0, "EOF in key in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
c = *ptr;
if (c == ';' || my_whitespace (c))
break;
@ -1143,13 +1195,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
while (1)
{
if (ptr >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
if (ptr == NULL)
#endif
error (1, 0, "EOF while looking for value in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
c = *ptr;
if (c == ';')
{
@ -1184,6 +1240,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
while (1)
{
while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
#ifndef HAVE_MMAP
{
/* Note that we pass PTREND as the PTR value to
rcsbuf_fill, so that we will wind up setting PTR to
@ -1191,25 +1248,31 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
that we don't search the same bytes again. */
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
if (ptr == NULL)
#endif
error (1, 0,
"EOF while looking for end of string in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
/* Handle the special case of an '@' right at the end of
the known bytes. */
if (pat + 1 >= ptrend)
#ifndef HAVE_MMAP
{
/* Note that we pass PAT, not PTR, here. */
pat = rcsbuf_fill (rcsbuf, pat, keyp, valp);
if (pat == NULL)
{
#endif
/* EOF here is OK; it just means that the last
character of the file was an '@' terminating a
value for a key type which does not require a
trailing ';'. */
pat = rcsbuf->ptrend - 1;
#ifndef HAVE_MMAP
}
ptrend = rcsbuf->ptrend;
@ -1217,6 +1280,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
/* Note that the value of PTR is bogus here. This is
OK, because we don't use it. */
}
#endif
if (pat + 1 >= ptrend || pat[1] != '@')
break;
@ -1266,13 +1330,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
char n;
if (ptr >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
if (ptr == NULL)
#endif
error (1, 0, "EOF in value in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
n = *ptr;
if (n == ';')
{
@ -1307,6 +1375,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
/* Find the ';' which must end the value. */
start = ptr;
while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL)
#ifndef HAVE_MMAP
{
int slen;
@ -1317,10 +1386,13 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
slen = start - *valp;
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
if (ptr == NULL)
#endif
error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename);
#ifndef HAVE_MMAP
start = *valp + slen;
ptrend = rcsbuf->ptrend;
}
#endif
/* See if there are any '@' strings in the value. */
pat = memchr (start, '@', psemi - start);
@ -1364,6 +1436,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
while (1)
{
while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
#ifndef HAVE_MMAP
{
/* Note that we pass PTREND as the PTR value to
rcsbuff_fill, so that we will wind up setting PTR
@ -1371,22 +1444,29 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
that we don't search the same bytes again. */
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
if (ptr == NULL)
#endif
error (1, 0,
"EOF while looking for end of string in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
/* Handle the special case of an '@' right at the end of
the known bytes. */
if (pat + 1 >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
if (ptr == NULL)
#endif
error (1, 0, "EOF in value in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
if (pat[1] != '@')
break;
@ -1429,12 +1509,16 @@ rcsbuf_getrevnum (rcsbuf, revp)
while (1)
{
if (ptr >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
if (ptr == NULL)
#endif
return 0;
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
c = *ptr;
if (! whitespace (c))
@ -1455,14 +1539,18 @@ unexpected '\\x%x' reading revision number in RCS file %s",
{
++ptr;
if (ptr >= ptrend)
#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL);
if (ptr == NULL)
#endif
error (1, 0,
"unexpected EOF reading revision number in RCS file %s",
rcsbuf->filename);
#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
#endif
c = *ptr;
}
@ -1480,6 +1568,7 @@ unexpected '\\x%x' reading revision number in RCS file %s",
return 1;
}
#ifndef HAVE_MMAP
/* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF,
updating PTR and the PTREND field. If KEYP and *KEYP are not NULL,
then *KEYP points into the buffer, and must be adjusted if the
@ -1531,6 +1620,7 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp)
return ptr;
}
#endif /* HAVE_MMAP */
/* Test whether the last value returned by rcsbuf_getkey is a composite
value or not. */
@ -1687,7 +1777,19 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
{
++from;
/* Sanity check. */
/* Sanity check.
*
* FIXME: I restored this to an abort from an assert based on
* advice from Larry Jones that asserts should not be used to
* confirm the validity of an RCS file... This leaves two
* issues here: 1) I am uncertain that the fact that we will
* only find double '@'s hasn't already been confirmed; and:
* 2) If this is the proper place to spot the error in the RCS
* file, then we should print a much clearer error here for the
* user!!!!!!!
*
* - DRP
*/
if (*from != '@' || clen == 0)
abort ();
@ -1711,11 +1813,8 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
}
/* Sanity check. */
if (from != orig_from + len
|| to != orig_to + (len - rcsbuf->embedded_at))
{
abort ();
}
assert (from == orig_from + len
&& to == orig_to + (len - rcsbuf->embedded_at));
*to = '\0';
}
@ -1736,7 +1835,7 @@ rcsbuf_valword (rcsbuf, valp)
register char *ptr, *pat;
char c;
#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
# define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
if (*valp == NULL)
return NULL;
@ -1794,7 +1893,7 @@ rcsbuf_valword (rcsbuf, valp)
or an id. Make sure it is not another special character. */
if (c == '$' || c == '.' || c == ',')
{
error (1, 0, "illegal special character in RCS field in %s",
error (1, 0, "invalid special character in RCS field in %s",
rcsbuf->filename);
}
@ -1814,7 +1913,7 @@ rcsbuf_valword (rcsbuf, valp)
the character in its memory cell. Check to make sure that it
is a legitimate word delimiter -- whitespace or end. */
if (c != '\0' && !my_whitespace (c))
error (1, 0, "illegal special character in RCS field in %s",
error (1, 0, "invalid special character in RCS field in %s",
rcsbuf->filename);
*pat = '\0';
@ -1822,7 +1921,7 @@ rcsbuf_valword (rcsbuf, valp)
*valp = pat;
return xstrdup (ptr);
#undef my_whitespace
# undef my_whitespace
}
#endif
@ -1833,7 +1932,7 @@ static unsigned long
rcsbuf_ftell (rcsbuf)
struct rcsbuffer *rcsbuf;
{
return rcsbuf->pos + (rcsbuf->ptr - rcsbuf_buffer);
return rcsbuf->pos + rcsbuf->ptr - rcsbuf_buffer;
}
/* Return a pointer to any data buffered for RCSBUF, along with the
@ -1880,9 +1979,9 @@ rcsbuf_cache_close ()
{
if (cached_rcs != NULL)
{
rcsbuf_close (&cached_rcsbuf);
if (fclose (cached_rcsbuf.fp) != 0)
error (0, errno, "cannot close %s", cached_rcsbuf.filename);
rcsbuf_close (&cached_rcsbuf);
freercsnode (&cached_rcs);
cached_rcs = NULL;
}
@ -1899,6 +1998,7 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
FILE **pfp;
struct rcsbuffer *prcsbuf;
{
#ifndef HAVE_MMAP
if (cached_rcs == rcs)
{
if (rcsbuf_ftell (&cached_rcsbuf) != pos)
@ -1929,19 +2029,32 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
}
else
{
#endif /* ifndef HAVE_MMAP */
/* FIXME: If these routines can be rewritten to not write to the
* rcs file buffer, there would be a considerably larger memory savings
* from using mmap since the shared file would never need be copied to
* process memory.
*
* If this happens, cached mmapped buffers would be usable, but don't
* forget to make sure rcs->pos < pos here...
*/
if (cached_rcs != NULL)
rcsbuf_cache_close ();
*pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ);
if (*pfp == NULL)
error (1, 0, "unable to reopen `%s'", rcs->path);
#ifndef HAVE_MMAP
if (pos != 0)
{
if (fseek (*pfp, pos, SEEK_SET) != 0)
error (1, 0, "cannot fseek RCS file %s", rcs->path);
}
#endif /* ifndef HAVE_MMAP */
rcsbuf_open (prcsbuf, *pfp, rcs->path, pos);
#ifndef HAVE_MMAP
}
#endif /* ifndef HAVE_MMAP */
}
@ -2239,7 +2352,7 @@ RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
/* If tag is "HEAD", special case to get head RCS revision */
if (tag && (STREQ (tag, TAG_HEAD) || *tag == '\0'))
if (tag && STREQ (tag, TAG_HEAD))
#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
return ((char *) NULL); /* head request for removed file */
@ -2848,16 +2961,21 @@ RCS_getdate (rcs, date, force_tag_match)
/* if the head is on a branch, try the branch first */
if (rcs->branch != NULL)
{
retval = RCS_getdatebranch (rcs, date, rcs->branch);
/* if we found a match, we are done */
if (retval != NULL)
return (retval);
if (retval != NULL)
return (retval);
}
/* otherwise if we have a trunk, try it */
if (rcs->head)
{
p = findnode (rcs->versions, rcs->head);
if (p == NULL)
{
error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
rcs->head);
}
while (p != NULL)
{
/* if the date of this one is before date, take it */
@ -2875,10 +2993,13 @@ RCS_getdate (rcs, date, force_tag_match)
p = (Node *) NULL;
}
}
else
error (0, 0, "%s: no head revision", rcs->path);
/*
* at this point, either we have the revision we want, or we have the
* first revision on the trunk (1.1?) in our hands
* first revision on the trunk (1.1?) in our hands, or we've come up
* completely empty
*/
/* if we found what we're looking for, and it's not 1.1 return it */
@ -2913,7 +3034,8 @@ RCS_getdate (rcs, date, force_tag_match)
if (retval != NULL)
return (retval);
if (!force_tag_match || RCS_datecmp (vers->date, date) <= 0)
if (!force_tag_match ||
(vers != NULL && RCS_datecmp (vers->date, date) <= 0))
return (xstrdup (vers->version));
else
return (NULL);
@ -3186,6 +3308,8 @@ translate_symtag (rcs, tag)
while (! whitespace (*cp) && *cp != '\0')
++cp;
if (*cp == '\0')
break;
}
}
@ -4267,7 +4391,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
/* If the size of `devtype' changes, fix the sscanf call also */
char devtype[16];
if (sscanf (info->data, "%16s %lu",
if (sscanf (info->data, "%15s %lu",
devtype, &devnum_long) < 2)
error (1, 0, "%s:%s has bad `special' newphrase %s",
workfile, vers->version, info->data);
@ -4332,7 +4456,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
#ifdef PRESERVE_PERMISSIONS_SUPPORT
else if (special_file)
{
#ifdef HAVE_MKNOD
# ifdef HAVE_MKNOD
char *dest;
/* Can send either to WORKFILE or to SOUT, as long as SOUT is
@ -4353,11 +4477,11 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
if (mknod (dest, special_file, devnum) < 0)
error (1, errno, "could not create special file %s",
dest);
#else
# else
error (1, 0,
"cannot create %s: unable to create special files on this system",
workfile);
#endif
# endif
}
#endif
else
@ -4960,7 +5084,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
case S_IFREG: break;
case S_IFCHR:
case S_IFBLK:
#ifdef HAVE_ST_RDEV
# ifdef HAVE_ST_RDEV
np = getnode();
np->type = RCSFIELD;
np->key = xstrdup ("special");
@ -4970,11 +5094,11 @@ RCS_checkin (rcs, workfile, message, rev, flags)
(unsigned long) sb.st_rdev);
np->data = xstrdup (buf);
addnode (delta->other_delta, np);
#else
# else
error (0, 0,
"can't preserve %s: unable to save device files on this system",
workfile);
#endif
# endif
break;
default:
@ -5825,7 +5949,9 @@ RCS_unlock (rcs, rev, unlock_quiet)
if (rcs->flags & PARTIAL)
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
/* If rev is NULL, unlock the latest revision (first in
/* If rev is NULL, unlock the revision held by the caller; if more
than one, make the user specify the revision explicitly. This
differs from RCS which unlocks the latest revision (first in
rcs->locks) held by the caller. */
if (rev == NULL)
{
@ -5850,17 +5976,24 @@ RCS_unlock (rcs, rev, unlock_quiet)
lock = NULL;
for (p = locks->list->next; p != locks->list; p = p->next)
{
if (lock != NULL)
if (STREQ (p->data, user))
{
if (!unlock_quiet)
error (0, 0, "\
if (lock != NULL)
{
if (!unlock_quiet)
error (0, 0, "\
%s: multiple revisions locked by %s; please specify one", rcs->path, user);
return 1;
return 1;
}
lock = p;
}
lock = p;
}
if (lock == NULL)
{
if (!unlock_quiet)
error (0, 0, "No locks are set for %s.\n", user);
return 0; /* no lock found, ergo nothing to do */
}
xrev = xstrdup (lock->key);
}
else
@ -5888,6 +6021,9 @@ RCS_unlock (rcs, rev, unlock_quiet)
is called with a NULL revision, since that means "whatever
revision is currently locked by the caller." */
char *repos, *workfile;
if (!unlock_quiet)
error (0, 0, "\
%s: revision %s locked by %s; breaking lock", rcs->path, xrev, lock->data);
repos = xstrdup (rcs->path);
workfile = strrchr (repos, '/');
*workfile++ = '\0';
@ -7109,8 +7245,8 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
node = findnode (rcs->versions, key);
if (node == NULL)
error (1, 0,
"mismatch in rcs file %s between deltas and deltatexts",
rcs->path);
"mismatch in rcs file %s between deltas and deltatexts (%s)",
rcs->path, key);
/* Stash the previous version. */
prev_vers = vers;
@ -7602,8 +7738,8 @@ RCS_getdeltatext (rcs, fp, rcsbuf)
p = findnode (rcs->versions, num);
if (p == NULL)
error (1, 0, "mismatch in rcs file %s between deltas and deltatexts",
rcs->path);
error (1, 0, "mismatch in rcs file %s between deltas and deltatexts (%s)",
rcs->path, num);
d = (Deltatext *) xmalloc (sizeof (Deltatext));
d->version = xstrdup (num);
@ -7963,8 +8099,10 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
char *bufrest;
int nls;
size_t buflen;
#ifndef HAVE_MMAP
char buf[8192];
int got;
#endif
/* Count the number of versions for which we have to do some
special operation. */
@ -8073,7 +8211,12 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
fwrite (bufrest, 1, buflen, fout);
}
#ifndef HAVE_MMAP
/* This bit isn't necessary when using mmap since the entire file
* will already be available via the RCS buffer. Besides, the
* mmap code doesn't always keep the file pointer up to date, so
* this adds some data twice.
*/
while ((got = fread (buf, 1, sizeof buf, fin)) != 0)
{
if (nls > 0
@ -8090,6 +8233,7 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
nls = 0;
}
#endif /* HAVE_MMAP */
}
/* A helper procedure for RCS_copydeltas. This is called via walklist
@ -8351,7 +8495,8 @@ RCS_rewrite (rcs, newdtext, insertpt)
/* Update delta_pos to the current position in the output file.
Do NOT move these statements: they must be done after fin has
been positioned at the old delta_pos, but before any delta
texts have been written to fout. */
texts have been written to fout.
*/
rcs->delta_pos = ftell (fout);
if (rcs->delta_pos == -1)
error (1, errno, "cannot ftell in RCS file %s", rcs->path);
@ -8368,7 +8513,7 @@ RCS_rewrite (rcs, newdtext, insertpt)
fragile even if it happens to sometimes be true. The real
solution is to make sure that all the code which reads
from fin checks for errors itself (some does, some doesn't). */
error (0, 0, "warning: when closing RCS file `%s'", rcs->path);
error (0, 0, "warning: ferror set while rewriting RCS file `%s'", rcs->path);
if (fclose (fin) < 0)
error (0, errno, "warning: closing RCS file `%s'", rcs->path);

View File

@ -248,7 +248,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
directories. */
if (!wrap_name_has (argv[i], WRAP_TOCVS) && isdir (argv[i]))
{
strip_trailing_slashes (argv[i]);
addlist (&dirlist, argv[i]);
}
else
{
/* otherwise, split argument into directory and component names. */

View File

@ -63,7 +63,10 @@ int cvs_gssapi_encrypt;
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
# include <syslog.h>
# ifndef LOG_DAEMON /* for ancient syslogs */
# define LOG_DAEMON 0
# endif
#endif
#ifdef HAVE_KERBEROS
@ -163,7 +166,7 @@ static int fd_buffer_input PROTO((void *, char *, int, int, int *));
static int fd_buffer_output PROTO((void *, const char *, int, int *));
static int fd_buffer_flush PROTO((void *));
static int fd_buffer_block PROTO((void *, int));
static int fd_buffer_shutdown PROTO((void *));
static int fd_buffer_shutdown PROTO((struct buffer *));
/* Initialize a buffer built on a file descriptor. FD is the file
descriptor. INPUT is nonzero if this is for input, zero if this is
@ -325,10 +328,10 @@ fd_buffer_block (closure, block)
/* The buffer shutdown function for a buffer built on a file descriptor. */
static int
fd_buffer_shutdown (closure)
void *closure;
fd_buffer_shutdown (buf)
struct buffer *buf;
{
free (closure);
free (buf->closure);
return 0;
}
@ -364,7 +367,7 @@ create_adm_p (base_dir, dir)
if (tmp == NULL)
return ENOMEM;
/* We make several passes through this loop. On the first pass,
we simply create the CVSADM directory in the deepest directory.
For each subsequent pass, we try to remove the last path
@ -427,8 +430,7 @@ create_adm_p (base_dir, dir)
}
(void) umask (omask);
}
f = CVS_FOPEN (tmp, "w");
if (f == NULL)
{
@ -735,7 +737,7 @@ serve_root (arg)
{
char *env;
char *path;
if (error_pending()) return;
if (!isabsolute (arg))
@ -773,12 +775,11 @@ serve_root (arg)
sprintf (pending_error_text, "\
E Protocol error: Root says \"%s\" but pserver says \"%s\"",
arg, Pserver_Repos);
return;
}
}
#endif
if (current_parsed_root != NULL)
free_cvsroot_t (current_parsed_root);
current_parsed_root = local_cvsroot (arg);
/* For pserver, this will already have happened, and the call will do
@ -919,7 +920,7 @@ E protocol error: directory '%s' not within current directory",
}
return 0;
}
/*
* Add as many directories to the temp directory as the client tells us it
* will use "..", so we never try to access something outside the temp
@ -1008,7 +1009,7 @@ dirswitch (dir, repos)
pending_error = ENOMEM;
return;
}
strcpy (dir_name, server_temp_dir);
strcat (dir_name, "/");
strcat (dir_name, dir);
@ -2125,9 +2126,9 @@ serve_argument (arg)
char *arg;
{
char *p;
if (error_pending()) return;
if (argument_vector_size <= argument_count)
{
argument_vector_size *= 2;
@ -2155,9 +2156,9 @@ serve_argumentx (arg)
char *arg;
{
char *p;
if (error_pending()) return;
p = argument_vector[argument_count - 1];
p = realloc (p, strlen (p) + 1 + strlen (arg) + 1);
if (p == NULL)
@ -2479,7 +2480,7 @@ check_command_legal_p (cmd_name)
size_t flen;
FILE *fp;
int found_it = 0;
/* else */
flen = strlen (current_parsed_root->directory)
+ strlen (CVSROOTADM)
@ -2571,7 +2572,7 @@ check_command_legal_p (cmd_name)
/* Chop newline by hand, for strcmp()'s sake. */
if (linebuf[num_red - 1] == '\n')
linebuf[num_red - 1] = '\0';
if (strcmp (linebuf, CVS_Username) == 0)
{
found_it = 1;
@ -2638,7 +2639,7 @@ do_cvs_command (cmd_name, command)
* interleaved with data from stdout_pipe or stderr_pipe).
*/
int protocol_pipe[2];
int dev_null_fd = -1;
int errs;
@ -3017,7 +3018,7 @@ error \n");
{
int status;
int count_read;
status = buf_input_data (protocol_inbuf, &count_read);
if (status == -1)
@ -3175,7 +3176,7 @@ error \n");
*/
continue;
}
if (WIFEXITED (status))
errs += WEXITSTATUS (status);
else
@ -3302,7 +3303,7 @@ server_pause_check()
FD_ZERO (&fds);
FD_SET (flowcontrol_pipe[0], &fds);
numtocheck = flowcontrol_pipe[0] + 1;
do {
numfds = select (numtocheck, &fds, (fd_set *)0,
(fd_set *)0, (struct timeval *)NULL);
@ -3314,7 +3315,7 @@ server_pause_check()
return;
}
} while (numfds < 0);
if (FD_ISSET (flowcontrol_pipe[0], &fds))
{
int got;
@ -3437,7 +3438,7 @@ server_register (name, version, timestamp, options, tag, date, conflict)
len += strlen (tag);
if (date)
len += strlen (date);
entries_line = xmalloc (len);
sprintf (entries_line, "/%s/%s/", name, version);
if (conflict != NULL)
@ -3672,7 +3673,7 @@ static void
serve_tag (arg)
char *arg;
{
do_cvs_command ("cvstag", cvstag);
do_cvs_command ("tag", cvstag);
}
static void
@ -3797,20 +3798,38 @@ static void
serve_init (arg)
char *arg;
{
cvsroot_t *saved_parsed_root;
if (!isabsolute (arg))
{
if (alloc_pending (80 + strlen (arg)))
sprintf (pending_error_text,
"E Root %s must be an absolute pathname", arg);
/* Fall through to do_cvs_command which will return the
actual error. */
"E init %s must be an absolute pathname", arg);
}
#ifdef AUTH_SERVER_SUPPORT
else if (Pserver_Repos != NULL)
{
if (strcmp (Pserver_Repos, arg) != 0)
{
if (alloc_pending (80 + strlen (Pserver_Repos) + strlen (arg)))
/* The explicitness is to aid people who are writing clients.
I don't see how this information could help an
attacker. */
sprintf (pending_error_text, "\
E Protocol error: init says \"%s\" but pserver says \"%s\"",
arg, Pserver_Repos);
}
}
#endif
if (current_parsed_root != NULL)
free_cvsroot_t (current_parsed_root);
if (print_pending_error ())
return;
saved_parsed_root = current_parsed_root;
current_parsed_root = local_cvsroot (arg);
do_cvs_command ("init", init);
free_cvsroot_t (current_parsed_root);
current_parsed_root = saved_parsed_root;
}
static void serve_annotate PROTO ((char *));
@ -4574,7 +4593,6 @@ serve_expand_modules (arg)
DBM *db;
err = 0;
server_expanding = 1;
db = open_module ();
for (i = 1; i < argument_count; i++)
err += do_module (db, argument_vector[i],
@ -4582,7 +4600,6 @@ serve_expand_modules (arg)
NULL, 0, 0, 0, 0,
(char *) NULL);
close_module (db);
server_expanding = 0;
{
/* argument_vector[0] is a dummy argument, we don't mess with it. */
char **cp;
@ -4612,23 +4629,24 @@ server_prog (dir, name, which)
{
if (!supported_response ("Set-checkin-prog"))
{
buf_output0 (buf_to_net, "E \
buf_output0 (protocol, "E \
warning: this client does not support -i or -u flags in the modules file.\n");
return;
}
switch (which)
{
case PROG_CHECKIN:
buf_output0 (buf_to_net, "Set-checkin-prog ");
buf_output0 (protocol, "Set-checkin-prog ");
break;
case PROG_UPDATE:
buf_output0 (buf_to_net, "Set-update-prog ");
buf_output0 (protocol, "Set-update-prog ");
break;
}
buf_output0 (buf_to_net, dir);
buf_append_char (buf_to_net, '\n');
buf_output0 (buf_to_net, name);
buf_append_char (buf_to_net, '\n');
buf_output0 (protocol, dir);
buf_append_char (protocol, '\n');
buf_output0 (protocol, name);
buf_append_char (protocol, '\n');
buf_send_counted (protocol);
}
static void
@ -4862,32 +4880,33 @@ server_cleanup (sig)
if (buf_to_net != NULL)
{
/* FIXME: If this is not the final call from server, this
could deadlock, because the client might be blocked writing
to us. This should not be a problem in practice, because
we do not generate much output when the client is not
waiting for it. */
/* Since we're done, go ahead and put BUF_TO_NET back into blocking
* mode and send any pending output. In the usual case there won't
* won't be any, but there might be if an error occured.
*/
set_block (buf_to_net);
buf_flush (buf_to_net, 1);
/* The calls to buf_shutdown are currently only meaningful
when we are using compression. First we shut down
BUF_FROM_NET. That will pick up the checksum generated
when the client shuts down its buffer. Then, after we have
generated any final output, we shut down BUF_TO_NET. */
/* Next we shut down BUF_FROM_NET. That will pick up the checksum
* generated when the client shuts down its buffer. Then, after we
* have generated any final output, we shut down BUF_TO_NET.
*/
status = buf_shutdown (buf_from_net);
if (status != 0)
{
error (0, status, "shutting down buffer from client");
buf_flush (buf_to_net, 1);
}
}
if (dont_delete_temp)
{
if (buf_to_net != NULL)
{
(void) buf_flush (buf_to_net, 1);
(void) buf_shutdown (buf_to_net);
}
return;
}
@ -4985,11 +5004,13 @@ server_cleanup (sig)
noexec = save_noexec;
if (buf_to_net != NULL)
{
(void) buf_flush (buf_to_net, 1);
(void) buf_shutdown (buf_to_net);
}
}
int server_active = 0;
int server_expanding = 0;
int
server (argc, argv)
@ -5010,7 +5031,7 @@ server (argc, argv)
buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
outbuf_memory_error);
buf_from_net = stdio_buffer_initialize (stdin, 1, outbuf_memory_error);
buf_from_net = stdio_buffer_initialize (stdin, 0, 1, outbuf_memory_error);
saved_output = buf_nonio_initialize (outbuf_memory_error);
saved_outerr = buf_nonio_initialize (outbuf_memory_error);
@ -5190,7 +5211,7 @@ error ENOMEM Virtual memory exhausted.\n");
char *cmd, *orig_cmd;
struct request *rq;
int status;
status = buf_read_line (buf_from_net, &cmd, (int *) NULL);
if (status == -2)
{
@ -5327,7 +5348,7 @@ error 0 %s: no such user\n", username);
error_exit ();
}
}
if (setuid (pw->pw_uid) < 0)
{
/* Note that this means that if run as a non-root user,
@ -5351,12 +5372,12 @@ error 0 %s: no such user\n", username);
if (CVS_Username == NULL)
CVS_Username = xstrdup (username);
#endif
#if HAVE_PUTENV
/* Set LOGNAME, USER and CVS_USER in the environment, in case they
are already set to something else. */
{
char *env, *cvs_user;
char *env;
env = xmalloc (sizeof "LOGNAME=" + strlen (username));
(void) sprintf (env, "LOGNAME=%s", username);
@ -5366,10 +5387,11 @@ error 0 %s: no such user\n", username);
(void) sprintf (env, "USER=%s", username);
(void) putenv (env);
cvs_user = NULL != CVS_Username ? CVS_Username : "";
env = xmalloc (sizeof "CVS_USER=" + strlen (cvs_user));
(void) sprintf (env, "CVS_USER=%s", cvs_user);
#ifdef AUTH_SERVER_SUPPORT
env = xmalloc (sizeof "CVS_USER=" + strlen (CVS_Username));
(void) sprintf (env, "CVS_USER=%s", CVS_Username);
(void) putenv (env);
#endif
}
#endif /* HAVE_PUTENV */
}
@ -5380,7 +5402,7 @@ error 0 %s: no such user\n", username);
extern char *crypt PROTO((const char *, const char *));
/*
/*
* 0 means no entry found for this user.
* 1 means entry found and password matches (or found password is empty)
* 2 means entry found, but password does not match.
@ -5449,7 +5471,7 @@ check_repository_password (username, password, repository, host_user_ptr)
char *found_password, *host_user_tmp;
char *non_cvsuser_portion;
/* We need to make sure lines such as
/* We need to make sure lines such as
*
* "username::sysuser\n"
* "username:\n"
@ -5582,7 +5604,7 @@ check_password (username, password, repository)
{
found_passwd = pw->pw_passwd;
}
if (found_passwd == NULL)
{
printf ("E Fatal error, aborting.\n\
@ -5600,7 +5622,7 @@ error 0 %s: no such user\n", username);
exit (EXIT_FAILURE);
}
if (*found_passwd)
{
/* user exists and has a password */
@ -5655,7 +5677,7 @@ error 0 %s: no such user\n", username);
handle_return:
if (host_user)
{
/* Set CVS_Username here, in allocated space.
/* Set CVS_Username here, in allocated space.
It might or might not be the same as host_user. */
CVS_Username = xmalloc (strlen (username) + 1);
strcpy (CVS_Username, username);
@ -5749,10 +5771,12 @@ pserver_authenticate_connection ()
/* Make sure the protocol starts off on the right foot... */
if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0)
/* FIXME: what? We could try writing error/eof, but chances
are the network connection is dead bidirectionally. log it
somewhere? */
;
{
#ifdef HAVE_SYSLOG_H
syslog (LOG_DAEMON | LOG_NOTICE, "bad auth protocol start: EOF");
#endif
error (1, 0, "bad auth protocol start: EOF");
}
if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
verify_and_exit = 1;
@ -5783,7 +5807,7 @@ pserver_authenticate_connection ()
getline_safe (&username, &username_allocated, stdin, PATH_MAX);
getline_safe (&password, &password_allocated, stdin, PATH_MAX);
/* Make them pure. */
/* Make them pure. */
strip_trailing_newlines (repository);
strip_trailing_newlines (username);
strip_trailing_newlines (password);
@ -5817,8 +5841,6 @@ pserver_authenticate_connection ()
/* We need the real cleartext before we hash it. */
descrambled_password = descramble (password);
host_user = check_password (username, descrambled_password, repository);
memset (descrambled_password, 0, strlen (descrambled_password));
free (descrambled_password);
if (host_user == NULL)
{
#ifdef HAVE_SYSLOG_H
@ -5828,6 +5850,8 @@ pserver_authenticate_connection ()
username, descrambled_password, repository);
#endif
#endif
memset (descrambled_password, 0, strlen (descrambled_password));
free (descrambled_password);
i_hate_you:
printf ("I HATE YOU\n");
fflush (stdout);
@ -5836,6 +5860,8 @@ pserver_authenticate_connection ()
yet. */
error_exit ();
}
memset (descrambled_password, 0, strlen (descrambled_password));
free (descrambled_password);
/* Don't go any farther if we're just responding to "cvs login". */
if (verify_and_exit)
@ -6521,7 +6547,7 @@ cvs_flusherr ()
{
/* make sure stderr is flushed before we send the flush count on the
* protocol pipe
*/
*/
fflush (stderr);
/* Send a special count to tell the parent to flush. */
buf_send_special_count (protocol, -2);
@ -6551,7 +6577,7 @@ cvs_flushout ()
main.c, didn't get called in the server child process. But
in the future it is quite plausible that we'll want to make
this case work analogously to cvs_flusherr.
FIXME - DRP - I tried to implement this and triggered the following
error: "Protocol error: uncounted data discarded". I don't need
this feature right now, so I'm not going to bother with it yet.

View File

@ -38,7 +38,7 @@
#include "cvs.h"
#include "savecwd.h"
#ifdef SERVER_SUPPORT
#include "md5.h"
# include "md5.h"
#endif
#include "watch.h"
#include "fileattr.h"
@ -1793,7 +1793,7 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
}
else
{
#define BINARY "Binary"
# define BINARY "Binary"
char buf[sizeof BINARY];
unsigned int c;
@ -2689,7 +2689,7 @@ special_file_mismatch (finfo, rev1, rev2)
rev1_symlink = xreadlink (finfo->file);
else
{
#ifdef HAVE_ST_RDEV
# ifdef HAVE_ST_RDEV
if (CVS_LSTAT (finfo->file, &sb) < 0)
error (1, errno, "could not get file information for %s",
finfo->file);
@ -2698,10 +2698,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
# else
error (1, 0, "cannot handle device files on this system (%s)",
finfo->file);
#endif
# endif
}
rev1_hardlinks = list_linked_files_on_disk (finfo->file);
}
@ -2740,7 +2740,7 @@ special_file_mismatch (finfo, rev1, rev2)
{
/* If the size of `ftype' changes, fix the sscanf call also */
char ftype[16];
if (sscanf (n->data, "%16s %lu", ftype,
if (sscanf (n->data, "%15s %lu", ftype,
&dev_long) < 2)
error (1, 0, "%s:%s has bad `special' newphrase %s",
finfo->file, rev1, n->data);
@ -2767,7 +2767,7 @@ special_file_mismatch (finfo, rev1, rev2)
rev2_symlink = xreadlink (finfo->file);
else
{
#ifdef HAVE_ST_RDEV
# ifdef HAVE_ST_RDEV
if (CVS_LSTAT (finfo->file, &sb) < 0)
error (1, errno, "could not get file information for %s",
finfo->file);
@ -2776,10 +2776,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
# else
error (1, 0, "cannot handle device files on this system (%s)",
finfo->file);
#endif
# endif
}
rev2_hardlinks = list_linked_files_on_disk (finfo->file);
}
@ -2818,7 +2818,7 @@ special_file_mismatch (finfo, rev1, rev2)
{
/* If the size of `ftype' changes, fix the sscanf call also */
char ftype[16];
if (sscanf (n->data, "%16s %lu", ftype,
if (sscanf (n->data, "%15s %lu", ftype,
&dev_long) < 2)
error (1, 0, "%s:%s has bad `special' newphrase %s",
finfo->file, rev2, n->data);