summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gnu/usr.bin/cvs/Makefile4
-rw-r--r--gnu/usr.bin/cvs/contrib/Makefile41
-rw-r--r--gnu/usr.bin/cvs/contrib/pcl-cvs/Makefile83
-rw-r--r--gnu/usr.bin/cvs/cvs/Makefile16
-rw-r--r--gnu/usr.bin/cvs/cvs/add.c176
-rw-r--r--gnu/usr.bin/cvs/cvs/admin.c73
-rw-r--r--gnu/usr.bin/cvs/cvs/checkin.c87
-rw-r--r--gnu/usr.bin/cvs/cvs/checkout.c215
-rw-r--r--gnu/usr.bin/cvs/cvs/classify.c105
-rw-r--r--gnu/usr.bin/cvs/cvs/commit.c572
-rw-r--r--gnu/usr.bin/cvs/cvs/create_adm.c91
-rw-r--r--gnu/usr.bin/cvs/cvs/cvs.1272
-rw-r--r--gnu/usr.bin/cvs/cvs/cvs.h279
-rw-r--r--gnu/usr.bin/cvs/cvs/cvsrc.c35
-rw-r--r--gnu/usr.bin/cvs/cvs/diff.c153
-rw-r--r--gnu/usr.bin/cvs/cvs/entries.c532
-rw-r--r--gnu/usr.bin/cvs/cvs/find_names.c21
-rw-r--r--gnu/usr.bin/cvs/cvs/history.c110
-rw-r--r--gnu/usr.bin/cvs/cvs/ignore.c36
-rw-r--r--gnu/usr.bin/cvs/cvs/import.c581
-rw-r--r--gnu/usr.bin/cvs/cvs/lock.c211
-rw-r--r--gnu/usr.bin/cvs/cvs/log.c91
-rw-r--r--gnu/usr.bin/cvs/cvs/logmsg.c101
-rw-r--r--gnu/usr.bin/cvs/cvs/main.c424
-rw-r--r--gnu/usr.bin/cvs/cvs/modules.c105
-rw-r--r--gnu/usr.bin/cvs/cvs/no_diff.c50
-rw-r--r--gnu/usr.bin/cvs/cvs/options.h100
-rw-r--r--gnu/usr.bin/cvs/cvs/parseinfo.c43
-rw-r--r--gnu/usr.bin/cvs/cvs/patch.c123
-rw-r--r--gnu/usr.bin/cvs/cvs/rcs.c499
-rw-r--r--gnu/usr.bin/cvs/cvs/rcs.h29
-rw-r--r--gnu/usr.bin/cvs/cvs/recurse.c103
-rw-r--r--gnu/usr.bin/cvs/cvs/release.c309
-rw-r--r--gnu/usr.bin/cvs/cvs/remove.c60
-rw-r--r--gnu/usr.bin/cvs/cvs/repos.c51
-rw-r--r--gnu/usr.bin/cvs/cvs/root.c29
-rw-r--r--gnu/usr.bin/cvs/cvs/rtag.c320
-rw-r--r--gnu/usr.bin/cvs/cvs/status.c52
-rw-r--r--gnu/usr.bin/cvs/cvs/tag.c341
-rw-r--r--gnu/usr.bin/cvs/cvs/update.c804
-rw-r--r--gnu/usr.bin/cvs/cvs/vers_ts.c106
-rw-r--r--gnu/usr.bin/cvs/cvsbug/Makefile25
-rw-r--r--gnu/usr.bin/cvs/cvsinit/Makefile23
-rw-r--r--gnu/usr.bin/cvs/cvsinit/cvsinit.sh232
-rw-r--r--gnu/usr.bin/cvs/doc/Makefile4
-rw-r--r--gnu/usr.bin/cvs/examples/Makefile9
-rw-r--r--gnu/usr.bin/cvs/lib/Makefile11
-rw-r--r--gnu/usr.bin/cvs/lib/argmatch.c4
-rw-r--r--gnu/usr.bin/cvs/lib/getopt.c6
-rw-r--r--gnu/usr.bin/cvs/lib/hash.c15
-rw-r--r--gnu/usr.bin/cvs/lib/hash.h17
-rw-r--r--gnu/usr.bin/cvs/lib/myndbm.c4
-rw-r--r--gnu/usr.bin/cvs/lib/subr.c817
-rw-r--r--gnu/usr.bin/cvs/lib/system.h338
-rw-r--r--gnu/usr.bin/cvs/lib/version.c20
-rw-r--r--gnu/usr.bin/cvs/mkmodules/Makefile4
-rw-r--r--gnu/usr.bin/cvs/mkmodules/mkmodules.c50
57 files changed, 6125 insertions, 2887 deletions
diff --git a/gnu/usr.bin/cvs/Makefile b/gnu/usr.bin/cvs/Makefile
index df2f874..a9b43ae 100644
--- a/gnu/usr.bin/cvs/Makefile
+++ b/gnu/usr.bin/cvs/Makefile
@@ -1,5 +1,5 @@
-# $Id: Makefile,v 1.5 1995/03/31 07:55:01 nate Exp $
+# $Id: Makefile,v 1.6 1995/04/14 15:15:27 nate Exp $
-SUBDIR = lib cvs mkmodules cvsinit doc examples
+SUBDIR = lib cvs mkmodules contrib cvsbug cvsinit doc examples
.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/cvs/contrib/Makefile b/gnu/usr.bin/cvs/contrib/Makefile
new file mode 100644
index 0000000..7e27e76
--- /dev/null
+++ b/gnu/usr.bin/cvs/contrib/Makefile
@@ -0,0 +1,41 @@
+# $Id: Makefile,v 1.2 1995/07/25 00:31:51 bde Exp $
+
+SCRIPTS= ccvs-rsh rcs2log clmerge cln_hist commit_prep cvs_acls cvscheck \
+ log log_accum mfpipe rcs-to-cvs rcs2log rcslock sccs2rcs
+
+FILES= README cvscheck.man cvshelp.man descend.man intro.doc
+
+PCLCVS= ChangeLog INSTALL NEWS README \
+ compile-all.el pcl-cvs-lucid.el pcl-cvs-lucid.elc pcl-cvs-startup.el \
+ pcl-cvs.el pcl-cvs.elc pcl-cvs.texinfo
+
+EXAMPDIR= /usr/share/examples/cvs
+PERLPATH= /usr/bin/perl
+CLEANFILES+= $(SCRIPTS)
+
+.SUFFIXES: .sh .csh .pl
+
+all: ${SCRIPTS}
+
+.sh:
+ cp $< $@
+
+.csh:
+ sed -e 's,xCSH_PATHx,/bin/csh,' $< > $@
+
+.pl:
+ sed -e 's,xPERL_PATHx,$(PERLPATH),' $< > $@
+
+
+afterinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${SCRIPTS} ${DESTDIR}${EXAMPDIR}/contrib
+ cd ${.CURDIR} ; \
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \
+ ${FILES} ${DESTDIR}${EXAMPDIR}/contrib
+ cd ${.CURDIR}/pcl-cvs ; \
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \
+ ${PCLCVS} ${DESTDIR}${EXAMPDIR}/pcl-cvs
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cvs/contrib/pcl-cvs/Makefile b/gnu/usr.bin/cvs/contrib/pcl-cvs/Makefile
deleted file mode 100644
index 7f6f5b1..0000000
--- a/gnu/usr.bin/cvs/contrib/pcl-cvs/Makefile
+++ /dev/null
@@ -1,83 +0,0 @@
-# @(#) Id: dist-makefile,v 1.19 1993/05/31 22:43:45 ceder Exp
-# Makefile for pcl-cvs release 1.05.
-# Copyright (C) 1992, 1993 Per Cederqvist
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-# This is the directory in which the ELFILES and ELCFILES will be
-# installed.
-
-lispdir = /usr/local/lib/elisp
-
-# Where to install the info file.
-
-prefix=/usr/local
-infodir = $(prefix)/info
-
-# Used to byte-compile files.
-
-EMACS=emacs
-
-#
-# The rest of this file should not need to be modified.
-#
-
-# Just in case...
-SHELL = /bin/sh
-
-ELFILES = pcl-cvs.el pcl-cvs-lucid.el
-ELCFILES = pcl-cvs.elc pcl-cvs-lucid.elc
-INFOFILES = pcl-cvs
-TEXTMPS = pcl-cvs.aux pcl-cvs.log pcl-cvs.toc pcl-cvs.dvi pcl-cvs.cp \
- pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky pcl-cvs.pg \
- pcl-cvs.cps pcl-cvs.fns pcl-cvs.kys pcl-cvs.pgs pcl-cvs.tps \
- pcl-cvs.vrs
-
-INSTALL = install
-INSTALL_DATA = $(INSTALL)
-
-elcfiles:
- $(EMACS) -batch -l ./compile-all.el -f compile-pcl-cvs
-
-all: elcfiles info
-
-# Don't install the info file yet, since it requires makeinfo
-# version 2.something (and version 1.something is distributed with emacs).
-#
-# install: install_elc install_info
-install: install_elc
- for i in $(ELFILES); do $(INSTALL_DATA) $$i $(lispdir)/$$i; done
-
-install_elc: elcfiles
- for i in $(ELCFILES); do $(INSTALL_DATA) $$i $(lispdir)/$$i; done
-
-install_info: pcl-cvs
- $(INSTALL_DATA) pcl-cvs $(infodir)/pcl-cvs
-
-info pcl-cvs: pcl-cvs.texinfo
- makeinfo +fill-column=70 pcl-cvs.texinfo
-
-pcl-cvs.dvi: pcl-cvs.texinfo
- tex pcl-cvs.texinfo
- tex pcl-cvs.texinfo
- -texindex pcl-cvs.cp pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky \
- pcl-cvs.pg
- tex pcl-cvs.texinfo
-
-mostlyclean clean realclean:
- rm -f *~ core $(ELCFILES) $(INFOFILES) $(TEXTMPS)
-
-tags TAGS:
- etags *.el
diff --git a/gnu/usr.bin/cvs/cvs/Makefile b/gnu/usr.bin/cvs/cvs/Makefile
index 02efe02..df8d1c2 100644
--- a/gnu/usr.bin/cvs/cvs/Makefile
+++ b/gnu/usr.bin/cvs/cvs/Makefile
@@ -1,18 +1,20 @@
-# $Id: Makefile,v 1.25 1995/03/22 19:39:45 nate Exp $
+# $Id: Makefile,v 1.10 1995/03/31 07:55:08 nate Exp $
PROG= cvs
MAN1= cvs.1
MAN5= cvs.5
-SRCS = add.c admin.c checkin.c checkout.c classify.c commit.c create_adm.c \
- cvsrc.c diff.c entries.c find_names.c history.c ignore.c import.c \
- lock.c log.c logmsg.c main.c modules.c no_diff.c parseinfo.c patch.c \
- rcs.c recurse.c release.c remove.c repos.c root.c rtag.c status.c \
- tag.c update.c vers_ts.c
+SRCS = add.c admin.c checkin.c checkout.c classify.c client.c commit.c \
+ create_adm.c cvsrc.c diff.c entries.c expand_path.c find_names.c \
+ history.c ignore.c import.c lock.c log.c login.c logmsg.c main.c \
+ modules.c no_diff.c parseinfo.c patch.c rcs.c rcscmds.c recurse.c \
+ release.c remove.c repos.c root.c rtag.c server.c status.c tag.c \
+ update.c vers_ts.c wrapper.c
-CFLAGS+= -I${.CURDIR}/../lib -DHAVE_CONFIG_H -DHAVE_TIMEZONE
+CFLAGS+= -I${.CURDIR}/../lib -DHAVE_CONFIG_H
DPADD+= ${LIBCVS} ${LIBGNUREGEX}
LDADD+= -lcvs -lgnuregex
.include "../../Makefile.inc"
.include <bsd.prog.mk>
+
diff --git a/gnu/usr.bin/cvs/cvs/add.c b/gnu/usr.bin/cvs/cvs/add.c
index e14c79c..f798a22 100644
--- a/gnu/usr.bin/cvs/cvs/add.c
+++ b/gnu/usr.bin/cvs/cvs/add.c
@@ -25,17 +25,18 @@
*/
#include "cvs.h"
+#include "save-cwd.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)add.c 1.55 94/10/22 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)add.c 1.55 94/10/22 $";
+USE(rcsid);
#endif
static int add_directory PROTO((char *repository, char *dir));
static int build_entry PROTO((char *repository, char *user, char *options,
char *message, List * entries, char *tag));
-static char *add_usage[] =
+static const char *const add_usage[] =
{
"Usage: %s %s [-k rcs-kflag] [-m message] files...\n",
"\t-k\tUse \"rcs-kflag\" to add the file with the specified kflag.\n",
@@ -46,7 +47,7 @@ static char *add_usage[] =
int
add (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
char *message = NULL;
char *user;
@@ -62,6 +63,8 @@ add (argc, argv)
if (argc == 1 || argc == -1)
usage (add_usage);
+ wrap_setup ();
+
/* parse args */
optind = 1;
while ((c = getopt (argc, argv, "k:m:")) != -1)
@@ -91,12 +94,54 @@ add (argc, argv)
/* find the repository associated with our current dir */
repository = Name_Repository ((char *) NULL, (char *) NULL);
- entries = ParseEntries (0);
+
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ int i;
+ start_server ();
+ ign_setup ();
+ if (options) send_arg(options);
+ option_with_arg ("-m", message);
+ for (i = 0; i < argc; ++i)
+ /* FIXME: Does this erroneously call Create_Admin in error
+ conditions which are only detected once the server gets its
+ hands on things? */
+ if (isdir (argv[i]))
+ {
+ char *tag;
+ char *date;
+ char *rcsdir = xmalloc (strlen (repository)
+ + strlen (argv[i]) + 10);
+
+ /* before we do anything else, see if we have any
+ per-directory tags */
+ ParseTag (&tag, &date);
+
+ sprintf (rcsdir, "%s/%s", repository, argv[i]);
+
+ Create_Admin (argv[i], argv[i], rcsdir, tag, date);
+
+ if (tag)
+ free (tag);
+ if (date)
+ free (date);
+ free (rcsdir);
+ }
+ send_files (argc, argv, 0, 0);
+ if (fprintf (to_server, "add\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
+ entries = Entries_Open (0);
/* walk the arg list adding files/dirs */
for (i = 0; i < argc; i++)
{
int begin_err = err;
+ int begin_added_files = added_files;
user = argv[i];
strip_trailing_slashes (user);
@@ -122,7 +167,7 @@ add (argc, argv)
error (0, 0, "nothing known about %s", user);
err++;
}
- else if (!isdir (user))
+ else if (!isdir (user) || wrap_name_has (user, WRAP_TOCVS))
{
/*
* See if a directory exists in the repository with
@@ -143,15 +188,53 @@ add (argc, argv)
/* There is a user file, so build the entry for it */
if (build_entry (repository, user, vers->options,
message, entries, vers->tag) != 0)
- err++;
+ err++;
else
{
- added_files++;
- if (!quiet)
- error (0, 0, "scheduling file `%s' for addition", user);
+ added_files++;
+ if (!quiet)
+ {
+#ifdef DEATH_SUPPORT
+ if (vers->tag)
+ error (0, 0, "\
+scheduling %s `%s' for addition on branch `%s'",
+ (wrap_name_has (user, WRAP_TOCVS)
+ ? "wrapper"
+ : "file"),
+ user, vers->tag);
+ else
+#endif /* DEATH_SUPPORT */
+ error (0, 0, "scheduling %s `%s' for addition",
+ (wrap_name_has (user, WRAP_TOCVS)
+ ? "wrapper"
+ : "file"),
+ user);
+ }
}
}
}
+#ifdef DEATH_SUPPORT
+ else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
+ {
+ if (isdir (user) && !wrap_name_has (user, WRAP_TOCVS))
+ {
+ error (0, 0, "the directory `%s' cannot be added because a file of the", user);
+ error (1, 0, "same name already exists in the repository.");
+ }
+ else
+ {
+ if (vers->tag)
+ error (0, 0, "file `%s' will be added on branch `%s' from version %s",
+ user, vers->tag, vers->vn_rcs);
+ else
+ error (0, 0, "version %s of `%s' will be resurrected",
+ vers->vn_rcs, user);
+ Register (entries, user, "0", vers->ts_user, NULL,
+ vers->tag, NULL, NULL);
+ ++added_files;
+ }
+ }
+#endif /* DEATH_SUPPORT */
else
{
/*
@@ -206,6 +289,9 @@ add (argc, argv)
free (tmp);
/* XXX - bugs here; this really resurrect the head */
+ /* Note that this depends on the Register above actually
+ having written Entries, or else it won't really
+ check the file out. */
if (update (2, argv + i - 1) == 0)
{
error (0, 0, "%s, version %s, resurrected", user,
@@ -235,16 +321,23 @@ add (argc, argv)
freevers_ts (&vers);
/* passed all the checks. Go ahead and add it if its a directory */
- if (begin_err == err && isdir (user))
+ if (begin_err == err
+ && isdir (user)
+ && !wrap_name_has (user, WRAP_TOCVS))
{
err += add_directory (repository, user);
continue;
}
+#ifdef SERVER_SUPPORT
+ if (server_active && begin_added_files != added_files)
+ server_checked_in (user, ".", repository);
+#endif
}
if (added_files)
error (0, 0, "use 'cvs commit' to add %s permanently",
(added_files == 1) ? "this file" : "these files");
- dellist (&entries);
+
+ Entries_Close (entries);
if (message)
free (message);
@@ -264,7 +357,8 @@ add_directory (repository, dir)
char *repository;
char *dir;
{
- char cwd[PATH_MAX], rcsdir[PATH_MAX];
+ char rcsdir[PATH_MAX];
+ struct saved_cwd cwd;
char message[PATH_MAX + 100];
char *tag, *date;
@@ -274,9 +368,9 @@ add_directory (repository, dir)
"directory %s not added; must be a direct sub-directory", dir);
return (1);
}
- if (strcmp (dir, CVSADM) == 0 || strcmp (dir, OCVSADM) == 0)
+ if (strcmp (dir, CVSADM) == 0)
{
- error (0, 0, "cannot add a `%s' or a `%s' directory", CVSADM, OCVSADM);
+ error (0, 0, "cannot add a `%s' directory", CVSADM);
return (1);
}
@@ -284,20 +378,20 @@ add_directory (repository, dir)
ParseTag (&tag, &date);
/* now, remember where we were, so we can get back */
- if (getwd (cwd) == NULL)
- {
- error (0, 0, "cannot get working directory: %s", cwd);
+ if (save_cwd (&cwd))
return (1);
- }
if (chdir (dir) < 0)
{
error (0, errno, "cannot chdir to %s", dir);
return (1);
}
- if (isfile (CVSADM) || isfile (OCVSADM))
+#ifdef SERVER_SUPPORT
+ if (!server_active && isfile (CVSADM))
+#else
+ if (isfile (CVSADM))
+#endif
{
- error (0, 0,
- "%s/%s (or %s/%s) already exists", dir, CVSADM, dir, OCVSADM);
+ error (0, 0, "%s/%s already exists", dir, CVSADM);
goto out;
}
@@ -344,14 +438,14 @@ add_directory (repository, dir)
}
#endif
- omask = umask (2);
- if (mkdir (rcsdir, 0777) < 0)
+ omask = umask (cvsumask);
+ if (CVS_MKDIR (rcsdir, 0777) < 0)
{
error (0, errno, "cannot mkdir %s", rcsdir);
- (void) umask ((int) omask);
+ (void) umask (omask);
goto out;
}
- (void) umask ((int) omask);
+ (void) umask (omask);
/*
* Set up an update list with a single title node for Update_Logfile
@@ -367,7 +461,12 @@ add_directory (repository, dir)
dellist (&ulist);
}
- Create_Admin (".", rcsdir, tag, date);
+#ifdef SERVER_SUPPORT
+ if (!server_active)
+ Create_Admin (".", dir, rcsdir, tag, date);
+#else
+ Create_Admin (".", dir, rcsdir, tag, date);
+#endif
if (tag)
free (tag);
if (date)
@@ -375,8 +474,9 @@ add_directory (repository, dir)
(void) printf ("%s", message);
out:
- if (chdir (cwd) < 0)
- error (1, errno, "cannot chdir to %s", cwd);
+ if (restore_cwd (&cwd, NULL))
+ exit (1);
+ free_cwd (&cwd);
return (0);
}
@@ -397,6 +497,8 @@ build_entry (repository, user, options, message, entries, tag)
char line[MAXLINELEN];
FILE *fp;
+#ifndef DEATH_SUPPORT
+ /* when using the rcs death support, this case is not a problem. */
/*
* There may be an old file with the same name in the Attic! This is,
* perhaps, an awkward place to check for this, but other places are
@@ -409,21 +511,13 @@ build_entry (repository, user, options, message, entries, tag)
repository, CVSATTIC);
return (1);
}
+#endif /* no DEATH_SUPPORT */
if (noexec)
return (0);
/*
- * The options for the "add" command are store in the file CVS/user,p
- * XXX - no they are not!
- */
- (void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_OPT);
- fp = open_file (fname, "w+");
- if (fclose (fp) == EOF)
- error(1, errno, "cannot close %s", fname);
-
- /*
- * And the requested log is read directly from the user and stored in the
+ * The requested log is read directly from the user and stored in the
* file user,t. If the "message" argument is set, use it as the
* initial creation log (which typically describes the file).
*/
@@ -436,8 +530,8 @@ build_entry (repository, user, options, message, entries, tag)
/*
* Create the entry now, since this allows the user to interrupt us above
- * without needing to clean anything up (well, we could clean up the ,p
- * and ,t files, but who cares).
+ * without needing to clean anything up (well, we could clean up the
+ * ,t file, but who cares).
*/
(void) sprintf (line, "Initial %s", user);
Register (entries, user, "0", line, options, tag, (char *) 0, (char *) 0);
diff --git a/gnu/usr.bin/cvs/cvs/admin.c b/gnu/usr.bin/cvs/cvs/admin.c
index 14a5b51..f12e143 100644
--- a/gnu/usr.bin/cvs/cvs/admin.c
+++ b/gnu/usr.bin/cvs/cvs/admin.c
@@ -12,10 +12,13 @@
*/
#include "cvs.h"
+#ifdef CVS_ADMIN_GROUP
+#include <grp.h>
+#endif
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)admin.c 1.20 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)admin.c 1.20 94/09/30 $";
+USE(rcsid);
#endif
static Dtype admin_dirproc PROTO((char *dir, char *repos, char *update_dir));
@@ -23,7 +26,7 @@ static int admin_fileproc PROTO((char *file, char *update_dir,
char *repository, List *entries,
List *srcfiles));
-static char *admin_usage[] =
+static const char *const admin_usage[] =
{
"Usage: %s %s rcs-options files...\n",
NULL
@@ -35,13 +38,42 @@ static char **av;
int
admin (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int err;
-
+#ifdef CVS_ADMIN_GROUP
+ struct group *grp;
+#endif
if (argc <= 1)
usage (admin_usage);
+#ifdef CVS_ADMIN_GROUP
+ grp = getgrnam(CVS_ADMIN_GROUP);
+ /* skip usage right check if group CVS_ADMIN_GROUP does not exist */
+ if (grp != NULL)
+ {
+ char *me = getcaller();
+ char **grnam = grp->gr_mem;
+ int denied = 1;
+
+ while (*grnam)
+ {
+ if (strcmp(*grnam, me) == 0)
+ {
+ denied = 0;
+ break;
+ }
+ grnam++;
+ }
+
+ if (denied)
+ error (1, 0, "usage is restricted to members of the group %s",
+ CVS_ADMIN_GROUP);
+ }
+#endif
+
+ wrap_setup ();
+
/* skip all optional arguments to see if we have any file names */
for (ac = 1; ac < argc; ac++)
if (argv[ac][0] != '-')
@@ -53,9 +85,36 @@ admin (argc, argv)
if (ac == 0 || argc == 0)
usage (admin_usage);
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ int i;
+
+ /* We're the client side. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ for (i = 0; i <= ac; ++i) /* XXX send -ko too with i = 0 */
+ send_arg (av[i]);
+
+#if 0
+ /* FIXME: We shouldn't have to send current files, but I'm not sure
+ whether it works. So send the files --
+ it's slower but it works. */
+ send_file_names (argc, argv);
+#else
+ send_files (argc, argv, 0, 0);
+#endif
+ if (fprintf (to_server, "admin\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif /* CLIENT_SUPPORT */
+
/* start the recursion processor */
- err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc,
- (int (*) ()) NULL, argc, argv, 0,
+ err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
+ (DIRLEAVEPROC) NULL, argc, argv, 0,
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err);
}
diff --git a/gnu/usr.bin/cvs/cvs/checkin.c b/gnu/usr.bin/cvs/cvs/checkin.c
index 1f7691b..ef3b81a 100644
--- a/gnu/usr.bin/cvs/cvs/checkin.c
+++ b/gnu/usr.bin/cvs/cvs/checkin.c
@@ -18,14 +18,16 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)checkin.c 1.48 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)checkin.c 1.48 94/10/07 $";
+USE(rcsid);
#endif
int
-Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
+Checkin (type, file, update_dir, repository,
+ rcs, rev, tag, options, message, entries)
int type;
char *file;
+ char *update_dir;
char *repository;
char *rcs;
char *rev;
@@ -37,8 +39,17 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
char fname[PATH_MAX];
Vers_TS *vers;
int set_time;
+ char *fullname;
- (void) printf ("Checking in %s;\n", file);
+ char *tocvsPath = NULL;
+
+ fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
+ if (update_dir[0] == '\0')
+ strcpy (fullname, file);
+ else
+ sprintf (fullname, "%s/%s", update_dir, file);
+
+ (void) printf ("Checking in %s;\n", fullname);
(void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
/*
@@ -46,13 +57,28 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
* modification times, then place a copy back in the original file name
* for the checkin and checkout.
*/
+
+ tocvsPath = wrap_tocvs_process_file (fullname);
+
if (!noexec)
- copy_file (file, fname);
+ {
+ if (tocvsPath)
+ {
+ copy_file (tocvsPath, fname);
+ if (unlink_file_dir (file) < 0)
+ if (! existence_error (errno))
+ error (1, errno, "cannot remove %s", file);
+ copy_file (tocvsPath, file);
+ }
+ else
+ {
+ copy_file (file, fname);
+ }
+ }
run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI,
rev ? "-r" : "", rev ? rev : "");
- run_args ("-m%s", (*message == '\0' || strcmp(message, "\n") == 0) ?
- "*** empty log message ***\n" : message);
+ run_args ("-m%s", make_message_rcslegal (message));
run_arg (rcs);
switch (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL))
@@ -83,11 +109,14 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
}
else
{
- (void) unlink_file (fname);
+ if (unlink_file (fname) < 0)
+ error (0, errno, "cannot remove %s", fname);
/* sync up with the time from the RCS file */
set_time = 1;
}
+ wrap_fromcvs_process_file (file);
+
/*
* If we want read-only files, muck the permissions here, before
* getting the file time-stamp.
@@ -95,13 +124,15 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
if (cvswrite == FALSE)
xchmod (file, 0);
+#ifndef DEATH_SUPPORT
+ /* With death_support, files added with tags go into branches immediately. */
+
/* for added files with symbolic tags, need to add the tag too */
if (type == 'A' && tag && !isdigit (*tag))
{
- run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, tag, rev);
- run_arg (rcs);
- (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+ (void) RCS_settag(rcs, tag, rev);
}
+#endif /* No DEATH_SUPPORT */
/* re-register with the new data */
vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL,
@@ -112,11 +143,21 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
vers->options, vers->tag, vers->date, (char *) 0);
history_write (type, (char *) 0, vers->vn_rcs, file, repository);
freevers_ts (&vers);
+
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
break;
case -1: /* fork failed */
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
if (!noexec)
- error (1, errno, "could not check in %s -- fork failed", file);
+ error (1, errno, "could not check in %s -- fork failed",
+ fullname);
return (1);
default: /* ci failed */
@@ -125,10 +166,14 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
* The checkin failed, for some unknown reason, so we restore the
* original user file, print an error, and return an error
*/
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
if (!noexec)
{
rename_file (fname, file);
- error (0, 0, "could not check in %s", file);
+ error (0, 0, "could not check in %s", fullname);
}
return (1);
}
@@ -140,10 +185,20 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
*/
if (rev)
{
- run_setup ("%s%s -q -u", Rcsbin, RCS);
- run_arg (rcs);
- (void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL);
+ (void) RCS_unlock (rcs, NULL, 1);
}
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ if (set_time)
+ /* Need to update the checked out file on the client side. */
+ server_updated (file, update_dir, repository, SERVER_UPDATED,
+ NULL, NULL);
+ else
+ server_checked_in (file, update_dir, repository);
+ }
+#endif
+
return (0);
}
diff --git a/gnu/usr.bin/cvs/cvs/checkout.c b/gnu/usr.bin/cvs/cvs/checkout.c
index a5a79ad..bb126dd 100644
--- a/gnu/usr.bin/cvs/cvs/checkout.c
+++ b/gnu/usr.bin/cvs/cvs/checkout.c
@@ -36,31 +36,30 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)checkout.c 1.78 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)checkout.c 1.78 94/10/07 $";
+USE(rcsid);
#endif
static char *findslash PROTO((char *start, char *p));
static int build_dirs_and_chdir PROTO((char *dir, char *prepath, char *realdir,
int sticky));
-static int checkout_proc PROTO((int *pargc, char *argv[], char *where,
+static int checkout_proc PROTO((int *pargc, char **argv, char *where,
char *mwhere, char *mfile, int shorten,
int local_specified, char *omodule,
char *msg));
+static int safe_location PROTO((void));
-static char *checkout_usage[] =
+static const char *const checkout_usage[] =
{
- "Usage:\n %s %s [-ANPQcflnpqs] [-r rev | -D date] [-d dir] [-k kopt] modules...\n",
+ "Usage:\n %s %s [-ANPcflnps] [-r rev | -D date] [-d dir] [-k kopt] modules...\n",
"\t-A\tReset any sticky tags/date/kopts.\n",
"\t-N\tDon't shorten module paths if -d specified.\n",
"\t-P\tPrune empty directories.\n",
- "\t-Q\tReally quiet.\n",
"\t-c\t\"cat\" the module database.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, not recursive\n",
"\t-n\tDo not run module program (if any).\n",
"\t-p\tCheck out files to standard output.\n",
- "\t-q\tSomewhat quiet.\n",
"\t-s\tLike -c, but include module status.\n",
"\t-r rev\tCheck out revision or tag. (implies -P)\n",
"\t-D date\tCheck out revisions as of date. (implies -P)\n",
@@ -70,18 +69,17 @@ static char *checkout_usage[] =
NULL
};
-static char *export_usage[] =
+static const char *const export_usage[] =
{
- "Usage: %s %s [-NPQflnq] [-r rev | -D date] [-d dir] module...\n",
+ "Usage: %s %s [-NPfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n",
"\t-N\tDon't shorten module paths if -d specified.\n",
- "\t-Q\tReally quiet.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, not recursive\n",
"\t-n\tDo not run module program (if any).\n",
- "\t-q\tSomewhat quiet.\n",
"\t-r rev\tCheck out revision or tag.\n",
"\t-D date\tCheck out revisions as of date.\n",
"\t-d dir\tCheck out into dir instead of module name.\n",
+ "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
NULL
};
@@ -99,7 +97,7 @@ static char *preload_update_dir = NULL;
int
checkout (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int i;
int c;
@@ -109,21 +107,25 @@ checkout (argc, argv)
int local = 0;
int shorten = -1;
char *where = NULL;
- char *valid_options, **valid_usage;
+ char *valid_options;
+ const char *const *valid_usage;
+ enum mtype m_type;
/*
* A smaller subset of options are allowed for the export command, which
* is essentially like checkout, except that it hard-codes certain
- * options to be on (like -kv) and takes care to remove the CVS directory
- * when it has done its duty
+ * options to be default (like -kv) and takes care to remove the CVS
+ * directory when it has done its duty
*/
if (strcmp (command_name, "export") == 0)
{
- valid_options = "Nnd:flRQqr:D:";
+ m_type = EXPORT;
+ valid_options = "Nnk:d:flRQqr:D:";
valid_usage = export_usage;
}
else
{
+ m_type = CHECKOUT;
valid_options = "ANnk:d:flRpQqcsr:D:j:P";
valid_usage = checkout_usage;
}
@@ -132,6 +134,7 @@ checkout (argc, argv)
usage (valid_usage);
ign_setup ();
+ wrap_setup ();
optind = 1;
while ((c = getopt (argc, argv, valid_options)) != -1)
@@ -153,10 +156,15 @@ checkout (argc, argv)
run_module_prog = 0;
break;
case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
case 'l':
local = 1;
@@ -230,9 +238,102 @@ checkout (argc, argv)
}
if (tag && isdigit (tag[0]))
error (1, 0, "tag `%s' must be a symbolic tag", tag);
- options = RCS_check_kflag ("v");/* -kv must be on */
+/*
+ * mhy 950615: -kv doesn't work for binaries with RCS keywords.
+ * Instead use the default provided in the RCS file (-ko for binaries).
+ */
+#if 0
+ if (!options)
+ options = RCS_check_kflag ("v");/* -kv is default */
+#endif
+ }
+
+ if (!safe_location()) {
+ error(1, 0, "Cannot check out files into the repository itself");
}
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ int expand_modules;
+
+ start_server ();
+
+ ign_setup ();
+
+ /* We have to expand names here because the "expand-modules"
+ directive to the server has the side-effect of having the
+ server send the check-in and update programs for the
+ various modules/dirs requested. If we turn this off and
+ simply request the names of the modules and directories (as
+ below in !expand_modules), those files (CVS/Checking.prog
+ or CVS/Update.prog) don't get created. Grrr. */
+
+ expand_modules = (!cat && !status && !pipeout
+ && supported_request ("expand-modules"));
+
+ if (expand_modules)
+ {
+ /* This is done here because we need to read responses
+ from the server before we send the command checkout or
+ export files. */
+
+ client_expand_modules (argc, argv, local);
+ }
+
+ if (!run_module_prog) send_arg ("-n");
+ if (local) send_arg ("-l");
+ if (pipeout) send_arg ("-p");
+ if (!force_tag_match) send_arg ("-f");
+ if (aflag)
+ send_arg("-A");
+ if (!shorten)
+ send_arg("-N");
+ if (checkout_prune_dirs && strcmp (command_name, "export") != 0)
+ send_arg("-P");
+ client_prune_dirs = checkout_prune_dirs;
+ if (cat)
+ send_arg("-c");
+ if (where != NULL)
+ {
+ option_with_arg ("-d", where);
+ }
+ if (status)
+ send_arg("-s");
+ if (strcmp (command_name, "export") != 0
+ && options != NULL
+ && options[0] != '\0')
+ send_arg (options);
+ option_with_arg ("-r", tag);
+ if (date)
+ client_senddate (date);
+ if (join_rev1 != NULL)
+ option_with_arg ("-j", join_rev1);
+ if (join_rev2 != NULL)
+ option_with_arg ("-j", join_rev2);
+
+ if (expand_modules)
+ {
+ client_send_expansions (local);
+ }
+ else
+ {
+ int i;
+ for (i = 0; i < argc; ++i)
+ send_arg (argv[i]);
+ client_nonexpanded_setup ();
+ }
+
+ if (fprintf
+ (to_server,
+ strcmp (command_name, "export") == 0 ? "export\n" : "co\n")
+ < 0)
+ error (1, errno, "writing to server");
+
+ return get_responses_and_close ();
+ }
+#endif
+
if (cat || status)
{
cat_module (status);
@@ -249,23 +350,29 @@ checkout (argc, argv)
{
char repository[PATH_MAX];
- (void) mkdir (where, 0777);
+ (void) CVS_MKDIR (where, 0777);
if (chdir (where) < 0)
error (1, errno, "cannot chdir to %s", where);
preload_update_dir = xstrdup (where);
where = (char *) NULL;
- if (!isfile (CVSADM) && !isfile (OCVSADM))
+ if (!isfile (CVSADM))
{
(void) sprintf (repository, "%s/%s/%s", CVSroot, CVSROOTADM,
CVSNULLREPOS);
if (!isfile (repository))
- (void) mkdir (repository, 0777);
+ {
+ mode_t omask;
+ omask = umask (cvsumask);
+ (void) CVS_MKDIR (repository, 0777);
+ (void) umask (omask);
+ }
/* I'm not sure whether this check is redundant. */
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
- Create_Admin (".", repository, (char *) NULL, (char *) NULL);
+ Create_Admin (".", where, repository,
+ (char *) NULL, (char *) NULL);
if (!noexec)
{
FILE *fp;
@@ -273,6 +380,10 @@ checkout (argc, argv)
fp = open_file (CVSADM_ENTSTAT, "w+");
if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_entstat (preload_update_dir, repository);
+#endif
}
}
}
@@ -302,13 +413,34 @@ checkout (argc, argv)
}
for (i = 0; i < argc; i++)
- err += do_module (db, argv[i], CHECKOUT, "Updating", checkout_proc,
+ err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
where, shorten, local, run_module_prog,
(char *) NULL);
close_module (db);
return (err);
}
+static int
+safe_location ()
+{
+ char current[PATH_MAX];
+ char hardpath[PATH_MAX+5];
+ int x;
+
+ x = readlink(CVSroot, hardpath, sizeof hardpath - 1);
+ if (x == -1)
+ {
+ strcpy(hardpath, CVSroot);
+ }
+ hardpath[x] = '\0';
+ getwd (current);
+ if (strncmp(current, hardpath, strlen(hardpath)) == 0)
+ {
+ return (0);
+ }
+ return (1);
+}
+
/*
* process_module calls us back here so we do the actual checkout stuff
*/
@@ -317,7 +449,7 @@ static int
checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
local_specified, omodule, msg)
int *pargc;
- char *argv[];
+ char **argv;
char *where;
char *mwhere;
char *mfile;
@@ -528,7 +660,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
free (prepath);
/* set up the repository (or make sure the old one matches) */
- if (!isfile (CVSADM) && !isfile (OCVSADM))
+ if (!isfile (CVSADM))
{
FILE *fp;
@@ -538,10 +670,15 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
- Create_Admin (".", repository, (char *) NULL, (char *) NULL);
+ Create_Admin (".", where, repository,
+ (char *) NULL, (char *) NULL);
fp = open_file (CVSADM_ENTSTAT, "w+");
if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_entstat (where, repository);
+#endif
}
else
{
@@ -549,7 +686,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
- Create_Admin (".", repository, tag, date);
+ Create_Admin (".", where, repository, tag, date);
}
}
else
@@ -558,7 +695,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
/* get the contents of the previously existing repository */
repos = Name_Repository ((char *) NULL, preload_update_dir);
- if (strcmp (repository, repos) != 0)
+ if (fncmp (repository, repos) != 0)
{
error (0, 0, "existing repository %s does not match %s",
repos, repository);
@@ -620,7 +757,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
List *entries;
/* we are only doing files, so register them */
- entries = ParseEntries (0);
+ entries = Entries_Open (0);
for (i = 1; i < *pargc; i++)
{
char line[MAXLINELEN];
@@ -639,7 +776,8 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
}
freevers_ts (&vers);
}
- dellist (&entries);
+
+ Entries_Close (entries);
}
/* Don't log "export", just regular "checkouts" */
@@ -698,32 +836,35 @@ build_dirs_and_chdir (dir, prepath, realdir, sticky)
{
*slash = '\0';
*slash2 = '\0';
- (void) mkdir (cp, 0777);
+ (void) CVS_MKDIR (cp, 0777);
if (chdir (cp) < 0)
{
error (0, errno, "cannot chdir to %s", cp);
return (1);
}
- if (!isfile (CVSADM) && !isfile (OCVSADM) &&
- strcmp (command_name, "export") != 0)
+ if (!isfile (CVSADM) && strcmp (command_name, "export") != 0)
{
(void) sprintf (repository, "%s/%s", prepath, path2);
/* I'm not sure whether this check is redundant. */
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
- Create_Admin (".", repository, sticky ? (char *) NULL : tag,
+ Create_Admin (".", cp, repository, sticky ? (char *) NULL : tag,
sticky ? (char *) NULL : date);
if (!noexec)
{
fp = open_file (CVSADM_ENTSTAT, "w+");
if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_entstat (path, repository);
+#endif
}
}
*slash = '/';
*slash2 = '/';
}
- (void) mkdir (cp, 0777);
+ (void) CVS_MKDIR (cp, 0777);
if (chdir (cp) < 0)
{
error (0, errno, "cannot chdir to %s", cp);
diff --git a/gnu/usr.bin/cvs/cvs/classify.c b/gnu/usr.bin/cvs/cvs/classify.c
index ff9305d..23fafca 100644
--- a/gnu/usr.bin/cvs/cvs/classify.c
+++ b/gnu/usr.bin/cvs/cvs/classify.c
@@ -10,11 +10,17 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)classify.c 1.17 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)classify.c 1.17 94/10/07 $";
+USE(rcsid);
#endif
+#ifdef SERVER_SUPPORT
+static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers,
+ List * entries,
+ char *repository, char *update_dir));
+#else
static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers, List * entries));
+#endif
/*
* Classify the state of a file
@@ -73,6 +79,25 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
ret = T_UNKNOWN;
}
}
+#ifdef DEATH_SUPPORT
+ else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
+ {
+ if (vers->ts_user == NULL)
+ /*
+ * Logically seems to me this should be T_UPTODATE.
+ * But the joining code in update.c seems to expect
+ * T_CHECKOUT, and that is what has traditionally been
+ * returned for this case.
+ */
+ ret = T_CHECKOUT;
+ else
+ {
+ error (0, 0, "use `cvs add' to create an entry for %s",
+ fullname);
+ ret = T_UNKNOWN;
+ }
+ }
+#endif
else
{
/* there is an rcs file */
@@ -133,8 +158,28 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (vers->vn_rcs == NULL)
/* There is no RCS file, added file */
ret = T_ADDED;
+#ifdef DEATH_SUPPORT
+ else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
+ /* we are resurrecting. */
+ ret = T_ADDED;
+#endif /* DEATH_SUPPORT */
else
{
+#ifdef DEATH_SUPPORT
+ if (vers->srcfile->flags & INATTIC
+ && vers->srcfile->flags & VALID)
+ {
+ /* This file has been added on some branch other than
+ the one we are looking at. In the branch we are
+ looking at, the file was already valid. */
+ if (!really_quiet)
+ error (0, 0,
+ "conflict: %s has been added, but already exists",
+ fullname);
+ }
+ else
+ {
+#endif /* DEATH_SUPPORT */
/*
* There is an RCS file, so someone else must have checked
* one in behind our back; conflict
@@ -143,6 +188,9 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
error (0, 0,
"conflict: %s created independently by second party",
fullname);
+#ifdef DEATH_SUPPORT
+ }
+#endif
ret = T_CONFLICT;
}
}
@@ -282,7 +330,12 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
ret = T_CHECKOUT;
else
{
+#ifdef SERVER_SUPPORT
+ sticky_ck (file, aflag, vers, entries,
+ repository, update_dir);
+#else
sticky_ck (file, aflag, vers, entries);
+#endif
ret = T_UPTODATE;
}
}
@@ -309,7 +362,12 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
ret = T_NEEDS_MERGE;
#else
ret = T_MODIFIED;
+#ifdef SERVER_SUPPORT
+ sticky_ck (file, aflag, vers, entries,
+ repository, update_dir);
+#else
sticky_ck (file, aflag, vers, entries);
+#endif /* SERVER_SUPPORT */
#endif
}
else
@@ -352,7 +410,17 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
/*
* The user file is still unmodified, so just get it as well
*/
+#ifdef SERVER_SUPPORT
+ if (strcmp (vers->entdata->options ?
+ vers->entdata->options : "", vers->options) != 0
+ || (vers->srcfile != NULL
+ && (vers->srcfile->flags & INATTIC) != 0))
+ ret = T_CHECKOUT;
+ else
+ ret = T_PATCH;
+#else
ret = T_CHECKOUT;
+#endif
}
else
{
@@ -360,9 +428,21 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
repository, update_dir))
/* really modified, needs to merge */
ret = T_NEEDS_MERGE;
+#ifdef SERVER_SUPPORT
+ else if ((strcmp (vers->entdata->options ?
+ vers->entdata->options : "", vers->options)
+ != 0)
+ || (vers->srcfile != NULL
+ && (vers->srcfile->flags & INATTIC) != 0))
+ /* not really modified, check it out */
+ ret = T_CHECKOUT;
+ else
+ ret = T_PATCH;
+#else
else
/* not really modified, check it out */
ret = T_CHECKOUT;
+#endif
}
}
}
@@ -380,11 +460,19 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
}
static void
+#ifdef SERVER_SUPPORT
+sticky_ck (file, aflag, vers, entries, repository, update_dir)
+#else
sticky_ck (file, aflag, vers, entries)
+#endif
char *file;
int aflag;
Vers_TS *vers;
List *entries;
+#ifdef SERVER_SUPPORT
+ char *repository;
+ char *update_dir;
+#endif
{
if (aflag || vers->tag || vers->date)
{
@@ -398,6 +486,19 @@ sticky_ck (file, aflag, vers, entries)
{
Register (entries, file, vers->vn_user, vers->ts_rcs,
vers->options, vers->tag, vers->date, vers->ts_conflict);
+
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ /* We need to update the entries line on the client side.
+ It is possible we will later update it again via
+ server_updated or some such, but that is OK. */
+ server_update_entries
+ (file, update_dir, repository,
+ strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
+ SERVER_UPDATED : SERVER_MERGED);
+ }
+#endif
}
}
}
diff --git a/gnu/usr.bin/cvs/cvs/commit.c b/gnu/usr.bin/cvs/cvs/commit.c
index cb36e9f..888804e 100644
--- a/gnu/usr.bin/cvs/cvs/commit.c
+++ b/gnu/usr.bin/cvs/cvs/commit.c
@@ -15,10 +15,11 @@
*/
#include "cvs.h"
+#include "getline.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)commit.c 1.101 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)commit.c 1.101 94/10/07 $";
+USE(rcsid);
#endif
static Dtype check_direntproc PROTO((char *dir, char *repos, char *update_dir));
@@ -26,16 +27,17 @@ static int check_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
static int checkaddfile PROTO((char *file, char *repository, char *tag,
- List *srcfiles));
+ char *options, List *srcfiles));
static Dtype commit_direntproc PROTO((char *dir, char *repos, char *update_dir));
static int commit_dirleaveproc PROTO((char *dir, int err, char *update_dir));
static int commit_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
static int commit_filesdoneproc PROTO((int err, char *repository, char *update_dir));
-static int finaladd PROTO((char *file, char *revision, char *tag, char *options,
- char *repository, List *entries));
+static int finaladd PROTO((char *file, char *revision, char *tag,
+ char *options, char *update_dir,
+ char *repository, List *entries));
static int findmaxrev PROTO((Node * p, void *closure));
-static int fsortcmp PROTO((Node * p, Node * q));
+static int fsortcmp PROTO((const Node * p, const Node * q));
static int lock_RCS PROTO((char *user, char *rcs, char *rev, char *repository));
static int lock_filesdoneproc PROTO((int err, char *repository, char *update_dir));
static int lockrcsfile PROTO((char *file, char *repository, char *rev));
@@ -64,7 +66,7 @@ struct master_lists
List *cilist; /* list with commit_info structs */
};
-static int force_ci;
+static int force_ci = 0;
static int got_message;
static int run_module_prog = 1;
static int aflag;
@@ -75,7 +77,7 @@ static List *mulist;
static List *locklist;
static char *message;
-static char *commit_usage[] =
+static const char *const commit_usage[] =
{
"Usage: %s %s [-nRlf] [-m msg | -F logfile] [-r rev] files...\n",
"\t-n\tDo not run the module program (if any).\n",
@@ -91,7 +93,7 @@ static char *commit_usage[] =
int
commit (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int c;
int err = 0;
@@ -188,7 +190,7 @@ commit (argc, argv)
if (message)
error (1, 0, "cannot specify both a message and a log file");
- if ((logfd = open (logfile, O_RDONLY)) < 0)
+ if ((logfd = open (logfile, O_RDONLY | OPEN_BINARY)) < 0)
error (1, errno, "cannot open log file %s", logfile);
if (fstat(logfd, &statbuf) < 0)
@@ -203,17 +205,60 @@ commit (argc, argv)
message[n] = '\0';
}
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ /*
+ * Do this now; don't ask for a log message if we can't talk to the
+ * server. But if there is a syntax error in the options, give
+ * an error message without connecting.
+ */
+ start_server ();
+
+ ign_setup ();
+
+ /*
+ * We do this once, not once for each directory as in normal CVS.
+ * The protocol is designed this way. This is a feature.
+ *
+ * We could provide the lists of changed, modified, etc. files,
+ * however. Our failure to do so is just laziness, not design.
+ */
+ if (use_editor)
+ do_editor (".", &message, (char *)NULL, (List *)NULL);
+
+ /* We always send some sort of message, even if empty. */
+ option_with_arg ("-m", message);
+
+ if (local)
+ send_arg("-l");
+ if (force_ci)
+ send_arg("-f");
+ if (!run_module_prog)
+ send_arg("-n");
+ option_with_arg ("-r", tag);
+
+ send_files (argc, argv, local, 0);
+
+ if (fprintf (to_server, "ci\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
/* XXX - this is not the perfect check for this */
if (argc <= 0)
write_dirtag = tag;
+ wrap_setup ();
+
/*
* Run the recursion processor to find all the dirs to lock and lock all
* the dirs
*/
locklist = getlist ();
- err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc,
- (Dtype (*) ()) NULL, (int (*) ()) NULL, argc,
+ err = start_recursion ((FILEPROC) NULL, lock_filesdoneproc,
+ (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, argc,
argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0,
0);
sortlist (locklist, fsortcmp);
@@ -229,7 +274,7 @@ commit (argc, argv)
* Run the recursion processor to verify the files are all up-to-date
*/
err = start_recursion (check_fileproc, check_filesdoneproc,
- check_direntproc, (int (*) ()) NULL, argc,
+ check_direntproc, (DIRLEAVEPROC) NULL, argc,
argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1,
0);
if (err)
@@ -261,7 +306,8 @@ commit (argc, argv)
*/
static int
fsortcmp (p, q)
- Node *p, *q;
+ const Node *p;
+ const Node *q;
{
return (strcmp (p->key, q->key));
}
@@ -395,14 +441,17 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
switch (status)
{
case T_CHECKOUT:
+#ifdef SERVER_SUPPORT
+ case T_PATCH:
+#endif
case T_NEEDS_MERGE:
case T_CONFLICT:
+ case T_REMOVE_ENTRY:
if (update_dir[0] == '\0')
error (0, 0, "Up-to-date check failed for `%s'", file);
else
error (0, 0, "Up-to-date check failed for `%s/%s'",
update_dir, file);
- error (0, 0, "Up-to-date check failed for `%s'", file);
freevers_ts (&vers);
return (1);
case T_MODIFIED:
@@ -463,9 +512,19 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
* If the timestamp on the file is the same as the
* timestamp stored in the Entries file, we block the commit.
*/
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ retcode = vers->ts_conflict[0] != '=';
+ else {
+ filestamp = time_stamp (file);
+ retcode = strcmp (vers->ts_conflict, filestamp);
+ free (filestamp);
+ }
+#else
filestamp = time_stamp (file);
retcode = strcmp (vers->ts_conflict, filestamp);
free (filestamp);
+#endif
if (retcode == 0)
{
if (update_dir[0] == '\0')
@@ -484,10 +543,10 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
* If the timestamps differ, look for Conflict indicators
* in the file to see if we should block the commit anyway
*/
- run_setup ("%s -s", GREP);
+ run_setup ("%s", GREP);
run_arg (RCS_MERGE_PAT);
run_arg (file);
- retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+ retcode = run_exec (RUN_TTY, DEVNULL, RUN_TTY, RUN_REALLY);
if (retcode == -1)
{
@@ -532,7 +591,13 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
{
char rcs[PATH_MAX];
+#ifdef DEATH_SUPPORT
+ /* Don't look in the attic; if it exists there we will
+ move it back out in checkaddfile. */
+ sprintf(rcs, "%s/%s%s", repository, file, RCSEXT);
+#else
locate_rcs (file, repository, rcs);
+#endif
if (isreadable (rcs))
{
if (update_dir[0] == '\0')
@@ -676,7 +741,7 @@ precommit_proc (repository, filter)
char *filter;
{
/* see if the filter is there, only if it's a full path */
- if (filter[0] == '/')
+ if (isabsolute (filter))
{
char *s, *cp;
@@ -797,12 +862,33 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
}
else if (ci->status == T_ADDED)
{
- if (checkaddfile (file, repository, ci->tag, srcfiles) != 0)
+ if (checkaddfile (file, repository, ci->tag, ci->options,
+ srcfiles) != 0)
{
fixaddfile (file, repository);
err = 1;
goto out;
}
+
+#ifdef DEATH_SUPPORT
+ /* adding files with a tag, now means adding them on a branch.
+ Since the branch test was done in check_fileproc for
+ modified files, we need to stub it in again here. */
+
+ if (ci->tag) {
+ locate_rcs (file, repository, rcs);
+ ci->rev = RCS_whatbranch (file, ci->tag, srcfiles);
+ err = Checkin ('A', file, update_dir, repository, rcs, ci->rev,
+ ci->tag, ci->options, message, entries);
+ if (err != 0)
+ {
+ unlockrcs (file, repository);
+ fixbranch (file, repository, sbranch);
+ }
+
+ ci->status = T_UPTODATE;
+ }
+#endif /* DEATH_SUPPORT */
}
/*
@@ -825,14 +911,15 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
/* XXX - an added file with symbolic -r should add tag as well */
err = finaladd (file, ci->rev ? ci->rev : xrev, ci->tag, ci->options,
- repository, entries);
+ update_dir, repository, entries);
if (xrev)
free (xrev);
}
else if (ci->status == T_MODIFIED)
{
locate_rcs (file, repository, rcs);
- err = Checkin ('M', file, repository, rcs, ci->rev, ci->tag,
+ err = Checkin ('M', file, update_dir, repository,
+ rcs, ci->rev, ci->tag,
ci->options, message, entries);
if (err != 0)
{
@@ -841,8 +928,19 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
}
}
else if (ci->status == T_REMOVED)
+ {
err = remove_file (file, repository, ci->tag, message,
entries, srcfiles);
+#ifdef SERVER_SUPPORT
+ if (server_active) {
+ server_scratch_entry_only ();
+ server_updated (file, update_dir, repository,
+ /* Doesn't matter, it won't get checked. */
+ SERVER_UPDATED, (struct stat *) NULL,
+ (unsigned char *) NULL);
+ }
+#endif
+ }
out:
if (err != 0)
@@ -888,18 +986,23 @@ commit_filesdoneproc (err, repository, update_dir)
if (err == 0 && run_module_prog)
{
- char *cp;
FILE *fp;
- char line[MAXLINELEN];
- char *repository;
- /* It is not an error if Checkin.prog does not exist. */
if ((fp = fopen (CVSADM_CIPROG, "r")) != NULL)
{
- if (fgets (line, sizeof (line), fp) != NULL)
+ char *line;
+ int line_length;
+ size_t line_chars_allocated;
+ char *repository;
+
+ line = NULL;
+ line_chars_allocated = 0;
+ line_length = getline (&line, &line_chars_allocated, fp);
+ if (line_length > 0)
{
- if ((cp = strrchr (line, '\n')) != NULL)
- *cp = '\0';
+ /* Remove any trailing newline. */
+ if (line[line_length - 1] == '\n')
+ line[--line_length] = '\0';
repository = Name_Repository ((char *) NULL, update_dir);
run_setup ("%s %s", line, repository);
(void) printf ("%s %s: Executing '", program_name,
@@ -909,7 +1012,21 @@ commit_filesdoneproc (err, repository, update_dir)
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
free (repository);
}
- (void) fclose (fp);
+ else
+ {
+ if (ferror (fp))
+ error (0, errno, "warning: error reading %s",
+ CVSADM_CIPROG);
+ }
+ if (line != NULL)
+ free (line);
+ if (fclose (fp) < 0)
+ error (0, errno, "warning: cannot close %s", CVSADM_CIPROG);
+ }
+ else
+ {
+ if (! existence_error (errno))
+ error (0, errno, "warning: cannot open %s", CVSADM_CIPROG);
}
}
@@ -968,7 +1085,14 @@ commit_dirleaveproc (dir, err, update_dir)
{
/* update the per-directory tag info */
if (err == 0 && write_dirtag != NULL)
+ {
WriteTag ((char *) NULL, write_dirtag, (char *) NULL);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_sticky (update_dir, Name_Repository (dir, update_dir),
+ write_dirtag, (char *) NULL);
+#endif
+ }
return (err);
}
@@ -1017,16 +1141,34 @@ remove_file (file, repository, tag, message, entries, srcfiles)
char rcs[PATH_MAX];
char *tmp;
+#ifdef DEATH_SUPPORT
+ int branch;
+ char *lockflag;
+ char *corev;
+ char *rev;
+ char *prev_rev;
+ Node *p;
+ RCSNode *rcsfile;
+
+ corev = NULL;
+ rev = NULL;
+ prev_rev = NULL;
+ lockflag = 0;
+#endif /* DEATH_SUPPORT */
+
retcode = 0;
locate_rcs (file, repository, rcs);
+#ifdef DEATH_SUPPORT
+ branch = 0;
+ if (tag && !(branch = RCS_isbranch (file, tag, srcfiles)))
+#else
if (tag)
+#endif
{
/* a symbolic tag is specified; just remove the tag from the file */
- run_setup ("%s%s -q -N%s", Rcsbin, RCS, tag);
- run_arg (rcs);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_deltag (rcs, tag, 1)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
@@ -1036,7 +1178,126 @@ remove_file (file, repository, tag, message, entries, srcfiles)
Scratch_Entry (entries, file);
return (0);
}
+
+#ifdef DEATH_SUPPORT
+ /* we are removing the file from either the head or a branch */
+ /* commit a new, dead revision. */
+
+ /* Print message indicating that file is going to be removed. */
+ (void) printf ("Removing %s;\n", file);
+
+ rev = NULL;
+ lockflag = "-l";
+ if (branch)
+ {
+ char *branchname;
+
+ rev = RCS_whatbranch (file, tag, srcfiles);
+ if (rev == NULL)
+ {
+ error (0, 0, "cannot find branch \"%s\".", tag);
+ return (1);
+ }
+
+ p = findnode (srcfiles, file);
+ if (p == NULL)
+ {
+ error (0, 0, "boy, I'm confused.");
+ return (1);
+ }
+ rcsfile = (RCSNode *) p->data;
+ branchname = RCS_getbranch (rcsfile, rev, 1);
+ if (branchname == NULL)
+ {
+ /* no revision exists on this branch. use the previous
+ revision but do not lock. */
+ corev = RCS_gettag (rcsfile, tag, 1, 0);
+ prev_rev = xstrdup(rev);
+ lockflag = "";
+ } else
+ {
+ corev = xstrdup (rev);
+ prev_rev = xstrdup(branchname);
+ free (branchname);
+ }
+
+ } else /* Not a branch */
+ {
+
+ /* Get current head revision of file. */
+ p = findnode (srcfiles, file);
+ if (p == NULL)
+ {
+ error (0, 0, "could not find parsed rcsfile %s", file);
+ return (1);
+ }
+ rcsfile = (RCSNode *) p->data;
+ prev_rev = RCS_head (rcsfile);
+ }
+
+ /* if removing without a tag or a branch, then make sure the default
+ branch is the trunk. */
+ if (!tag && !branch)
+ {
+ if (RCS_setbranch (rcs, NULL) != 0)
+ {
+ error (0, 0, "cannot change branch to default for %s",
+ rcs);
+ return (1);
+ }
+ }
+
+#ifdef SERVER_SUPPORT
+ if (server_active) {
+ /* If this is the server, there will be a file sitting in the
+ temp directory which is the kludgy way in which server.c
+ tells time_stamp that the file is no longer around. Remove
+ it so we can create temp files with that name (ignore errors). */
+ unlink_file (file);
+ }
+#endif
+
+ /* check something out. Generally this is the head. If we have a
+ particular rev, then name it. except when creating a branch,
+ lock the rev we're checking out. */
+ run_setup ("%s%s %s %s%s %s", Rcsbin, RCS_CO,
+ lockflag,
+ rev ? "-r" : "",
+ rev ? corev : "", rcs);
+ if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL))
+ != 0) {
+ if (!quiet)
+ error (0, retcode == -1 ? errno : 0,
+ "failed to check out `%s'", rcs);
+ return (1);
+ }
+
+ if (corev != NULL)
+ free (corev);
+
+#ifdef DEATH_STATE
+ run_setup ("%s%s -f -sdead %s%s", Rcsbin, RCS_CI, rev ? "-r" : "",
+#else
+ run_setup ("%s%s -K %s%s", Rcsbin, RCS_CI, rev ? "-r" : "",
+#endif
+ rev ? rev : "");
+ run_args ("-m%s", make_message_rcslegal (message));
+ run_arg (rcs);
+ if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL))
+ != 0) {
+ if (!quiet)
+ error (0, retcode == -1 ? errno : 0,
+ "failed to commit dead revision for `%s'", rcs);
+ return (1);
+ }
+
+ if (rev != NULL)
+ free (rev);
+
+ if (!branch)
+#else /* No DEATH_SUPPORT */
else
+#endif /* No DEATH_SUPPORT */
{
/* this was the head; really move it into the Attic */
tmp = xmalloc(strlen(repository) +
@@ -1046,31 +1307,56 @@ remove_file (file, repository, tag, message, entries, srcfiles)
strlen(file) +
sizeof(RCSEXT) + 1);
(void) sprintf (tmp, "%s/%s", repository, CVSATTIC);
- omask = umask (2);
- (void) mkdir (tmp, 0777);
+ omask = umask (cvsumask);
+ (void) CVS_MKDIR (tmp, 0777);
(void) umask (omask);
(void) sprintf (tmp, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
+#ifdef DEATH_SUPPORT
+ if (strcmp (rcs, tmp) != 0
+ && rename (rcs, tmp) == -1
+ && (isreadable (rcs) || !isreadable (tmp)))
+ {
+ free(tmp);
+ return (1);
+ }
+ free(tmp);
+ }
+
+ /* Print message that file was removed. */
+ (void) printf ("%s <-- %s\n", rcs, file);
+ (void) printf ("new revision: delete; ");
+ (void) printf ("previous revision: %s\n", prev_rev);
+ (void) printf ("done\n");
+ free(prev_rev);
+
+ Scratch_Entry (entries, file);
+ return (0);
+#else /* No DEATH_SUPPORT */
if ((strcmp (rcs, tmp) == 0 || rename (rcs, tmp) != -1) ||
(!isreadable (rcs) && isreadable (tmp)))
{
Scratch_Entry (entries, file);
+ /* FIXME: should free tmp. */
return (0);
}
+ /* FIXME: should free tmp. */
}
return (1);
+#endif /* No DEATH_SUPPORT */
}
/*
* Do the actual checkin for added files
*/
static int
-finaladd (file, rev, tag, options, repository, entries)
+finaladd (file, rev, tag, options, update_dir, repository, entries)
char *file;
char *rev;
char *tag;
char *options;
+ char *update_dir;
char *repository;
List *entries;
{
@@ -1079,12 +1365,10 @@ finaladd (file, rev, tag, options, repository, entries)
char rcs[PATH_MAX];
locate_rcs (file, repository, rcs);
- ret = Checkin ('A', file, repository, rcs, rev, tag, options,
+ ret = Checkin ('A', file, update_dir, repository, rcs, rev, tag, options,
message, entries);
if (ret == 0)
{
- (void) sprintf (tmp, "%s/%s%s", CVSADM, file, CVSEXT_OPT);
- (void) unlink_file (tmp);
(void) sprintf (tmp, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
(void) unlink_file (tmp);
}
@@ -1105,10 +1389,8 @@ unlockrcs (file, repository)
int retcode = 0;
locate_rcs (file, repository, rcs);
- run_setup ("%s%s -q -u", Rcsbin, RCS);
- run_arg (rcs);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_unlock (rcs, NULL, 0)) != 0)
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
"could not unlock %s", rcs);
}
@@ -1150,9 +1432,7 @@ fixbranch (file, repository, branch)
if (branch != NULL && branch[0] != '\0')
{
locate_rcs (file, repository, rcs);
- run_setup ("%s%s -q -b%s", Rcsbin, RCS, branch);
- run_arg (rcs);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_setbranch (rcs, branch)) != 0)
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
"cannot restore branch to %s for %s", branch, rcs);
}
@@ -1165,24 +1445,26 @@ fixbranch (file, repository, branch)
*/
static int
-checkaddfile (file, repository, tag, srcfiles)
+checkaddfile (file, repository, tag, options, srcfiles)
char *file;
char *repository;
char *tag;
+ char *options;
List *srcfiles;
{
- FILE *fp;
- char *cp;
char rcs[PATH_MAX];
char fname[PATH_MAX];
mode_t omask;
int retcode = 0;
+#ifdef DEATH_SUPPORT
+ int newfile = 0;
+#endif
if (tag)
{
(void) sprintf(rcs, "%s/%s", repository, CVSATTIC);
- omask = umask (2);
- if (mkdir (rcs, 0777) != 0 && errno != EEXIST)
+ omask = umask (cvsumask);
+ if (CVS_MKDIR (rcs, 0777) != 0 && errno != EEXIST)
error (1, errno, "cannot make directory `%s'", rcs);;
(void) umask (omask);
(void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
@@ -1190,18 +1472,177 @@ checkaddfile (file, repository, tag, srcfiles)
else
locate_rcs (file, repository, rcs);
- run_setup ("%s%s -i", Rcsbin, RCS);
- run_args ("-t%s/%s%s", CVSADM, file, CVSEXT_LOG);
- (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_OPT);
- fp = open_file (fname, "r");
- while (fgets (fname, sizeof (fname), fp) != NULL)
+#ifdef DEATH_SUPPORT
+ if (isreadable(rcs))
+ {
+ /* file has existed in the past. Prepare to resurrect. */
+ char oldfile[PATH_MAX];
+ char *rev;
+ Node *p;
+ RCSNode *rcsfile;
+
+ if (tag == NULL)
+ {
+ /* we are adding on the trunk, so move the file out of the
+ Attic. */
+ strcpy (oldfile, rcs);
+ sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
+
+ if (strcmp (oldfile, rcs) == 0
+ || rename (oldfile, rcs) != 0
+ || isreadable (oldfile)
+ || !isreadable (rcs))
+ {
+ error (0, 0, "failed to move `%s' out of the attic.",
+ file);
+ return (1);
+ }
+ }
+
+ p = findnode (srcfiles, file);
+ if (p == NULL)
+ {
+ error (0, 0, "could not find parsed rcsfile %s", file);
+ return (1);
+ }
+
+ rcsfile = (RCSNode *) p->data;
+ rev = RCS_getversion (rcsfile, tag, NULL, 1, 0);
+ /* and lock it */
+ if (lock_RCS (file, rcs, rev, repository)) {
+ error (0, 0, "cannot lock `%s'.", rcs);
+ free (rev);
+ return (1);
+ }
+
+ free (rev);
+ } else {
+ /* this is the first time we have ever seen this file; create
+ an rcs file. */
+ run_setup ("%s%s -i", Rcsbin, RCS);
+
+ (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
+ /* If the file does not exist, no big deal. In particular, the
+ server does not (yet at least) create CVSEXT_LOG files. */
+ if (isfile (fname))
+ run_args ("-t%s/%s%s", CVSADM, file, CVSEXT_LOG);
+
+ /* Set RCS keyword expansion options. */
+ if (options && options[0] == '-' && options[1] == 'k')
+ run_arg (options);
+ run_arg (rcs);
+ if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ {
+ error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
+ "could not create %s", rcs);
+ return (1);
+ }
+ newfile = 1;
+ }
+
+ /* when adding a file for the first time, and using a tag, we need
+ to create a dead revision on the trunk. */
+ if (tag && newfile)
+ {
+ char tmp[PATH_MAX];
+
+ /* move the new file out of the way. */
+ (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
+ rename_file (file, fname);
+ copy_file (DEVNULL, file);
+
+ /* commit a dead revision. */
+ (void) sprintf (tmp, "-mfile %s was initially added on branch %s.", file, tag);
+#ifdef DEATH_STATE
+ run_setup ("%s%s -q -f -sdead", Rcsbin, RCS_CI);
+#else
+ run_setup ("%s%s -q -K", Rcsbin, RCS_CI);
+#endif
+ run_arg (tmp);
+ run_arg (rcs);
+ if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ {
+ error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
+ "could not create initial dead revision %s", rcs);
+ return (1);
+ }
+
+ /* put the new file back where it was */
+ rename_file (fname, file);
+
+ /* and lock it once again. */
+ if (lock_RCS (file, rcs, NULL, repository)) {
+ error (0, 0, "cannot lock `%s'.", rcs);
+ return (1);
+ }
+ }
+
+ if (tag != NULL)
{
- if ((cp = strrchr (fname, '\n')) != NULL)
- *cp = '\0';
- if (*fname)
- run_arg (fname);
+ /* when adding with a tag, we need to stub a branch, if it
+ doesn't already exist. */
+ Node *p;
+ RCSNode *rcsfile;
+
+ rcsfile = RCS_parse (file, repository);
+ if (rcsfile == NULL)
+ {
+ error (0, 0, "could not read %s", rcs);
+ return (1);
+ }
+
+ if (!RCS_nodeisbranch (tag, rcsfile)) {
+ /* branch does not exist. Stub it. */
+ char *head;
+ char *magicrev;
+
+ head = RCS_getversion (rcsfile, NULL, NULL, 0, 0);
+ magicrev = RCS_magicrev (rcsfile, head);
+ if ((retcode = RCS_settag(rcs, tag, magicrev)) != 0)
+ {
+ error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
+ "could not stub branch %s for %s", tag, rcs);
+ return (1);
+ }
+
+ freercsnode (&rcsfile);
+
+ /* reparse the file, then add it to our list. */
+ rcsfile = RCS_parse (file, repository);
+ if (rcsfile == NULL)
+ {
+ error (0, 0, "could not reparse %s", rcs);
+ return (1);
+ }
+
+ free (head);
+ free (magicrev);
+ }
+ else
+ {
+ /* lock the branch. (stubbed branches need not be locked.) */
+ if (lock_RCS (file, rcs, NULL, repository)) {
+ error (0, 0, "cannot lock `%s'.", rcs);
+ return (1);
+ }
+ }
+
+ /* add (replace) this rcs file to our list */
+ p = findnode (srcfiles, file);
+
+ if (p != NULL)
+ freercsnode((RCSNode **) &p->data);
+
+ delnode(p);
+
+ RCS_addnode (file, rcsfile, srcfiles);
}
- (void) fclose (fp);
+#else /* No DEATH_SUPPORT */
+ run_setup ("%s%s -i", Rcsbin, RCS);
+ run_args ("-t%s/%s%s", CVSADM, file, CVSEXT_LOG);
+ /* Set RCS keyword expansion options. */
+ if (options && options[0] == '-' && options[1] == 'k')
+ run_arg (options);
run_arg (rcs);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
{
@@ -1209,6 +1650,7 @@ checkaddfile (file, repository, tag, srcfiles)
"could not create %s", rcs);
return (1);
}
+#endif /* No DEATH_SUPPORT */
fix_rcs_modes (rcs, file);
return (0);
@@ -1272,9 +1714,7 @@ lock_RCS (user, rcs, rev, repository)
freercsnode (&rcsfile);
if (branch != NULL)
{
- run_setup ("%s%s -q -b", Rcsbin, RCS);
- run_arg (rcs);
- if (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
+ if (RCS_setbranch (rcs, NULL) != 0)
{
error (0, 0, "cannot change branch to default for %s",
rcs);
@@ -1283,16 +1723,12 @@ lock_RCS (user, rcs, rev, repository)
return (1);
}
}
- run_setup ("%s%s -q -l", Rcsbin, RCS);
- run_arg (rcs);
- err = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+ err = RCS_lock(rcs, NULL, 0);
}
}
else
{
- run_setup ("%s%s -q -l%s", Rcsbin, RCS, rev ? rev : "");
- run_arg (rcs);
- (void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL);
+ (void) RCS_lock(rcs, rev, 1);
}
if (err == 0)
diff --git a/gnu/usr.bin/cvs/cvs/create_adm.c b/gnu/usr.bin/cvs/cvs/create_adm.c
index 55eb649..1fe8185 100644
--- a/gnu/usr.bin/cvs/cvs/create_adm.c
+++ b/gnu/usr.bin/cvs/cvs/create_adm.c
@@ -14,13 +14,16 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)create_adm.c 1.28 94/09/23 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)create_adm.c 1.28 94/09/23 $";
+USE(rcsid);
#endif
+/* update_dir includes dir as its last component. */
+
void
-Create_Admin (dir, repository, tag, date)
+Create_Admin (dir, update_dir, repository, tag, date)
char *dir;
+ char *update_dir;
char *repository;
char *tag;
char *date;
@@ -29,6 +32,18 @@ Create_Admin (dir, repository, tag, date)
char *cp;
char tmp[PATH_MAX];
+#ifdef SERVER_SUPPORT
+ if (trace)
+ {
+ char wd[PATH_MAX];
+ getwd (wd);
+ fprintf (stderr, "%c-> Create_Admin (%s, %s, %s, %s, %s) in %s\n",
+ (server_active) ? 'S' : ' ',
+ dir, update_dir, repository, tag ? tag : "",
+ date ? date : "", wd);
+ }
+#endif
+
if (noexec)
return;
@@ -36,24 +51,9 @@ Create_Admin (dir, repository, tag, date)
(void) sprintf (tmp, "%s/%s", dir, CVSADM);
else
(void) strcpy (tmp, CVSADM);
-
if (isfile (tmp))
- error (1, 0, "there is a version here already");
- else
- {
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, OCVSADM);
- else
- (void) strcpy (tmp, OCVSADM);
-
- if (isfile (tmp))
- error (1, 0, "there is a version here already");
- }
+ error (1, 0, "there is a version in %s already", update_dir);
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, CVSADM);
- else
- (void) strcpy (tmp, CVSADM);
make_directory (tmp);
#ifdef CVSADM_ROOT
@@ -65,7 +65,14 @@ Create_Admin (dir, repository, tag, date)
(void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
else
(void) strcpy (tmp, CVSADM_REP);
- fout = open_file (tmp, "w+");
+ fout = fopen (tmp, "w+");
+ if (fout == NULL)
+ {
+ if (update_dir[0] == '\0')
+ error (1, errno, "cannot open %s", tmp);
+ else
+ error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP);
+ }
cp = repository;
strip_path (cp);
@@ -84,20 +91,54 @@ Create_Admin (dir, repository, tag, date)
}
#endif
- if (fprintf (fout, "%s\n", cp) == EOF)
- error (1, errno, "write to %s failed", tmp);
+ if (fprintf (fout, "%s\n", cp) < 0)
+ {
+ if (update_dir[0] == '\0')
+ error (1, errno, "write to %s failed", tmp);
+ else
+ error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP);
+ }
if (fclose (fout) == EOF)
- error (1, errno, "cannot close %s", tmp);
+ {
+ if (update_dir[0] == '\0')
+ error (1, errno, "cannot close %s", tmp);
+ else
+ error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP);
+ }
/* now, do the Entries file */
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
else
(void) strcpy (tmp, CVSADM_ENT);
- fout = open_file (tmp, "w+");
+ fout = fopen (tmp, "w+");
+ if (fout == NULL)
+ {
+ if (update_dir[0] == '\0')
+ error (1, errno, "cannot open %s", tmp);
+ else
+ error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT);
+ }
if (fclose (fout) == EOF)
- error (1, errno, "cannot close %s", tmp);
+ {
+ if (update_dir[0] == '\0')
+ error (1, errno, "cannot close %s", tmp);
+ else
+ error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT);
+ }
/* Create a new CVS/Tag file */
WriteTag (dir, tag, date);
+
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_sticky (update_dir, repository, tag, date);
+
+ if (trace)
+ {
+ fprintf (stderr, "%c<- Create_Admin\n",
+ (server_active) ? 'S' : ' ');
+ }
+#endif
+
}
diff --git a/gnu/usr.bin/cvs/cvs/cvs.1 b/gnu/usr.bin/cvs/cvs/cvs.1
index 749969e..5a70301 100644
--- a/gnu/usr.bin/cvs/cvs/cvs.1
+++ b/gnu/usr.bin/cvs/cvs/cvs.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: cvs.1,v 1.1.1.2 1995/03/31 07:44:48 nate Exp $
+.Id $Id: cvs.1,v 1.7 1995/11/15 01:02:41 woods Exp $
.TH CVS 1 "\*(Dt"
.\" Full space in nroff; half space in troff
.de SP
@@ -128,16 +128,28 @@ command).
There are only two situations where you may omit
.IR cvs_command :
.` "cvs \-H"
+or
+.` "cvs --help"
elicits a list of available commands, and
-.` "cvs \-v "
+.` "cvs \-v"
+or
+.` "cvs --version"
displays version information on \fBcvs\fP itself.
.SP
.SH "CVS OPTIONS"
+As of release 1.6,
+.B cvs
+supports
+.SM GNU
+style long options as well as short options. Only
+a few long options are currently supported, these are listed in
+brackets after the short options whose functions they duplicate.
+.SP
Use these options to control the overall
.B cvs
program:
.TP
-.B \-H
+.B \-H [ --help ]
Display usage information about the specified
.I cvs_command
(but do not actually execute the command). If you don't specify a
@@ -186,6 +198,11 @@ and the
.SM EDITOR
environment variables.
.TP
+.B \-f
+Do not read the
+.B cvs
+startup file (\fI~/.cvsrc\fP).
+.TP
.B \-l
Do not log the
.I cvs_command
@@ -213,7 +230,7 @@ Same effect as if the
.SM CVSREAD
environment variable is set.
.TP
-.B \-v
+.B \-v [ --version ]
Displays version and copyright information for
.BR cvs .
.TP
@@ -222,6 +239,16 @@ Makes new working files read-write (default).
Overrides the setting of the
.SM CVSREAD
environment variable.
+.TP
+\fB\-z\fP \fIcompression\-level\fP
+When transferring files across the network use
+.B gzip
+with compression level \fIcompression\-level\fP to compress and
+de-compress data as it is transferred. Requires the presence of
+the
+.SM GNU
+.B gzip
+program in the current search path at both ends of the link.
.SH "USAGE"
Except when requesting general help with
.` "cvs \-H",
@@ -237,6 +264,29 @@ However, many options are available across several commands.
You can display a usage summary for each command by specifying the
.B \-H
option with the command.
+.SH "CVS STARTUP FILE"
+Normally, when CVS starts up, it reads the
+.I .cvsrc
+file from the home directory of the user reading it. This startup
+procedure can be turned off with the
+.B \-f
+flag.
+.SP
+The
+.I .cvsrc
+file lists CVS commands with a list of arguments, one command per
+line. For example, the following line in \fI.cvsrc\fP:
+.SP
+diff \-c
+.SP
+will mean that the
+.` "cvs diff"
+command will always be passed the \-c option in addition to any
+other options that are specified in the command line (in this case
+it will have the effect of producing context sensitive diffs for
+all executions of
+.` "cvs diff"
+).
.SH "CVS COMMAND SUMMARY"
Here are brief descriptions of all the
.B cvs
@@ -343,7 +393,8 @@ file. (Does not change
repository or working directory.)
.TP
.B tag
-Specify a symbolic tag for files in the repository. Tags the revisions
+Specify a symbolic tag for files in the repository. By default, tags
+the revisions
that were last synchronized with your working directory. (Changes
repository directly; uses working directory without changing it.)
.TP
@@ -436,9 +487,9 @@ Alter the default
processing of keywords; all the
.B \-k
options described in
-.BR rcs ( 1 )
+.BR co ( 1 )
are available. The \fB\-k\fP option is available with the
-.BR add ", " checkout ", " diff ", "
+.BR add ", " checkout ", " diff ", " export ", "
.BR rdiff ", and " update
commands. Your \fIkflag\fP specification is ``sticky'' when you use
it to create a private copy of a source file; that is, when you use
@@ -446,6 +497,15 @@ this option with the \fBcheckout\fP or \fBupdate\fP commands,
\fBcvs\fP associates your selected \fIkflag\fP with the file, and
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
+.B export
+where you wish to retain keyword information after an
+.B import
+at some other site.
.TP
.B \-l
Local; run only in current working directory, rather than recurring through
@@ -508,23 +568,6 @@ rather than writing them in the current directory. Available with the
.BR checkout " and " update
commands.
.TP
-.B \-Q
-Causes the command to be
-.I really
-quiet; the command will generate output only for serious problems.
-Available with the following commands:
-.BR checkout ", " import ", " export ", "
-.BR rdiff ", " rtag ", "
-.BR tag ", and " update .
-.TP
-.B \-q
-Causes the command to be somewhat quiet; informational messages, such
-as reports of recursion through subdirectories, are suppressed.
-Available with the following commands:
-.BR checkout ", " import ", " export ", "
-.BR rtag ", "
-.BR tag ", and " update .
-.TP
\fB\-r\fP \fItag\fP
Use the revision specified by the
.I tag
@@ -553,9 +596,9 @@ can be either a symbolic or numeric tag, in
fashion.
Specifying the
.B \-q
-option along with the
+global option along with the
.B \-r
-option is often useful, to suppress the warning messages when the
+command option is often useful, to suppress the warning messages when the
.SM RCS
file does not contain the specified tag.
.B \-r
@@ -787,7 +830,7 @@ sure that it will be a sub-directory, and that
will show the relative path leading to each file as it is extracted into
your private work area (unless you specify the
.B \-Q
-option).
+global option).
.SP
Running
.` "cvs checkout"
@@ -805,11 +848,11 @@ The
permitted with
.` "cvs checkout"
include the standard command options
-.BR \-P ", " \-Q ", " \-f ", "
+.BR \-P ", " \-f ", "
.BI \-k " kflag"
\&,
.BR \-l ", " \-n ", " \-p ", "
-.BR \-q ", " \-r
+.BR \-r
.IR tag ", and"
.BI \-D " date"\c
\&.
@@ -1068,7 +1111,7 @@ differ from the corresponding revision in the source repository
.I you
have changed), or that differ from the revision specified.
.TP
-\fBexport\fP [\-\fBf\|lNnQq\fP] \fB\-r\fP \fIrev\fP\||\|\fB\-D\fP \fIdate\fP [\fB\-d\fP \fIdir\fP] \fImodule\fP.\|.\|.
+\fBexport\fP [\-\fBf\|lNnQq\fP] \fB\-r\fP \fIrev\fP\||\|\fB\-D\fP \fIdate\fP [\fB\-d\fP \fIdir\fP] [\fB\-k\fP \fIkflag\fP] \fImodule\fP.\|.\|.
.I Requires:
repository.
.br
@@ -1098,7 +1141,7 @@ These have the same meanings as the same options in
.SP
The
.B \-kv
-option is always set when
+option is useful when
.B export
is used.
This causes any
@@ -1106,7 +1149,10 @@ This causes any
keywords to be expanded such that an
.B import
done at some other site will not lose the keyword revision information.
-There is no way to override this.
+Other \fIkflag\fPs may be used with
+.` "cvs export"
+and are described in
+.BR co ( 1 ).
.TP
\fBhistory\fP [\fB\-\fP\fIreport\fP] [\fB\-\fP\fIflags\fP] [\fB\-\fP\fIoptions args\fP] [\fIfiles\fP.\|.\|.]
.I Requires:
@@ -1310,9 +1356,9 @@ least one \fIreleasetag\fP to identify the files at the leaves created
each time you execute
.` "cvs import".
.SP
-Three of the standard
+One of the standard
.B cvs
-command options are available: \fB\-Q\fP, \fB\-q\fP, and \fB\-m\fP
+command options is available: \fB\-m\fP
\fImessage\fP. If you do not specify a logging message with
\fB\-m\fP, your editor is invoked (as with \fBcommit\fP) to allow you
to enter one.
@@ -1411,8 +1457,8 @@ version \fIvn\fP (the expansion format changed with
.SM RCS
version 5).
.SP
-The standard option \fIflags\fP \fB\-f\fP, \fB\-l\fP, \fB\-Q\fP, and
-\fB\-q\fP are available with this command. There are also several
+The standard option \fIflags\fP \fB\-f\fP, and \fB\-l\fP
+are available with this command. There are also several
special options flags:
.SP
If you use the
@@ -1543,6 +1589,17 @@ should not be removed, but the
option is available as a means to remove completely obsolete symbolic names
if necessary (as might be the case for an Alpha release, say).
.SP
+.` "cvs rtag"
+will not move a tag that already exists. With the \fB\-F\fP option,
+however,
+.` "cvs rtag"
+will re-locate any instance of \fIsymbolic_tag\fP that already exists
+on that file to the new repository versions. Without the \fB\-F\fP
+option, attempting to use
+.` "cvs rtag"
+to apply a tag that already exists on that file will produce an error
+message.
+.SP
The \fB-b\fP option makes the tag a ``branch'' tag, allowing
concurrent, isolated development.
This is most useful for creating a patch to a previously released software
@@ -1564,9 +1621,6 @@ is specified; a typical use is to send electronic mail to a group of
interested parties. If you want to bypass that program, use the
standard \fB\-n\fP option.
.SP
-The standard options \fB\-Q\fP and \fB\-q\fP are also available with
-this command.
-.SP
Use the
.B \-a
option to have
@@ -1578,7 +1632,7 @@ The tag is removed from these files, which makes it convenient to re-use a
symbolic tag as development continues (and files get removed from the
up-coming distribution).
.TP
-\fBstatus\fP [\fB\-lR\fP] [\fB\-v\fP] [\fIfiles\fP\|.\|.\|.]
+\fBstatus\fP [\fB\-lRqQ\fP] [\fB\-v\fP] [\fIfiles\fP\|.\|.\|.]
.I Requires:
working directory, repository.
.br
@@ -1609,7 +1663,7 @@ option causes the symbolic tags for the
.SM RCS
file to be displayed as well.
.TP
-\fBtag\fP [\fB\-lQqR\fP] [\fB\-b\fP] [\fB\-d\fP] \fIsymbolic_tag\fP [\fIfiles\fP\|.\|.\|.\|]
+\fBtag\fP [\fB\-lQqR\fP] [\fB\-F\fP] [\fB\-b\fP] [\fB\-d\fP] [\fB\-r\fP \fItag\fP | \fB\-D\fP \fIdate\fP] [\fB\-f\fP] \fIsymbolic_tag\fP [\fIfiles\fP\|.\|.\|.\|]
.I Requires:
working directory, repository.
.br
@@ -1621,9 +1675,7 @@ repository.
.br
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, but the versions are supplied
-implicitly by the \fBcvs\fP records of your working files' history
-rather than applied explicitly.
+the repository, as with \fBrtag\fP.
.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
@@ -1633,13 +1685,28 @@ of the release need be re-tagged.
The symbolic tags are meant to permanently record which revisions of which
files were used in creating a software distribution.
The
-.B checkout
+.BR checkout ,
+.B export
and
.B update
commands allow you to extract an exact copy of a tagged release at any time in
the future, regardless of whether files have been changed, added, or removed
since the release was tagged.
.SP
+You can use the standard \fB\-r\fP and \fB\-D\fP options to tag only those
+files that already contain a certain tag. This method would be used
+to rename a tag: tag only the files identified by the old tag, then delete the
+old tag, leaving the new tag on exactly the same files as the old tag.
+.SP
+Specifying the \fB\-f\fP flag in addition to the \fB\-r\fP or \fB\-D\fP
+flags will tag those files named on the command line even if they do not
+contain the old tag or did not exist on the specified date.
+.SP
+By default (without a \fB\-r\fP or \fB\-D\fP flag)
+the versions to be tagged are supplied
+implicitly by the \fBcvs\fP records of your working files' history
+rather than applied explicitly.
+.SP
If you use
.` "cvs tag \-d \fIsymbolic_tag\fP\|.\|.\|.",
the
@@ -1649,6 +1716,17 @@ instead of being added. \fIWarning\fP: Be very certain of your ground
before you delete a tag; doing this effectively discards some
historical information, which may later turn out to have been valuable.
.SP
+.` "cvs tag"
+will not move a tag that already exists. With the \fB\-F\fP option,
+however,
+.` "cvs tag"
+will re-locate any instance of \fIsymbolic_tag\fP that already exists
+on that file to the new repository versions. Without the \fB\-F\fP
+option, attempting to use
+.` "cvs tag"
+to apply a tag that already exists on that file will produce an error
+message.
+.SP
The \fB-b\fP option makes the tag a ``branch'' tag, allowing
concurrent, isolated development.
This is most useful for creating a patch to a previously released software
@@ -1834,7 +1912,7 @@ Use
to avoid ignoring any files at all.
.SP
The standard \fBcvs\fP command options \fB\-f\fP, \fB\-k\fP,
-\fB\-l\fP, \fB\-P\fP, \fB\-p\fP, \fB\-Q\fP, \fB\-q\fP, and \fB\-r\fP
+\fB\-l\fP, \fB\-P\fP, \fB\-p\fP, and \fB\-r\fP
are also available with \fBupdate\fP.
.RE
.SH "FILES"
@@ -1844,6 +1922,27 @@ supporting files, see
.BR cvs ( 5 ).
.LP
.I
+Files in home directories:
+.TP
+\&.cvsrc
+The
+.B cvs
+initialisation file. Lines in this file can be used to specify default
+options for each
+.B cvs
+command. For example the line
+.` "diff \-c"
+will ensure that
+.` "cvs diff"
+is always passed the
+.B \-c
+option in addition to any other options passed on the command line.
+.TP
+\&.cvswrappers
+Specifies wrappers to be used in addition to those specified in the
+CVSROOT/cvswrappers file in the repository.
+.LP
+.I
Files in working directories:
.TP
CVS
@@ -1862,6 +1961,21 @@ CVS/Entries.Static
Flag: do not add more entries on
.` "cvs update".
.TP
+CVS/Root
+Pathname to the repository (
+.SM CVSROOT
+) location at the time of checkout. This file is used instead
+of the
+.SM CVSROOT
+environment variable if the environment variable is not
+set. A warning message will be issued when the contents of this
+file and the
+.SM CVSROOT
+environment variable differ. The file may be over-ridden by the
+presence of the
+.SM CVS_IGNORE_REMOTE_ROOT
+environment variable.
+.TP
CVS/Repository
Pathname to the corresponding directory in the source repository.
.TP
@@ -1896,28 +2010,44 @@ Records programs for filtering
.` "cvs commit"
requests.
.TP
+CVSROOT/cvswrappers,v
+Records
+.B cvs
+wrapper commands to be used when checking files into and out of the
+repository. Wrappers allow the file or directory to be processed
+on the way in and out of CVS. The intended uses are many, one
+possible use would be to reformat a C file before the file is checked
+in, so all of the code in the repository looks the same.
+.TP
+CVSROOT/editinfo,v
+Records programs for editing/validating
+.` "cvs commit"
+log entries.
+.TP
CVSROOT/history
Log file of \fBcvs\fP transactions.
.TP
-CVSROOT/modules,v
-Definitions for modules in this repository.
-.TP
CVSROOT/loginfo,v
Records programs for piping
.` "cvs commit"
log entries.
.TP
+CVSROOT/modules,v
+Definitions for modules in this repository.
+.TP
CVSROOT/rcsinfo,v
Records pathnames to templates used during a
.` "cvs commit"
operation.
.TP
-CVSROOT/editinfo,v
-Records programs for editing/validating
-.` "cvs commit"
-log entries.
+CVSROOT/taginfo,v
+Records programs for validating/logging
+.` "cvs tag"
+and
+.` "cvs rtag"
+operations.
.TP
-Attic
+MODULE/Attic
Directory for removed source files.
.TP
#cvs.lock
@@ -1982,7 +2112,37 @@ environment variable is used instead.
If
.SM EDITOR
is not set either, the default is
-.BR vi .
+.BR /usr/ucb/vi .
+.TP
+.SM CVS_IGNORE_REMOTE_ROOT
+If this variable is set then
+.B cvs
+will ignore all references to remote repositories in the CVS/Root file.
+.TP
+.SM CVS_RSH
+.B cvs
+uses the contents of this variable to determine the name of the
+remote shell command to use when starting a
+.B cvs
+server. If this variable is not set then
+.` "rsh"
+is used.
+.TP
+.SM CVS_SERVER
+.B cvs
+uses the contents of this variable to determine the name of the
+.B cvs
+server command. If this variable is not set then
+.` "cvs"
+is used.
+.TP
+.SM CVSWRAPPERS
+This variable is used by the
+.` "cvswrappers"
+script to determine the name of the wrapper file, in addition to the
+wrappers defaults contained in the repository
+.SM (CVSROOT/cvswrappers)
+and the user's home directory (~/.cvswrappers).
.SH "AUTHORS"
.TP
Dick Grune
@@ -2011,6 +2171,8 @@ shell script (the ancestor of
.BR ci ( 1 ),
.BR co ( 1 ),
.BR cvs ( 5 ),
+.BR cvsbug ( 8 ),
+.BR cvsinit ( 8 ),
.BR diff ( 1 ),
.BR grep ( 1 ),
.BR mkmodules ( 1 ),
diff --git a/gnu/usr.bin/cvs/cvs/cvs.h b/gnu/usr.bin/cvs/cvs/cvs.h
index 95c6a9b..34c9d8c 100644
--- a/gnu/usr.bin/cvs/cvs/cvs.h
+++ b/gnu/usr.bin/cvs/cvs/cvs.h
@@ -21,16 +21,20 @@
#ifdef _AIX
#pragma alloca
#else /* not _AIX */
+#ifdef ALLOCA_IN_STDLIB
+ /* then we need do nothing */
+#else
char *alloca ();
+#endif /* not ALLOCA_IN_STDLIB */
#endif /* not _AIX */
#endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
-#if __STDC__
-#define CONST const
+/* Changed from if __STDC__ to ifdef __STDC__ because of Sun's acc compiler */
+
+#ifdef __STDC__
#define PTR void *
#else
-#define CONST
#define PTR char *
#endif
@@ -44,17 +48,29 @@ char *alloca ();
#endif
#if __GNUC__ == 2
-#define USE(var) static char sizeof##var = sizeof(sizeof##var) + sizeof(var);
+#define USE(var) static const char sizeof##var = sizeof(sizeof##var) + sizeof(var)
#else
-#define USE(var)
+#define USE(var) static const char standalone_semis_illegal_sigh
#endif
#include <stdio.h>
+/* Under OS/2, <stdio.h> doesn't define popen()/pclose(). */
+#ifdef USE_OWN_POPEN
+#include "popen.h"
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern void exit ();
+extern char *getenv();
+#endif
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
+#endif
#ifdef HAVE_STRING_H
#include <string.h>
@@ -62,7 +78,13 @@ char *alloca ();
#include <strings.h>
#endif
-#include <fnmatch.h> /* This is supposed to be available on Posix systems */
+#ifdef SERVER_SUPPORT
+/* If the system doesn't provide strerror, it won't be declared in
+ string.h. */
+char *strerror ();
+#endif
+
+#include <fnmatch.h> /* This is supposed to be available on Posix systems */
#include <ctype.h>
#include <pwd.h>
@@ -79,6 +101,18 @@ extern int errno;
#include "system.h"
#include "hash.h"
+#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
+#include "server.h"
+#include "client.h"
+#endif
+
+#ifdef AUTH_CLIENT_SUPPORT
+extern int use_authenticating_server;
+void connect_to_pserver();
+# ifndef CVS_AUTH_PORT
+# define CVS_AUTH_PORT 2401
+# endif /* CVS_AUTH_PORT */
+#endif /* AUTH_CLIENT_SUPPORT */
#ifdef MY_NDBM
#include "myndbm.h"
@@ -90,6 +124,11 @@ extern int errno;
#include "getopt.h"
#include "wait.h"
+/* Define to enable alternate death support (which uses the RCS state). */
+#define DEATH_STATE 1
+
+#define DEATH_SUPPORT 1
+
#include "rcs.h"
@@ -111,16 +150,17 @@ extern int errno;
/*
* 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 1.4 kit.
- *
+ *
* Definitions for the CVS Administrative directory and the files it contains.
* Here as #define's to make changing the names a simple task.
*/
#define CVSADM "CVS"
#define CVSADM_ENT "CVS/Entries"
#define CVSADM_ENTBAK "CVS/Entries.Backup"
+#define CVSADM_ENTLOG "CVS/Entries.Log"
#define CVSADM_ENTSTAT "CVS/Entries.Static"
#define CVSADM_REP "CVS/Repository"
#define CVSADM_ROOT "CVS/Root"
@@ -129,14 +169,6 @@ extern int errno;
#define CVSADM_TAG "CVS/Tag"
/*
- * The following are obsolete and are maintained here only so that they can be
- * cleaned up during the transition
- */
-#define OCVSADM "CVS.adm" /* for CVS 1.2 and earlier */
-#define CVSADM_FILE "CVS/Files"
-#define CVSADM_MOD "CVS/Mod"
-
-/*
* Definitions for the CVSROOT Administrative directory and the files it
* contains. This directory is created as a sub-directory of the $CVSROOT
* environment variable, and holds global administration information for the
@@ -147,33 +179,36 @@ extern int errno;
#define CVSROOTADM_LOGINFO "loginfo"
#define CVSROOTADM_RCSINFO "rcsinfo"
#define CVSROOTADM_COMMITINFO "commitinfo"
+#define CVSROOTADM_TAGINFO "taginfo"
#define CVSROOTADM_EDITINFO "editinfo"
#define CVSROOTADM_HISTORY "history"
#define CVSROOTADM_IGNORE "cvsignore"
#define CVSROOTADM_CHECKOUTLIST "checkoutlist"
+#define CVSROOTADM_WRAPPER "cvswrappers"
#define CVSNULLREPOS "Emptydir" /* an empty directory */
/* support for the modules file (CVSROOTADM_MODULES) */
-#define CVSMODULE_OPTS "ad:i:lo:s:t:u:"/* options in modules file */
+#define CVSMODULE_OPTS "ad:i:lo:e:s:t:u:"/* options in modules file */
#define CVSMODULE_SPEC '&' /* special delimiter */
-/*
- * The following are obsolete and are maintained here only so that they can be
- * cleaned up during the transition
- */
-#define OCVSROOTADM "CVSROOT.adm" /* for CVS 1.2 and earlier */
-
/* Other CVS file names */
+
+/* Files go in the attic if the head main branch revision is dead,
+ otherwise they go in the regular repository directories. The whole
+ concept of having an attic is sort of a relic from before death
+ support but on the other hand, it probably does help the speed of
+ some operations (such as main branch checkouts and updates). */
#define CVSATTIC "Attic"
+
#define CVSLCK "#cvs.lock"
#define CVSTFL "#cvs.tfl"
#define CVSRFL "#cvs.rfl"
#define CVSWFL "#cvs.wfl"
#define CVSRFLPAT "#cvs.rfl.*" /* wildcard expr to match read locks */
-#define CVSEXT_OPT ",p"
#define CVSEXT_LOG ",t"
#define CVSPREFIX ",,"
#define CVSDOTIGNORE ".cvsignore"
+#define CVSDOTWRAPPER ".cvswrappers"
/* miscellaneous CVS defines */
#define CVSEDITPREFIX "CVS: "
@@ -181,7 +216,9 @@ extern int errno;
#define CVSLCKSLEEP 30 /* wait 30 seconds before retrying */
#define CVSBRANCH "1.1.1" /* RCS branch used for vendor srcs */
#define BAKPREFIX ".#" /* when rcsmerge'ing */
+#ifndef DEVNULL
#define DEVNULL "/dev/null"
+#endif
#define FALSE 0
#define TRUE 1
@@ -202,18 +239,23 @@ extern int errno;
/* #define RCSBIN_DFLT Set by config.h */
#define EDITOR1_ENV "CVSEDITOR" /* which editor to use */
-#define EDITOR2_ENV "EDITOR" /* which editor to use */
+#define EDITOR2_ENV "VISUAL" /* which editor to use */
+#define EDITOR3_ENV "EDITOR" /* which editor to use */
/* #define EDITOR_DFLT Set by config.h */
#define CVSROOT_ENV "CVSROOT" /* source directory root */
#define CVSROOT_DFLT NULL /* No dflt; must set for checkout */
#define IGNORE_ENV "CVSIGNORE" /* More files to ignore */
+#define WRAPPER_ENV "CVSWRAPPERS" /* name of the wrapper file */
+
+#define CVSUMASK_ENV "CVSUMASK" /* Effective umask for repository */
+/* #define CVSUMASK_DFLT Set by config.h */
/*
* If the beginning of the Repository matches the following string, strip it
* so that the output to the logfile does not contain a full pathname.
- *
+ *
* If the CVSROOT environment variable is set, it overrides this define.
*/
#define REPOS_STRIP "/master/"
@@ -229,10 +271,23 @@ extern int errno;
#define MAXLISTLEN 40000 /* For [A-Z]list holders */
#define MAXDATELEN 50 /* max length for a date */
+/* structure of a entry record */
+struct entnode
+{
+ char *user;
+ char *version;
+ char *timestamp;
+ char *options;
+ char *tag;
+ char *date;
+ char *conflict;
+};
+typedef struct entnode Entnode;
+
/* The type of request that is being done in do_module() */
enum mtype
{
- CHECKOUT, TAG, PATCH
+ CHECKOUT, TAG, PATCH, EXPORT
};
/*
@@ -251,6 +306,9 @@ enum classify_type
T_REMOVED, /* R (removed file) list */
T_REMOVE_ENTRY, /* W (removed entry) list */
T_UPTODATE, /* File is up-to-date */
+#ifdef SERVER_SUPPORT
+ T_PATCH, /* P Like C, but can patch */
+#endif
T_TITLE /* title for node type */
};
typedef enum classify_type Ctype;
@@ -258,7 +316,7 @@ typedef enum classify_type Ctype;
/*
* a struct vers_ts contains all the information about a file including the
* user and rcs file names, and the version checked out and the head.
- *
+ *
* this is usually obtained from a call to Version_TS which takes a tag argument
* for the RCS file if desired
*/
@@ -266,15 +324,16 @@ struct vers_ts
{
char *vn_user; /* rcs version user file derives from
* it can have the following special
- * values:
- * empty = no user file
+ * values:
+ * empty = no user file
* 0 = user file is new
* -vers = user file to be removed */
char *vn_rcs; /* the version for the rcs file
* (tag version?) */
+ char *vn_tag; /* the symbolic tag name */
char *ts_user; /* the timestamp for the user file */
char *ts_rcs; /* the user timestamp from entries */
- char *options; /* opts from Entries file
+ char *options; /* opts from Entries file
* (keyword expansion) */
char *ts_conflict; /* Holds time_stamp of conflict */
char *tag; /* tag stored in the Entries file */
@@ -285,7 +344,7 @@ struct vers_ts
typedef struct vers_ts Vers_TS;
/*
- * structure used for list-private storage by ParseEntries() and
+ * structure used for list-private storage by Entries_Open() and
* Version_TS().
*/
struct stickydirtag
@@ -296,15 +355,6 @@ struct stickydirtag
char *options;
};
-/* flags for run_exec(), the fast system() for CVS */
-#define RUN_NORMAL 0x0000 /* no special behaviour */
-#define RUN_COMBINED 0x0001 /* stdout is duped to stderr */
-#define RUN_REALLY 0x0002 /* do the exec, even if noexec is on */
-#define RUN_STDOUT_APPEND 0x0004 /* append to stdout, don't truncate */
-#define RUN_STDERR_APPEND 0x0008 /* append to stderr, don't truncate */
-#define RUN_SIGIGNORE 0x0010 /* ignore interrupts for command */
-#define RUN_TTY (char *)0 /* for the benefit of lint */
-
/* Flags for find_{names,dirs} routines */
#define W_LOCAL 0x01 /* look for files locally */
#define W_REPOS 0x02 /* look for files in the repository */
@@ -320,7 +370,7 @@ enum direnter_type
};
typedef enum direnter_type Dtype;
-extern char *program_name, *command_name;
+extern char *program_name, *program_path, *command_name;
extern char *Rcsbin, *Editor, *CVSroot;
#ifdef CVSADM_ROOT
extern char *CVSADM_Root;
@@ -330,17 +380,29 @@ extern char *CurDir;
extern int really_quiet, quiet;
extern int use_editor;
extern int cvswrite;
+extern mode_t cvsumask;
extern int trace; /* Show all commands */
extern int noexec; /* Don't modify disk anywhere */
extern int logoff; /* Don't write history entry */
+extern char hostname[];
+
/* Externs that are included directly in the CVS sources */
+int RCS_settag PROTO((const char *, const char *, const char *));
+int RCS_deltag PROTO((const char *, const char *, int));
+int RCS_setbranch PROTO((const char *, const char *));
+int RCS_lock PROTO((const char *, const char *, int));
+int RCS_unlock PROTO((const char *, const char *, int));
+int RCS_merge PROTO((const char *, const char *, const char *, const char *));
+
+#include "error.h"
+
DBM *open_module PROTO((void));
-FILE *Fopen PROTO((char *name, char *mode));
-FILE *open_file PROTO((char *name, char *mode));
+FILE *open_file PROTO((const char *, const char *));
List *Find_Dirs PROTO((char *repository, int which));
-List *ParseEntries PROTO((int aflag));
+void Entries_Close PROTO((List *entries));
+List *Entries_Open PROTO((int aflag));
char *Make_Date PROTO((char *rawdate));
char *Name_Repository PROTO((char *dir, char *update_dir));
#ifdef CVSADM_ROOT
@@ -354,29 +416,37 @@ char *getcaller PROTO((void));
char *time_stamp PROTO((char *file));
char *xmalloc PROTO((size_t bytes));
char *xrealloc PROTO((char *ptr, size_t bytes));
-char *xstrdup PROTO((char *str));
+char *xstrdup PROTO((const char *str));
+void strip_trailing_newlines PROTO((char *str));
int No_Difference PROTO((char *file, Vers_TS * vers, List * entries,
char *repository, char *update_dir));
-int Parse_Info PROTO((char *infofile, char *repository, int PROTO((*callproc)) PROTO(()), int all));
+typedef int (*CALLPROC) PROTO((char *repository, char *value));
+int Parse_Info PROTO((char *infofile, char *repository, CALLPROC callproc, int all));
int Reader_Lock PROTO((char *xrepository));
-int SIG_register PROTO((int sig, RETSIGTYPE PROTO((*fn)) PROTO(())));
+typedef RETSIGTYPE (*SIGCLEANUPPROC) PROTO(());
+int SIG_register PROTO((int sig, SIGCLEANUPPROC sigcleanup));
int Writer_Lock PROTO((List * list));
int ign_name PROTO((char *name));
-int isdir PROTO((char *file));
-int isfile PROTO((char *file));
-int islink PROTO((char *file));
-int isreadable PROTO((char *file));
-int iswritable PROTO((char *file));
+int isdir PROTO((const char *file));
+int isfile PROTO((const char *file));
+int islink PROTO((const char *file));
+int isreadable PROTO((const char *file));
+int iswritable PROTO((const char *file));
+int isaccessible PROTO((const char *file, const int mode));
+int isabsolute PROTO((const char *filename));
+char *last_component PROTO((char *path));
+
int joining PROTO((void));
-int link_file PROTO((char *from, char *to));
-int numdots PROTO((char *s));
-int run_exec PROTO((char *stin, char *stout, char *sterr, int flags));
-int unlink_file PROTO((char *f));
+int numdots PROTO((const char *s));
+int unlink_file PROTO((const char *f));
+int unlink_file_dir PROTO((const char *f));
int update PROTO((int argc, char *argv[]));
-int xcmp PROTO((char *file1, char *file2));
+int xcmp PROTO((const char *file1, const char *file2));
int yesno PROTO((void));
+void *valloc PROTO((size_t bytes));
time_t get_date PROTO((char *date, struct timeb *now));
-void Create_Admin PROTO((char *dir, char *repository, char *tag, char *date));
+void Create_Admin PROTO((char *dir, char *update_dir,
+ char *repository, char *tag, char *date));
void Lock_Cleanup PROTO((void));
void ParseTag PROTO((char **tagp, char **datep));
void Scratch_Entry PROTO((List * list, char *fname));
@@ -384,8 +454,8 @@ void WriteTag PROTO((char *dir, char *tag, char *date));
void cat_module PROTO((int status));
void check_entries PROTO((char *dir));
void close_module PROTO((DBM * db));
-void copy_file PROTO((char *from, char *to));
-void error PROTO((int status, int errnum, char *message,...));
+void copy_file PROTO((const char *from, const char *to));
+void (*error_set_cleanup PROTO((void (*) (void)))) PROTO ((void));
void fperror PROTO((FILE * fp, int status, int errnum, char *message,...));
void free_names PROTO((int *pargc, char *argv[]));
void freevers_ts PROTO((Vers_TS ** versp));
@@ -395,20 +465,18 @@ void ign_setup PROTO((void));
void ign_dir_add PROTO((char *name));
int ignore_directory PROTO((char *name));
void line2argv PROTO((int *pargc, char *argv[], char *line));
-void make_directories PROTO((char *name));
-void make_directory PROTO((char *name));
-void rename_file PROTO((char *from, char *to));
-void run_arg PROTO((char *s));
-void run_args PROTO((char *fmt,...));
-void run_print PROTO((FILE * fp));
-void run_setup PROTO((char *fmt,...));
+void make_directories PROTO((const char *name));
+void make_directory PROTO((const char *name));
+void rename_file PROTO((const char *from, const char *to));
void strip_path PROTO((char *path));
void strip_trailing_slashes PROTO((char *path));
void update_delproc PROTO((Node * p));
-void usage PROTO((char **cpp));
+void usage PROTO((const char *const *cpp));
void xchmod PROTO((char *fname, int writable));
-int Checkin PROTO((int type, char *file, char *repository, char *rcs, char *rev,
- char *tag, char *options, char *message, List *entries));
+char *xgetwd PROTO((void));
+int Checkin PROTO((int type, char *file, char *update_dir,
+ char *repository, char *rcs, char *rev,
+ char *tag, char *options, char *message, List *entries));
Ctype Classify_File PROTO((char *file, char *tag, char *date, char *options,
int force_tag_match, int aflag, char *repository,
List *entries, List *srcfiles, Vers_TS **versp,
@@ -424,11 +492,21 @@ Vers_TS *Version_TS PROTO((char *repository, char *options, char *tag,
int set_time, List * entries, List * xfiles));
void do_editor PROTO((char *dir, char **messagep,
char *repository, List * changes));
+
+typedef int (*CALLBACKPROC) PROTO((int *pargc, char *argv[], char *where,
+ char *mwhere, char *mfile, int horten, int local_specified,
+ char *omodule, char *msg));
+typedef int (*FILEPROC) PROTO((char *file, char *update_dir, char *repository,
+ List * entries, List * srcfiles));
+typedef int (*FILESDONEPROC) PROTO((int err, char *repository, char *update_dir));
+typedef Dtype (*DIRENTPROC) PROTO((char *dir, char *repos, char *update_dir));
+typedef int (*DIRLEAVEPROC) PROTO((char *dir, int err, char *update_dir));
+
int do_module PROTO((DBM * db, char *mname, enum mtype m_type, char *msg,
- int PROTO((*callback_proc)) (), char *where, int shorten,
- int local_specified, int run_module_prog, char *extra_arg));
-int do_recursion PROTO((int PROTO((*xfileproc)) (), int PROTO((*xfilesdoneproc)) (),
- Dtype PROTO((*xdirentproc)) (), int PROTO((*xdirleaveproc)) (),
+ CALLBACKPROC callback_proc, char *where, int shorten,
+ int local_specified, int run_module_prog, char *extra_arg));
+int do_recursion PROTO((FILEPROC xfileproc, FILESDONEPROC xfilesdoneproc,
+ DIRENTPROC xdirentproc, DIRLEAVEPROC xdirleaveproc,
Dtype xflags, int xwhich, int xaflag, int xreadlock,
int xdosrcs));
int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
@@ -437,11 +515,56 @@ int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir));
void history_write PROTO((int type, char *update_dir, char *revs, char *name,
char *repository));
-int start_recursion PROTO((int PROTO((*fileproc)) (), int PROTO((*filesdoneproc)) (),
- Dtype PROTO((*direntproc)) (), int PROTO((*dirleaveproc)) (),
+int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
+ DIRENTPROC direntproc, DIRLEAVEPROC dirleaveproc,
int argc, char *argv[], int local, int which,
int aflag, int readlock, char *update_preload,
int dosrcs, int wd_is_repos));
void SIG_beginCrSect PROTO((void));
void SIG_endCrSect PROTO((void));
void read_cvsrc PROTO((int *argc, char ***argv));
+
+char *make_message_rcslegal PROTO((char *message));
+
+/* flags for run_exec(), the fast system() for CVS */
+#define RUN_NORMAL 0x0000 /* no special behaviour */
+#define RUN_COMBINED 0x0001 /* stdout is duped to stderr */
+#define RUN_REALLY 0x0002 /* do the exec, even if noexec is on */
+#define RUN_STDOUT_APPEND 0x0004 /* append to stdout, don't truncate */
+#define RUN_STDERR_APPEND 0x0008 /* append to stderr, don't truncate */
+#define RUN_SIGIGNORE 0x0010 /* ignore interrupts for command */
+#define RUN_TTY (char *)0 /* for the benefit of lint */
+
+void run_arg PROTO((const char *s));
+void run_print PROTO((FILE * fp));
+#ifdef HAVE_VPRINTF
+void run_setup PROTO((const char *fmt,...));
+void run_args PROTO((const char *fmt,...));
+#else
+void run_setup ();
+void run_args ();
+#endif
+int run_exec PROTO((char *stin, char *stout, char *sterr, int flags));
+
+/* other similar-minded stuff from run.c. */
+FILE *Popen PROTO((const char *, const char *));
+int piped_child PROTO((char **, int *, int *));
+void close_on_exec PROTO((int));
+int filter_stream_through_program PROTO((int, int, char **, pid_t *));
+
+pid_t waitpid PROTO((pid_t, int *, int));
+
+/* Wrappers. */
+
+typedef enum { WRAP_MERGE, WRAP_COPY } WrapMergeMethod;
+typedef enum { WRAP_TOCVS, WRAP_FROMCVS, WRAP_CONFLICT } WrapMergeHas;
+
+void wrap_setup PROTO((void));
+int wrap_name_has PROTO((const char *name,WrapMergeHas has));
+char *wrap_tocvs_process_file PROTO((const char *fileName));
+int wrap_merge_is_copy PROTO((const char *fileName));
+char *wrap_fromcvs_process_file PROTO((const char *fileName));
+/* Pathname expansion */
+char *expand_path PROTO((char *name));
+void wrap_add_file PROTO((const char *file,int temp));
+void wrap_add PROTO((char *line,int temp));
diff --git a/gnu/usr.bin/cvs/cvs/cvsrc.c b/gnu/usr.bin/cvs/cvs/cvsrc.c
index fedd020..5882afc 100644
--- a/gnu/usr.bin/cvs/cvs/cvsrc.c
+++ b/gnu/usr.bin/cvs/cvs/cvsrc.c
@@ -10,10 +10,11 @@
#include "cvs.h"
+#include "getline.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)cvsrc.c 1.9 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)cvsrc.c 1.9 94/09/30 $";
+USE(rcsid);
#endif /* lint */
/* this file is to be found in the user's home directory */
@@ -25,7 +26,6 @@ char cvsrc[] = CVSRC_FILENAME;
#define GROW 10
-extern char *getenv ();
extern char *strtok ();
void
@@ -37,10 +37,13 @@ read_cvsrc (argc, argv)
char *homeinit;
FILE *cvsrcfile;
- char linebuf [MAXLINELEN];
-
+ char *line;
+ int line_length;
+ size_t line_chars_allocated;
+
char *optstart;
+ int command_len;
int found = 0;
int i;
@@ -73,7 +76,7 @@ read_cvsrc (argc, argv)
/* if it can't be read, there's no point to continuing */
- if (access (homeinit, R_OK) != 0)
+ if (!isreadable (homeinit))
{
free (homeinit);
return;
@@ -81,15 +84,20 @@ read_cvsrc (argc, argv)
/* now scan the file until we find the line for the command in question */
+ line = NULL;
+ line_chars_allocated = 0;
+ command_len = strlen (command_name);
cvsrcfile = open_file (homeinit, "r");
- while (fgets (linebuf, MAXLINELEN, cvsrcfile))
+ while ((line_length = getline (&line, &line_chars_allocated, cvsrcfile))
+ >= 0)
{
/* skip over comment lines */
- if (linebuf[0] == '#')
+ if (line[0] == '#')
continue;
/* stop if we match the current command */
- if (!strncmp (linebuf, (*argv)[0], strlen ((*argv)[0])))
+ if (!strncmp (line, command_name, command_len)
+ && isspace (*(line + command_len)))
{
found = 1;
break;
@@ -101,8 +109,8 @@ read_cvsrc (argc, argv)
if (found)
{
/* skip over command in the options line */
- optstart = strtok(linebuf+strlen((*argv)[0]), "\t \n");
-
+ optstart = strtok (line + command_len, "\t \n");
+
do
{
new_argv [new_argc] = xstrdup (optstart);
@@ -121,9 +129,12 @@ read_cvsrc (argc, argv)
}
}
- while (optstart = strtok (NULL, "\t \n"));
+ while ((optstart = strtok (NULL, "\t \n")) != NULL);
}
+ if (line != NULL)
+ free (line);
+
/* now copy the remaining arguments */
for (i=1; i < *argc; i++)
diff --git a/gnu/usr.bin/cvs/cvs/diff.c b/gnu/usr.bin/cvs/cvs/diff.c
index 99d8c18..22fda75 100644
--- a/gnu/usr.bin/cvs/cvs/diff.c
+++ b/gnu/usr.bin/cvs/cvs/diff.c
@@ -17,8 +17,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)diff.c 1.61 94/10/22 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)diff.c 1.61 94/10/22 $";
+USE(rcsid);
#endif
static Dtype diff_dirproc PROTO((char *dir, char *pos_repos, char *update_dir));
@@ -33,12 +33,19 @@ static void diff_mark_errors PROTO((int err));
static char *diff_rev1, *diff_rev2;
static char *diff_date1, *diff_date2;
static char *use_rev1, *use_rev2;
+
+#ifdef SERVER_SUPPORT
+/* Revision of the user file, if it is unchanged from something in the
+ repository and we want to use that fact. */
+static char *user_file_rev;
+#endif
+
static char *options;
static char opts[PATH_MAX];
static int diff_errors;
static int empty_files = 0;
-static char *diff_usage[] =
+static const char *const diff_usage[] =
{
"Usage: %s %s [-lN] [rcsdiff-options]\n",
#ifdef CVS_DIFFDATE
@@ -58,7 +65,7 @@ static char *diff_usage[] =
int
diff (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
char tmp[50];
int c, err = 0;
@@ -73,6 +80,11 @@ diff (argc, argv)
* intercept the -r arguments for doing revision diffs; and -l/-R for a
* non-recursive/recursive diff.
*/
+#ifdef SERVER_SUPPORT
+ /* Need to be able to do this command more than once (according to
+ the protocol spec, even if the current client doesn't use it). */
+ opts[0] = '\0';
+#endif
optind = 1;
while ((c = getopt (argc, argv,
"abcdefhilnpqtuw0123456789BHNQRTC:D:F:I:L:V:k:r:")) != -1)
@@ -150,10 +162,63 @@ diff (argc, argv)
if (!options)
options = xstrdup ("");
+#ifdef CLIENT_SUPPORT
+ if (client_active) {
+ /* We're the client side. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ if (local)
+ send_arg("-l");
+ if (empty_files)
+ send_arg("-N");
+ send_option_string (opts);
+ if (diff_rev1)
+ option_with_arg ("-r", diff_rev1);
+ if (diff_date1)
+ client_senddate (diff_date1);
+ if (diff_rev2)
+ option_with_arg ("-r", diff_rev2);
+ if (diff_date2)
+ client_senddate (diff_date2);
+
+#if 0
+/* FIXME: We shouldn't have to send current files to diff two revs, but it
+ doesn't work yet and I haven't debugged it. So send the files --
+ it's slower but it works. gnu@cygnus.com Apr94 */
+
+/* Idea: often times the changed region of a file is relatively small.
+ It would be cool if the client could just divide the file into 4k
+ blocks or whatever and send hash values for the blocks. Send hash
+ values for blocks aligned with the beginning of the file and the
+ end of the file. Then the server can tell how much of the head and
+ tail of the file is unchanged. Well, hash collisions will screw
+ things up, but MD5 has 128 bits of hash value... */
+
+ /* Send the current files unless diffing two revs from the archive */
+ if (diff_rev2 == NULL && diff_date2 == NULL)
+ send_files (argc, argv, local);
+ else
+ send_file_names (argc, argv);
+#else
+ send_files (argc, argv, local, 0);
+#endif
+
+ if (fprintf (to_server, "diff\n") < 0)
+ error (1, errno, "writing to server");
+ err = get_responses_and_close ();
+ free (options);
+ return (err);
+ }
+#endif
+
which = W_LOCAL;
if (diff_rev2 != NULL || diff_date2 != NULL)
which |= W_REPOS | W_ATTIC;
+ wrap_setup ();
+
/* start the recursion processor */
err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc,
diff_dirleaveproc, argc, argv, local,
@@ -185,7 +250,12 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
DIFF_NEITHER
} empty_file = DIFF_NEITHER;
char tmp[L_tmpnam+1];
+ char *tocvsPath;
+ char fname[PATH_MAX];
+#ifdef SERVER_SUPPORT
+ user_file_rev = 0;
+#endif
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
file, 1, 0, entries, srcfiles);
@@ -243,6 +313,15 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
diff_mark_errors (err);
return (err);
}
+#ifdef SERVER_SUPPORT
+ else if (!strcmp (vers->ts_user, vers->ts_rcs))
+ {
+ /* The user file matches some revision in the repository
+ Diff against the repository (for remote CVS, we might not
+ have a copy of the user file around). */
+ user_file_rev = vers->vn_user;
+ }
+#endif
}
}
@@ -252,6 +331,11 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
return (0);
}
+#ifdef DEATH_SUPPORT
+ /* FIXME: Check whether use_rev1 and use_rev2 are dead and deal
+ accordingly. */
+#endif
+
/* Output an "Index:" line for patch to use */
(void) fflush (stdout);
if (update_dir[0])
@@ -260,6 +344,19 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
(void) printf ("Index: %s\n", file);
(void) fflush (stdout);
+ tocvsPath = wrap_tocvs_process_file(file);
+ if (tocvsPath)
+ {
+ /* Backup the current version of the file to CVS/,,filename */
+ sprintf(fname,"%s/%s%s",CVSADM, CVSPREFIX, file);
+ if (unlink_file_dir (fname) < 0)
+ if (! existence_error (errno))
+ error (1, errno, "cannot remove %s", file);
+ rename_file (file, fname);
+ /* Copy the wrapped file to the current directory then go to work */
+ copy_file (tocvsPath, file);
+ }
+
if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
{
(void) printf ("===================================================================\nRCS file: %s\n",
@@ -320,6 +417,17 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
break;
}
+ if (tocvsPath)
+ {
+ if (unlink_file_dir (file) < 0)
+ if (! existence_error (errno))
+ error (1, errno, "cannot remove %s", file);
+
+ rename_file (fname,file);
+ if (unlink_file (tocvsPath) < 0)
+ error (1, errno, "cannot remove %s", file);
+ }
+
if (empty_file == DIFF_REMOVED)
(void) unlink (tmp);
@@ -342,6 +450,8 @@ diff_mark_errors (err)
/*
* Print a warm fuzzy message when we enter a dir
+ *
+ * Don't try to diff directories that don't exist! -- DW
*/
/* ARGSUSED */
static Dtype
@@ -351,6 +461,11 @@ diff_dirproc (dir, pos_repos, update_dir)
char *update_dir;
{
/* XXX - check for dirs we don't want to process??? */
+
+ /* YES ... for instance dirs that don't exist!!! -- DW */
+ if (!isdir (dir) )
+ return (R_SKIP_ALL);
+
if (!quiet)
error (0, 0, "Diffing %s", update_dir);
return (R_PROCESS);
@@ -414,8 +529,11 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
diff_date1, file, 1, 0, entries, srcfiles);
if (xvers->vn_rcs == NULL)
{
- if (diff_rev1)
- error (0, 0, "tag %s is not in file %s", diff_rev1, file);
+ /* Don't gripe if it doesn't exist, just ignore! */
+ if (! isfile (file))
+ /* null statement */ ;
+ else if (diff_rev1)
+ error (0, 0, "tag %s is not in file %s", diff_rev1, file);
else
error (0, 0, "no revision for date %s in file %s",
diff_date1, file);
@@ -436,7 +554,10 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
diff_date2, file, 1, 0, entries, srcfiles);
if (xvers->vn_rcs == NULL)
{
- if (diff_rev1)
+ /* Don't gripe if it doesn't exist, just ignore! */
+ if (! isfile (file))
+ /* null statement */ ;
+ else if (diff_rev1)
error (0, 0, "tag %s is not in file %s", diff_rev2, file);
else
error (0, 0, "no revision for date %s in file %s",
@@ -455,6 +576,24 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
return (1);
}
}
+#ifdef SERVER_SUPPORT
+ if (user_file_rev)
+ {
+ /* drop user_file_rev into first unused use_rev */
+ if (!use_rev1)
+ use_rev1 = xstrdup (user_file_rev);
+ else if (!use_rev2)
+ use_rev2 = xstrdup (user_file_rev);
+ /* and if not, it wasn't needed anyhow */
+ user_file_rev = 0;
+ }
+
+ /* now, see if we really need to do the diff */
+ if (use_rev1 && use_rev2)
+ {
+ return (strcmp (use_rev1, use_rev2) == 0);
+ }
+#endif /* SERVER_SUPPORT */
if (use_rev1 == NULL || strcmp (use_rev1, vers->vn_user) == 0)
{
if (strcmp (vers->ts_rcs, vers->ts_user) == 0 &&
diff --git a/gnu/usr.bin/cvs/cvs/entries.c b/gnu/usr.bin/cvs/cvs/entries.c
index 0dfd165..7ae3e58 100644
--- a/gnu/usr.bin/cvs/cvs/entries.c
+++ b/gnu/usr.bin/cvs/cvs/entries.c
@@ -12,53 +12,81 @@
*/
#include "cvs.h"
+#include "getline.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $";
+USE(rcsid);
#endif
-static Node *AddEntryNode PROTO((List * list, char *name, char *version,
- char *timestamp, char *options, char *tag,
- char *date, char *conflict));
+static Node *AddEntryNode PROTO((List * list, Entnode *entnode));
+
+static Entnode *fgetentent PROTO((FILE *));
+static int fputentent PROTO((FILE *, Entnode *));
static FILE *entfile;
static char *entfilename; /* for error messages */
/*
+ * Construct an Entnode
+ */
+Entnode *
+Entnode_Create(user, vn, ts, options, tag, date, ts_conflict)
+ const char *user;
+ const char *vn;
+ const char *ts;
+ const char *options;
+ const char *tag;
+ const char *date;
+ const char *ts_conflict;
+{
+ Entnode *ent;
+
+ /* Note that timestamp and options must be non-NULL */
+ ent = (Entnode *) xmalloc (sizeof (Entnode));
+ ent->user = xstrdup (user);
+ ent->version = xstrdup (vn);
+ ent->timestamp = xstrdup (ts ? ts : "");
+ ent->options = xstrdup (options ? options : "");
+ ent->tag = xstrdup (tag);
+ ent->date = xstrdup (date);
+ ent->conflict = xstrdup (ts_conflict);
+
+ return ent;
+}
+
+/*
+ * Destruct an Entnode
+ */
+void
+Entnode_Destroy (ent)
+ Entnode *ent;
+{
+ free (ent->user);
+ free (ent->version);
+ free (ent->timestamp);
+ free (ent->options);
+ if (ent->tag)
+ free (ent->tag);
+ if (ent->date)
+ free (ent->date);
+ if (ent->conflict)
+ free (ent->conflict);
+ free (ent);
+}
+
+/*
* Write out the line associated with a node of an entries file
*/
+static int write_ent_proc PROTO ((Node *, void *));
static int
write_ent_proc (node, closure)
Node *node;
void *closure;
{
- Entnode *p;
-
- p = (Entnode *) node->data;
- if (fprintf (entfile, "/%s/%s/%s", node->key, p->version,
- p->timestamp) == EOF)
- error (1, errno, "cannot write %s", entfilename);
- if (p->conflict)
- {
- if (fprintf (entfile, "+%s", p->conflict) == EOF)
- error (1, errno, "cannot write %s", entfilename);
- }
- if (fprintf (entfile, "/%s/", p->options) == EOF)
+ if (fputentent(entfile, (Entnode *) node->data))
error (1, errno, "cannot write %s", entfilename);
- if (p->tag)
- {
- if (fprintf (entfile, "T%s\n", p->tag) == EOF)
- error (1, errno, "cannot write %s", entfilename);
- }
- else if (p->date)
- {
- if (fprintf (entfile, "D%s\n", p->date) == EOF)
- error (1, errno, "cannot write %s", entfilename);
- }
- else if (fprintf (entfile, "\n") == EOF)
- error (1, errno, "cannot write %s", entfilename);
return (0);
}
@@ -79,6 +107,9 @@ write_entries (list)
/* now, atomically (on systems that support it) rename it */
rename_file (entfilename, CVSADM_ENT);
+
+ /* now, remove the log file */
+ unlink_file (CVSADM_ENTLOG);
}
/*
@@ -92,12 +123,21 @@ Scratch_Entry (list, fname)
Node *node;
if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> Scratch_Entry(%s)\n",
+ (server_active) ? 'S' : ' ', fname);
+#else
(void) fprintf (stderr, "-> Scratch_Entry(%s)\n", fname);
+#endif
/* hashlookup to see if it is there */
if ((node = findnode (list, fname)) != NULL)
{
delnode (node); /* delete the node */
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_scratch (fname);
+#endif
if (!noexec)
write_entries (list); /* re-write the file */
}
@@ -118,45 +158,43 @@ Register (list, fname, vn, ts, options, tag, date, ts_conflict)
char *date;
char *ts_conflict;
{
- int should_write_file = !noexec;
+ Entnode *entnode;
Node *node;
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ server_register (fname, vn, ts, options, tag, date, ts_conflict);
+ }
+#endif
+
if (trace)
{
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
+ (server_active) ? 'S' : ' ',
+ fname, vn, ts ? ts : "",
+ ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
+ options, tag ? tag : "", date ? date : "");
+#else
(void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
- fname, vn, ts,
+ fname, vn, ts ? ts : "",
ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
- options, tag ? tag : "", date ? date : "");
+ options, tag ? tag : "", date ? date : "");
+#endif
}
- /* was it already there? */
- if ((node = findnode (list, fname)) != NULL)
- {
- /* take it out */
- delnode (node);
+ entnode = Entnode_Create(fname, vn, ts, options, tag, date, ts_conflict);
+ node = AddEntryNode (list, entnode);
- /* add the new one and re-write the file */
- (void) AddEntryNode (list, fname, vn, ts, options, tag,
- date, ts_conflict);
-
- if (should_write_file)
- write_entries (list);
- }
- else
+ if (!noexec)
{
- /* add the new one */
- node = AddEntryNode (list, fname, vn, ts, options, tag,
- date, ts_conflict);
+ entfile = open_file (CVSADM_ENTLOG, "a");
+
+ write_ent_proc (node, NULL);
- if (should_write_file)
- {
- /* append it to the end */
- entfilename = CVSADM_ENT;
- entfile = open_file (entfilename, "a");
- (void) write_ent_proc (node, NULL);
- if (fclose (entfile) == EOF)
- error (1, errno, "error closing %s", entfilename);
- }
+ if (fclose (entfile) == EOF)
+ error (1, errno, "error closing %s", CVSADM_ENTLOG);
}
}
@@ -179,24 +217,138 @@ freesdt (p)
free ((char *) sdtp);
}
+static Entnode *
+fgetentent(fpin)
+ FILE *fpin;
+{
+ Entnode *ent;
+ char *line;
+ size_t line_chars_allocated;
+ register char *cp;
+ char *user, *vn, *ts, *options;
+ char *tag_or_date, *tag, *date, *ts_conflict;
+
+ line = NULL;
+ line_chars_allocated = 0;
+
+ ent = NULL;
+ while (getline (&line, &line_chars_allocated, fpin) > 0)
+ {
+ if (line[0] != '/')
+ continue;
+
+ user = line + 1;
+ if ((cp = strchr (user, '/')) == NULL)
+ continue;
+ *cp++ = '\0';
+ vn = cp;
+ if ((cp = strchr (vn, '/')) == NULL)
+ continue;
+ *cp++ = '\0';
+ ts = cp;
+ if ((cp = strchr (ts, '/')) == NULL)
+ continue;
+ *cp++ = '\0';
+ options = cp;
+ if ((cp = strchr (options, '/')) == NULL)
+ continue;
+ *cp++ = '\0';
+ tag_or_date = cp;
+ if ((cp = strchr (tag_or_date, '\n')) == NULL)
+ continue;
+ *cp = '\0';
+ tag = (char *) NULL;
+ date = (char *) NULL;
+ if (*tag_or_date == 'T')
+ tag = tag_or_date + 1;
+ else if (*tag_or_date == 'D')
+ date = tag_or_date + 1;
+
+ if ((ts_conflict = strchr (ts, '+')))
+ *ts_conflict++ = '\0';
+
+ /*
+ * XXX - Convert timestamp from old format to new format.
+ *
+ * If the timestamp doesn't match the file's current
+ * mtime, we'd have to generate a string that doesn't
+ * match anyways, so cheat and base it on the existing
+ * string; it doesn't have to match the same mod time.
+ *
+ * For an unmodified file, write the correct timestamp.
+ */
+ {
+ struct stat sb;
+ if (strlen (ts) > 30 && stat (user, &sb) == 0)
+ {
+ char *c = ctime (&sb.st_mtime);
+
+ if (!strncmp (ts + 25, c, 24))
+ ts = time_stamp (user);
+ else
+ {
+ ts += 24;
+ ts[0] = '*';
+ }
+ }
+ }
+
+ ent = Entnode_Create(user, vn, ts, options, tag, date, ts_conflict);
+ break;
+ }
+
+ free (line);
+ return ent;
+}
+
+static int
+fputentent(fp, p)
+ FILE *fp;
+ Entnode *p;
+{
+ if (fprintf (fp, "/%s/%s/%s", p->user, p->version, p->timestamp) < 0)
+ return 1;
+ if (p->conflict)
+ {
+ if (fprintf (fp, "+%s", p->conflict) < 0)
+ return 1;
+ }
+ if (fprintf (fp, "/%s/", p->options) < 0)
+ return 1;
+
+ if (p->tag)
+ {
+ if (fprintf (fp, "T%s\n", p->tag) < 0)
+ return 1;
+ }
+ else if (p->date)
+ {
+ if (fprintf (fp, "D%s\n", p->date) < 0)
+ return 1;
+ }
+ else
+ {
+ if (fprintf (fp, "\n") < 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
/*
* Read the entries file into a list, hashing on the file name.
*/
List *
-ParseEntries (aflag)
+Entries_Open (aflag)
int aflag;
{
List *entries;
- char line[MAXLINELEN];
- char *cp, *user, *vn, *ts, *options;
- char *tag_or_date, *tag, *date, *ts_conflict;
+ Entnode *ent;
char *dirtag, *dirdate;
- int lineno = 0;
int do_rewrite = 0;
FILE *fpin;
- vn = ts = options = tag = date = ts_conflict = 0;
-
/* get a fresh list... */
entries = getlist ();
@@ -220,89 +372,28 @@ ParseEntries (aflag)
entries->list->delproc = freesdt;
}
- again:
fpin = fopen (CVSADM_ENT, "r");
if (fpin == NULL)
error (0, errno, "cannot open %s for reading", CVSADM_ENT);
else
{
- while (fgets (line, sizeof (line), fpin) != NULL)
+ while ((ent = fgetentent (fpin)) != NULL)
{
- lineno++;
- if (line[0] == '/')
- {
- user = line + 1;
- if ((cp = strchr (user, '/')) == NULL)
- continue;
- *cp++ = '\0';
- vn = cp;
- if ((cp = strchr (vn, '/')) == NULL)
- continue;
- *cp++ = '\0';
- ts = cp;
- if ((cp = strchr (ts, '/')) == NULL)
- continue;
- *cp++ = '\0';
- options = cp;
- if ((cp = strchr (options, '/')) == NULL)
- continue;
- *cp++ = '\0';
- tag_or_date = cp;
- if ((cp = strchr (tag_or_date, '\n')) == NULL)
- continue;
- *cp = '\0';
- tag = (char *) NULL;
- date = (char *) NULL;
- if (*tag_or_date == 'T')
- tag = tag_or_date + 1;
- else if (*tag_or_date == 'D')
- date = tag_or_date + 1;
-
- if (ts_conflict = strchr (ts, '+'))
- *ts_conflict++ = '\0';
-
- /*
- * XXX - Convert timestamp from old format to new format.
- *
- * If the timestamp doesn't match the file's current
- * mtime, we'd have to generate a string that doesn't
- * match anyways, so cheat and base it on the existing
- * string; it doesn't have to match the same mod time.
- *
- * For an unmodified file, write the correct timestamp.
- */
- {
- struct stat sb;
- if (strlen (ts) > 30 && stat (user, &sb) == 0)
- {
- extern char *ctime ();
- char *c = ctime (&sb.st_mtime);
-
- if (!strncmp (ts + 25, c, 24))
- ts = time_stamp (user);
- else
- {
- ts += 24;
- ts[0] = '*';
- }
- do_rewrite = 1;
- }
- }
+ (void) AddEntryNode (entries, ent);
+ }
- (void) AddEntryNode (entries, user, vn, ts, options, tag,
- date, ts_conflict);
- }
- else
- {
- /* try conversion only on first line */
- if (lineno == 1)
- {
- (void) fclose (fpin);
- check_entries ((char *) NULL);
- goto again;
- }
- }
+ fclose (fpin);
+ }
+
+ fpin = fopen (CVSADM_ENTLOG, "r");
+ if (fpin != NULL)
+ {
+ while ((ent = fgetentent (fpin)) != NULL)
+ {
+ (void) AddEntryNode (entries, ent);
}
+ do_rewrite = 1;
+ fclose (fpin);
}
if (do_rewrite && !noexec)
@@ -318,92 +409,22 @@ ParseEntries (aflag)
return (entries);
}
-/*
- * Look at the entries file to determine if it is in the old entries format.
- * If so, convert it to the new format.
- */
void
-check_entries (dir)
- char *dir;
+Entries_Close(list)
+ List *list;
{
- FILE *fpin, *fpout;
- char tmp[MAXLINELEN];
- char line[MAXLINELEN];
- char entname[MAXLINELEN];
- char entbak[MAXLINELEN];
- char *cp, *user, *rev, *ts, *opt;
-
- if (dir != NULL)
+ if (list)
{
- (void) sprintf (entname, "%s/%s", dir, CVSADM_ENT);
- (void) sprintf (entbak, "%s/%s", dir, CVSADM_ENTBAK);
- }
- else
- {
- (void) strcpy (entname, CVSADM_ENT);
- (void) strcpy (entbak, CVSADM_ENTBAK);
- }
-
- fpin = open_file (entname, "r");
- if (fgets (line, sizeof (line), fpin) == NULL)
- {
- (void) fclose (fpin);
- return;
- }
- (void) fclose (fpin);
- if (line[0] != '/')
- {
- rename_file (entname, entbak);
- fpin = open_file (entbak, "r");
- fpout = open_file (entname, "w+");
- while (fgets (line, sizeof (line), fpin) != NULL)
- {
- if (line[0] == '/')
- {
- if (fputs (line, fpout) == EOF)
- error (1, errno, "cannot write %s", CVSADM_ENT);
- continue;
- }
- rev = line;
- if ((ts = strchr (line, '|')) == NULL)
- continue;
- *ts++ = '\0';
- if ((user = strrchr (ts, ' ')) == NULL)
- continue;
- *user++ = '\0';
- if ((cp = strchr (user, '|')) == NULL)
- continue;
- *cp = '\0';
- opt = "";
-#ifdef HAVE_RCS5
-#ifdef HAD_RCS4
- opt = "-V4";
-#endif
-#endif
- if (fprintf (fpout, "/%s/%s/%s/%s/\n", user, rev, ts, opt) == EOF)
- error (1, errno, "cannot write %s", CVSADM_ENT);
+ if (!noexec)
+ {
+ if (isfile (CVSADM_ENTLOG))
+ write_entries (list);
}
- (void) fclose (fpin);
- if (fclose (fpout) == EOF)
- error (1, errno, "cannot close %s", entname);
-
- /* clean up any old Files or Mod files */
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_FILE);
- else
- (void) strcpy (tmp, CVSADM_FILE);
- if (isfile (tmp))
- (void) unlink (tmp);
-
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_MOD);
- else
- (void) strcpy (tmp, CVSADM_MOD);
- if (isfile (tmp))
- (void) unlink (tmp);
+ dellist(&list);
}
}
+
/*
* Free up the memory associated with the data section of an ENTRIES type
* node
@@ -415,16 +436,7 @@ Entries_delproc (node)
Entnode *p;
p = (Entnode *) node->data;
- free (p->version);
- free (p->timestamp);
- free (p->options);
- if (p->tag)
- free (p->tag);
- if (p->date)
- free (p->date);
- if (p->conflict)
- free (p->conflict);
- free ((char *) p);
+ Entnode_Destroy(p);
}
/*
@@ -432,18 +444,18 @@ Entries_delproc (node)
* list
*/
static Node *
-AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
+AddEntryNode (list, entdata)
List *list;
- char *name;
- char *version;
- char *timestamp;
- char *options;
- char *tag;
- char *date;
- char *conflict;
+ Entnode *entdata;
{
Node *p;
- Entnode *entdata;
+
+ /* was it already there? */
+ if ((p = findnode (list, entdata->user)) != NULL)
+ {
+ /* take it out */
+ delnode (p);
+ }
/* get a node and fill in the regular stuff */
p = getnode ();
@@ -451,25 +463,14 @@ AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
p->delproc = Entries_delproc;
/* this one gets a key of the name for hashing */
- p->key = xstrdup (name);
-
- /* malloc the data parts and fill them in */
- p->data = xmalloc (sizeof (Entnode));
- entdata = (Entnode *) p->data;
- entdata->version = xstrdup (version);
- entdata->timestamp = xstrdup (timestamp);
- entdata->options = xstrdup (options);
- if (entdata->options == NULL)
- entdata->options = xstrdup ("");/* must be non-NULL */
- entdata->conflict = xstrdup (conflict);
- entdata->tag = xstrdup (tag);
- entdata->date = xstrdup (date);
+ /* FIXME This results in duplicated data --- the hash package shouldn't
+ assume that the key is dynamically allocated. The user's free proc
+ should be responsible for freeing the key. */
+ p->key = xstrdup (entdata->user);
+ p->data = (char *) entdata;
/* put the node into the list */
- if (addnode (list, p) != 0)
- error (0, 0, "Duplicate filename in entries file (%s) -- ignored",
- name);
-
+ addnode (list, p);
return (p);
}
@@ -498,19 +499,19 @@ WriteTag (dir, tag, date)
fout = open_file (tmp, "w+");
if (tag)
{
- if (fprintf (fout, "T%s\n", tag) == EOF)
+ if (fprintf (fout, "T%s\n", tag) < 0)
error (1, errno, "write to %s failed", tmp);
}
else
{
- if (fprintf (fout, "D%s\n", date) == EOF)
+ if (fprintf (fout, "D%s\n", date) < 0)
error (1, errno, "write to %s failed", tmp);
}
if (fclose (fout) == EOF)
error (1, errno, "cannot close %s", tmp);
}
else
- if (unlink_file (tmp) < 0 && errno != ENOENT)
+ if (unlink_file (tmp) < 0 && ! existence_error (errno))
error (1, errno, "cannot remove %s", tmp);
}
@@ -523,8 +524,6 @@ ParseTag (tagp, datep)
char **datep;
{
FILE *fp;
- char line[MAXLINELEN];
- char *cp;
if (tagp)
*tagp = (char *) NULL;
@@ -533,15 +532,24 @@ ParseTag (tagp, datep)
fp = fopen (CVSADM_TAG, "r");
if (fp)
{
- if (fgets (line, sizeof (line), fp) != NULL)
+ char *line;
+ int line_length;
+ size_t line_chars_allocated;
+
+ line = NULL;
+ line_chars_allocated = 0;
+
+ if ((line_length = getline (&line, &line_chars_allocated, fp)) > 0)
{
- if ((cp = strrchr (line, '\n')) != NULL)
- *cp = '\0';
+ /* Remove any trailing newline. */
+ if (line[line_length - 1] == '\n')
+ line[--line_length] = '\0';
if (*line == 'T' && tagp)
*tagp = xstrdup (line + 1);
else if (*line == 'D' && datep)
*datep = xstrdup (line + 1);
}
(void) fclose (fp);
+ free (line);
}
}
diff --git a/gnu/usr.bin/cvs/cvs/find_names.c b/gnu/usr.bin/cvs/cvs/find_names.c
index a77807b..82959b5 100644
--- a/gnu/usr.bin/cvs/cvs/find_names.c
+++ b/gnu/usr.bin/cvs/cvs/find_names.c
@@ -19,8 +19,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)find_names.c 1.45 94/10/22 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)find_names.c 1.45 94/10/22 $";
+USE(rcsid);
#endif
static int find_dirs PROTO((char *dir, List * list, int checkadm));
@@ -31,6 +31,7 @@ static List *filelist;
/*
* add the key from entry on entries list to the files list
*/
+static int add_entries_proc PROTO((Node *, void *));
static int
add_entries_proc (node, closure)
Node *node;
@@ -49,9 +50,11 @@ add_entries_proc (node, closure)
/*
* compare two files list node (for sort)
*/
+static int fsortcmp PROTO ((const Node *, const Node *));
static int
fsortcmp (p, q)
- Node *p, *q;
+ const Node *p;
+ const Node *q;
{
return (strcmp (p->key, q->key));
}
@@ -74,8 +77,7 @@ Find_Names (repository, which, aflag, optentries)
if (which & W_LOCAL)
{
/* parse the entries file (if it exists) */
- entries = ParseEntries (aflag);
-
+ entries = Entries_Open (aflag);
if (entries != NULL)
{
/* walk the entries file adding elements to the files list */
@@ -85,7 +87,7 @@ Find_Names (repository, which, aflag, optentries)
if (optentries != NULL)
*optentries = entries;
else
- dellist (&entries);
+ Entries_Close (entries);
}
}
@@ -258,12 +260,7 @@ find_dirs (dir, list, checkadm)
/* check for new style */
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
if (!isdir (tmp))
- {
- /* and old style */
- (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, OCVSADM);
- if (!isdir (tmp))
- continue;
- }
+ continue;
}
/* put it in the list */
diff --git a/gnu/usr.bin/cvs/cvs/history.c b/gnu/usr.bin/cvs/cvs/history.c
index acec3cf..7a40b7b 100644
--- a/gnu/usr.bin/cvs/cvs/history.c
+++ b/gnu/usr.bin/cvs/cvs/history.c
@@ -179,8 +179,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)history.c 1.33 94/09/21 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)history.c 1.33 94/09/21 $";
+USE(rcsid);
#endif
static struct hrec
@@ -201,7 +201,7 @@ static struct hrec
static char *fill_hrec PROTO((char *line, struct hrec * hr));
static int accept_hrec PROTO((struct hrec * hr, struct hrec * lr));
static int select_hrec PROTO((struct hrec * hr));
-static int sort_order PROTO((CONST PTR l, CONST PTR r));
+static int sort_order PROTO((const PTR l, const PTR r));
static int within PROTO((char *find, char *string));
static time_t date_and_time PROTO((char *date_str));
static void expand_modules PROTO((void));
@@ -268,11 +268,9 @@ static char **mod_list; /* Ptr to array of ptrs to module names */
static int mod_max; /* Number of elements allocated */
static int mod_count; /* Number of elements used */
-static int histsize;
-static char *histdata;
static char *histfile; /* Ptr to the history file name */
-static char *history_usg[] =
+static const char *const history_usg[] =
{
"Usage: %s %s [-report] [-flags] [-options args] [files...]\n\n",
" Reports:\n",
@@ -307,12 +305,12 @@ static char *history_usg[] =
*/
static int
sort_order (l, r)
- CONST PTR l;
- CONST PTR r;
+ const PTR l;
+ const PTR r;
{
int i;
- CONST struct hrec *left = (CONST struct hrec *) l;
- CONST struct hrec *right = (CONST struct hrec *) r;
+ const struct hrec *left = (const struct hrec *) l;
+ const struct hrec *right = (const struct hrec *) r;
if (user_sort) /* If Sort by username, compare users */
{
@@ -531,6 +529,62 @@ history (argc, argv)
else if (report_count > 1)
error (1, 0, "Only one report type allowed from: \"-Tcomx\".");
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ struct file_list_str *f1;
+ char **mod;
+
+ /* We're the client side. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ if (tag_report)
+ send_arg("-T");
+ if (all_users)
+ send_arg("-a");
+ if (modified)
+ send_arg("-c");
+ if (last_entry)
+ send_arg("-l");
+ if (v_checkout)
+ send_arg("-o");
+ if (working)
+ send_arg("-w");
+ if (histfile)
+ send_arg("-X");
+ if (since_date)
+ option_with_arg ("-D", asctime (gmtime (&since_date)));
+ if (backto[0] != '\0')
+ option_with_arg ("-b", backto);
+ for (f1 = file_list; f1 < &file_list[file_count]; ++f1)
+ {
+ if (f1->l_file[0] == '*')
+ option_with_arg ("-p", f1->l_file + 1);
+ else
+ option_with_arg ("-f", f1->l_file);
+ }
+ if (module_report)
+ send_arg("-m");
+ for (mod = mod_list; mod < &mod_list[mod_count]; ++mod)
+ option_with_arg ("-n", *mod);
+ if (since_rev != NULL)
+ option_with_arg ("-r", since_rev);
+ if (since_tag != NULL)
+ option_with_arg ("-t", since_tag);
+ for (mod = user_list; mod < &user_list[user_count]; ++mod)
+ option_with_arg ("-u", *mod);
+ if (extract)
+ option_with_arg ("-x", rec_types);
+ option_with_arg ("-z", tz_name);
+
+ if (fprintf (to_server, "history\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
if (all_users)
save_user ("");
@@ -621,7 +675,8 @@ history_write (type, update_dir, revs, name, repository)
{
char fname[PATH_MAX], workdir[PATH_MAX], homedir[PATH_MAX];
static char username[20]; /* !!! Should be global */
- FILE *fp;
+ int fd;
+ char *line;
char *slash = "", *cp, *cp2, *repos;
int i;
static char *tilde = "";
@@ -638,8 +693,17 @@ history_write (type, update_dir, revs, name, repository)
return;
}
- if (!(fp = Fopen (fname, "a"))) /* Some directory not there! */
+ if (trace)
+#ifdef SERVER_SUPPORT
+ fprintf (stderr, "%c-> fopen(%s,a)\n",
+ (server_active) ? 'S' : ' ', fname);
+#else
+ fprintf (stderr, "-> fopen(%s,a)\n", fname);
+#endif
+ if (noexec)
return;
+ if ((fd = open (fname, O_WRONLY | O_APPEND | O_CREAT, 0666)) < 0)
+ error (1, errno, "cannot open history file: %s", fname);
repos = Short_Repository (repository);
@@ -747,10 +811,23 @@ history_write (type, update_dir, revs, name, repository)
(void) sprintf ((cp + 1), "*%x", i);
}
- if (fprintf (fp, "%c%08x|%s|%s|%s|%s|%s\n", type, time ((time_t *) NULL),
- username, workdir, repos, revs ? revs : "", name) == EOF)
+ if (!revs)
+ revs = "";
+ line = xmalloc (strlen (username) + strlen (workdir) + strlen (repos)
+ + strlen (revs) + strlen (name) + 100);
+ sprintf (line, "%c%08lx|%s|%s|%s|%s|%s\n",
+ type, (long) time ((time_t *) NULL),
+ username, workdir, repos, revs, name);
+
+ /* Lessen some race conditions on non-Posix-compliant hosts. */
+ if (lseek (fd, (off_t) 0, SEEK_END) == -1)
+ error (1, errno, "cannot seek to end of history file: %s", fname);
+
+ if (write (fd, line, strlen (line)) < 0)
error (1, errno, "cannot write to history file: %s", fname);
- (void) fclose (fp);
+ free (line);
+ if (close (fd) != 0)
+ error (1, errno, "cannot close history file: %s", fname);
}
/*
@@ -931,8 +1008,7 @@ read_hrecs (fname)
/* Exactly enough space for lines data */
if (!(i = st_buf.st_size))
error (1, 0, "history file is empty");
- histdata = cp = xmalloc (i + 2);
- histsize = i;
+ cp = xmalloc (i + 2);
if (read (fd, cp, i) != i)
error (1, errno, "cannot read log file");
diff --git a/gnu/usr.bin/cvs/cvs/ignore.c b/gnu/usr.bin/cvs/cvs/ignore.c
index 0005f40..f70fe78 100644
--- a/gnu/usr.bin/cvs/cvs/ignore.c
+++ b/gnu/usr.bin/cvs/cvs/ignore.c
@@ -5,8 +5,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)ignore.c 1.16 94/09/24 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)ignore.c 1.16 94/09/24 $";
+USE(rcsid);
#endif
/*
@@ -27,7 +27,7 @@ static int ign_size; /* This many slots available (plus
static int ign_hold; /* Index where first "temporary" item
* is held */
-char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state .nse_depinfo #* .#* cvslog.* ,* CVS* .del-* *.a *.o *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej";
+const char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state .nse_depinfo #* .#* cvslog.* ,* CVS* .del-* *.a *.o *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej";
#define IGN_GROW 16 /* grow the list by 16 elements at a
* time */
@@ -41,7 +41,6 @@ char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state .nse_depinf
void
ign_setup ()
{
- extern char *getenv ();
struct passwd *pw;
char file[PATH_MAX];
char *tmp;
@@ -51,17 +50,26 @@ ign_setup ()
ign_add (tmp, 0);
free (tmp);
- /* Then add entries found in repository, if it exists */
- (void) sprintf (file, "%s/%s/%s", CVSroot, CVSROOTADM, CVSROOTADM_IGNORE);
- if (isfile (file))
+#ifdef CLIENT_SUPPORT
+ /* Chances are we should have some way to provide this feature
+ client/server, but I'm not sure how (surely not by introducing
+ another network turnaround to each operation--perhaps by
+ putting a file in the CVS directory on checkout, or with some
+ sort of "slave cvsroot" on the client). */
+ if (!client_active)
+#endif
+ {
+ /* Then add entries found in repository, if it exists */
+ (void) sprintf (file, "%s/%s/%s", CVSroot, CVSROOTADM,
+ CVSROOTADM_IGNORE);
ign_add_file (file, 0);
+ }
/* Then add entries found in home dir, (if user has one) and file exists */
if ((pw = (struct passwd *) getpwuid (getuid ())) && pw->pw_dir)
{
(void) sprintf (file, "%s/%s", pw->pw_dir, CVSDOTIGNORE);
- if (isfile (file))
- ign_add_file (file, 0);
+ ign_add_file (file, 0);
}
/* Then add entries found in CVSIGNORE environment variable. */
@@ -118,11 +126,17 @@ ign_add_file (file, hold)
}
/* load the file */
- if (!(fp = fopen (file, "r")))
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ {
+ if (! existence_error (errno))
+ error (0, errno, "cannot open %s", file);
return;
+ }
while (fgets (line, sizeof (line), fp))
ign_add (line, hold);
- (void) fclose (fp);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", file);
}
/* Parse a line of space-separated wildcards and add them to the list. */
diff --git a/gnu/usr.bin/cvs/cvs/import.c b/gnu/usr.bin/cvs/cvs/import.c
index 3a46953..9980763 100644
--- a/gnu/usr.bin/cvs/cvs/import.c
+++ b/gnu/usr.bin/cvs/cvs/import.c
@@ -17,10 +17,11 @@
*/
#include "cvs.h"
+#include "save-cwd.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)import.c 1.63 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)import.c 1.63 94/09/30 $";
+USE(rcsid);
#endif
#define FILE_HOLDER ".#cvsxxx"
@@ -40,8 +41,6 @@ static int process_import_file PROTO((char *message, char *vfile, char *vtag,
static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,
char *targv[], int inattic));
static void add_log PROTO((int ch, char *fname));
-static int str2expmode PROTO((char const* expstring));
-static int strn2expmode PROTO((char const* expstring, size_t n));
static int repos_len;
static char vhead[50];
@@ -52,37 +51,23 @@ static int conflicts;
static int use_file_modtime;
static char *keyword_opt = NULL;
-static char *import_usage[] =
+static const char *const import_usage[] =
{
- "Usage: %s %s [-Qq] [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
- " repository vendor-tag release-tags...\n",
- "\t-Q\tReally quiet.\n",
- "\t-q\tSomewhat quiet.\n",
+ "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
+ " [-W spec] repository vendor-tag release-tags...\n",
"\t-d\tUse the file's modification time as the time of import.\n",
"\t-k sub\tSet default RCS keyword substitution mode.\n",
"\t-I ign\tMore files to ignore (! to reset).\n",
"\t-b bra\tVendor branch id.\n",
"\t-m msg\tLog message.\n",
+ "\t-W spec\tWrappers specification line.\n",
NULL
};
-static char *keyword_usage[] =
-{
- "%s %s: invalid RCS keyword expansion mode\n",
- "Valid expansion modes include:\n",
- " -kkv\tGenerate keywords using the default form.\n",
- " -kkvl\tLike -kkv, except locker's name inserted.\n",
- " -kk\tGenerate only keyword names in keyword strings.\n",
- " -kv\tGenerate only keyword values in keyword strings.\n",
- " -ko\tGenerate the old keyword string (no changes from checked in file).\n",
- NULL,
-};
-
-
int
import (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
char *message = NULL;
char tmpfile[L_tmpnam+1];
@@ -95,18 +80,24 @@ import (argc, argv)
usage (import_usage);
ign_setup ();
+ wrap_setup ();
(void) strcpy (vbranch, CVSBRANCH);
optind = 1;
- while ((c = getopt (argc, argv, "Qqdb:m:I:k:")) != -1)
+ while ((c = getopt (argc, argv, "Qqdb:m:I:k:W:")) != -1)
{
switch (c)
{
case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
case 'd':
use_file_modtime = 1;
@@ -126,10 +117,14 @@ import (argc, argv)
ign_add (optarg, 0);
break;
case 'k':
- if (str2expmode(optarg) != -1)
- keyword_opt = optarg;
- else
- usage (keyword_usage);
+ /* RCS_check_kflag returns strings of the form -kxx. We
+ only use it for validation, so we can free the value
+ as soon as it is returned. */
+ free (RCS_check_kflag(optarg));
+ keyword_opt = optarg;
+ break;
+ case 'W':
+ wrap_add (optarg, 0);
break;
case '?':
default:
@@ -146,7 +141,7 @@ import (argc, argv)
RCS_check_tag (argv[i]);
/* XXX - this should be a module, not just a pathname */
- if (argv[0][0] != '/')
+ if (! isabsolute (argv[0]))
{
if (CVSroot == NULL)
{
@@ -177,6 +172,17 @@ import (argc, argv)
(void) strcpy (vhead, vbranch);
cp = strrchr (vhead, '.');
*cp = '\0';
+
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ /* Do this now; don't ask for a log message if we can't talk to the
+ server. But if there is a syntax error in the options, give
+ an error message without connecting. */
+ start_server ();
+ }
+#endif
+
if (use_editor)
{
do_editor ((char *) NULL, &message, repository,
@@ -196,11 +202,45 @@ import (argc, argv)
message = nm;
}
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ int err;
+
+ ign_setup ();
+
+ if (use_file_modtime)
+ send_arg("-d");
+
+ if (vbranch[0] != '\0')
+ option_with_arg ("-b", vbranch);
+ if (message)
+ option_with_arg ("-m", message);
+ if (keyword_opt != NULL)
+ option_with_arg ("-k", keyword_opt);
+
+ {
+ int i;
+ for (i = 0; i < argc; ++i)
+ send_arg (argv[i]);
+ }
+
+ logfp = stdin;
+ client_import_setup (repository);
+ err = import_descend (message, argv[1], argc - 2, argv + 2);
+ client_import_done ();
+ if (fprintf (to_server, "import\n") < 0)
+ error (1, errno, "writing to server");
+ err += get_responses_and_close ();
+ return err;
+ }
+#endif
+
/*
* Make all newly created directories writable. Should really use a more
* sophisticated security mechanism here.
*/
- (void) umask (2);
+ (void) umask (cvsumask);
make_directories (repository);
/* Create the logfile that will be logged upon completion */
@@ -254,6 +294,10 @@ import (argc, argv)
dellist (&ulist);
(void) fclose (logfp);
+ /* Make sure the temporary file goes away, even on systems that don't let
+ you delete a file that's in use. */
+ unlink (tmpfile);
+
if (message)
free (message);
@@ -273,10 +317,11 @@ import_descend (message, vtag, targc, targv)
DIR *dirp;
struct dirent *dp;
int err = 0;
- int has_dirs = 0;
+ List *dirlist = NULL;
/* first, load up any per-directory ignore lists */
ign_add_file (CVSDOTIGNORE, 1);
+ wrap_add_file (CVSDOTWRAPPER, 1);
if ((dirp = opendir (".")) == NULL)
{
@@ -290,49 +335,75 @@ import_descend (message, vtag, targc, targv)
continue;
if (ign_name (dp->d_name))
{
+#ifdef SERVER_SUPPORT
+ /* CVS directories are created by server.c because it doesn't
+ special-case import. So don't print a message about them.
+ Do print a message about other ignored files (although
+ most of these will get ignored on the client side). */
+ if (server_active && strcmp (dp->d_name, CVSADM) == 0)
+ continue;
+#endif
add_log ('I', dp->d_name);
continue;
}
- if (isdir (dp->d_name))
+
+ if (
+#ifdef DT_DIR
+ (dp->d_type == DT_DIR
+ || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
+#else
+ isdir (dp->d_name)
+#endif
+ && !wrap_name_has (dp->d_name, WRAP_TOCVS)
+ )
+ {
+ Node *n;
+
+ if (dirlist == NULL)
+ dirlist = getlist();
+
+ n = getnode();
+ n->key = xstrdup (dp->d_name);
+ addnode(dirlist, n);
+ }
+ else if (
+#ifdef DT_DIR
+ dp->d_type == DT_LNK || dp->d_type == DT_UNKNOWN &&
+#endif
+ islink (dp->d_name))
{
- has_dirs = 1;
+ add_log ('L', dp->d_name);
+ err++;
}
else
{
- if (islink (dp->d_name))
- {
- add_log ('L', dp->d_name);
- err++;
- }
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ err += client_process_import_file (message, dp->d_name,
+ vtag, targc, targv,
+ repository);
else
- {
+#endif
err += process_import_file (message, dp->d_name,
vtag, targc, targv);
- }
}
}
(void) closedir (dirp);
}
- if (has_dirs)
+
+ if (dirlist != NULL)
{
- if ((dirp = opendir (".")) == NULL)
- err++;
- else
+ Node *head, *p;
+
+ head = dirlist->list;
+ for (p = head->next; p != head; p = p->next)
{
- while ((dp = readdir (dirp)) != NULL)
- {
- if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name))
- continue;
- if (!isdir (dp->d_name) || ign_name (dp->d_name))
- continue;
- err += import_descend_dir (message, dp->d_name,
- vtag, targc, targv);
- /* need to re-load .cvsignore after each dir traversal */
- ign_add_file (CVSDOTIGNORE, 1);
- }
- (void) closedir (dirp);
+ err += import_descend_dir (message, p->key, vtag, targc, targv);
}
+
+ dellist(&dirlist);
}
+
return (err);
}
@@ -392,10 +463,16 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
int letter;
int ierrno;
char *tmpdir;
+ char *tocvsPath;
vers = Version_TS (repository, (char *) NULL, vbranch, (char *) NULL, vfile,
1, 0, (List *) NULL, (List *) NULL);
+#ifdef DEATH_SUPPORT
+ if (vers->vn_rcs != NULL
+ && !RCS_isdead(vers->srcfile, vers->vn_rcs))
+#else
if (vers->vn_rcs != NULL)
+#endif
{
char xtmpfile[PATH_MAX];
int different;
@@ -435,7 +512,13 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
(void) unlink_file (xtmpfile);
return (1);
}
+
+ tocvsPath = wrap_tocvs_process_file (vfile);
different = xcmp (xtmpfile, vfile);
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
(void) unlink_file (xtmpfile);
if (!different)
{
@@ -488,7 +571,8 @@ add_rev (message, rcs, vfile, vers)
char *vers;
{
int locked, status, ierrno;
- int retcode = 0;
+ char *tocvsPath;
+ struct stat vfile_stat;
if (noexec)
return (0);
@@ -496,39 +580,43 @@ add_rev (message, rcs, vfile, vers)
locked = 0;
if (vers != NULL)
{
- run_setup ("%s%s -q -l%s", Rcsbin, RCS, vbranch);
- run_arg (rcs);
- if ((retcode = run_exec (RUN_TTY, DEVNULL, DEVNULL, RUN_NORMAL)) == 0)
- locked = 1;
- else if (retcode == -1)
+ /* Before RCS_lock existed, we were directing stdout, as well as
+ stderr, from the RCS command, to DEVNULL. I wouldn't guess that
+ was necessary, but I don't know for sure. */
+ if (RCS_lock (rcs, vbranch, 1) != 0)
{
error (0, errno, "fork failed");
return (1);
}
+ locked = 1;
}
- 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);
- }
- }
- run_setup ("%s%s -q -f -r%s", Rcsbin, RCS_CI, vbranch);
- run_args ("-m%s", message);
+ tocvsPath = wrap_tocvs_process_file (vfile);
+
+ /* We used to deposit the revision with -r; RCS would delete the
+ working file, but we'd keep a hard link to it, and rename it
+ back after running RCS (ooh, atomicity). However, that
+ strategy doesn't work on operating systems without hard links
+ (like Windows NT). Instead, let's deposit it using -u, and
+ restore its permission bits afterwards. This also means the
+ file always exists under its own name. */
+ if (! tocvsPath)
+ stat (vfile, &vfile_stat);
+
+ run_setup ("%s%s -q -f %s%s", Rcsbin, RCS_CI,
+ (tocvsPath ? "-r" : "-u"),
+ vbranch);
+ run_args ("-m%s", make_message_rcslegal (message));
if (use_file_modtime)
run_arg ("-d");
+ run_arg (tocvsPath == NULL ? vfile : tocvsPath);
run_arg (rcs);
status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
ierrno = errno;
- rename_file (FILE_HOLDER, vfile);
+
+ /* Restore the permissions on vfile. */
+ if (! tocvsPath)
+ chmod (vfile, vfile_stat.st_mode);
+
if (status)
{
if (!noexec)
@@ -538,9 +626,7 @@ add_rev (message, rcs, vfile, vers)
}
if (locked)
{
- run_setup ("%s%s -q -u%s", Rcsbin, RCS, vbranch);
- run_arg (rcs);
- (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+ (void) RCS_unlock(rcs, vbranch, 0);
}
return (1);
}
@@ -568,9 +654,7 @@ add_tags (rcs, vfile, vtag, targc, targv)
if (noexec)
return (0);
- run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, vtag, vbranch);
- run_arg (rcs);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
{
ierrno = errno;
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
@@ -583,9 +667,7 @@ add_tags (rcs, vfile, vtag, targc, targv)
1, 0, (List *) NULL, (List *) NULL);
for (i = 0; i < targc; i++)
{
- run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, targv[i], vers->vn_rcs);
- run_arg (rcs);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) != 0)
{
ierrno = errno;
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
@@ -606,7 +688,7 @@ struct compair
char *suffix, *comlead;
};
-struct compair comtable[] =
+static const struct compair comtable[] =
{
/*
@@ -616,83 +698,89 @@ struct compair comtable[] =
* suffix during initial ci (see InitAdmin()). Comment leaders are needed for
* languages without multiline comments; for others they are optional.
*/
- "a", "-- ", /* Ada */
- "ada", "-- ",
- "adb", "-- ",
- "asm", ";; ", /* assembler (MS-DOS) */
- "ads", "-- ", /* Ada */
- "bat", ":: ", /* batch (MS-DOS) */
- "body", "-- ", /* Ada */
- "c", " * ", /* C */
- "c++", "// ", /* C++ in all its infinite guises */
- "cc", "// ",
- "cpp", "// ",
- "cxx", "// ",
- "cl", ";;; ", /* Common Lisp */
- "cmd", ":: ", /* command (OS/2) */
- "cmf", "c ", /* CM Fortran */
- "cs", " * ", /* C* */
- "csh", "# ", /* shell */
- "e", "# ", /* efl */
- "epsf", "% ", /* encapsulated postscript */
- "epsi", "% ", /* encapsulated postscript */
- "el", "; ", /* Emacs Lisp */
- "f", "c ", /* Fortran */
- "for", "c ",
- "h", " * ", /* C-header */
- "hh", "// ", /* C++ header */
- "hpp", "// ",
- "hxx", "// ",
- "in", "# ", /* for Makefile.in */
- "l", " * ", /* lex (conflict between lex and
+ {"a", "-- "}, /* Ada */
+ {"ada", "-- "},
+ {"adb", "-- "},
+ {"asm", ";; "}, /* assembler (MS-DOS) */
+ {"ads", "-- "}, /* Ada */
+ {"bat", ":: "}, /* batch (MS-DOS) */
+ {"body", "-- "}, /* Ada */
+ {"c", " * "}, /* C */
+ {"c++", "// "}, /* C++ in all its infinite guises */
+ {"cc", "// "},
+ {"cpp", "// "},
+ {"cxx", "// "},
+ {"m", "// "}, /* Objective-C */
+ {"cl", ";;; "}, /* Common Lisp */
+ {"cmd", ":: "}, /* command (OS/2) */
+ {"cmf", "c "}, /* CM Fortran */
+ {"cs", " * "}, /* C* */
+ {"csh", "# "}, /* shell */
+ {"e", "# "}, /* efl */
+ {"epsf", "% "}, /* encapsulated postscript */
+ {"epsi", "% "}, /* encapsulated postscript */
+ {"el", "; "}, /* Emacs Lisp */
+ {"f", "c "}, /* Fortran */
+ {"for", "c "},
+ {"h", " * "}, /* C-header */
+ {"hh", "// "}, /* C++ header */
+ {"hpp", "// "},
+ {"hxx", "// "},
+ {"in", "# "}, /* for Makefile.in */
+ {"l", " * "}, /* lex (conflict between lex and
* franzlisp) */
- "mac", ";; ", /* macro (DEC-10, MS-DOS, PDP-11,
+ {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
* VMS, etc) */
- "me", ".\\\" ", /* me-macros t/nroff */
- "ml", "; ", /* mocklisp */
- "mm", ".\\\" ", /* mm-macros t/nroff */
- "ms", ".\\\" ", /* ms-macros t/nroff */
- "man", ".\\\" ", /* man-macros t/nroff */
- "1", ".\\\" ", /* feeble attempt at man pages... */
- "2", ".\\\" ",
- "3", ".\\\" ",
- "4", ".\\\" ",
- "5", ".\\\" ",
- "6", ".\\\" ",
- "7", ".\\\" ",
- "8", ".\\\" ",
- "9", ".\\\" ",
- "p", " * ", /* pascal */
- "pas", " * ",
- "pl", "# ", /* perl (conflict with Prolog) */
- "ps", "% ", /* postscript */
- "r", "# ", /* ratfor */
- "red", "% ", /* psl/rlisp */
+ {"me", ".\\\" "}, /* me-macros t/nroff */
+ {"ml", "; "}, /* mocklisp */
+ {"mm", ".\\\" "}, /* mm-macros t/nroff */
+ {"ms", ".\\\" "}, /* ms-macros t/nroff */
+ {"man", ".\\\" "}, /* man-macros t/nroff */
+ {"1", ".\\\" "}, /* feeble attempt at man pages... */
+ {"2", ".\\\" "},
+ {"3", ".\\\" "},
+ {"4", ".\\\" "},
+ {"5", ".\\\" "},
+ {"6", ".\\\" "},
+ {"7", ".\\\" "},
+ {"8", ".\\\" "},
+ {"9", ".\\\" "},
+ {"p", " * "}, /* pascal */
+ {"pas", " * "},
+ {"pl", "# "}, /* perl (conflict with Prolog) */
+ {"ps", "% "}, /* postscript */
+ {"psw", "% "}, /* postscript wrap */
+ {"pswm", "% "}, /* postscript wrap */
+ {"r", "# "}, /* ratfor */
+ {"red", "% "}, /* psl/rlisp */
#ifdef sparc
- "s", "! ", /* assembler */
+ {"s", "! "}, /* assembler */
#endif
#ifdef mc68000
- "s", "| ", /* assembler */
+ {"s", "| "}, /* assembler */
#endif
#ifdef pdp11
- "s", "/ ", /* assembler */
+ {"s", "/ "}, /* assembler */
#endif
#ifdef vax
- "s", "# ", /* assembler */
+ {"s", "# "}, /* assembler */
#endif
#ifdef __ksr__
- "s", "# ", /* assembler */
- "S", "# ", /* Macro assembler */
+ {"s", "# "}, /* assembler */
+ {"S", "# "}, /* Macro assembler */
+#endif
+ {"sh", "# "}, /* shell */
+ {"sl", "% "}, /* psl */
+ {"spec", "-- "}, /* Ada */
+ {"tex", "% "}, /* tex */
+ {"y", " * "}, /* yacc */
+ {"ye", " * "}, /* yacc-efl */
+ {"yr", " * "}, /* yacc-ratfor */
+#ifdef SYSTEM_COMMENT_TABLE
+ SYSTEM_COMMENT_TABLE
#endif
- "sh", "# ", /* shell */
- "sl", "% ", /* psl */
- "spec", "-- ", /* Ada */
- "tex", "% ", /* tex */
- "y", " * ", /* yacc */
- "ye", " * ", /* yacc-efl */
- "yr", " * ", /* yacc-ratfor */
- "", "# ", /* default for empty suffix */
- NULL, "# " /* default for unknown suffix; */
+ {"", "# "}, /* default for empty suffix */
+ {NULL, "# "} /* default for unknown suffix; */
/* must always be last */
};
@@ -748,17 +836,27 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
char altdate2[50];
#endif
char *author, *buf;
- int i, mode, ierrno, err = 0;
+ int i, ierrno, err = 0;
+ mode_t mode;
+ char *tocvsPath;
+ char *userfile;
if (noexec)
return (0);
- /* open the user file first, before we change the RCS files... */
- fpuser = fopen (user, "r");
+#ifdef LINES_CRLF_TERMINATED
+ /* There exits a port of RCS to such a system that stores files with
+ straight newlines. If we ever reach this point on such a system,
+ we'll need to decide what to do with the open_file call below. */
+ abort ();
+#endif
+ tocvsPath = wrap_tocvs_process_file (user);
+ userfile = (tocvsPath == NULL ? user : tocvsPath);
+ fpuser = fopen (userfile, "r");
if (fpuser == NULL) {
- /* not fatal, continue the import */
- fperror (logfp, 0, errno, "ERROR: cannot read file %s", user);
- error (0, errno, "ERROR: cannot read file %s", user);
+ /* not fatal, continue import */
+ fperror (logfp, 0, errno, "ERROR: cannot read file %s", userfile);
+ error (0, errno, "ERROR: cannot read file %s", userfile);
goto read_error;
}
fprcs = fopen (rcs, "w+");
@@ -770,33 +868,33 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
/*
* putadmin()
*/
- if (fprintf (fprcs, "head %s;\n", vhead) == EOF ||
- fprintf (fprcs, "branch %s;\n", vbranch) == EOF ||
- fprintf (fprcs, "access ;\n") == EOF ||
- fprintf (fprcs, "symbols ") == EOF)
+ if (fprintf (fprcs, "head %s;\n", vhead) < 0 ||
+ fprintf (fprcs, "branch %s;\n", vbranch) < 0 ||
+ fprintf (fprcs, "access ;\n") < 0 ||
+ fprintf (fprcs, "symbols ") < 0)
{
goto write_error;
}
for (i = targc - 1; i >= 0; i--) /* RCS writes the symbols backwards */
- if (fprintf (fprcs, "%s:%s.1 ", targv[i], vbranch) == EOF)
+ if (fprintf (fprcs, "%s:%s.1 ", targv[i], vbranch) < 0)
goto write_error;
- if (fprintf (fprcs, "%s:%s;\n", vtag, vbranch) == EOF ||
- fprintf (fprcs, "locks ; strict;\n") == EOF ||
+ if (fprintf (fprcs, "%s:%s;\n", vtag, vbranch) < 0 ||
+ fprintf (fprcs, "locks ; strict;\n") < 0 ||
/* XXX - make sure @@ processing works in the RCS file */
- fprintf (fprcs, "comment @%s@;\n", get_comment (user)) == EOF)
+ fprintf (fprcs, "comment @%s@;\n", get_comment (user)) < 0)
{
goto write_error;
}
if (keyword_opt != NULL)
- if (fprintf (fprcs, "expand @%s@;\n", keyword_opt) == EOF)
+ if (fprintf (fprcs, "expand @%s@;\n", keyword_opt) < 0)
{
goto write_error;
}
- if (fprintf (fprcs, "\n") == EOF)
+ if (fprintf (fprcs, "\n") < 0)
goto write_error;
/*
@@ -833,28 +931,28 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
#endif
author = getcaller ();
- if (fprintf (fprcs, "\n%s\n", vhead) == EOF ||
+ if (fprintf (fprcs, "\n%s\n", vhead) < 0 ||
fprintf (fprcs, "date %s; author %s; state Exp;\n",
- altdate1, author) == EOF ||
- fprintf (fprcs, "branches %s.1;\n", vbranch) == EOF ||
- fprintf (fprcs, "next ;\n") == EOF ||
- fprintf (fprcs, "\n%s.1\n", vbranch) == EOF ||
+ altdate1, author) < 0 ||
+ fprintf (fprcs, "branches %s.1;\n", vbranch) < 0 ||
+ fprintf (fprcs, "next ;\n") < 0 ||
+ fprintf (fprcs, "\n%s.1\n", vbranch) < 0 ||
fprintf (fprcs, "date %s; author %s; state Exp;\n",
- altdate2, author) == EOF ||
- fprintf (fprcs, "branches ;\n") == EOF ||
- fprintf (fprcs, "next ;\n\n") == EOF ||
+ altdate2, author) < 0 ||
+ fprintf (fprcs, "branches ;\n") < 0 ||
+ fprintf (fprcs, "next ;\n\n") < 0 ||
/*
* putdesc()
*/
- fprintf (fprcs, "\ndesc\n") == EOF ||
- fprintf (fprcs, "@@\n\n\n") == EOF ||
+ fprintf (fprcs, "\ndesc\n") < 0 ||
+ fprintf (fprcs, "@@\n\n\n") < 0 ||
/*
* putdelta()
*/
- fprintf (fprcs, "\n%s\n", vhead) == EOF ||
- fprintf (fprcs, "log\n") == EOF ||
- fprintf (fprcs, "@Initial revision\n@\n") == EOF ||
- fprintf (fprcs, "text\n@") == EOF)
+ fprintf (fprcs, "\n%s\n", vhead) < 0 ||
+ fprintf (fprcs, "log\n") < 0 ||
+ fprintf (fprcs, "@Initial revision\n@\n") < 0 ||
+ fprintf (fprcs, "text\n@") < 0)
{
goto write_error;
}
@@ -867,19 +965,19 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
buf = xmalloc ((int) size);
if (fread (buf, (int) size, 1, fpuser) != 1)
error (1, errno, "cannot read file %s for copying", user);
- if (expand_at_signs (buf, size, fprcs) == EOF)
+ if (expand_at_signs (buf, size, fprcs) < 0)
{
free (buf);
goto write_error;
}
free (buf);
}
- if (fprintf (fprcs, "@\n\n") == EOF ||
- fprintf (fprcs, "\n%s.1\n", vbranch) == EOF ||
- fprintf (fprcs, "log\n@") == EOF ||
- expand_at_signs (message, (off_t) strlen (message), fprcs) == EOF ||
- fprintf (fprcs, "@\ntext\n") == EOF ||
- fprintf (fprcs, "@@\n") == EOF)
+ if (fprintf (fprcs, "@\n\n") < 0 ||
+ fprintf (fprcs, "\n%s.1\n", vbranch) < 0 ||
+ fprintf (fprcs, "log\n@") < 0 ||
+ expand_at_signs (message, (off_t) strlen (message), fprcs) < 0 ||
+ fprintf (fprcs, "@\ntext\n") < 0 ||
+ fprintf (fprcs, "@@\n") < 0)
{
goto write_error;
}
@@ -891,11 +989,16 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
(void) fclose (fpuser);
/*
- * Fix the modes on the RCS files. They must maintain the same modes as
- * the original user file, except that all write permissions must be
+ * Fix the modes on the RCS files. The user modes of the original
+ * user file are propagated to the group and other modes as allowed
+ * by the repository umask, except that all write permissions are
* turned off.
*/
- mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH);
+ mode = (sb.st_mode |
+ (sb.st_mode & S_IRWXU) >> 3 |
+ (sb.st_mode & S_IRWXU) >> 6) &
+ ~cvsumask &
+ ~(S_IWRITE | S_IWGRP | S_IWOTH);
if (chmod (rcs, mode) < 0)
{
ierrno = errno;
@@ -904,6 +1007,9 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
err++;
}
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
return (err);
write_error:
@@ -920,11 +1026,17 @@ write_error_noclose:
error (1, 0, "ERROR: out of space - aborting");
}
read_error:
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
return (err + 1);
}
/*
- * Sigh.. need to expand @ signs into double @ signs
+ * Write SIZE bytes at BUF to FP, expanding @ signs into double @
+ * signs. If an error occurs, return a negative value and set errno
+ * to indicate the error. If not, return a nonnegative value.
*/
static int
expand_at_signs (buf, size, fp)
@@ -934,11 +1046,15 @@ expand_at_signs (buf, size, fp)
{
char *cp, *end;
+ errno = 0;
for (cp = buf, end = buf + size; cp < end; cp++)
{
if (*cp == '@')
- (void) putc ('@', fp);
- if (putc (*cp, fp) == EOF)
+ {
+ if (putc ('@', fp) == EOF && errno != 0)
+ return EOF;
+ }
+ if (putc (*cp, fp) == EOF && errno != 0)
return (EOF);
}
return (1);
@@ -986,16 +1102,15 @@ import_descend_dir (message, dir, vtag, targc, targv)
int targc;
char *targv[];
{
- char cwd[PATH_MAX];
+ struct saved_cwd cwd;
char *cp;
int ierrno, err;
if (islink (dir))
return (0);
- if (getwd (cwd) == NULL)
+ if (save_cwd (&cwd))
{
- fperror (logfp, 0, 0, "ERROR: cannot get working directory: %s", cwd);
- error (0, 0, "ERROR: cannot get working directory: %s", cwd);
+ fperror (logfp, 0, 0, "ERROR: cannot get working directory");
return (1);
}
if (repository[0] == '\0')
@@ -1005,8 +1120,20 @@ import_descend_dir (message, dir, vtag, targc, targv)
(void) strcat (repository, "/");
(void) strcat (repository, dir);
}
+#ifdef CLIENT_SUPPORT
+ if (!quiet && !client_active)
+#else
if (!quiet)
+#endif
+#ifdef SERVER_SUPPORT
+ /* Needs to go on stdout, not stderr, to avoid being interspersed
+ with the add_log messages. */
+ printf ("%s %s: Importing %s\n",
+ program_name, command_name, repository);
+#else
error (0, 0, "Importing %s", repository);
+#endif
+
if (chdir (dir) < 0)
{
ierrno = errno;
@@ -1015,7 +1142,11 @@ import_descend_dir (message, dir, vtag, targc, targv)
err = 1;
goto out;
}
+#ifdef CLIENT_SUPPORT
+ if (!client_active && !isdir (repository))
+#else
if (!isdir (repository))
+#endif
{
if (isfile (repository))
{
@@ -1026,7 +1157,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
err = 1;
goto out;
}
- if (noexec == 0 && mkdir (repository, 0777) < 0)
+ if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
{
ierrno = errno;
fperror (logfp, 0, ierrno,
@@ -1043,40 +1174,8 @@ import_descend_dir (message, dir, vtag, targc, targv)
*cp = '\0';
else
repository[0] = '\0';
- if (chdir (cwd) < 0)
- error (1, errno, "cannot chdir to %s", cwd);
+ if (restore_cwd (&cwd, NULL))
+ exit (1);
+ free_cwd (&cwd);
return (err);
}
-
-/* the following code is taken from code in rcs/src/rcssyn.c, and returns a
- * positive value if 'expstring' contains a valid RCS expansion token for
- * the -k option. If an invalid expansion is named, then return -1.
- */
-
-char const *const expand_names[] = {
- /* These must agree with *_EXPAND in rcs/src/rcsbase.h. */
- "kv","kvl","k","v","o",
- 0
-};
-
-static int
-str2expmode(s)
- char const *s;
-/* Yield expand mode corresponding to S, or -1 if bad. */
-{
- return strn2expmode(s, strlen(s));
-}
-
-static int
-strn2expmode(s, n)
- char const *s;
- size_t n;
-{
- char const *const *p;
-
- for (p = expand_names; *p; ++p)
- if (memcmp(*p,s,n) == 0 && !(*p)[n])
- return p - expand_names;
- return -1;
-}
-
diff --git a/gnu/usr.bin/cvs/cvs/lock.c b/gnu/usr.bin/cvs/cvs/lock.c
index 940e963..3e15fbb 100644
--- a/gnu/usr.bin/cvs/cvs/lock.c
+++ b/gnu/usr.bin/cvs/cvs/lock.c
@@ -13,31 +13,30 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)lock.c 1.50 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)lock.c 1.50 94/09/30 $";
+USE(rcsid);
#endif
-extern char *ctime ();
-
static int readers_exist PROTO((char *repository));
-static int set_lock PROTO((char *lockdir, int will_wait, char *repository));
+static int set_lock PROTO((char *repository, int will_wait));
+static void clear_lock PROTO((void));
static void set_lockers_name PROTO((struct stat *statp));
static int set_writelock_proc PROTO((Node * p, void *closure));
static int unlock_proc PROTO((Node * p, void *closure));
static int write_lock PROTO((char *repository));
static void unlock PROTO((char *repository));
static void lock_wait PROTO((char *repository));
+static int Check_Owner PROTO((char *lockdir));
static char lockers_name[20];
static char *repository;
-static char readlock[PATH_MAX], writelock[PATH_MAX];
+static char readlock[PATH_MAX], writelock[PATH_MAX], masterlock[PATH_MAX];
static int cleanup_lckdir;
static List *locklist;
#define L_OK 0 /* success */
#define L_ERROR 1 /* error condition */
-#define L_LOCK_OWNED 2 /* lock already owned by us */
-#define L_LOCKED 3 /* lock owned by someone else */
+#define L_LOCKED 2 /* lock owned by someone else */
/*
* Clean up all outstanding locks
@@ -80,19 +79,18 @@ unlock (repository)
char *repository;
{
char tmp[PATH_MAX];
- struct stat sb;
if (readlock[0] != '\0')
{
(void) sprintf (tmp, "%s/%s", repository, readlock);
- if (unlink (tmp) < 0 && errno != ENOENT)
+ if (unlink (tmp) < 0 && ! existence_error (errno))
error (0, errno, "failed to remove lock %s", tmp);
}
if (writelock[0] != '\0')
{
(void) sprintf (tmp, "%s/%s", repository, writelock);
- if (unlink (tmp) < 0 && errno != ENOENT)
+ if (unlink (tmp) < 0 && ! existence_error (errno))
error (0, errno, "failed to remove lock %s", tmp);
}
@@ -101,21 +99,53 @@ unlock (repository)
* lead to the limitation that one user ID should not be committing
* files into the same Repository directory at the same time. Oh well.
*/
- (void) sprintf (tmp, "%s/%s", repository, CVSLCK);
- if (stat (tmp, &sb) != -1 && sb.st_uid == geteuid () &&
- (writelock[0] != '\0' || (readlock[0] != '\0' && cleanup_lckdir)))
+ if (writelock[0] != '\0' || (readlock[0] != '\0' && cleanup_lckdir))
{
- (void) rmdir (tmp);
+ (void) sprintf (tmp, "%s/%s", repository, CVSLCK);
+ if (Check_Owner(tmp))
+ {
+#ifdef AFSCVS
+ char rmuidlock[PATH_MAX];
+ sprintf(rmuidlock, "rm -f %s/uidlock%d", tmp, geteuid() );
+ system(rmuidlock);
+#endif
+ (void) rmdir (tmp);
+ }
}
cleanup_lckdir = 0;
}
/*
- * Since some systems don't define this...
+ * Check the owner of a lock. Returns 1 if we own it, 0 otherwise.
*/
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
+static int
+Check_Owner(lockdir)
+ char *lockdir;
+{
+ struct stat sb;
+
+#ifdef AFSCVS
+ /* In the Andrew File System (AFS), user ids from stat don't match
+ those from geteuid(). The AFSCVS code can deal with either AFS or
+ non-AFS repositories; the non-AFSCVS code is faster. */
+ char uidlock[PATH_MAX];
+
+ /* Check if the uidlock is in the lock directory */
+ sprintf(uidlock, "%s/uidlock%d", lockdir, geteuid() );
+ if( stat(uidlock, &sb) != -1)
+ return 1; /* The file exists, therefore we own the lock */
+ else
+ return 0; /* The file didn't exist or some other error.
+ * Assume that we don't own it.
+ */
+#else
+ if (stat (lockdir, &sb) != -1 && sb.st_uid == geteuid ())
+ return 1;
+ else
+ return 0;
#endif
+} /* end Check_Owner() */
+
/*
* Create a lock file for readers
@@ -127,18 +157,10 @@ Reader_Lock (xrepository)
int err = 0;
FILE *fp;
char tmp[PATH_MAX];
-#ifdef HAVE_LONG_FILE_NAMES
- char hostname[MAXHOSTNAMELEN];
-#endif
if (noexec)
return (0);
-#ifdef HAVE_LONG_FILE_NAMES
- memset(hostname, 0, sizeof(hostname));
- gethostname(hostname, sizeof(hostname) - 1);
-#endif
-
/* we only do one directory at a time for read locks! */
if (repository != NULL)
{
@@ -158,13 +180,7 @@ Reader_Lock (xrepository)
/* remember what we're locking (for lock_cleanup) */
repository = xrepository;
- /* make sure we clean up on error */
- (void) SIG_register (SIGHUP, Lock_Cleanup);
- (void) SIG_register (SIGINT, Lock_Cleanup);
- (void) SIG_register (SIGQUIT, Lock_Cleanup);
- (void) SIG_register (SIGPIPE, Lock_Cleanup);
- (void) SIG_register (SIGTERM, Lock_Cleanup);
-
+#ifdef BOGUS_UNLESS_PROVEN_OTHERWISE
/* make sure we can write the repository */
(void) sprintf (tmp,
#ifdef HAVE_LONG_FILE_NAMES
@@ -178,16 +194,16 @@ Reader_Lock (xrepository)
error (0, errno, "cannot create read lock in repository `%s'",
xrepository);
readlock[0] = '\0';
- if (unlink (tmp) < 0 && errno != ENOENT)
+ if (unlink (tmp) < 0 && ! existence_error (errno))
error (0, errno, "failed to remove lock %s", tmp);
return (1);
}
if (unlink (tmp) < 0)
error (0, errno, "failed to remove lock %s", tmp);
+#endif
/* get the lock dir for our own */
- (void) sprintf (tmp, "%s/%s", xrepository, CVSLCK);
- if (set_lock (tmp, 1, xrepository) != L_OK)
+ if (set_lock (xrepository, 1) != L_OK)
{
error (0, 0, "failed to obtain dir lock in repository `%s'",
xrepository);
@@ -206,9 +222,7 @@ Reader_Lock (xrepository)
}
/* free the lock dir */
- (void) sprintf (tmp, "%s/%s", xrepository, CVSLCK);
- if (rmdir (tmp) < 0)
- error (0, errno, "failed to remove lock dir `%s'", tmp);
+ clear_lock();
return (err);
}
@@ -294,14 +308,6 @@ write_lock (repository)
int status;
FILE *fp;
char tmp[PATH_MAX];
-#ifdef HAVE_LONG_FILE_NAMES
- char hostname[MAXHOSTNAMELEN];
-#endif
-
-#ifdef HAVE_LONG_FILE_NAMES
- memset(hostname, 0, sizeof(hostname));
- gethostname(hostname, sizeof(hostname) - 1);
-#endif
if (writelock[0] == '\0')
(void) sprintf (writelock,
@@ -312,13 +318,7 @@ write_lock (repository)
#endif
getpid());
- /* make sure we clean up on error */
- (void) SIG_register (SIGHUP, Lock_Cleanup);
- (void) SIG_register (SIGINT, Lock_Cleanup);
- (void) SIG_register (SIGQUIT, Lock_Cleanup);
- (void) SIG_register (SIGPIPE, Lock_Cleanup);
- (void) SIG_register (SIGTERM, Lock_Cleanup);
-
+#ifdef BOGUS_UNLESS_PROVEN_OTHERWISE
/* make sure we can write the repository */
(void) sprintf (tmp,
#ifdef HAVE_LONG_FILE_NAMES
@@ -331,17 +331,17 @@ write_lock (repository)
{
error (0, errno, "cannot create write lock in repository `%s'",
repository);
- if (unlink (tmp) < 0 && errno != ENOENT)
+ if (unlink (tmp) < 0 && ! existence_error (errno))
error (0, errno, "failed to remove lock %s", tmp);
return (L_ERROR);
}
if (unlink (tmp) < 0)
error (0, errno, "failed to remove lock %s", tmp);
+#endif
/* make sure the lock dir is ours (not necessarily unique to us!) */
- (void) sprintf (tmp, "%s/%s", repository, CVSLCK);
- status = set_lock (tmp, 0, repository);
- if (status == L_OK || status == L_LOCK_OWNED)
+ status = set_lock (repository, 0);
+ if (status == L_OK)
{
/* we now own a writer - make sure there are no readers */
if (readers_exist (repository))
@@ -349,8 +349,7 @@ write_lock (repository)
/* clean up the lock dir if we created it */
if (status == L_OK)
{
- if (rmdir (tmp) < 0)
- error (0, errno, "failed to remove lock dir `%s'", tmp);
+ clear_lock();
}
/* indicate we failed due to read locks instead of error */
@@ -363,15 +362,13 @@ write_lock (repository)
{
int xerrno = errno;
- if (unlink (tmp) < 0 && errno != ENOENT)
+ if (unlink (tmp) < 0 && ! existence_error (errno))
error (0, errno, "failed to remove lock %s", tmp);
/* free the lock dir if we created it */
if (status == L_OK)
{
- (void) sprintf (tmp, "%s/%s", repository, CVSLCK);
- if (rmdir (tmp) < 0)
- error (0, errno, "failed to remove lock dir `%s'", tmp);
+ clear_lock();
}
/* return the error */
@@ -428,9 +425,7 @@ again:
*/
if (now >= (sb.st_ctime + CVSLCKAGE) && unlink (line) != -1)
{
- if (closedir (dirp) < 0)
- error (0, errno,
- "error closing directory %s", repository);
+ (void) closedir (dirp);
goto again;
}
#endif
@@ -445,8 +440,7 @@ again:
if (errno != 0)
error (0, errno, "error reading directory %s", repository);
- if (closedir (dirp) < 0)
- error (0, errno, "error closing directory %s", repository);
+ closedir (dirp);
return (ret);
}
@@ -466,7 +460,7 @@ set_lockers_name (statp)
(void) strcpy (lockers_name, pw->pw_name);
}
else
- (void) sprintf (lockers_name, "uid%d", statp->st_uid);
+ (void) sprintf (lockers_name, "uid%lu", (unsigned long) statp->st_uid);
}
/*
@@ -475,16 +469,18 @@ set_lockers_name (statp)
* seconds old, just try to remove the directory.
*/
static int
-set_lock (lockdir, will_wait, repository)
- char *lockdir;
- int will_wait;
+set_lock (repository, will_wait)
char *repository;
+ int will_wait;
{
struct stat sb;
+ mode_t omask;
#ifdef CVS_FUDGELOCKS
time_t now;
#endif
+ (void) sprintf (masterlock, "%s/%s", repository, CVSLCK);
+
/*
* Note that it is up to the callers of set_lock() to arrange for signal
* handlers that do the appropriate things, like remove the lock
@@ -493,14 +489,39 @@ set_lock (lockdir, will_wait, repository)
cleanup_lckdir = 0;
for (;;)
{
+ int status = -1;
+ omask = umask (cvsumask);
SIG_beginCrSect ();
- if (mkdir (lockdir, 0777) == 0)
+ if (CVS_MKDIR (masterlock, 0777) == 0)
{
+#ifdef AFSCVS
+ char uidlock[PATH_MAX];
+ FILE *fp;
+
+ sprintf(uidlock, "%s/uidlock%d", masterlock, geteuid() );
+ if ((fp = fopen(uidlock, "w+")) == NULL)
+ {
+ /* We failed to create the uidlock,
+ so rm masterlock and leave */
+ rmdir(masterlock);
+ SIG_endCrSect ();
+ status = L_ERROR;
+ goto out;
+ }
+
+ /* We successfully created the uid lock, so close the file */
+ fclose(fp);
+#endif
cleanup_lckdir = 1;
SIG_endCrSect ();
- return (L_OK);
+ status = L_OK;
+ goto out;
}
SIG_endCrSect ();
+ out:
+ (void) umask (omask);
+ if (status != -1)
+ return status;
if (errno != EEXIST)
{
@@ -514,24 +535,16 @@ set_lock (lockdir, will_wait, repository)
* stat the dir - if it is non-existent, re-try the loop since
* someone probably just removed it (thus releasing the lock)
*/
- if (stat (lockdir, &sb) < 0)
+ if (stat (masterlock, &sb) < 0)
{
- if (errno == ENOENT)
+ if (existence_error (errno))
continue;
- error (0, errno, "couldn't stat lock directory `%s'", lockdir);
+ error (0, errno, "couldn't stat lock directory `%s'", masterlock);
return (L_ERROR);
}
- /*
- * if we already own the lock, go ahead and return 1 which means it
- * existed but we owned it
- */
- if (sb.st_uid == geteuid () && !will_wait)
- return (L_LOCK_OWNED);
-
#ifdef CVS_FUDGELOCKS
-
/*
* If the create time of the directory is more than CVSLCKAGE seconds
* ago, try to clean-up the lock directory, and if successful, just
@@ -540,7 +553,13 @@ set_lock (lockdir, will_wait, repository)
(void) time (&now);
if (now >= (sb.st_ctime + CVSLCKAGE))
{
- if (rmdir (lockdir) >= 0)
+#ifdef AFSCVS
+ /* Remove the uidlock first */
+ char rmuidlock[PATH_MAX];
+ sprintf(rmuidlock, "rm -f %s/uidlock%d", masterlock, geteuid() );
+ system(rmuidlock);
+#endif
+ if (rmdir (masterlock) >= 0)
continue;
}
#endif
@@ -556,6 +575,24 @@ set_lock (lockdir, will_wait, repository)
}
/*
+ * Clear master lock. We don't have to recompute the lock name since
+ * clear_lock is never called except after a successful set_lock().
+ */
+static void
+clear_lock()
+{
+#ifdef AFSCVS
+ /* Remove the uidlock first */
+ char rmuidlock[PATH_MAX];
+ sprintf(rmuidlock, "rm -f %s/uidlock%d", masterlock, geteuid() );
+ system(rmuidlock);
+#endif
+ if (rmdir (masterlock) < 0)
+ error (0, errno, "failed to remove lock dir `%s'", masterlock);
+ cleanup_lckdir = 0;
+}
+
+/*
* Print out a message that the lock is still held, then sleep a while.
*/
static void
diff --git a/gnu/usr.bin/cvs/cvs/log.c b/gnu/usr.bin/cvs/cvs/log.c
index 4c3718e..88c9adc 100644
--- a/gnu/usr.bin/cvs/cvs/log.c
+++ b/gnu/usr.bin/cvs/cvs/log.c
@@ -7,6 +7,9 @@
*
* Print Log Information
*
+ * This line exists solely to test some pcl-cvs/ChangeLog stuff. You
+ * can delete it, if indeed it's still here when you read it. -Karl
+ *
* Prints the RCS "log" (rlog) information for the specified files. With no
* argument, prints the log information for all the files in the directory
* (recursive by default).
@@ -15,30 +18,30 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)log.c 1.44 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)log.c 1.44 94/09/30 $";
+USE(rcsid);
#endif
static Dtype log_dirproc PROTO((char *dir, char *repository, char *update_dir));
static int log_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
-static char options[PATH_MAX];
-
-static char *log_usage[] =
+static const char *const log_usage[] =
{
"Usage: %s %s [-l] [rlog-options] [files...]\n",
"\t-l\tLocal directory only, no recursion.\n",
NULL
};
+static int ac;
+static char **av;
+
int
cvslog (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int i;
- int numopt = 1;
int err = 0;
int local = 0;
@@ -48,34 +51,49 @@ cvslog (argc, argv)
/*
* All 'log' command options except -l are passed directly on to 'rlog'
*/
- options[0] = '\0'; /* Assume none */
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] == '-' || argv[i][0] == '\0')
- {
- numopt++;
- switch (argv[i][1])
- {
- case 'l':
- local = 1;
- break;
- default:
- (void) strcat (options, " ");
- (void) strcat (options, argv[i]);
- break;
- }
- }
+ for (i = 1; i < argc && argv[i][0] == '-'; i++)
+ if (argv[i][1] == 'l')
+ local = 1;
+
+ wrap_setup ();
+
+#ifdef CLIENT_SUPPORT
+ if (client_active) {
+ /* We're the local client. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ for (i = 1; i < argc && argv[i][0] == '-'; i++)
+ send_arg (argv[i]);
+
+#if 0
+/* FIXME: We shouldn't have to send current files to get log entries, but it
+ doesn't work yet and I haven't debugged it. So send the files --
+ it's slower but it works. gnu@cygnus.com Apr94 */
+ send_file_names (argc - i, argv + i);
+#else
+ send_files (argc - i, argv + i, local, 0);
+#endif
+
+ if (fprintf (to_server, "log\n") < 0)
+ error (1, errno, "writing to server");
+ err = get_responses_and_close ();
+ return err;
}
- argc -= numopt;
- argv += numopt;
- err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc,
- (int (*) ()) NULL, argc, argv, local,
+ ac = argc;
+ av = argv;
+#endif
+
+ err = start_recursion (log_fileproc, (FILESDONEPROC) NULL, log_dirproc,
+ (DIRLEAVEPROC) NULL, argc - i, argv + i, local,
W_LOCAL | W_REPOS | W_ATTIC, 0, 1,
(char *) NULL, 1, 0);
return (err);
}
+
/*
* Do an rlog on a file
*/
@@ -117,8 +135,23 @@ log_fileproc (file, update_dir, repository, entries, srcfiles)
return (1);
}
- run_setup ("%s%s %s", Rcsbin, RCS_RLOG, options);
+ run_setup ("%s%s", Rcsbin, RCS_RLOG);
+ {
+ int i;
+ for (i = 1; i < ac && av[i][0] == '-'; i++)
+ if (av[i][1] != 'l')
+ run_arg (av[i]);
+ }
run_arg (rcsfile->path);
+
+ if (*update_dir)
+ {
+ char *workfile = xmalloc (strlen (update_dir) + strlen (file) + 2);
+ sprintf (workfile, "%s/%s", update_dir, file);
+ run_arg (workfile);
+ free (workfile);
+ }
+
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_REALLY)) == -1)
{
error (1, errno, "fork failed for rlog on %s", file);
diff --git a/gnu/usr.bin/cvs/cvs/logmsg.c b/gnu/usr.bin/cvs/cvs/logmsg.c
index 8fd0b2d..5f2763f 100644
--- a/gnu/usr.bin/cvs/cvs/logmsg.c
+++ b/gnu/usr.bin/cvs/cvs/logmsg.c
@@ -7,18 +7,11 @@
*/
#include "cvs.h"
+#include "getline.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)logmsg.c 1.48 94/09/29 $";
-USE(rcsid)
-#endif
-
-/* this is slightly dangerous, since it could conflict with other systems'
- * own prototype.
- */
-#if 0
-/* Which is why I'll nuke this */
-extern int gethostname PROTO((char *name, int len));
+static const char rcsid[] = "$CVSid: @(#)logmsg.c 1.48 94/09/29 $";
+USE(rcsid);
#endif
static int find_type PROTO((Node * p, void *closure));
@@ -33,7 +26,7 @@ static void setup_tmpfile PROTO((FILE * xfp, char *xprefix, List * changes));
static int editinfo_proc PROTO((char *repository, char *template));
static FILE *fp;
-static char *strlist;
+static char *str_list;
static char *editinfo_editor;
static Ctype type;
@@ -137,7 +130,10 @@ do_editor (dir, messagep, repository, changes)
List *changes;
{
static int reuse_log_message = 0;
- char line[MAXLINELEN], fname[L_tmpnam+1];
+ char *line;
+ int line_length;
+ size_t line_chars_allocated;
+ char fname[L_tmpnam+1];
struct stat pre_stbuf, post_stbuf;
int retcode = 0;
char *p;
@@ -171,7 +167,7 @@ do_editor (dir, messagep, repository, changes)
(void) fprintf (fp,
"%sEnter Log. Lines beginning with `%s' are removed automatically\n%s\n",
CVSEDITPREFIX, CVSEDITPREFIX, CVSEDITPREFIX);
- if (dir != NULL)
+ if (dir != NULL && *dir)
(void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
dir, CVSEDITPREFIX);
if (changes != NULL)
@@ -181,7 +177,8 @@ do_editor (dir, messagep, repository, changes)
CVSEDITPREFIX);
/* finish off the temp file */
- (void) fclose (fp);
+ if (fclose (fp) == EOF)
+ error (1, errno, "%s", fname);
if (stat (fname, &pre_stbuf) == -1)
pre_stbuf.st_mtime = 0;
@@ -214,25 +211,34 @@ do_editor (dir, messagep, repository, changes)
*messagep = NULL;
else
{
- *messagep = (char *) xmalloc (post_stbuf.st_size);
+ *messagep = (char *) xmalloc (post_stbuf.st_size + 1);
*messagep[0] = '\0';
}
-/* !!! XXX FIXME: fgets is broken. This should not have any line
- length limits. */
+ line = NULL;
+ line_chars_allocated = 0;
if (*messagep)
{
p = *messagep;
- while (fgets (line, sizeof (line), fp) != NULL)
+ while (1)
{
+ line_length = getline (&line, &line_chars_allocated, fp);
+ if (line_length == -1)
+ {
+ if (ferror (fp))
+ error (0, errno, "warning: cannot read %s", fname);
+ break;
+ }
if (strncmp (line, CVSEDITPREFIX, sizeof (CVSEDITPREFIX) - 1) == 0)
continue;
(void) strcpy (p, line);
- p += strlen (line);
+ p += line_length;
}
}
- (void) fclose (fp);
+ if (fclose (fp) < 0)
+ error (0, errno, "warning: cannot close %s", fname);
+
if (pre_stbuf.st_mtime == post_stbuf.st_mtime ||
*messagep == NULL ||
strcmp (*messagep, "\n") == 0)
@@ -243,9 +249,9 @@ do_editor (dir, messagep, repository, changes)
(void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
(void) printf ("Action: (continue) ");
(void) fflush (stdout);
- *line = '\0';
- (void) fgets (line, sizeof (line), stdin);
- if (*line == '\0' || *line == '\n' || *line == 'c' || *line == 'C')
+ line_length = getline (&line, &line_chars_allocated, stdin);
+ if (line_length <= 0
+ || *line == '\n' || *line == 'c' || *line == 'C')
break;
if (*line == 'a' || *line == 'A')
error (1, 0, "aborted by user");
@@ -259,7 +265,10 @@ do_editor (dir, messagep, repository, changes)
(void) printf ("Unknown input\n");
}
}
- (void) unlink_file (fname);
+ if (line)
+ free (line);
+ if (unlink_file (fname) < 0)
+ error (0, errno, "warning: cannot remove temp file %s", fname);
}
/*
@@ -275,7 +284,6 @@ rcsinfo_proc (repository, template)
{
static char *last_template;
FILE *tfp;
- char line[MAXLINELEN];
/* nothing to do if the last one included is the same as this one */
if (last_template && strcmp (last_template, template) == 0)
@@ -286,14 +294,22 @@ rcsinfo_proc (repository, template)
if ((tfp = fopen (template, "r")) != NULL)
{
- while (fgets (line, sizeof (line), tfp) != NULL)
+ char *line;
+ size_t line_chars_allocated;
+
+ while (getline (&line, &line_chars_allocated, tfp) >= 0)
(void) fputs (line, fp);
- (void) fclose (tfp);
+ if (ferror (tfp))
+ error (0, errno, "warning: cannot read %s", template);
+ if (fclose (tfp) < 0)
+ error (0, errno, "warning: cannot close %s", template);
+ if (line)
+ free (line);
return (0);
}
else
{
- error (0, 0, "Couldn't open rcsinfo template file %s", template);
+ error (0, errno, "Couldn't open rcsinfo template file %s", template);
return (1);
}
}
@@ -334,9 +350,9 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
srepos = Short_Repository (repository);
/* allocate a chunk of memory to hold the title string */
- if (!strlist)
- strlist = xmalloc (MAXLISTLEN);
- strlist[0] = '\0';
+ if (!str_list)
+ str_list = xmalloc (MAXLISTLEN);
+ str_list[0] = '\0';
type = T_TITLE;
(void) walklist (changes, title_proc, NULL);
@@ -346,12 +362,12 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
(void) walklist (changes, title_proc, NULL);
type = T_REMOVED;
(void) walklist (changes, title_proc, NULL);
- title = xmalloc (strlen (srepos) + strlen (strlist) + 1 + 2); /* for 's */
- (void) sprintf (title, "'%s%s'", srepos, strlist);
+ title = xmalloc (strlen (srepos) + strlen (str_list) + 1 + 2); /* for 's */
+ (void) sprintf (title, "'%s%s'", srepos, str_list);
/* to be nice, free up this chunk of memory */
- free (strlist);
- strlist = (char *) NULL;
+ free (str_list);
+ str_list = (char *) NULL;
/* call Parse_Info to do the actual logfile updates */
(void) Parse_Info (CVSROOTADM_LOGINFO, repository, update_logfile_proc, 1);
@@ -373,7 +389,7 @@ update_logfile_proc (repository, filter)
}
/*
- * concatenate each name onto strlist
+ * concatenate each name onto str_list
*/
static int
title_proc (p, closure)
@@ -382,8 +398,8 @@ title_proc (p, closure)
{
if (p->data == (char *) type)
{
- (void) strcat (strlist, " ");
- (void) strcat (strlist, p->key);
+ (void) strcat (str_list, " ");
+ (void) strcat (str_list, p->key);
}
return (0);
}
@@ -409,12 +425,13 @@ logfile_write (repository, filter, title, message, revision, logfp, changes)
FILE *logfp;
List *changes;
{
- char cwd[PATH_MAX], host[MAXHOSTNAMELEN];
+ char cwd[PATH_MAX];
FILE *pipefp, *Popen ();
char *prog = xmalloc (MAXPROGLEN);
char *cp;
int c;
+ /* XXX <woods@web.net> -- this is gross, ugly, and a hack! FIXME! */
/*
* A maximum of 6 %s arguments are supported in the filter
*/
@@ -426,10 +443,8 @@ logfile_write (repository, filter, title, message, revision, logfp, changes)
free (prog);
return (1);
}
- if (gethostname (host, sizeof (host)) < 0)
- (void) strcpy (host, "(unknown)");
(void) fprintf (pipefp, "Update of %s\n", repository);
- (void) fprintf (pipefp, "In directory %s:%s\n\n", host,
+ (void) fprintf (pipefp, "In directory %s:%s\n\n", hostname,
((cp = getwd (cwd)) != NULL) ? cp : cwd);
if (revision && *revision)
(void) fprintf (pipefp, "Revision/Branch: %s\n\n", revision);
@@ -438,7 +453,7 @@ logfile_write (repository, filter, title, message, revision, logfp, changes)
if (logfp != (FILE *) 0)
{
(void) fprintf (pipefp, "Status:\n");
- (void) rewind (logfp);
+ rewind (logfp);
while ((c = getc (logfp)) != EOF)
(void) putc ((char) c, pipefp);
}
diff --git a/gnu/usr.bin/cvs/cvs/main.c b/gnu/usr.bin/cvs/cvs/main.c
index 3751b3c..91e376d 100644
--- a/gnu/usr.bin/cvs/cvs/main.c
+++ b/gnu/usr.bin/cvs/cvs/main.c
@@ -21,6 +21,7 @@
* commit Checks files into the repository
* diff Runs diffs between revisions
* log Prints "rlog" information for files
+ * login Record user, host, repos, password
* add Adds an entry to the repository
* remove Removes an entry from the repository
* status Status info on the revisions
@@ -35,16 +36,40 @@
#include "cvs.h"
#include "patchlevel.h"
-#ifndef lint
-char rcsid[] = "$CVSid: @(#)main.c 1.78 94/10/07 $\n";
-USE(rcsid)
+#if HAVE_KERBEROS
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <krb.h>
+#ifndef HAVE_KRB_GET_ERR_TEXT
+#define krb_get_err_text(status) krb_err_txt[status]
+#endif
#endif
-extern char *getenv ();
+#ifndef lint
+static const char rcsid[] = "$CVSid: @(#)main.c 1.78 94/10/07 $\n";
+USE(rcsid);
+#endif
char *program_name;
-char *command_name = "";
+char *program_path;
+/*
+ * Initialize comamnd_name to "cvs" so that the first call to
+ * read_cvsrc tries to find global cvs options.
+ */
+char *command_name = "cvs";
+/*
+ * Since some systems don't define this...
+ */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+char hostname[MAXHOSTNAMELEN];
+
+#ifdef AUTH_CLIENT_SUPPORT
+int use_authenticating_server = FALSE;
+#endif /* AUTH_CLIENT_SUPPORT */
int use_editor = TRUE;
int use_cvsrc = TRUE;
int cvswrite = !CVSREAD_DFLT;
@@ -53,6 +78,7 @@ int quiet = FALSE;
int trace = FALSE;
int noexec = FALSE;
int logoff = FALSE;
+mode_t cvsumask = UMASK_DFLT;
char *CurDir;
@@ -77,6 +103,9 @@ int diff PROTO((int argc, char **argv));
int history PROTO((int argc, char **argv));
int import PROTO((int argc, char **argv));
int cvslog PROTO((int argc, char **argv));
+#ifdef AUTH_CLIENT_SUPPORT
+int login PROTO((int argc, char **argv));
+#endif /* AUTH_CLIENT_SUPPORT */
int patch PROTO((int argc, char **argv));
int release PROTO((int argc, char **argv));
int cvsremove PROTO((int argc, char **argv));
@@ -85,41 +114,69 @@ int status PROTO((int argc, char **argv));
int tag PROTO((int argc, char **argv));
int update PROTO((int argc, char **argv));
-struct cmd
+const struct cmd
{
char *fullname; /* Full name of the function (e.g. "commit") */
char *nick1; /* alternate name (e.g. "ci") */
char *nick2; /* another alternate names (e.g. "ci") */
int (*func) (); /* Function takes (argc, argv) arguments. */
+#ifdef CLIENT_SUPPORT
+ int (*client_func) (); /* Function to do it via the protocol. */
+#endif
} cmds[] =
{
- { "add", "ad", "new", add },
- { "admin", "adm", "rcs", admin },
- { "checkout", "co", "get", checkout },
- { "commit", "ci", "com", commit },
- { "diff", "di", "dif", diff },
- { "export", "exp", "ex", checkout },
- { "history", "hi", "his", history },
- { "import", "im", "imp", import },
- { "log", "lo", "rlog", cvslog },
- { "rdiff", "patch", "pa", patch },
- { "release", "re", "rel", release },
- { "remove", "rm", "delete", cvsremove },
- { "status", "st", "stat", status },
- { "rtag", "rt", "rfreeze", rtag },
- { "tag", "ta", "freeze", tag },
- { "update", "up", "upd", update },
- { NULL, NULL, NULL, NULL },
+#ifdef CLIENT_SUPPORT
+#define CMD_ENTRY(n1, n2, n3, f1, f2) { n1, n2, n3, f1, f2 }
+#else
+#define CMD_ENTRY(n1, n2, n3, f1, f2) { n1, n2, n3, f1 }
+#endif
+
+ CMD_ENTRY("add", "ad", "new", add, client_add),
+#ifndef CVS_NOADMIN
+ CMD_ENTRY("admin", "adm", "rcs", admin, client_admin),
+#endif
+ CMD_ENTRY("checkout", "co", "get", checkout, client_checkout),
+ CMD_ENTRY("commit", "ci", "com", commit, client_commit),
+ CMD_ENTRY("diff", "di", "dif", diff, client_diff),
+ CMD_ENTRY("export", "exp", "ex", checkout, client_export),
+ CMD_ENTRY("history", "hi", "his", history, client_history),
+ CMD_ENTRY("import", "im", "imp", import, client_import),
+ CMD_ENTRY("log", "lo", "rlog", cvslog, client_log),
+#ifdef AUTH_CLIENT_SUPPORT
+ CMD_ENTRY("login", "logon", "lgn", login, login),
+#endif /* AUTH_CLIENT_SUPPORT */
+ CMD_ENTRY("rdiff", "patch", "pa", patch, client_rdiff),
+ CMD_ENTRY("release", "re", "rel", release, client_release),
+ CMD_ENTRY("remove", "rm", "delete", cvsremove, client_remove),
+ CMD_ENTRY("status", "st", "stat", status, client_status),
+ CMD_ENTRY("rtag", "rt", "rfreeze", rtag, client_rtag),
+ CMD_ENTRY("tag", "ta", "freeze", tag, client_tag),
+ CMD_ENTRY("update", "up", "upd", update, client_update),
+
+#ifdef SERVER_SUPPORT
+ /*
+ * The client_func is also server because we might have picked up a
+ * CVSROOT environment variable containing a colon. The client will send
+ * the real root later.
+ */
+ CMD_ENTRY("server", "server", "server", server, server),
+#endif
+ CMD_ENTRY(NULL, NULL, NULL, NULL, NULL),
+
+#undef CMD_ENTRY
};
-static char *usg[] =
+static const char *const usg[] =
{
"Usage: %s [cvs-options] command [command-options] [files...]\n",
" Where 'cvs-options' are:\n",
" -H Displays Usage information for command\n",
" -Q Cause CVS to be really quiet.\n",
" -q Cause CVS to be somewhat quiet.\n",
+#ifdef AUTH_CLIENT_SUPPORT
+ " -a Use the authenticating server, not rsh.\n",
+#endif /* AUTH_CLIENT_SUPPORT */
" -r Make checked-out files read-only\n",
" -w Make checked-out files read-write (default)\n",
" -l Turn History logging off\n",
@@ -130,6 +187,9 @@ static char *usg[] =
" -e editor Use 'editor' for editing log information\n",
" -d CVS_root Overrides $CVSROOT as the root of the CVS tree\n",
" -f Do not use the ~/.cvsrc file\n",
+#ifdef CLIENT_SUPPORT
+ " -z # Use 'gzip -#' for net traffic if possible.\n",
+#endif
"\n",
" and where 'command' is:\n",
" add Adds a new file/directory to the repository\n",
@@ -141,6 +201,9 @@ static char *usg[] =
" import Import sources into CVS, using vendor branches\n",
" export Export sources from CVS, similar to checkout\n",
" log Prints out 'rlog' information for files\n",
+#ifdef AUTH_CLIENT_SUPPORT
+ " login Prompt for password for authenticating server.\n",
+#endif /* AUTH_CLIENT_SUPPORT */
" rdiff 'patch' format diffs between releases\n",
" release Indicate that a Module is no longer in use\n",
" remove Removes an entry from the repository\n",
@@ -157,29 +220,61 @@ main_cleanup ()
exit (1);
}
+static void
+error_cleanup ()
+{
+ Lock_Cleanup();
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_cleanup (0);
+#endif
+}
+
int
main (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
extern char *version_string;
- char *cp;
- struct cmd *cm;
- int c, help = FALSE, err = 0;
+ extern char *config_string;
+ char *cp, *end;
+ const struct cmd *cm;
+ int c, err = 0;
+ static int help = FALSE, version_flag = FALSE;
int rcsbin_update_env, cvs_update_env = 0;
char tmp[PATH_MAX];
+ static struct option long_options[] =
+ {
+ {"help", 0, &help, TRUE},
+ {"version", 0, &version_flag, TRUE},
+ {0, 0, 0, 0}
+ };
+ /* `getopt_long' stores the option index here, but right now we
+ don't use it. */
+ int option_index = 0;
+
+ error_set_cleanup (error_cleanup);
+
+/* The IBM TCP/IP library under OS/2 needs to be initialized: */
+#ifdef NEED_CALL_SOCKINIT
+ if (SockInit () != TRUE)
+ {
+ fprintf (stderr, "SockInit() failed!\n");
+ exit (1);
+ }
+#endif /* NEED_CALL_SOCKINIT */
/*
* Just save the last component of the path for error messages
*/
- if ((program_name = strrchr (argv[0], '/')) == NULL)
- program_name = argv[0];
- else
- program_name++;
+ program_path = xstrdup (argv[0]);
+ program_name = last_component (argv[0]);
CurDir = xmalloc (PATH_MAX);
+#ifndef SERVER_SUPPORT
if (!getwd (CurDir))
error (1, 0, "cannot get working directory: %s", CurDir);
+#endif
/*
* Query the environment variables up-front, so that
@@ -196,6 +291,8 @@ main (argc, argv)
Editor = cp;
else if ((cp = getenv (EDITOR2_ENV)) != NULL)
Editor = cp;
+ else if ((cp = getenv (EDITOR3_ENV)) != NULL)
+ Editor = cp;
if ((cp = getenv (CVSROOT_ENV)) != NULL)
{
CVSroot = cp;
@@ -203,12 +300,36 @@ main (argc, argv)
}
if (getenv (CVSREAD_ENV) != NULL)
cvswrite = FALSE;
+ if ((cp = getenv (CVSUMASK_ENV)) != NULL)
+ {
+ /* FIXME: Should be accepting symbolic as well as numeric mask. */
+ cvsumask = strtol (cp, &end, 8) & 0777;
+ if (*end != '\0')
+ error (1, errno, "invalid umask value in %s (%s)",
+ CVSUMASK_ENV, cp);
+ }
+
+ /*
+ * Scan cvsrc file for global options.
+ */
+ read_cvsrc(&argc, &argv);
+ /* This has the effect of setting getopt's ordering to REQUIRE_ORDER,
+ which is what we need to distinguish between global options and
+ command options. FIXME: It would appear to be possible to do this
+ much less kludgily by passing "+" as the first character to the
+ option string we pass to getopt_long. */
optind = 1;
- while ((c = getopt (argc, argv, "Qqrwtnlvb:e:d:Hf")) != -1)
- {
+
+ while ((c = getopt_long
+ (argc, argv, "Qqrawtnlvb:e:d:Hfz:", long_options, &option_index))
+ != EOF)
+ {
switch (c)
- {
+ {
+ case 0:
+ /* getopt_long took care of setting the flag. */
+ break;
case 'Q':
really_quiet = TRUE;
/* FALL THROUGH */
@@ -218,6 +339,11 @@ main (argc, argv)
case 'r':
cvswrite = FALSE;
break;
+#ifdef AUTH_CLIENT_SUPPORT
+ case 'a':
+ use_authenticating_server = TRUE;
+ break;
+#endif /* AUTH_CLIENT_SUPPORT */
case 'w':
cvswrite = TRUE;
break;
@@ -230,11 +356,7 @@ main (argc, argv)
logoff = TRUE;
break;
case 'v':
- (void) fputs (version_string, stdout);
- (void) sprintf (tmp, "Patch Level: %d\n", PATCHLEVEL);
- (void) fputs (tmp, stdout);
- (void) fputs ("\nCopyright (c) 1993-1994 Brian Berliner\nCopyright (c) 1993-1994 david d `zoo' zuhn\nCopyright (c) 1992, Brian Berliner and Jeff Polk\nCopyright (c) 1989-1992, Brian Berliner\n\nCVS may be copied only under the terms of the GNU General Public License,\na copy of which can be found with the CVS distribution kit.\n", stdout);
- exit (0);
+ version_flag = TRUE;
break;
case 'b':
Rcsbin = optarg;
@@ -254,55 +376,181 @@ main (argc, argv)
case 'f':
use_cvsrc = FALSE;
break;
+#ifdef CLIENT_SUPPORT
+ case 'z':
+ gzip_level = atoi (optarg);
+ if (gzip_level <= 0 || gzip_level > 9)
+ error (1, 0,
+ "gzip compression level must be between 1 and 9");
+ break;
+#endif
case '?':
default:
- usage (usg);
+ usage (usg);
}
}
+
+ if (version_flag == TRUE)
+ {
+ (void) fputs (version_string, stdout);
+ (void) fputs (config_string, stdout);
+ (void) sprintf (tmp, "Patch Level: %d\n", PATCHLEVEL);
+ (void) fputs (tmp, stdout);
+ (void) fputs ("\n", stdout);
+ (void) fputs ("Copyright (c) 1993-1994 Brian Berliner\n", stdout);
+ (void) fputs ("Copyright (c) 1993-1994 david d `zoo' zuhn\n", stdout);
+ (void) fputs ("Copyright (c) 1992, Brian Berliner and Jeff Polk\n", stdout);
+ (void) fputs ("Copyright (c) 1989-1992, Brian Berliner\n", stdout);
+ (void) fputs ("\n", stdout);
+ (void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
+ (void) fputs ("a copy of which can be found with the CVS distribution kit.\n", stdout);
+ exit (0);
+ }
+
argc -= optind;
argv += optind;
if (argc < 1)
usage (usg);
+#ifdef HAVE_KERBEROS
+ /* If we are invoked with a single argument "kserver", then we are
+ running as Kerberos server as root. Do the authentication as
+ the very first thing, to minimize the amount of time we are
+ running as root. */
+ if (strcmp (argv[0], "kserver") == 0)
+ {
+ int status;
+ char instance[INST_SZ];
+ struct sockaddr_in peer;
+ struct sockaddr_in laddr;
+ int len;
+ KTEXT_ST ticket;
+ AUTH_DAT auth;
+ char version[KRB_SENDAUTH_VLEN];
+ Key_schedule sched;
+ char user[ANAME_SZ];
+ struct passwd *pw;
+
+ strcpy (instance, "*");
+ len = sizeof peer;
+ if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0
+ || getsockname (STDIN_FILENO, (struct sockaddr *) &laddr,
+ &len) < 0)
+ {
+ printf ("E Fatal error, aborting.\n\
+error %s getpeername or getsockname failed\n", strerror (errno));
+ exit (1);
+ }
+
+ status = krb_recvauth (KOPT_DO_MUTUAL, STDIN_FILENO, &ticket, "rcmd",
+ instance, &peer, &laddr, &auth, "", sched,
+ version);
+ if (status != KSUCCESS)
+ {
+ printf ("E Fatal error, aborting.\n\
+error 0 kerberos: %s\n", krb_get_err_text(status));
+ exit (1);
+ }
+
+ /* Get the local name. */
+ status = krb_kntoln (&auth, user);
+ if (status != KSUCCESS)
+ {
+ printf ("E Fatal error, aborting.\n\
+error 0 kerberos: can't get local name: %s\n", krb_get_err_text(status));
+ exit (1);
+ }
+
+ pw = getpwnam (user);
+ if (pw == NULL)
+ {
+ printf ("E Fatal error, aborting.\n\
+error 0 %s: no such user\n", user);
+ exit (1);
+ }
+
+ initgroups (pw->pw_name, pw->pw_gid);
+ setgid (pw->pw_gid);
+ setuid (pw->pw_uid);
+ /* Inhibit access by randoms. Don't want people randomly
+ changing our temporary tree before we check things in. */
+ umask (077);
+
+#if HAVE_PUTENV
+ /* Set LOGNAME and USER in the environment, in case they are
+ already set to something else. */
+ {
+ char *env;
+
+ env = xmalloc (sizeof "LOGNAME=" + strlen (user));
+ (void) sprintf (env, "LOGNAME=%s", user);
+ (void) putenv (env);
+
+ env = xmalloc (sizeof "USER=" + strlen (user));
+ (void) sprintf (env, "USER=%s", user);
+ (void) putenv (env);
+ }
+#endif
+
+ /* Pretend we were invoked as a plain server. */
+ argv[0] = "server";
+ }
+#endif /* HAVE_KERBEROS */
+
+
+#if defined(AUTH_SERVER_SUPPORT) && defined(SERVER_SUPPORT)
+ if (strcmp (argv[0], "pserver") == 0)
+ {
+ /* Gets username and password from client, authenticates, then
+ switches to run as that user and sends an ACK back to the
+ client. */
+ authenticate_connection ();
+
+ /* Pretend we were invoked as a plain server. */
+ argv[0] = "server";
+ }
+#endif /* AUTH_SERVER_SUPPORT && SERVER_SUPPORT */
+
+
#ifdef CVSADM_ROOT
/*
* See if we are able to find a 'better' value for CVSroot in the
* CVSADM_ROOT directory.
*/
+#ifdef SERVER_SUPPORT
+ if (strcmp (argv[0], "server") == 0 && CVSroot == NULL)
+ CVSADM_Root = NULL;
+ else
+ CVSADM_Root = Name_Root((char *) NULL, (char *) NULL);
+#else /* No SERVER_SUPPORT */
CVSADM_Root = Name_Root((char *) NULL, (char *) NULL);
+#endif /* No SERVER_SUPPORT */
if (CVSADM_Root != NULL)
{
- if (CVSroot == NULL)
+ if (CVSroot == NULL || !cvs_update_env)
{
CVSroot = CVSADM_Root;
cvs_update_env = 1; /* need to update environment */
}
+#ifdef CLIENT_SUPPORT
+ else if (!getenv ("CVS_IGNORE_REMOTE_ROOT"))
+#else
else
+#endif
{
/*
* Now for the hard part, compare the two directories. If they
* are not identical, then abort this command.
*/
- if ((strcmp (CVSroot, CVSADM_Root) != 0) &&
+ if ((fncmp (CVSroot, CVSADM_Root) != 0) &&
!same_directories(CVSroot, CVSADM_Root))
{
- error (0, 0, "%s value for CVS Root found in %s",
- CVSADM_Root, CVSADM_ROOT);
- if (cvs_update_env)
- {
- error (0, 0, "does not match command line -d %s setting",
- CVSroot);
- error (1, 0,
- "you may wish to try the cvs command again without the -d option ");
- }
- else
- {
- error (0, 0,
- "does not match CVSROOT environment value of %s",
- CVSroot);
- error (1, 0,
- "you may wish to unsetenv CVSROOT and try again");
- }
+ error (0, 0, "%s value for CVS Root found in %s",
+ CVSADM_Root, CVSADM_ROOT);
+ error (0, 0, "does not match command line -d %s setting",
+ CVSroot);
+ error (1, 0,
+ "you may wish to try the cvs command again without the -d option ");
}
}
}
@@ -322,6 +570,9 @@ main (argc, argv)
* we assume that we can't work in the repository.
* BUT, only if the history file exists.
*/
+#ifdef SERVER_SUPPORT
+ if (strcmp (command_name, "server") != 0 || CVSroot != NULL)
+#endif
{
char path[PATH_MAX];
int save_errno;
@@ -330,16 +581,23 @@ main (argc, argv)
error (1, 0, "You don't have a %s environment variable",
CVSROOT_ENV);
(void) sprintf (path, "%s/%s", CVSroot, CVSROOTADM);
- if (access (path, R_OK | X_OK))
+ if (!isaccessible (path, R_OK | X_OK))
{
save_errno = errno;
+#ifdef CLIENT_SUPPORT
+ if (strchr (CVSroot, ':') == NULL)
+ {
+#endif
error (0, 0,
"Sorry, you don't have sufficient access to %s", CVSroot);
error (1, save_errno, "%s", path);
+#ifdef CLIENT_SUPPORT
+ }
+#endif
}
(void) strcat (path, "/");
(void) strcat (path, CVSROOTADM_HISTORY);
- if (isfile (path) && access (path, R_OK | W_OK))
+ if (isfile (path) && !isaccessible (path, R_OK | W_OK))
{
save_errno = errno;
error (0, 0,
@@ -349,6 +607,16 @@ main (argc, argv)
}
}
+#ifdef SERVER_SUPPORT
+ if (strcmp (command_name, "server") == 0)
+ /* This is only used for writing into the history file. Might
+ be nice to have hostname and/or remote path, on the other hand
+ I'm not sure whether it is worth the trouble. */
+ strcpy (CurDir, "<remote>");
+ else if (!getwd (CurDir))
+ error (1, 0, "cannot get working directory: %s", CurDir);
+#endif
+
#ifdef HAVE_PUTENV
/* Now, see if we should update the environment with the Rcsbin value */
if (cvs_update_env)
@@ -404,11 +672,30 @@ main (argc, argv)
else
{
command_name = cm->fullname; /* Global pointer for later use */
+
+ /* make sure we clean up on error */
+#ifdef SIGHUP
(void) SIG_register (SIGHUP, main_cleanup);
+ (void) SIG_register (SIGHUP, Lock_Cleanup);
+#endif
+#ifdef SIGINT
(void) SIG_register (SIGINT, main_cleanup);
+ (void) SIG_register (SIGINT, Lock_Cleanup);
+#endif
+#ifdef SIGQUIT
(void) SIG_register (SIGQUIT, main_cleanup);
+ (void) SIG_register (SIGQUIT, Lock_Cleanup);
+#endif
+#ifdef SIGPIPE
(void) SIG_register (SIGPIPE, main_cleanup);
+ (void) SIG_register (SIGPIPE, Lock_Cleanup);
+#endif
+#ifdef SIGTERM
(void) SIG_register (SIGTERM, main_cleanup);
+ (void) SIG_register (SIGTERM, Lock_Cleanup);
+#endif
+
+ gethostname(hostname, sizeof (hostname));
#ifdef HAVE_SETVBUF
/*
@@ -422,8 +709,19 @@ main (argc, argv)
if (use_cvsrc)
read_cvsrc(&argc, &argv);
+#ifdef CLIENT_SUPPORT
+ /* If cvsroot contains a colon, try to do it via the protocol. */
+ {
+ char *p = CVSroot == NULL ? NULL : strchr (CVSroot, ':');
+ if (p)
+ err = (*(cm->client_func)) (argc, argv);
+ else
+ err = (*(cm->func)) (argc, argv);
+ }
+#else /* No CLIENT_SUPPORT */
err = (*(cm->func)) (argc, argv);
+#endif /* No CLIENT_SUPPORT */
}
/*
* If the command's error count is modulo 256, we need to change it
@@ -462,7 +760,7 @@ Make_Date (rawdate)
void
usage (cpp)
- register char **cpp;
+ register const char *const *cpp;
{
(void) fprintf (stderr, *cpp++, program_name, command_name);
for (; *cpp; cpp++)
diff --git a/gnu/usr.bin/cvs/cvs/modules.c b/gnu/usr.bin/cvs/cvs/modules.c
index 384fbfd..528287a 100644
--- a/gnu/usr.bin/cvs/cvs/modules.c
+++ b/gnu/usr.bin/cvs/cvs/modules.c
@@ -21,10 +21,11 @@
*/
#include "cvs.h"
+#include "save-cwd.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)modules.c 1.62 94/09/29 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)modules.c 1.62 94/09/29 $";
+USE(rcsid);
#endif
struct sortrec
@@ -35,7 +36,7 @@ struct sortrec
char *comment;
};
-static int sort_order PROTO((CONST PTR l, CONST PTR r));
+static int sort_order PROTO((const PTR l, const PTR r));
static void save_d PROTO((char *k, int ks, char *d, int ds));
@@ -83,7 +84,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
char *mname;
enum mtype m_type;
char *msg;
- int (*callback_proc) ();
+ CALLBACKPROC callback_proc;
char *where;
int shorten;
int local_specified;
@@ -92,26 +93,39 @@ do_module (db, mname, m_type, msg, callback_proc, where,
{
char *checkin_prog = NULL;
char *checkout_prog = NULL;
+ char *export_prog = NULL;
char *tag_prog = NULL;
char *update_prog = NULL;
- char cwd[PATH_MAX];
+ struct saved_cwd cwd;
char line[MAXLINELEN];
- char *xmodargv[MAXFILEPERDIR];
+ int modargc;
+ int xmodargc;
char **modargv;
+ char *xmodargv[MAXFILEPERDIR];
char *value;
char *zvalue;
char *mwhere = NULL;
char *mfile = NULL;
char *spec_opt = NULL;
char xvalue[PATH_MAX];
- int modargc, alias = 0;
+ int alias = 0;
datum key, val;
char *cp;
int c, err = 0;
+#ifdef SERVER_SUPPORT
+ if (trace)
+ {
+ fprintf (stderr, "%c-> do_module (%s, %s, %s, %s)\n",
+ (server_active) ? 'S' : ' ',
+ mname, msg, where ? where : "",
+ extra_arg ? extra_arg : "");
+ }
+#endif
+
/* remember where we start */
- if (getwd (cwd) == NULL)
- error (1, 0, "cannot get current working directory: %s", cwd);
+ if (save_cwd (&cwd))
+ exit (1);
/* if this is a directory to ignore, add it to that list */
if (mname[0] == '!' && mname[1] != '\0')
@@ -329,18 +343,24 @@ do_module (db, mname, m_type, msg, callback_proc, where,
err++;
goto out;
}
- if (!isfile (CVSADM) && !isfile (OCVSADM))
+ if (!isfile (CVSADM))
{
char nullrepos[PATH_MAX];
(void) sprintf (nullrepos, "%s/%s/%s", CVSroot,
CVSROOTADM, CVSNULLREPOS);
if (!isfile (nullrepos))
- (void) mkdir (nullrepos, 0777);
+ {
+ mode_t omask;
+ omask = umask (cvsumask);
+ (void) CVS_MKDIR (nullrepos, 0777);
+ (void) umask (omask);
+ }
if (!isdir (nullrepos))
error (1, 0, "there is no repository %s", nullrepos);
- Create_Admin (".", nullrepos, (char *) NULL, (char *) NULL);
+ Create_Admin (".", dir,
+ nullrepos, (char *) NULL, (char *) NULL);
if (!noexec)
{
FILE *fp;
@@ -348,6 +368,10 @@ do_module (db, mname, m_type, msg, callback_proc, where,
fp = open_file (CVSADM_ENTSTAT, "w+");
if (fclose (fp) == EOF)
error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_entstat (dir, nullrepos);
+#endif
}
}
out:
@@ -372,7 +396,8 @@ do_module (db, mname, m_type, msg, callback_proc, where,
(void) sprintf (line, "%s %s", "XXX", value);
/* turn the line into an argv[] array */
- line2argv (&modargc, xmodargv, line);
+ line2argv (&xmodargc, xmodargv, line);
+ modargc = xmodargc;
modargv = xmodargv;
/* parse the args */
@@ -397,6 +422,9 @@ do_module (db, mname, m_type, msg, callback_proc, where,
case 'o':
checkout_prog = optarg;
break;
+ case 'e':
+ export_prog = optarg;
+ break;
case 't':
tag_prog = optarg;
break;
@@ -451,8 +479,12 @@ do_module (db, mname, m_type, msg, callback_proc, where,
err += callback_proc (&modargc, modargv, where, mwhere, mfile, shorten,
local_specified, mname, msg);
- /* clean up */
- free_names (&modargc, modargv);
+#if 0
+ /* FIXME: I've fixed this so that the correct arguments are called,
+ but now this fails because there is code below this point that
+ uses optarg values extracted from the arg vector. */
+ free_names (&xmodargc, xmodargv);
+#endif
/* if there were special include args, process them now */
@@ -495,6 +527,16 @@ do_module (db, mname, m_type, msg, callback_proc, where,
}
/* write out the checkin/update prog files if necessary */
+#ifdef SERVER_SUPPORT
+ if (err == 0 && !noexec && m_type == CHECKOUT && server_expanding)
+ {
+ if (checkin_prog != NULL)
+ server_prog (where ? where : mname, checkin_prog, PROG_CHECKIN);
+ if (update_prog != NULL)
+ server_prog (where ? where : mname, update_prog, PROG_UPDATE);
+ }
+ else
+#endif
if (err == 0 && !noexec && m_type == CHECKOUT && run_module_prog)
{
FILE *fp;
@@ -516,23 +558,26 @@ do_module (db, mname, m_type, msg, callback_proc, where,
}
/* cd back to where we started */
- if (chdir (cwd) < 0)
- error (1, errno, "failed chdir to %s!", cwd);
+ if (restore_cwd (&cwd, NULL))
+ exit (1);
+ free_cwd (&cwd);
/* run checkout or tag prog if appropriate */
if (err == 0 && run_module_prog)
{
if ((m_type == TAG && tag_prog != NULL) ||
- (m_type == CHECKOUT && checkout_prog != NULL))
+ (m_type == CHECKOUT && checkout_prog != NULL) ||
+ (m_type == EXPORT && export_prog != NULL))
{
/*
- * If a relative pathname is specified as the checkout or
- * tag proc, try to tack on the current "where" value.
+ * If a relative pathname is specified as the checkout, tag
+ * or export proc, try to tack on the current "where" value.
* if we can't find a matching program, just punt and use
* whatever is specified in the modules file.
*/
char real_prog[PATH_MAX];
- char *prog = (m_type == TAG ? tag_prog : checkout_prog);
+ char *prog = (m_type == TAG ? tag_prog :
+ (m_type == CHECKOUT ? checkout_prog : export_prog));
char *real_where = (where != NULL ? where : mwhere);
if ((*prog != '/') && (*prog != '.'))
@@ -594,7 +639,10 @@ static struct sortrec *s_head;
static int s_max = 0; /* Number of elements allocated */
static int s_count = 0; /* Number of elements used */
-static int Status;
+static int Status; /* Nonzero if the user is
+ interested in status
+ information as well as
+ module name */
static char def_status[] = "NONE";
/* Sort routine for qsort:
@@ -604,12 +652,12 @@ static char def_status[] = "NONE";
*/
static int
sort_order (l, r)
- CONST PTR l;
- CONST PTR r;
+ const PTR l;
+ const PTR r;
{
int i;
- CONST struct sortrec *left = (CONST struct sortrec *) l;
- CONST struct sortrec *right = (CONST struct sortrec *) r;
+ const struct sortrec *left = (const struct sortrec *) l;
+ const struct sortrec *right = (const struct sortrec *) r;
if (Status)
{
@@ -700,6 +748,9 @@ save_d (k, ks, d, ds)
s_count++;
}
+/* Print out the module database as we know it. If STATUS is
+ non-zero, print out status information for each module. */
+
void
cat_module (status)
int status;
@@ -827,5 +878,7 @@ cat_module (status)
*cp++ = '\0';
(void) printf ("%s\n", cp2);
}
+
+ free_names(&moduleargc, moduleargv);
}
}
diff --git a/gnu/usr.bin/cvs/cvs/no_diff.c b/gnu/usr.bin/cvs/cvs/no_diff.c
index ec3e641..281d348 100644
--- a/gnu/usr.bin/cvs/cvs/no_diff.c
+++ b/gnu/usr.bin/cvs/cvs/no_diff.c
@@ -17,8 +17,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)no_diff.c 1.39 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)no_diff.c 1.39 94/10/07 $";
+USE(rcsid);
#endif
int
@@ -34,6 +34,7 @@ No_Difference (file, vers, entries, repository, update_dir)
int ret;
char *ts, *options;
int retcode = 0;
+ char *tocvsPath;
if (!vers->srcfile || !vers->srcfile->path)
return (-1); /* different since we couldn't tell */
@@ -48,20 +49,39 @@ No_Difference (file, vers, entries, repository, update_dir)
run_arg (vers->srcfile->path);
if ((retcode = run_exec (RUN_TTY, tmpnam (tmp), RUN_TTY, RUN_REALLY)) == 0)
{
+#if 0
+ /* Why would we want to munge the modes? And only if the timestamps
+ are different? And even for commands like "cvs status"???? */
if (!iswritable (file)) /* fix the modes as a side effect */
xchmod (file, 1);
+#endif
+
+ tocvsPath = wrap_tocvs_process_file (file);
/* do the byte by byte compare */
- if (xcmp (file, tmp) == 0)
+ if (xcmp (tocvsPath == NULL ? file : tocvsPath, tmp) == 0)
{
+#if 0
+ /* Why would we want to munge the modes? And only if the
+ timestamps are different? And even for commands like
+ "cvs status"???? */
if (cvswrite == FALSE) /* fix the modes as a side effect */
xchmod (file, 0);
+#endif
/* no difference was found, so fix the entries file */
ts = time_stamp (file);
Register (entries, file,
vers->vn_user ? vers->vn_user : vers->vn_rcs, ts,
options, vers->tag, vers->date, (char *) 0);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ /* We need to update the entries line on the client side. */
+ server_update_entries
+ (file, update_dir, repository, SERVER_UPDATED);
+ }
+#endif
free (ts);
/* update the entdata pointer in the vers_ts structure */
@@ -72,10 +92,25 @@ No_Difference (file, vers, entries, repository, update_dir)
}
else
ret = 1; /* files were really different */
+ if (tocvsPath)
+ {
+ /* Need to call unlink myself because the noexec variable
+ * has been set to 1. */
+ if (trace)
+ (void) fprintf (stderr, "%c-> unlink (%s)\n",
+#ifdef SERVER_SUPPORT
+ (server_active) ? 'S' : ' ',
+#else
+ ' ',
+#endif
+ tocvsPath);
+ if (unlink (tocvsPath) < 0)
+ error (0, errno, "could not remove %s", tocvsPath);
+ }
}
else
{
- if (update_dir[0] == '\0')
+ if (update_dir[0] == '\0')
error (0, retcode == -1 ? errno : 0,
"could not check out revision %s of %s",
vers->vn_user, file);
@@ -87,7 +122,12 @@ No_Difference (file, vers, entries, repository, update_dir)
}
if (trace)
- (void) fprintf (stderr, "-> unlink(%s)\n", tmp);
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> unlink2 (%s)\n",
+ (server_active) ? 'S' : ' ', tmp);
+#else
+ (void) fprintf (stderr, "-> unlink (%s)\n", tmp);
+#endif
if (unlink (tmp) < 0)
error (0, errno, "could not remove %s", tmp);
free (options);
diff --git a/gnu/usr.bin/cvs/cvs/options.h b/gnu/usr.bin/cvs/cvs/options.h
index ad07c14..9944653 100644
--- a/gnu/usr.bin/cvs/cvs/options.h
+++ b/gnu/usr.bin/cvs/cvs/options.h
@@ -53,26 +53,30 @@
/*
* The "diff" program to execute when creating patch output. This "diff"
- * must support the "-c" option for context diffing. Specify a full pathname
- * if your site wants to use a particular diff. If you are using the GNU
- * version of diff (version 1.15 or later), this should be "diff -a".
+ * must support the "-c" option for context diffing. Specify a full
+ * pathname if your site wants to use a particular diff. If you are
+ * using the GNU version of diff (version 1.15 or later), this should
+ * be "diff -a".
*
- * NOTE: this program is only used for the ``patch'' sub-command. The other
- * commands use rcsdiff which will use whatever version of diff was specified
+ * NOTE: this program is only used for the ``patch'' sub-command (and
+ * for ``update'' if you are using the server). The other commands
+ * use rcsdiff which will use whatever version of diff was specified
* when rcsdiff was built on your system.
*/
+
#ifndef DIFF
-#define DIFF "diff"
+#define DIFF "/usr/bin/diff -a"
#endif
/*
* The "grep" program to execute when checking to see if a merged file had
- * any conflicts. This "grep" must support the "-s" option and a standard
+ * any conflicts. This "grep" must support a standard basic
* regular expression as an argument. Specify a full pathname if your site
* wants to use a particular grep.
*/
+
#ifndef GREP
-#define GREP "grep"
+#define GREP "grep"
#endif
/*
@@ -93,6 +97,15 @@
#endif
/*
+ * The "patch" program to run when using the CVS server and accepting
+ * patches across the network. Specify a full pathname if your site
+ * wants to use a particular patch.
+ */
+#ifndef PATCH_PROGRAM
+#define PATCH_PROGRAM "patch"
+#endif
+
+/*
* By default, RCS programs are executed with the shell or through execlp(),
* so the user's PATH environment variable is searched. If you'd like to
* bind all RCS programs to a certain directory (perhaps one not in most
@@ -120,6 +133,30 @@
#endif
/*
+ * The default umask to use when creating or otherwise setting file or
+ * directory permissions in the repository. Must be a value in the
+ * range of 0 through 0777. For example, a value of 002 allows group
+ * rwx access and world rx access; a value of 007 allows group rwx
+ * access but no world access. This value is overridden by the value
+ * of the CVSUMASK environment variable, which is interpreted as an
+ * octal number.
+ */
+#ifndef UMASK_DFLT
+#define UMASK_DFLT 002
+#endif
+
+/*
+ * The cvs admin command is restricted to the members of the group
+ * CVS_ADMIN_GROUP. If this group does not exist, all users are
+ * allowed to run cvs admin. To disable the cvs admin for all users,
+ * create an empty group CVS_ADMIN_GROUP. To disable access control for
+ * cvs admin, comment out the define below.
+ */
+#ifndef CVS_ADMIN_GROUP
+#define CVS_ADMIN_GROUP "cvsadmin"
+#endif
+
+/*
* The Repository file holds the path to the directory within the source
* repository that contains the RCS ,v files for each CVS working directory.
* This path is either a full-path or a path relative to CVSROOT.
@@ -175,6 +212,19 @@
#endif
/*
+ * The "cvs admin" command allows people to get around most of the logging
+ * and info procedures within CVS. For exmaple, "cvs tag tagname filename"
+ * will perform some validity checks on the tag, while "cvs admin -Ntagname"
+ * will not perform those checks. For this reason, some sites may wish to
+ * disable the admin function completely.
+ *
+ * To disable the admin function, uncomment the lines below.
+ */
+#ifndef CVS_NOADMIN
+/* #define CVS_NOADMIN */
+#endif
+
+/*
* The "cvs diff" command accepts all the single-character options that GNU
* diff (1.15) accepts. Except -D. GNU diff uses -D as a way to put
* cpp-style #define's around the output differences. CVS, by default, uses
@@ -186,6 +236,40 @@
#define CVS_DIFFDATE
#endif
+/*
+ * define this to enable the SETXID support (see FAQ 4D.13)
+ */
+#ifndef SETXID_SUPPORT
+/* #define SETXID_SUPPORT */
+#endif
+
+/*
+ * The authenticated client/server is under construction. Don't
+ * define either of these unless you're testing them, in which case
+ * you're me and you already know that.
+ */
+/* #undef AUTH_CLIENT_SUPPORT */
+/* #undef AUTH_SERVER_SUPPORT */
+
+/*
+ * If you are working with a large remote repository and a 'cvs checkout' is
+ * swamping your network and memory, define these to enable flow control.
+ * You will end up with even less guarantees of a consistant checkout,
+ * but that may be better than no checkout at all. The master server process
+ * will monitor how far it is getting behind, if it reaches the high water
+ * mark, it will signal the child process to stop generating data when
+ * convenient (ie: no locks are held, currently at the beginning of a
+ * new directory). Once the buffer has drained sufficiently to reach the
+ * low water mark, it will be signalled to start again.
+ * -- EXPERIMENTAL! -- A better solution may be in the works.
+ * You may override the default hi/low watermarks here too.
+ */
+#ifndef SERVER_FLOWCONTROL
+# define SERVER_FLOWCONTROL
+# define SERVER_HI_WATER (2 * 1024 * 1024)
+# define SERVER_LO_WATER (1 * 1024 * 1024)
+#endif
+
/* End of CVS configuration section */
/*
diff --git a/gnu/usr.bin/cvs/cvs/parseinfo.c b/gnu/usr.bin/cvs/cvs/parseinfo.c
index 17cf1da..6d59884 100644
--- a/gnu/usr.bin/cvs/cvs/parseinfo.c
+++ b/gnu/usr.bin/cvs/cvs/parseinfo.c
@@ -9,20 +9,22 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)parseinfo.c 1.18 94/09/23 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)parseinfo.c 1.18 94/09/23 $";
+USE(rcsid);
#endif
/*
* Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
- * each line in the file that matches the REPOSITORY.
+ * the first line in the file that matches the REPOSITORY, or if ALL != 0, any lines
+ * matching "ALL", or if no lines match, the last line matching "DEFAULT".
+ *
* Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
*/
int
Parse_Info (infofile, repository, callproc, all)
char *infofile;
char *repository;
- int (*callproc) ();
+ CALLPROC callproc;
int all;
{
int err = 0;
@@ -30,9 +32,10 @@ Parse_Info (infofile, repository, callproc, all)
char infopath[PATH_MAX];
char line[MAXLINELEN];
char *default_value = NULL;
+ char *expanded_value= NULL;
int callback_done, line_number;
char *cp, *exp, *value, *srepos;
- CONST char *regex_err;
+ const char *regex_err;
if (CVSroot == NULL)
{
@@ -50,6 +53,10 @@ Parse_Info (infofile, repository, callproc, all)
/* strip off the CVSROOT if repository was absolute */
srepos = Short_Repository (repository);
+ if (trace)
+ (void) fprintf (stderr, "-> ParseInfo(%s, %s, %s)\n",
+ infopath, srepos, all ? "ALL" : "not ALL");
+
/* search the info file for lines that match */
callback_done = line_number = 0;
while (fgets (line, sizeof (line), fp_info) != NULL)
@@ -91,6 +98,16 @@ Parse_Info (infofile, repository, callproc, all)
if ((cp = strrchr (value, '\n')) != NULL)
*cp = '\0';
+ expanded_value = expand_path (value);
+ if (!expanded_value)
+ {
+ error (0, 0,
+ "Invalid environmental variable at line %d in file %s",
+ line_number, infofile);
+ continue;
+
+ }
+
/*
* At this point, exp points to the regular expression, and value
* points to the value to call the callback routine with. Evaluate
@@ -101,25 +118,29 @@ Parse_Info (infofile, repository, callproc, all)
/* save the default value so we have it later if we need it */
if (strcmp (exp, "DEFAULT") == 0)
{
- default_value = xstrdup (value);
+ default_value = xstrdup (expanded_value);
continue;
}
/*
* For a regular expression of "ALL", do the callback always We may
- * execute lots of ALL callbacks in addition to one regular matching
+ * execute lots of ALL callbacks in addition to *one* regular matching
* callback or default
*/
if (strcmp (exp, "ALL") == 0)
{
if (all)
- err += callproc (repository, value);
+ err += callproc (repository, expanded_value);
else
error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
line_number, infofile);
continue;
}
+ if (callback_done)
+ /* only first matching, plus "ALL"'s */
+ continue;
+
/* see if the repository matched this regular expression */
if ((regex_err = re_comp (exp)) != NULL)
{
@@ -128,10 +149,10 @@ Parse_Info (infofile, repository, callproc, all)
continue;
}
if (re_exec (srepos) == 0)
- continue; /* no match */
+ continue; /* no match */
/* it did, so do the callback and note that we did one */
- err += callproc (repository, value);
+ err += callproc (repository, expanded_value);
callback_done = 1;
}
(void) fclose (fp_info);
@@ -143,6 +164,8 @@ Parse_Info (infofile, repository, callproc, all)
/* free up space if necessary */
if (default_value != NULL)
free (default_value);
+ if (expanded_value != NULL)
+ free (expanded_value);
return (err);
}
diff --git a/gnu/usr.bin/cvs/cvs/patch.c b/gnu/usr.bin/cvs/cvs/patch.c
index 69e5b09..560f4b4 100644
--- a/gnu/usr.bin/cvs/cvs/patch.c
+++ b/gnu/usr.bin/cvs/cvs/patch.c
@@ -13,17 +13,18 @@
*/
#include "cvs.h"
+#include "getline.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)patch.c 1.57 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)patch.c 1.57 94/09/30 $";
+USE(rcsid);
#endif
static RETSIGTYPE patch_cleanup PROTO((void));
static Dtype patch_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int patch_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
-static int patch_proc PROTO((int *pargc, char *argv[], char *xwhere,
+static int patch_proc PROTO((int *pargc, char **argv, char *xwhere,
char *mwhere, char *mfile, int shorten,
int local_specified, char *mname, char *msg));
@@ -39,11 +40,10 @@ static char *date2 = NULL;
static char tmpfile1[L_tmpnam+1], tmpfile2[L_tmpnam+1], tmpfile3[L_tmpnam+1];
static int unidiff = 0;
-static char *patch_usage[] =
+static const char *const patch_usage[] =
{
- "Usage: %s %s [-Qflq] [-c|-u] [-s|-t] [-V %%d]\n",
+ "Usage: %s %s [-fl] [-c|-u] [-s|-t] [-V %%d]\n",
" -r rev|-D date [-r rev2 | -D date2] modules...\n",
- "\t-Q\tReally quiet.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, not recursive\n",
"\t-c\tContext diffs (default)\n",
@@ -59,7 +59,7 @@ static char *patch_usage[] =
int
patch (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
register int i;
int c;
@@ -75,10 +75,15 @@ patch (argc, argv)
switch (c)
{
case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
case 'f':
force_tag_match = 0;
@@ -162,12 +167,64 @@ patch (argc, argv)
if (options == NULL)
options = xstrdup ("");
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ /* We're the client side. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ if (local)
+ send_arg("-l");
+ if (force_tag_match)
+ send_arg("-f");
+ if (toptwo_diffs)
+ send_arg("-t");
+ if (patch_short)
+ send_arg("-s");
+ if (unidiff)
+ send_arg("-u");
+
+ if (rev1)
+ option_with_arg ("-r", rev1);
+ if (date1)
+ client_senddate (date1);
+ if (rev2)
+ option_with_arg ("-r", rev2);
+ if (date2)
+ client_senddate (date2);
+ if (options[0] != '\0')
+ send_arg (options);
+
+ {
+ int i;
+ for (i = 0; i < argc; ++i)
+ send_arg (argv[i]);
+ }
+
+ if (fprintf (to_server, "rdiff\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
/* clean up if we get a signal */
+#ifdef SIGHUP
(void) SIG_register (SIGHUP, patch_cleanup);
+#endif
+#ifdef SIGINT
(void) SIG_register (SIGINT, patch_cleanup);
+#endif
+#ifdef SIGQUIT
(void) SIG_register (SIGQUIT, patch_cleanup);
+#endif
+#ifdef SIGPIPE
(void) SIG_register (SIGPIPE, patch_cleanup);
+#endif
+#ifdef SIGTERM
(void) SIG_register (SIGTERM, patch_cleanup);
+#endif
db = open_module ();
for (i = 0; i < argc; i++)
@@ -188,7 +245,7 @@ static int
patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
mname, msg)
int *pargc;
- char *argv[];
+ char **argv;
char *xwhere;
char *mwhere;
char *mfile;
@@ -255,8 +312,8 @@ patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
which = W_REPOS;
/* start the recursion processor */
- err = start_recursion (patch_fileproc, (int (*) ()) NULL, patch_dirproc,
- (int (*) ()) NULL, *pargc - 1, argv + 1, local,
+ err = start_recursion (patch_fileproc, (FILESDONEPROC) NULL, patch_dirproc,
+ (DIRLEAVEPROC) NULL, *pargc - 1, argv + 1, local,
which, 0, 1, where, 1, 1);
return (err);
@@ -286,7 +343,9 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
int isattic = 0;
int retcode = 0;
char file1[PATH_MAX], file2[PATH_MAX], strippath[PATH_MAX];
- char line1[MAXLINELEN], line2[MAXLINELEN];
+ char *line1, *line2;
+ size_t line1_chars_allocated;
+ size_t line2_chars_allocated;
char *cp1, *cp2, *commap;
FILE *fp;
@@ -304,7 +363,7 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
if (isattic && rev2 == NULL && date2 == NULL)
vers_head = NULL;
else
- vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match);
+ vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match, 0);
if (toptwo_diffs)
{
@@ -322,7 +381,7 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
return (1);
}
}
- vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match);
+ vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, 0);
if (vers_tag == NULL && (vers_head == NULL || isattic))
return (0); /* nothing known about specified revs */
@@ -336,8 +395,21 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
if (vers_tag == NULL)
(void) printf ("%s is new; current revision %s\n", rcs, vers_head);
else if (vers_head == NULL)
+#ifdef DEATH_SUPPORT
+ {
+ (void) printf ("%s is removed; not included in ", rcs);
+ if (rev2 != NULL)
+ (void) printf ("release tag %s", rev2);
+ else if (date2 != NULL)
+ (void) printf ("release date %s", date2);
+ else
+ (void) printf ("current release");
+ (void) printf ("\n");
+ }
+#else
(void) printf ("%s is removed; not included in release %s\n",
rcs, rev2 ? rev2 : date2);
+#endif
else
(void) printf ("%s changed from revision %s to %s\n",
rcs, vers_tag, vers_head);
@@ -396,6 +468,12 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
run_setup ("%s -%c", DIFF, unidiff ? 'u' : 'c');
run_arg (tmpfile1);
run_arg (tmpfile2);
+
+ line1 = NULL;
+ line1_chars_allocated = 0;
+ line2 = NULL;
+ line2_chars_allocated = 0;
+
switch (run_exec (RUN_TTY, tmpfile3, RUN_TTY, RUN_NORMAL))
{
case -1: /* fork/wait failure */
@@ -419,8 +497,8 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
(void) fflush (stdout);
fp = open_file (tmpfile3, "r");
- if (fgets (line1, sizeof (line1), fp) == NULL ||
- fgets (line2, sizeof (line2), fp) == NULL)
+ if (getline (&line1, &line1_chars_allocated, fp) < 0 ||
+ getline (&line2, &line2_chars_allocated, fp) < 0)
{
error (0, errno, "failed to read diff file header %s for %s",
tmpfile3, rcs);
@@ -488,14 +566,19 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
if (update_dir[0] != '\0')
(void) printf ("%s/", update_dir);
(void) printf ("%s%s", rcs, cp2);
- while (fgets (line1, sizeof (line1), fp) != NULL)
- (void) printf ("%s", line1);
+ /* spew the rest of the diff out */
+ while (getline (&line1, &line1_chars_allocated, fp) >= 0)
+ (void) fputs (line1, stdout);
(void) fclose (fp);
break;
default:
error (0, 0, "diff failed for %s", rcs);
}
out:
+ if (line1)
+ free (line1);
+ if (line2)
+ free (line2);
(void) unlink_file (tmpfile1);
(void) unlink_file (tmpfile2);
(void) unlink_file (tmpfile3);
diff --git a/gnu/usr.bin/cvs/cvs/rcs.c b/gnu/usr.bin/cvs/cvs/rcs.c
index 2c424d9..43282a6 100644
--- a/gnu/usr.bin/cvs/cvs/rcs.c
+++ b/gnu/usr.bin/cvs/cvs/rcs.c
@@ -8,14 +8,15 @@
* manipulation
*/
+#include <assert.h>
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)rcs.c 1.40 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)rcs.c 1.40 94/10/07 $";
+USE(rcsid);
#endif
-static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, char *rcsfile));
+static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile));
static char *RCS_getdatebranch PROTO((RCSNode * rcs, char *date, char *branch));
static int getrcskey PROTO((FILE * fp, char **keyp, char **valp));
static int parse_rcs_proc PROTO((Node * file, void *closure));
@@ -56,7 +57,7 @@ static const char spacetab[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
};
-#define whitespace(c) (spacetab[c] != 0)
+#define whitespace(c) (spacetab[(unsigned char)c] != 0)
/*
* Parse all the rcs files specified and return a list
@@ -108,7 +109,7 @@ parse_rcs_proc (file, closure)
void
RCS_addnode (file, rcs, list)
- char *file;
+ const char *file;
RCSNode *rcs;
List *list;
{
@@ -128,13 +129,19 @@ RCS_addnode (file, rcs, list)
*/
RCSNode *
RCS_parse (file, repos)
- char *file;
- char *repos;
+ const char *file;
+ const char *repos;
{
RCSNode *rcs;
FILE *fp;
char rcsfile[PATH_MAX];
+#ifdef LINES_CRLF_TERMINATED
+ /* Some ports of RCS to Windows NT write RCS files with newline-
+ delimited lines. We would need to pass fopen a "binary" flag. */
+ abort ();
+#endif
+
(void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT);
if ((fp = fopen (rcsfile, "r")) != NULL)
{
@@ -145,6 +152,17 @@ RCS_parse (file, repos)
fclose (fp);
return (rcs);
}
+ else if (! existence_error (errno))
+ {
+ error (0, errno, "cannot open %s", rcsfile);
+ return NULL;
+ }
+
+#ifdef LINES_CRLF_TERMINATED
+ /* Some ports of RCS to Windows NT write RCS files with newline-
+ delimited lines. We would need to pass fopen a "binary" flag. */
+ abort ();
+#endif
(void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, file, RCSEXT);
if ((fp = fopen (rcsfile, "r")) != NULL)
@@ -159,6 +177,11 @@ RCS_parse (file, repos)
fclose (fp);
return (rcs);
}
+ else if (! existence_error (errno))
+ {
+ error (0, errno, "cannot open %s", rcsfile);
+ return NULL;
+ }
return (NULL);
}
@@ -173,6 +196,12 @@ RCS_parsercsfile (rcsfile)
FILE *fp;
RCSNode *rcs;
+#ifdef LINES_CRLF_TERMINATED
+ /* Some ports of RCS to Windows NT write RCS files with newline-
+ delimited lines. We would need to pass fopen a "binary" flag. */
+ abort ();
+#endif
+
/* open the rcsfile */
if ((fp = fopen (rcsfile, "r")) == NULL)
{
@@ -186,19 +215,15 @@ RCS_parsercsfile (rcsfile)
return (rcs);
}
+
/*
- * Do the real work of parsing an RCS file
- */
+ */
static RCSNode *
RCS_parsercsfile_i (fp, rcsfile)
FILE *fp;
- char *rcsfile;
+ const char *rcsfile;
{
- Node *q, *r;
RCSNode *rdata;
- RCSVers *vnode;
- int n;
- char *cp;
char *key, *value;
/* make a node */
@@ -206,6 +231,87 @@ RCS_parsercsfile_i (fp, rcsfile)
memset ((char *) rdata, 0, sizeof (RCSNode));
rdata->refcount = 1;
rdata->path = xstrdup (rcsfile);
+
+ /* Process HEAD and BRANCH keywords from the RCS header.
+ *
+ * Most cvs operatations on the main branch don't need any more
+ * information. Those that do call XXX to completely parse the
+ * RCS file. */
+
+ if (getrcskey (fp, &key, &value) == -1 || key == NULL)
+ goto l_error;
+
+ if (strcmp (RCSHEAD, key) == 0 && value != NULL)
+ rdata->head = xstrdup (value);
+
+ if (getrcskey (fp, &key, &value) == -1 || key == NULL)
+ goto l_error;
+
+ if (strcmp (RCSBRANCH, key) == 0 && value != NULL)
+ {
+ char *cp;
+
+ rdata->branch = xstrdup (value);
+ if ((numdots (rdata->branch) & 1) != 0)
+ {
+ /* turn it into a branch if it's a revision */
+ cp = strrchr (rdata->branch, '.');
+ *cp = '\0';
+ }
+ }
+
+ rdata->flags |= PARTIAL;
+ return rdata;
+
+l_error:
+ if (!really_quiet)
+ {
+ if (ferror(fp))
+ {
+ error (1, 0, "error reading `%s'", rcsfile);
+ }
+ else
+ {
+ error (0, 0, "`%s' does not appear to be a valid rcs file",
+ rcsfile);
+ }
+ }
+ freercsnode (&rdata);
+ return (NULL);
+}
+
+
+/*
+ * Do the real work of parsing an RCS file
+ *
+ * There are no allowances for error here.
+ */
+void
+RCS_reparsercsfile (rdata)
+ RCSNode *rdata;
+{
+ FILE *fp;
+ char *rcsfile;
+
+ Node *q, *r;
+ RCSVers *vnode;
+ int n;
+ char *cp;
+ char *key, *value;
+
+ rcsfile = rdata->path;
+
+#ifdef LINES_CRLF_TERMINATED
+ /* Some ports of RCS to Windows NT write RCS files with newline-
+ delimited lines. We would need to pass fopen a "binary" flag. */
+ abort ();
+#endif
+
+ fp = fopen(rcsfile, "r");
+ if (fp == NULL)
+ error (1, 0, "unable to reopen `%s'", rcsfile);
+
+ /* make a node */
rdata->versions = getlist ();
rdata->dates = getlist ();
@@ -221,40 +327,17 @@ RCS_parsercsfile_i (fp, rcsfile)
or we had trouble reading the file. */
if (getrcskey (fp, &key, &value) == -1 || key == NULL)
{
-
- if (!really_quiet)
+ if (ferror(fp))
{
- if (ferror(fp))
- {
- error (1, 0, "error reading `%s'", rcsfile);
- }
- else
- {
- error (0, 0, "`%s' does not appear to be a valid rcs file",
- rcsfile);
- }
+ error (1, 0, "error reading `%s'", rcsfile);
}
- freercsnode (&rdata);
- return (NULL);
- }
-
- /* process it */
- if (strcmp (RCSHEAD, key) == 0 && value != NULL)
- {
- rdata->head = xstrdup (value);
- continue;
- }
- if (strcmp (RCSBRANCH, key) == 0 && value != NULL)
- {
- rdata->branch = xstrdup (value);
- if ((numdots (rdata->branch) & 1) != 0)
+ else
{
- /* turn it into a branch if it's a revision */
- cp = strrchr (rdata->branch, '.');
- *cp = '\0';
+ error (1, 0, "`%s' does not appear to be a valid rcs file",
+ rcsfile);
}
- continue;
}
+
if (strcmp (RCSSYMBOLS, key) == 0)
{
if (value != NULL)
@@ -264,6 +347,12 @@ RCS_parsercsfile_i (fp, rcsfile)
}
}
+ if (strcmp (RCSEXPAND, key) == 0)
+ {
+ rdata->expand = xstrdup (value);
+ continue;
+ }
+
/*
* check key for '.''s and digits (probably a rev) if it is a
* revision, we are done with the headers and are down to the
@@ -312,6 +401,17 @@ RCS_parsercsfile_i (fp, rcsfile)
/* throw away the state field */
(void) getrcskey (fp, &key, &value);
+#ifdef DEATH_SUPPORT
+ /* Accept this regardless of DEATH_STATE, so that we can read
+ repositories created with different versions of CVS. */
+ if (strcmp (key, "state") != 0)
+ error (1, 0, "\
+unable to parse rcs file; `state' not in the expected place");
+ if (strcmp (value, "dead") == 0)
+ {
+ vnode->dead = 1;
+ }
+#endif
/* fill in the date field */
r->key = vnode->date = xstrdup (date);
@@ -335,6 +435,15 @@ RCS_parsercsfile_i (fp, rcsfile)
*/
while ((n = getrcskey (fp, &key, &value)) >= 0)
{
+#ifdef DEATH_SUPPORT
+ /* Enable use of repositories created with a CVS which defines
+ DEATH_SUPPORT and not DEATH_STATE. */
+ if (strcmp(key, RCSDEAD) == 0)
+ {
+ vnode->dead = 1;
+ continue;
+ }
+#endif
/* if we have a revision, break and do it */
for (cp = key; (isdigit (*cp) || *cp == '.') && *cp != '\0'; cp++)
/* do nothing */ ;
@@ -354,7 +463,8 @@ RCS_parsercsfile_i (fp, rcsfile)
break;
}
- return (rdata);
+ fclose (fp);
+ rdata->flags &= ~PARTIAL;
}
/*
@@ -390,6 +500,8 @@ freercsnode (rnodep)
dellist (&(*rnodep)->symbols);
if ((*rnodep)->symbols_data != (char *) NULL)
free ((*rnodep)->symbols_data);
+ if ((*rnodep)->expand != NULL)
+ free ((*rnodep)->expand);
if ((*rnodep)->head != (char *) NULL)
free ((*rnodep)->head);
if ((*rnodep)->branch != (char *) NULL)
@@ -435,17 +547,17 @@ null_delproc (p)
* space or semicolon
* o if key == "desc" then key and data are NULL and return -1
* o if key wasn't terminated by a semicolon, skip white space and fill
- * in value with everything up to a semicolon o compress all whitespace
- * down to a single space
+ * in value with everything up to a semicolon
+ * o compress all whitespace down to a single space
* o if a word starts with @, do funky rcs processing
* o strip whitespace off end of value or set value to NULL if it empty
* o return 0 since we found something besides "desc"
*/
static char *key = NULL;
-static int keysize = 0;
static char *value = NULL;
-static int valsize = 0;
+static size_t keysize = 0;
+static size_t valsize = 0;
#define ALLOCINCR 1024
@@ -457,11 +569,9 @@ getrcskey (fp, keyp, valp)
{
char *cur, *max;
int c;
- int funky = 0;
- int white = 1;
/* skip leading whitespace */
- while (1)
+ do
{
c = getc (fp);
if (c == EOF)
@@ -470,25 +580,22 @@ getrcskey (fp, keyp, valp)
*valp = (char *) NULL;
return (-1);
}
- if (!whitespace (c))
- break;
- }
+ } while (whitespace (c));
/* fill in key */
cur = key;
max = key + keysize;
while (!whitespace (c) && c != ';')
{
- if (cur < max)
- *cur++ = c;
- else
+ if (cur >= max)
{
key = xrealloc (key, keysize + ALLOCINCR);
cur = key + keysize;
keysize += ALLOCINCR;
max = key + keysize;
- *cur++ = c;
}
+ *cur++ = c;
+
c = getc (fp);
if (c == EOF)
{
@@ -504,7 +611,6 @@ getrcskey (fp, keyp, valp)
keysize += ALLOCINCR;
max = key + keysize;
}
-
*cur = '\0';
/* if we got "desc", we are done with the file */
@@ -515,6 +621,18 @@ getrcskey (fp, keyp, valp)
return (-1);
}
+ /* skip whitespace between key and val */
+ while (whitespace (c))
+ {
+ c = getc (fp);
+ if (c == EOF)
+ {
+ *keyp = (char *) NULL;
+ *valp = (char *) NULL;
+ return (-1);
+ }
+ }
+
/* if we ended key with a semicolon, there is no value */
if (c == ';')
{
@@ -524,33 +642,25 @@ getrcskey (fp, keyp, valp)
}
/* otherwise, there might be a value, so fill it in */
- (void) ungetc (c, fp);
cur = value;
max = value + valsize;
/* process the value */
for (;;)
{
- /* get a character */
- c = getc (fp);
- if (c == EOF)
- {
- *keyp = (char *) NULL;
- *valp = (char *) NULL;
- return (-1);
- }
-
- /* if we are in funky mode, do the rest of this string */
- if (funky)
+ /* handle RCS "strings" */
+ if (c == '@')
{
-
- /*
- * funky mode processing does the following: o @@ means one @ o
- * all other characters are literal up to a single @ (including
- * ';')
- */
for (;;)
{
+ c = getc (fp);
+ if (c == EOF)
+ {
+ *keyp = (char *) NULL;
+ *valp = (char *) NULL;
+ return (-1);
+ }
+
if (c == '@')
{
c = getc (fp);
@@ -560,16 +670,11 @@ getrcskey (fp, keyp, valp)
*valp = (char *) NULL;
return (-1);
}
+
if (c != '@')
- {
- /* @ followed by non @ turns off funky mode */
- funky = 0;
break;
- }
- /* otherwise, we already ate one @ so copy the other one */
}
- /* put the character on the value (maybe allocating space) */
if (cur >= max)
{
value = xrealloc (value, valsize + ALLOCINCR);
@@ -578,6 +683,13 @@ getrcskey (fp, keyp, valp)
max = value + valsize;
}
*cur++ = c;
+ }
+ }
+
+ /* compress whitespace down to a single space */
+ if (whitespace (c))
+ {
+ do {
c = getc (fp);
if (c == EOF)
{
@@ -585,45 +697,8 @@ getrcskey (fp, keyp, valp)
*valp = (char *) NULL;
return (-1);
}
- }
- }
+ } while (whitespace (c));
- /* if we got the semi-colon we are done with the entire value */
- if (c == ';')
- break;
-
- /* process the character we got */
- if (white && c == '@')
- {
-
- /*
- * if we are starting a word with an '@', enable funky processing
- */
- white = 0; /* you can't be funky and white :-) */
- funky = 1;
- }
- else
- {
-
- /*
- * we put the character on the list, compressing all whitespace
- * to a single space
- */
-
- /* whitespace with white set means compress it out */
- if (white && whitespace (c))
- continue;
-
- if (whitespace (c))
- {
- /* make c a space and set white */
- white = 1;
- c = ' ';
- }
- else
- white = 0;
-
- /* put the char on the end of value (maybe allocating space) */
if (cur >= max)
{
value = xrealloc (value, valsize + ALLOCINCR);
@@ -631,17 +706,13 @@ getrcskey (fp, keyp, valp)
valsize += ALLOCINCR;
max = value + valsize;
}
- *cur++ = c;
+ *cur++ = ' ';
}
- }
- /* if the last char was white space, take it off */
- if (white && cur != value)
- cur--;
+ /* if we got a semi-colon we are done with the entire value */
+ if (c == ';')
+ break;
- /* terminate the string */
- if (cur)
- {
if (cur >= max)
{
value = xrealloc (value, valsize + ALLOCINCR);
@@ -649,8 +720,26 @@ getrcskey (fp, keyp, valp)
valsize += ALLOCINCR;
max = value + valsize;
}
- *cur = '\0';
+ *cur++ = c;
+
+ c = getc (fp);
+ if (c == EOF)
+ {
+ *keyp = (char *) NULL;
+ *valp = (char *) NULL;
+ return (-1);
+ }
+ }
+
+ /* terminate the string */
+ if (cur >= max)
+ {
+ value = xrealloc (value, valsize + ALLOCINCR);
+ cur = value + valsize;
+ valsize += ALLOCINCR;
+ max = value + valsize;
}
+ *cur = '\0';
/* if the string is empty, make it null */
if (value && *value != '\0')
@@ -746,15 +835,15 @@ do_branches (list, val)
* The result is returned; null-string if error.
*/
char *
-RCS_getversion (rcs, tag, date, force_tag_match)
+RCS_getversion (rcs, tag, date, force_tag_match, return_both)
RCSNode *rcs;
char *tag;
char *date;
int force_tag_match;
+ int return_both;
{
/* make sure we have something to look at... */
- if (rcs == NULL)
- return ((char *) NULL);
+ assert (rcs != NULL);
if (tag && date)
{
@@ -764,7 +853,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
* first lookup the tag; if that works, turn the revision into
* a branch and lookup the date.
*/
- tagrev = RCS_gettag (rcs, tag, force_tag_match);
+ tagrev = RCS_gettag (rcs, tag, force_tag_match, 0);
if (tagrev == NULL)
return ((char *) NULL);
@@ -775,7 +864,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
return (rev);
}
else if (tag)
- return (RCS_gettag (rcs, tag, force_tag_match));
+ return (RCS_gettag (rcs, tag, force_tag_match, return_both));
else if (date)
return (RCS_getdate (rcs, date, force_tag_match));
else
@@ -792,22 +881,29 @@ RCS_getversion (rcs, tag, date, force_tag_match)
* If the matched tag is a branch tag, find the head of the branch.
*/
char *
-RCS_gettag (rcs, tag, force_tag_match)
+RCS_gettag (rcs, symtag, force_tag_match, return_both)
RCSNode *rcs;
- char *tag;
+ char *symtag;
int force_tag_match;
+ int return_both;
{
Node *p;
+ char *tag = symtag;
/* make sure we have something to look at... */
- if (rcs == NULL)
- return ((char *) NULL);
+ assert (rcs != NULL);
+
+ /* XXX this is probably not necessary, --jtc */
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
/* If tag is "HEAD", special case to get head RCS revision */
if (tag && (strcmp (tag, TAG_HEAD) == 0 || *tag == '\0'))
+#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 */
else
+#endif
return (RCS_head (rcs));
if (!isdigit (tag[0]))
@@ -895,7 +991,25 @@ RCS_gettag (rcs, tag, force_tag_match)
else
p = findnode (rcs->versions, tag);
if (p != NULL)
- return (xstrdup (tag));
+ {
+ /*
+ * we have found a numeric revision for the revision tag.
+ * To support expanding the RCS keyword Name, return both
+ * the numeric tag and the supplied tag (which might be
+ * symbolic). They are separated with a ':' which is not
+ * a valid tag char. The variable return_both is only set
+ * if this function is called through Version_TS ->
+ * RCS_getversion.
+ */
+ if (return_both)
+ {
+ char *both = xmalloc(strlen(tag) + 2 + strlen(symtag));
+ sprintf(both, "%s:%s", tag, symtag);
+ return both;
+ }
+ else
+ return (xstrdup (tag));
+ }
else
{
/* The revision wasn't there, so return the head or NULL */
@@ -1124,8 +1238,10 @@ RCS_getbranch (rcs, tag, force_tag_match)
char *cp;
/* make sure we have something to look at... */
- if (rcs == NULL)
- return ((char *) NULL);
+ assert (rcs != NULL);
+
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
/* find out if the tag contains a dot, or is on the trunk */
cp = strrchr (tag, '.');
@@ -1233,16 +1349,14 @@ RCS_head (rcs)
RCSNode *rcs;
{
/* make sure we have something to look at... */
- if (rcs == NULL)
- return ((char *) NULL);
-
- if (rcs->branch)
- return (RCS_getbranch (rcs, rcs->branch, 1));
+ assert (rcs != NULL);
/*
* NOTE: we call getbranch with force_tag_match set to avoid any
* possibility of recursion
*/
+ if (rcs->branch)
+ return (RCS_getbranch (rcs, rcs->branch, 1));
else
return (xstrdup (rcs->head));
}
@@ -1263,8 +1377,10 @@ RCS_getdate (rcs, date, force_tag_match)
RCSVers *vers = NULL;
/* make sure we have something to look at... */
- if (rcs == NULL)
- return ((char *) NULL);
+ assert (rcs != NULL);
+
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
/* if the head is on a branch, try the branch first */
if (rcs->branch != NULL)
@@ -1347,6 +1463,12 @@ RCS_getdatebranch (rcs, date, branch)
return (NULL);
}
*cp = '\0'; /* turn it into a revision */
+
+ assert (rcs != NULL);
+
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
+
p = findnode (rcs->versions, xrev);
free (xrev);
if (p == NULL)
@@ -1427,8 +1549,10 @@ RCS_getrevtime (rcs, rev, date, fudge)
RCSVers *vers;
/* make sure we have something to look at... */
- if (rcs == NULL)
- return (revdate);
+ assert (rcs != NULL);
+
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
/* look up the revision */
p = findnode (rcs->versions, rev);
@@ -1481,14 +1605,19 @@ List *
RCS_symbols(rcs)
RCSNode *rcs;
{
- if (rcs->symbols_data) {
- rcs->symbols = getlist ();
- do_symbols (rcs->symbols, rcs->symbols_data);
- free(rcs->symbols_data);
- rcs->symbols_data = NULL;
- }
+ assert(rcs != NULL);
- return rcs->symbols;
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
+
+ if (rcs->symbols_data) {
+ rcs->symbols = getlist ();
+ do_symbols (rcs->symbols, rcs->symbols_data);
+ free(rcs->symbols_data);
+ rcs->symbols_data = NULL;
+ }
+
+ return rcs->symbols;
}
/*
@@ -1498,12 +1627,24 @@ RCS_symbols(rcs)
*/
char *
RCS_check_kflag (arg)
- char *arg;
+ const char *arg;
{
- static char *kflags[] =
- {"kv", "kvl", "k", "v", "o", (char *) NULL};
+ static const char *const kflags[] =
+ {"kv", "kvl", "k", "v", "o", "b", (char *) NULL};
+ static const char *const keyword_usage[] =
+ {
+ "%s %s: invalid RCS keyword expansion mode\n",
+ "Valid expansion modes include:\n",
+ " -kkv\tGenerate keywords using the default form.\n",
+ " -kkvl\tLike -kkv, except locker's name inserted.\n",
+ " -kk\tGenerate only keyword names in keyword strings.\n",
+ " -kv\tGenerate only keyword values in keyword strings.\n",
+ " -ko\tGenerate the old keyword string (no changes from checked in file).\n",
+ " -kb\tGenerate binary file unmodified (merges not allowed) (RCS 5.7).\n",
+ NULL,
+ };
char karg[10];
- char **cpp = NULL;
+ char const *const *cpp = NULL;
#ifndef HAVE_RCS5
error (1, 0, "%s %s: your version of RCS does not support the -k option",
@@ -1521,12 +1662,7 @@ RCS_check_kflag (arg)
if (arg == NULL || *cpp == NULL)
{
- (void) fprintf (stderr, "%s %s: invalid -k option\n",
- program_name, command_name);
- (void) fprintf (stderr, "\tvalid options are:\n");
- for (cpp = kflags; *cpp != NULL; cpp++)
- (void) fprintf (stderr, "\t\t-k%s\n", *cpp);
- error (1, 0, "Please retry with a valid -k option");
+ usage (keyword_usage);
}
(void) sprintf (karg, "-k%s", *cpp);
@@ -1539,10 +1675,10 @@ RCS_check_kflag (arg)
*/
void
RCS_check_tag (tag)
- char *tag;
+ const char *tag;
{
char *invalid = "$,.:;@"; /* invalid RCS tag characters */
- char *cp;
+ const char *cp;
/*
* The first character must be an alphabetic letter. The remaining
@@ -1565,3 +1701,26 @@ RCS_check_tag (tag)
error (1, 0, "tag `%s' must start with a letter", tag);
}
+#ifdef DEATH_SUPPORT
+/*
+ * Return true if RCS revision with TAG is a dead revision.
+ */
+int
+RCS_isdead (rcs, tag)
+ RCSNode *rcs;
+ const char *tag;
+{
+ Node *p;
+ RCSVers *version;
+
+ if (rcs->flags & PARTIAL)
+ RCS_reparsercsfile (rcs);
+
+ p = findnode (rcs->versions, tag);
+ if (p == NULL)
+ return (0);
+
+ version = (RCSVers *) p->data;
+ return (version->dead);
+}
+#endif /* DEATH_SUPPORT */
diff --git a/gnu/usr.bin/cvs/cvs/rcs.h b/gnu/usr.bin/cvs/cvs/rcs.h
index 6d6ecd4..f64501d 100644
--- a/gnu/usr.bin/cvs/cvs/rcs.h
+++ b/gnu/usr.bin/cvs/cvs/rcs.h
@@ -25,6 +25,13 @@
#define RCSSYMBOLS "symbols"
#define RCSDATE "date"
#define RCSDESC "desc"
+#define RCSEXPAND "expand"
+
+/* Used by the version of death support which results if you define
+ DEATH_SUPPORT and not DEATH_STATE. Requires a hacked up RCS. Considered
+ obsolete. */
+#define RCSDEAD "dead"
+
#define DATEFORM "%02d.%02d.%02d.%02d.%02d.%02d"
#define SDATEFORM "%d.%d.%d.%d.%d.%d"
@@ -33,6 +40,8 @@
*/
#define VALID 0x1 /* flags field contains valid data */
#define INATTIC 0x2 /* RCS file is located in the Attic */
+#define PARTIAL 0x4 /* RCS file not completly parsed */
+
struct rcsnode
{
int refcount;
@@ -41,10 +50,12 @@ struct rcsnode
char *head;
char *branch;
char *symbols_data;
+ char *expand;
List *symbols;
List *versions;
List *dates;
};
+
typedef struct rcsnode RCSNode;
struct rcsversnode
@@ -52,6 +63,7 @@ struct rcsversnode
char *version;
char *date;
char *next;
+ int dead;
List *branches;
};
typedef struct rcsversnode RCSVers;
@@ -69,13 +81,14 @@ typedef struct rcsversnode RCSVers;
* exported interfaces
*/
List *RCS_parsefiles PROTO((List * files, char *xrepos));
-RCSNode *RCS_parse PROTO((char *file, char *repos));
+RCSNode *RCS_parse PROTO((const char *file, const char *repos));
RCSNode *RCS_parsercsfile PROTO((char *rcsfile));
-char *RCS_check_kflag PROTO((char *arg));
+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 *tag, int force_tag_match));
+char *RCS_gettag PROTO((RCSNode * rcs, char *symtag, int force_tag_match,
+ int return_both));
char *RCS_getversion PROTO((RCSNode * rcs, char *tag, char *date,
- int force_tag_match));
+ int force_tag_match, int return_both));
char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
int RCS_isbranch PROTO((char *file, char *rev, List *srcfiles));
int RCS_nodeisbranch PROTO((char *rev, RCSNode *rcs));
@@ -84,7 +97,11 @@ char *RCS_head PROTO((RCSNode * rcs));
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((char *tag));
+void RCS_check_tag PROTO((const char *tag));
void freercsnode PROTO((RCSNode ** rnodep));
-void RCS_addnode PROTO((char *file, RCSNode *rcs, List *list));
+void RCS_addnode PROTO((const char *file, RCSNode *rcs, List *list));
char *RCS_getbranch PROTO((RCSNode * rcs, char *tag, int force_tag_match));
+
+#ifdef DEATH_SUPPORT
+int RCS_isdead PROTO((RCSNode *, const char *));
+#endif
diff --git a/gnu/usr.bin/cvs/cvs/recurse.c b/gnu/usr.bin/cvs/cvs/recurse.c
index 5ea344c..f5d9433 100644
--- a/gnu/usr.bin/cvs/cvs/recurse.c
+++ b/gnu/usr.bin/cvs/cvs/recurse.c
@@ -9,10 +9,11 @@
*/
#include "cvs.h"
+#include "save-cwd.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)recurse.c 1.31 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)recurse.c 1.31 94/09/30 $";
+USE(rcsid);
#endif
static int do_dir_proc PROTO((Node * p, void *closure));
@@ -25,10 +26,10 @@ static void addfile PROTO((List **listp, char *dir, char *file));
/*
* Local static versions eliminates the need for globals
*/
-static int (*fileproc) ();
-static int (*filesdoneproc) ();
-static Dtype (*direntproc) ();
-static int (*dirleaveproc) ();
+static FILEPROC fileproc;
+static FILESDONEPROC filesdoneproc;
+static DIRENTPROC direntproc;
+static DIRLEAVEPROC dirleaveproc;
static int which;
static Dtype flags;
static int aflag;
@@ -43,10 +44,10 @@ static List *filelist = NULL; /* holds list of files on which to operate */
static List *dirlist = NULL; /* holds list of directories on which to operate */
struct recursion_frame {
- int (*fileproc)();
- int (*filesdoneproc) ();
- Dtype (*direntproc) ();
- int (*dirleaveproc) ();
+ FILEPROC fileproc;
+ FILESDONEPROC filesdoneproc;
+ DIRENTPROC direntproc;
+ DIRLEAVEPROC dirleaveproc;
Dtype flags;
int which;
int aflag;
@@ -61,18 +62,18 @@ struct recursion_frame {
* we operate. In the special case of no arguments, we default to
* ".".
*
- * The general algorythm is as follows.
+ * The general algorithm is as follows.
*/
int
start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
argc, argv, local, which, aflag, readlock,
update_preload, dosrcs, wd_is_repos)
- int (*fileproc) ();
- int (*filesdoneproc) ();
- Dtype (*direntproc) ();
- int (*dirleaveproc) ();
+ FILEPROC fileproc;
+ FILESDONEPROC filesdoneproc;
+ DIRENTPROC direntproc;
+ DIRLEAVEPROC dirleaveproc;
int argc;
- char *argv[];
+ char **argv;
int local;
int which;
int aflag;
@@ -103,7 +104,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
repository = (char *) NULL;
}
if (entries)
- dellist (&entries);
+ {
+ Entries_Close (entries);
+ entries = NULL;
+ }
if (srcfiles)
dellist (&srcfiles);
if (filelist)
@@ -122,7 +126,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
* process each of the sub-directories, so we pretend like we were
* called with the list of sub-dirs of the current dir as args
*/
- if ((which & W_LOCAL) && !isdir (CVSADM) && !isdir (OCVSADM))
+ if ((which & W_LOCAL) && !isdir (CVSADM))
dirlist = Find_Dirs ((char *) NULL, W_LOCAL);
else
addlist (&dirlist, ".");
@@ -151,7 +155,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
/* if this argument is a directory, then add it to the list of
directories. */
- if (isdir(argv[i]))
+ if (!wrap_name_has (argv[i], WRAP_TOCVS) && isdir (argv[i]))
addlist (&dirlist, argv[i]);
else
{
@@ -192,7 +196,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
addfile (&files_by_dir, dir, comp);
else if (isdir (dir))
{
- if (isdir (CVSADM) || isdir (OCVSADM))
+ if (isdir (CVSADM))
{
/* otherwise, look for it in the repository. */
char *save_update_dir;
@@ -209,8 +213,9 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
/* look for it in the repository. */
repos = Name_Repository (dir, update_dir);
(void) sprintf (tmp, "%s/%s", repos, comp);
-
- if (isdir(tmp))
+ free (repos);
+
+ if (!wrap_name_has (comp, WRAP_TOCVS) && isdir(tmp))
addlist (&dirlist, argv[i]);
else
addfile (&files_by_dir, dir, comp);
@@ -262,10 +267,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
int
do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
xflags, xwhich, xaflag, xreadlock, xdosrcs)
- int (*xfileproc) ();
- int (*xfilesdoneproc) ();
- Dtype (*xdirentproc) ();
- int (*xdirleaveproc) ();
+ FILEPROC xfileproc;
+ FILESDONEPROC xfilesdoneproc;
+ DIRENTPROC xdirentproc;
+ DIRLEAVEPROC xdirleaveproc;
Dtype xflags;
int xwhich;
int xaflag;
@@ -291,12 +296,24 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
readlock = noexec ? 0 : xreadlock;
dosrcs = xdosrcs;
+#if defined(SERVER_SUPPORT) && defined(SERVER_FLOWCONTROL)
+ /*
+ * Now would be a good time to check to see if we need to stop
+ * generating data, to give the buffers a chance to drain to the
+ * remote client. We should not have locks active at this point.
+ */
+ if (server_active
+ /* If there are writelocks around, we cannot pause here. */
+ && (readlock || noexec))
+ server_pause_check();
+#endif
+
/*
* Fill in repository with the current repository
*/
if (which & W_LOCAL)
{
- if (isdir (CVSADM) || isdir (OCVSADM))
+ if (isdir (CVSADM))
repository = Name_Repository ((char *) NULL, update_dir);
else
repository = NULL;
@@ -350,7 +367,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
{
/* we will process files, so pre-parse entries */
if (which & W_LOCAL)
- entries = ParseEntries (aflag);
+ entries = Entries_Open (aflag);
}
}
@@ -377,7 +394,8 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
/* clean up */
dellist (&filelist);
dellist (&srcfiles);
- dellist (&entries);
+ Entries_Close (entries);
+ entries = NULL;
}
/* call-back files done proc (if any) */
@@ -396,7 +414,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
/* free the saved copy of the pointer if necessary */
if (srepository)
{
- (void) free (srepository);
+ free (srepository);
repository = (char *) NULL;
}
@@ -426,7 +444,6 @@ do_dir_proc (p, closure)
void *closure;
{
char *dir = p->key;
- char savewd[PATH_MAX];
char newrepos[PATH_MAX];
List *sdirlist;
char *srepository;
@@ -434,6 +451,7 @@ do_dir_proc (p, closure)
Dtype dir_return = R_PROCESS;
int stripped_dot = 0;
int err = 0;
+ struct saved_cwd cwd;
/* set up update_dir - skip dots if not at start */
if (strcmp (dir, ".") != 0)
@@ -477,8 +495,8 @@ do_dir_proc (p, closure)
if (dir_return != R_SKIP_ALL)
{
/* save our current directory and static vars */
- if (getwd (savewd) == NULL)
- error (1, 0, "could not get working directory: %s", savewd);
+ if (save_cwd (&cwd))
+ exit (1);
sdirlist = dirlist;
srepository = repository;
dirlist = NULL;
@@ -511,8 +529,9 @@ do_dir_proc (p, closure)
err = dirleaveproc (dir, err, update_dir);
/* get back to where we started and restore state vars */
- if (chdir (savewd) < 0)
- error (1, errno, "could not chdir to %s", savewd);
+ if (restore_cwd (&cwd, NULL))
+ exit (1);
+ free_cwd (&cwd);
dirlist = sdirlist;
repository = srepository;
}
@@ -554,7 +573,7 @@ addfile (listp, dir, file)
Node *n;
/* add this dir. */
- (void) addlist (listp, dir);
+ addlist (listp, dir);
n = findnode (*listp, dir);
if (n == NULL)
@@ -577,8 +596,8 @@ unroll_files_proc (p, closure)
struct recursion_frame *frame = (struct recursion_frame *) closure;
int err = 0;
List *save_dirlist;
- char savewd[PATH_MAX];
char *save_update_dir = NULL;
+ struct saved_cwd cwd;
/* if this dir was also an explicitly named argument, then skip
it. We'll catch it later when we do dirs. */
@@ -593,9 +612,8 @@ unroll_files_proc (p, closure)
if (strcmp(p->key, ".") != 0)
{
- if (getwd (savewd) == NULL)
- error (1, 0, "could not get working directory: %s", savewd);
-
+ if (save_cwd (&cwd))
+ exit (1);
if (chdir (p->key) < 0)
error (1, errno, "could not chdir to %s", p->key);
@@ -617,8 +635,9 @@ unroll_files_proc (p, closure)
(void) strcpy (update_dir, save_update_dir);
free (save_update_dir);
- if (chdir (savewd) < 0)
- error (1, errno, "could not chdir to %s", savewd);
+ if (restore_cwd (&cwd, NULL))
+ exit (1);
+ free_cwd (&cwd);
}
dirlist = save_dirlist;
diff --git a/gnu/usr.bin/cvs/cvs/release.c b/gnu/usr.bin/cvs/cvs/release.c
index a6200d9..c768bd3 100644
--- a/gnu/usr.bin/cvs/cvs/release.c
+++ b/gnu/usr.bin/cvs/cvs/release.c
@@ -12,18 +12,16 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)release.c 1.23 94/09/21 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)release.c 1.23 94/09/21 $";
+USE(rcsid);
#endif
static void release_delete PROTO((char *dir));
-static char *release_usage[] =
+static const char *const release_usage[] =
{
"Usage: %s %s [-d] modules...\n",
- "\t-Q\tReally quiet.\n",
"\t-d\tDelete the given directory.\n",
- "\t-q\tSomewhat quiet.\n",
NULL
};
@@ -36,160 +34,201 @@ release (argc, argv)
{
FILE *fp;
register int i, c;
- register char *cp;
- int margc;
- DBM *db;
- datum key, val;
char *repository, *srepos;
- char **margv, *modargv[MAXFILEPERDIR], line[PATH_MAX];
+ char line[PATH_MAX], update_cmd[PATH_MAX];
+ char *thisarg;
+ int arg_start_idx;
- if (argc == -1)
- usage (release_usage);
- optind = 1;
- while ((c = getopt (argc, argv, "Qdq")) != -1)
- {
- switch (c)
- {
- case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
- case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ if (!server_active)
+ {
+#endif /* SERVER_SUPPORT */
+ if (argc == -1)
+ usage (release_usage);
+ optind = 1;
+ while ((c = getopt (argc, argv, "Qdq")) != -1)
+ {
+ switch (c)
+ {
+ case 'Q':
+ case 'q':
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
- case 'd':
+ case 'd':
delete++;
break;
- case '?':
- default:
+ case '?':
+ default:
usage (release_usage);
break;
- }
- }
- argc -= optind;
- argv += optind;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+#ifdef SERVER_SUPPORT
+ }
+#endif /* SERVER_SUPPORT */
- if (!(db = open_module ()))
- return (1);
- for (i = 0; i < argc; i++)
- {
+ /* We're going to run "cvs -n -q update" and check its output; if
+ * the output is sufficiently unalarming, then we release with no
+ * questions asked. Else we prompt, then maybe release.
+ */
+ /* Construct the update command. */
+ sprintf (update_cmd, "%s -n -q -d %s update",
+ program_path, CVSroot);
- /*
- * If we are in a repository, do it. Else if we are in the parent of
- * a directory with the same name as the module, "cd" into it and
- * look for a repository there.
- */
- if (isdir (argv[i]))
- {
- if (chdir (argv[i]) < 0)
- {
- if (!really_quiet)
- error (0, 0, "can't chdir to: %s", argv[i]);
- continue;
- }
- if (!isdir (CVSADM) && !isdir (OCVSADM))
- {
- if (!really_quiet)
- error (0, 0, "no repository module: %s", argv[i]);
- continue;
- }
+#ifdef CLIENT_SUPPORT
+ /* Start the server; we'll close it after looping. */
+ if (client_active)
+ {
+ start_server ();
+ ign_setup ();
+ }
+#endif /* CLIENT_SUPPORT */
+
+ /* If !server_active, we already skipped over argv[0] in the "argc
+ -= optind;" statement above. But if server_active, we need to
+ skip it now. */
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ arg_start_idx = 1;
+ else
+ arg_start_idx = 0;
+#endif /* SERVER_SUPPORT */
+
+ for (i = arg_start_idx; i < argc; i++)
+ {
+ thisarg = argv[i];
+
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ /* Just log the release -- all the interesting stuff happened
+ * on the client.
+ */
+ history_write ('F', thisarg, "", thisarg, ""); /* F == Free */
+ }
+ else
+ {
+#endif /* SERVER_SUPPORT */
+
+ /*
+ * If we are in a repository, do it. Else if we are in the parent of
+ * a directory with the same name as the module, "cd" into it and
+ * look for a repository there.
+ */
+ if (isdir (thisarg))
+ {
+ if (chdir (thisarg) < 0)
+ {
+ if (!really_quiet)
+ error (0, 0, "can't chdir to: %s", thisarg);
+ continue;
+ }
+ if (!isdir (CVSADM))
+ {
+ if (!really_quiet)
+ error (0, 0, "no repository module: %s", thisarg);
+ continue;
+ }
}
else
- {
- if (!really_quiet)
- error (0, 0, "no such directory/module: %s", argv[i]);
- continue;
+ {
+ if (!really_quiet)
+ error (0, 0, "no such directory: %s", thisarg);
+ continue;
}
repository = Name_Repository ((char *) NULL, (char *) NULL);
srepos = Short_Repository (repository);
-
- /* grab module entry from database and check against short repos */
- key.dptr = argv[i];
- key.dsize = strlen (key.dptr);
- val = dbm_fetch (db, key);
- if (!val.dptr)
- {
- error (0, 0, "no such module name: %s", argv[i]);
- continue;
- }
- val.dptr[val.dsize] = '\0';
- if ((cp = strchr (val.dptr, '#')) != NULL) /* Strip out a comment */
+
+ if (!really_quiet)
{
- do
- {
- *cp-- = '\0';
- } while (isspace (*cp));
- }
- (void) sprintf (line, "%s %s", key.dptr, val.dptr);
- line2argv (&margc, modargv, line);
- margv = modargv;
+ /* The "release" command piggybacks on "update", which
+ * does the real work of finding out if anything is not
+ * up-to-date with the repository. Then "release" prompts
+ * the user, telling her how many files have been
+ * modified, and asking if she still wants to do the
+ * release.
+ */
+ fp = Popen (update_cmd, "r");
+ c = 0;
- optind = 1;
- while (getopt (margc, margv, CVSMODULE_OPTS) != -1)
- /* do nothing */ ;
- margc -= optind;
- margv += optind;
+ while (fgets (line, sizeof (line), fp))
+ {
+ if (strchr ("MARCZ", *line))
+ c++;
+ (void) printf (line);
+ }
- if (margc < 1)
- {
- error (0, 0, "modules file missing directory for key %s value %s",
- key.dptr, val.dptr);
- continue;
- }
- if (strcmp (*margv, srepos))
- {
- error (0, 0, "repository mismatch: module[%s], here[%s]",
- *margv, srepos);
- free (repository);
- continue;
- }
+ /* If the update exited with an error, then we just want to
+ * complain and go on to the next arg. Especially, we do
+ * not want to delete the local copy, since it's obviously
+ * not what the user thinks it is.
+ */
+ if ((pclose (fp)) != 0)
+ {
+ error (0, 0, "unable to release `%s'", thisarg);
+ continue;
+ }
- if (!really_quiet)
- {
-
- /*
- * Now see if there is any reason not to allow a "Release" This
- * is "popen()" instead of "Popen()" since we don't want "-n" to
- * stop it.
- */
- fp = popen ("cvs -n -q update", "r");
- c = 0;
- while (fgets (line, sizeof (line), fp))
- {
- if (strchr ("MARCZ", *line))
- c++;
- (void) printf (line);
- }
- (void) pclose (fp);
- (void) printf ("You have [%d] altered files in this repository.\n",
- c);
- (void) printf ("Are you sure you want to release %smodule `%s': ",
- delete ? "(and delete) " : "", argv[i]);
- c = !yesno ();
- if (c) /* "No" */
- {
- (void) fprintf (stderr, "** `%s' aborted by user choice.\n",
- command_name);
- free (repository);
- continue;
- }
+ (void) printf ("You have [%d] altered files in this repository.\n",
+ c);
+ (void) printf ("Are you sure you want to release %smodule `%s': ",
+ delete ? "(and delete) " : "", thisarg);
+ c = !yesno ();
+ if (c) /* "No" */
+ {
+ (void) fprintf (stderr, "** `%s' aborted by user choice.\n",
+ command_name);
+ free (repository);
+ continue;
+ }
}
- /*
- * So, we've passed all the tests, go ahead and release it. First,
- * log the release, then attempt to delete it.
- */
- history_write ('F', argv[i], "", argv[i], ""); /* F == Free */
- free (repository);
-
- if (delete)
- release_delete (argv[i]);
- }
- close_module (db);
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ if (fprintf (to_server, "Argument %s\n", thisarg) < 0)
+ error (1, errno, "writing to server");
+ if (fprintf (to_server, "release\n") < 0)
+ error (1, errno, "writing to server");
+ }
+ else
+ {
+#endif /* CLIENT_SUPPORT */
+ history_write ('F', thisarg, "", thisarg, ""); /* F == Free */
+#ifdef CLIENT_SUPPORT
+ } /* else client not active */
+#endif /* CLIENT_SUPPORT */
+
+ free (repository);
+ if (delete) release_delete (thisarg);
+
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ return get_responses_and_close ();
+ else
+#endif /* CLIENT_SUPPORT */
+ return (0);
+
+#ifdef SERVER_SUPPORT
+ } /* else server not active */
+#endif /* SERVER_SUPPORT */
+ } /* `for' loop */
return (0);
}
-/* We want to "rm -r" the repository, but let us be a little paranoid. */
+
+/* We want to "rm -r" the working directory, but let us be a little
+ paranoid. */
static void
release_delete (dir)
char *dir;
diff --git a/gnu/usr.bin/cvs/cvs/remove.c b/gnu/usr.bin/cvs/cvs/remove.c
index 0a893d1..a33c4f9 100644
--- a/gnu/usr.bin/cvs/cvs/remove.c
+++ b/gnu/usr.bin/cvs/cvs/remove.c
@@ -18,8 +18,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)remove.c 1.39 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)remove.c 1.39 94/10/07 $";
+USE(rcsid);
#endif
static int remove_fileproc PROTO((char *file, char *update_dir,
@@ -32,7 +32,7 @@ static int local;
static int removed_files;
static int existing_files;
-static char *remove_usage[] =
+static const char *const remove_usage[] =
{
"Usage: %s %s [-flR] [files...]\n",
"\t-f\tDelete the file before removing it.\n",
@@ -44,7 +44,7 @@ static char *remove_usage[] =
int
cvsremove (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int c, err;
@@ -74,6 +74,21 @@ cvsremove (argc, argv)
argc -= optind;
argv += optind;
+ wrap_setup ();
+
+#ifdef CLIENT_SUPPORT
+ if (client_active) {
+ start_server ();
+ ign_setup ();
+ if (local)
+ send_arg("-l");
+ send_files (argc, argv, local, 0);
+ if (fprintf (to_server, "remove\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
/* start the recursion processor */
err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc,
(int (*) ()) NULL, argc, argv, local,
@@ -108,12 +123,22 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
char fname[PATH_MAX];
Vers_TS *vers;
- /*
- * If unlinking the file works, good. If not, the "unremoved"
- * error will indicate problems.
- */
if (force)
- (void) unlink (file);
+ {
+ if (!noexec)
+ {
+ if (unlink (file) < 0 && ! existence_error (errno))
+ {
+ if (update_dir[0] == '\0')
+ error (0, errno, "unable to remove %s", file);
+ else
+ error (0, errno, "unable to remove %s/%s", update_dir,
+ file);
+ }
+ }
+ /* else FIXME should probably act as if the file doesn't exist
+ in doing the following checks. */
+ }
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
file, 0, 0, entries, srcfiles);
@@ -133,16 +158,18 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
{
/*
* It's a file that has been added, but not commited yet. So,
- * remove the ,p and ,t file for it and scratch it from the
- * entries file.
- */
+ * remove the ,t file for it and scratch it from the
+ * entries file. */
Scratch_Entry (entries, file);
- (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_OPT);
- (void) unlink_file (fname);
(void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
(void) unlink_file (fname);
if (!quiet)
error (0, 0, "removed `%s'", file);
+
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_checked_in (file, update_dir, repository);
+#endif
}
else if (vers->vn_user[0] == '-')
{
@@ -159,6 +186,11 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
if (!quiet)
error (0, 0, "scheduling `%s' for removal", file);
removed_files++;
+
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_checked_in (file, update_dir, repository);
+#endif
}
freevers_ts (&vers);
diff --git a/gnu/usr.bin/cvs/cvs/repos.c b/gnu/usr.bin/cvs/cvs/repos.c
index e7794d4..8566433 100644
--- a/gnu/usr.bin/cvs/cvs/repos.c
+++ b/gnu/usr.bin/cvs/cvs/repos.c
@@ -13,8 +13,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)repos.c 1.32 94/09/23 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)repos.c 1.32 94/09/23 $";
+USE(rcsid);
#endif
char *
@@ -28,9 +28,7 @@ Name_Repository (dir, update_dir)
char path[PATH_MAX];
char tmp[PATH_MAX];
char cvsadm[PATH_MAX];
- char ocvsadm[PATH_MAX];
char *cp;
- int has_cvsadm = 0, has_ocvsadm = 0;
if (update_dir && *update_dir)
xupdate_dir = update_dir;
@@ -38,47 +36,18 @@ Name_Repository (dir, update_dir)
xupdate_dir = ".";
if (dir != NULL)
- {
(void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
- (void) sprintf (ocvsadm, "%s/%s", dir, OCVSADM);
- }
else
- {
(void) strcpy (cvsadm, CVSADM);
- (void) strcpy (ocvsadm, OCVSADM);
- }
/* sanity checks */
- if (!(has_cvsadm = isdir (cvsadm)) && !(has_ocvsadm = isdir (ocvsadm)))
+ if (!isdir (cvsadm))
{
error (0, 0, "in directory %s:", xupdate_dir);
error (1, 0, "there is no version here; do '%s checkout' first",
program_name);
}
- if (has_ocvsadm)
- {
- if (has_cvsadm)
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (1, 0, "error: both `%s' and `%s' exist; I give up",
- CVSADM, OCVSADM);
- }
- if (rename (ocvsadm, cvsadm) < 0)
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (1, errno, "cannot rename `%s' to `%s'; I give up",
- OCVSADM, CVSADM);
- }
-
- /*
- * We have converted the old CVS.adm directory to the new CVS
- * directory. Now, convert the Entries file to the new format, if
- * necessary.
- */
- check_entries (dir);
- }
-
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
else
@@ -127,7 +96,7 @@ Name_Repository (dir, update_dir)
error (0, 0, "`..'-relative repositories are not supported.");
error (1, 0, "illegal source repository");
}
- if (repos[0] != '/')
+ if (! isabsolute(repos))
{
if (CVSroot == NULL)
{
@@ -139,7 +108,11 @@ Name_Repository (dir, update_dir)
(void) strcpy (path, repos);
(void) sprintf (repos, "%s/%s", CVSroot, path);
}
+#ifdef CLIENT_SUPPORT
+ if (!client_active && !isdir (repos))
+#else
if (!isdir (repos))
+#endif
{
error (0, 0, "in directory %s:", xupdate_dir);
error (1, 0, "there is no repository %s", repos);
@@ -162,9 +135,13 @@ Short_Repository (repository)
if (repository == NULL)
return (NULL);
- /* if repository matches CVSroot at the beginning, strip off CVSroot */
+ /* If repository matches CVSroot at the beginning, strip off CVSroot */
+ /* And skip leading '/' in rep, in case CVSroot ended with '/'. */
if (strncmp (CVSroot, repository, strlen (CVSroot)) == 0)
- return (repository + strlen (CVSroot) + 1);
+ {
+ char *rep = repository + strlen (CVSroot);
+ return (*rep == '/') ? rep+1 : rep;
+ }
else
return (repository);
}
diff --git a/gnu/usr.bin/cvs/cvs/root.c b/gnu/usr.bin/cvs/cvs/root.c
index 9ff9ffa..e3cb979 100644
--- a/gnu/usr.bin/cvs/cvs/root.c
+++ b/gnu/usr.bin/cvs/cvs/root.c
@@ -14,8 +14,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "@(#)root.c,v 1.2 1994/09/15 05:32:17 zoo Exp";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)root.c,v 1.2 1994/09/15 05:32:17 zoo Exp";
+USE(rcsid);
#endif
char *
@@ -38,22 +38,19 @@ Name_Root(dir, update_dir)
if (dir != NULL)
{
(void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
+ (void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
}
else
{
(void) strcpy (cvsadm, CVSADM);
- }
-
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
- else
(void) strcpy (tmp, CVSADM_ROOT);
+ }
/*
* Do not bother looking for a readable file if there is no cvsadm
* directory present.
*
- * It is possiible that not all repositories will have a CVS/Root
+ * It is possible that not all repositories will have a CVS/Root
* file. This is ok, but the user will need to specify -d
* /path/name or have the environment variable CVSROOT set in
* order to continue.
@@ -90,7 +87,14 @@ Name_Root(dir, update_dir)
* root now contains a candidate for CVSroot. It must be an
* absolute pathname
*/
+
+#ifdef CLIENT_SUPPORT
+ /* It must specify a server via remote CVS or be an absolute pathname. */
+ if ((strchr (root, ':') == NULL)
+ && ! isabsolute (root))
+#else
if (root[0] != '/')
+#endif
{
error (0, 0, "in directory %s:", xupdate_dir);
error (0, 0,
@@ -99,7 +103,11 @@ Name_Root(dir, update_dir)
return (NULL);
}
+#ifdef CLIENT_SUPPORT
+ if ((strchr (root, ':') == NULL) && !isdir (root))
+#else
if (!isdir (root))
+#endif
{
error (0, 0, "in directory %s:", xupdate_dir);
error (0, 0,
@@ -154,6 +162,9 @@ Create_Root (dir, rootdir)
FILE *fout;
char tmp[PATH_MAX];
+ if (noexec)
+ return;
+
/* record the current cvs root */
if (rootdir != NULL)
@@ -163,7 +174,7 @@ Create_Root (dir, rootdir)
else
(void) strcpy (tmp, CVSADM_ROOT);
fout = open_file (tmp, "w+");
- if (fprintf (fout, "%s\n", rootdir) == EOF)
+ if (fprintf (fout, "%s\n", rootdir) < 0)
error (1, errno, "write to %s failed", tmp);
if (fclose (fout) == EOF)
error (1, errno, "cannot close %s", tmp);
diff --git a/gnu/usr.bin/cvs/cvs/rtag.c b/gnu/usr.bin/cvs/cvs/rtag.c
index c10f68b..76e1776 100644
--- a/gnu/usr.bin/cvs/cvs/rtag.c
+++ b/gnu/usr.bin/cvs/cvs/rtag.c
@@ -14,19 +14,45 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)rtag.c 1.61 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)rtag.c 1.61 94/09/30 $";
+USE(rcsid);
#endif
+static int check_fileproc PROTO((char *file, char *update_dir,
+ char *repository, List * entries,
+ List * srcfiles));
+static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
+static int pretag_proc PROTO((char *repository, char *filter));
+static void masterlist_delproc PROTO((Node *p));
+static void tag_delproc PROTO((Node *p));
+static int pretag_list_proc PROTO((Node *p, void *closure));
+
static Dtype rtag_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int rtag_fileproc PROTO((char *file, char *update_dir,
char *repository, List * entries,
List * srcfiles));
-static int rtag_proc PROTO((int *pargc, char *argv[], char *xwhere,
+static int rtag_proc PROTO((int *pargc, char **argv, char *xwhere,
char *mwhere, char *mfile, int shorten,
int local_specified, char *mname, char *msg));
static int rtag_delete PROTO((RCSNode *rcsfile));
+
+struct tag_info
+{
+ Ctype status;
+ char *rev;
+ char *tag;
+ char *options;
+};
+
+struct master_lists
+{
+ List *tlist;
+};
+
+static List *mtlist;
+static List *tlist;
+
static char *symtag;
static char *numtag;
static int delete; /* adding a tag by default */
@@ -37,16 +63,14 @@ static int local; /* recursive by default */
static int force_tag_match = 1; /* force by default */
static int force_tag_move; /* don't move existing tags by default */
-static char *rtag_usage[] =
+static const char *const rtag_usage[] =
{
- "Usage: %s %s [-QaflRnqF] [-b] [-d] [-r tag|-D date] tag modules...\n",
- "\t-Q\tReally quiet.\n",
+ "Usage: %s %s [-aflRnF] [-b] [-d] [-r tag|-D date] tag modules...\n",
"\t-a\tClear tag from removed files that would not otherwise be tagged.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, not recursive\n",
"\t-R\tProcess directories recursively.\n",
"\t-n\tNo execution of 'tag program'\n",
- "\t-q\tSomewhat quiet.\n",
"\t-d\tDelete the given Tag.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-[rD]\tExisting tag or Date.\n",
@@ -57,7 +81,7 @@ static char *rtag_usage[] =
int
rtag (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
register int i;
int c;
@@ -80,10 +104,15 @@ rtag (argc, argv)
run_module_prog = 0;
break;
case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
case 'l':
local = 1;
@@ -131,6 +160,46 @@ rtag (argc, argv)
error (0, 0, "warning: -b ignored with -d options");
RCS_check_tag (symtag);
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ /* We're the client side. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ if (local)
+ send_arg("-l");
+ if (delete)
+ send_arg("-d");
+ if (branch_mode)
+ send_arg("-b");
+ if (force_tag_move)
+ send_arg("-F");
+ if (run_module_prog)
+ send_arg("-n");
+ if (attic_too)
+ send_arg("-a");
+
+ if (numtag)
+ option_with_arg ("-r", numtag);
+ if (date)
+ client_senddate (date);
+
+ send_arg (symtag);
+
+ {
+ int i;
+ for (i = 0; i < argc; ++i)
+ send_arg (argv[i]);
+ }
+
+ if (fprintf (to_server, "rtag\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
db = open_module ();
for (i = 0; i < argc; i++)
{
@@ -153,7 +222,7 @@ static int
rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
mname, msg)
int *pargc;
- char *argv[];
+ char **argv;
char *xwhere;
char *mwhere;
char *mfile;
@@ -220,14 +289,214 @@ rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
else
which = W_REPOS;
+ /* check to make sure they are authorized to tag all the
+ specified files in the repository */
+
+ mtlist = getlist();
+ err = start_recursion (check_fileproc, check_filesdoneproc,
+ (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL,
+ *pargc - 1, argv + 1, local, which, 0, 1,
+ where, 1, 1);
+
+ if (err)
+ {
+ error (1, 0, "correct the above errors first!");
+ }
+
/* start the recursion processor */
- err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc,
- (int (*) ()) NULL, *pargc - 1, argv + 1, local,
+ err = start_recursion (rtag_fileproc, (FILESDONEPROC) NULL, rtag_dirproc,
+ (DIRLEAVEPROC) NULL, *pargc - 1, argv + 1, local,
which, 0, 1, where, 1, 1);
+ dellist(&mtlist);
+
return (err);
}
+/* check file that is to be tagged */
+/* All we do here is add it to our list */
+
+static int
+check_fileproc(file, update_dir, repository, entries, srcfiles)
+ char *file;
+ char *update_dir;
+ char *repository;
+ List * entries;
+ List * srcfiles;
+{
+ char *xdir;
+ Node *p;
+ Vers_TS *vers;
+
+ if (update_dir[0] == '\0')
+ xdir = ".";
+ else
+ xdir = update_dir;
+ if ((p = findnode (mtlist, xdir)) != NULL)
+ {
+ tlist = ((struct master_lists *) p->data)->tlist;
+ }
+ else
+ {
+ struct master_lists *ml;
+
+ tlist = getlist ();
+ p = getnode ();
+ p->key = xstrdup (xdir);
+ p->type = UPDATE;
+ ml = (struct master_lists *)
+ xmalloc (sizeof (struct master_lists));
+ ml->tlist = tlist;
+ p->data = (char *) ml;
+ p->delproc = masterlist_delproc;
+ (void) addnode (mtlist, p);
+ }
+ /* do tlist */
+ p = getnode ();
+ p->key = xstrdup (file);
+ p->type = UPDATE;
+ p->delproc = tag_delproc;
+ vers = Version_TS (repository, (char *) NULL, (char *) NULL,
+ (char *) NULL, file, 0, 0, entries, srcfiles);
+ p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match, 0);
+ if (p->data != NULL)
+ {
+ int addit = 1;
+ char *oversion;
+
+ oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
+ if (oversion == NULL)
+ {
+ if (delete)
+ {
+ addit = 0;
+ }
+ }
+ else if (strcmp(oversion, p->data) == 0)
+ {
+ addit = 0;
+ }
+ else if (!force_tag_move)
+ {
+ addit = 0;
+ }
+ if (oversion != NULL)
+ {
+ free(oversion);
+ }
+ if (!addit)
+ {
+ free(p->data);
+ p->data = NULL;
+ }
+ }
+ freevers_ts (&vers);
+ (void) addnode (tlist, p);
+ return (0);
+}
+
+static int
+check_filesdoneproc(err, repos, update_dir)
+ int err;
+ char *repos;
+ char *update_dir;
+{
+ int n;
+ Node *p;
+
+ p = findnode(mtlist, update_dir);
+ if (p != NULL)
+ {
+ tlist = ((struct master_lists *) p->data)->tlist;
+ }
+ else
+ {
+ tlist = (List *) NULL;
+ }
+ if ((tlist == NULL) || (tlist->list->next == tlist->list))
+ {
+ return (err);
+ }
+ if ((n = Parse_Info(CVSROOTADM_TAGINFO, repos, pretag_proc, 1)) > 0)
+ {
+ error (0, 0, "Pre-tag check failed");
+ err += n;
+ }
+ return (err);
+}
+
+static int
+pretag_proc(repository, filter)
+ char *repository;
+ char *filter;
+{
+ if (filter[0] == '/')
+ {
+ char *s, *cp;
+
+ s = xstrdup(filter);
+ for (cp=s; *cp; cp++)
+ {
+ if (isspace(*cp))
+ {
+ *cp = '\0';
+ break;
+ }
+ }
+ if (!isfile(s))
+ {
+ error (0, errno, "cannot find pre-tag filter '%s'", s);
+ free(s);
+ return (1);
+ }
+ free(s);
+ }
+ run_setup("%s %s %s %s",
+ filter,
+ symtag,
+ delete ? "del" : force_tag_move ? "mov" : "add",
+ repository);
+ walklist(tlist, pretag_list_proc, NULL);
+ return (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
+}
+
+static void
+masterlist_delproc(p)
+ Node *p;
+{
+ struct master_lists *ml;
+
+ ml = (struct master_lists *)p->data;
+ dellist(&ml->tlist);
+ free(ml);
+ return;
+}
+
+static void
+tag_delproc(p)
+ Node *p;
+{
+ if (p->data != NULL)
+ {
+ free(p->data);
+ p->data = NULL;
+ }
+ return;
+}
+
+static int
+pretag_list_proc(p, closure)
+ Node *p;
+ void *closure;
+{
+ if (p->data != NULL)
+ {
+ run_arg(p->key);
+ run_arg(p->data);
+ }
+ return (0);
+}
+
/*
* Called to tag a particular file, as appropriate with the options that were
* set above.
@@ -272,7 +541,7 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
return (rtag_delete (rcsfile));
}
- version = RCS_getversion (rcsfile, numtag, date, force_tag_match);
+ version = RCS_getversion (rcsfile, numtag, date, force_tag_match, 0);
if (version == NULL)
{
/* If -a specified, clean up any old tags */
@@ -299,7 +568,7 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
* the branch. Use a symbolic tag for that.
*/
rev = branch_mode ? RCS_magicrev (rcsfile, version) : numtag;
- run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, numtag);
+ retcode = RCS_settag(rcsfile->path, symtag, numtag);
}
else
{
@@ -315,7 +584,7 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
* typical tagging operation.
*/
rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
- oversion = RCS_getversion (rcsfile, symtag, (char *) 0, 1);
+ oversion = RCS_getversion (rcsfile, symtag, (char *) NULL, 1, 0);
if (oversion != NULL)
{
int isbranch = RCS_isbranch (file, symtag, srcfiles);
@@ -347,10 +616,10 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
}
free (oversion);
}
- run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
+ retcode = RCS_settag(rcsfile->path, symtag, rev);
}
- run_arg (rcsfile->path);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+
+ if (retcode != 0)
{
error (1, retcode == -1 ? errno : 0,
"failed to set tag `%s' to revision `%s' in `%s'",
@@ -382,20 +651,18 @@ rtag_delete (rcsfile)
if (numtag)
{
- version = RCS_getversion (rcsfile, numtag, (char *) 0, 1);
+ version = RCS_getversion (rcsfile, numtag, (char *) NULL, 1, 0);
if (version == NULL)
return (0);
free (version);
}
- version = RCS_getversion (rcsfile, symtag, (char *) 0, 1);
+ version = RCS_getversion (rcsfile, symtag, (char *) NULL, 1, 0);
if (version == NULL)
return (0);
free (version);
- run_setup ("%s%s -q -N%s", Rcsbin, RCS, symtag);
- run_arg (rcsfile->path);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_deltag(rcsfile->path, symtag, 1)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
@@ -420,3 +687,6 @@ rtag_dirproc (dir, repos, update_dir)
error (0, 0, "%s %s", delete ? "Untagging" : "Tagging", update_dir);
return (R_PROCESS);
}
+
+
+
diff --git a/gnu/usr.bin/cvs/cvs/status.c b/gnu/usr.bin/cvs/cvs/status.c
index 2f14a0b..fe53bcb 100644
--- a/gnu/usr.bin/cvs/cvs/status.c
+++ b/gnu/usr.bin/cvs/cvs/status.c
@@ -11,8 +11,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)status.c 1.56 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)status.c 1.56 94/10/07 $";
+USE(rcsid);
#endif
static Dtype status_dirproc PROTO((char *dir, char *repos, char *update_dir));
@@ -26,7 +26,7 @@ static int long_format = 0;
static char *xfile;
static List *xsrcfiles;
-static char *status_usage[] =
+static const char *const status_usage[] =
{
"Usage: %s %s [-vlR] [files...]\n",
"\t-v\tVerbose format; includes tag information for the file\n",
@@ -38,7 +38,7 @@ static char *status_usage[] =
int
status (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int c;
int err = 0;
@@ -69,9 +69,34 @@ status (argc, argv)
argc -= optind;
argv += optind;
+ wrap_setup ();
+
+#ifdef CLIENT_SUPPORT
+ if (client_active) {
+ start_server ();
+
+ ign_setup ();
+
+ if (long_format)
+ send_arg("-v");
+ if (local)
+ send_arg("-l");
+
+ /* XXX This should only need to send file info; the file
+ contents themselves will not be examined. */
+ send_files (argc, argv, local, 0);
+
+ if (fprintf (to_server, "status\n") < 0)
+ error (1, errno, "writing to server");
+ err = get_responses_and_close ();
+
+ return err;
+ }
+#endif
+
/* start the recursion processor */
- err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc,
- (int (*) ()) NULL, argc, argv, local,
+ err = start_recursion (status_fileproc, (FILESDONEPROC) NULL, status_dirproc,
+ (DIRLEAVEPROC) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err);
@@ -104,6 +129,11 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
case T_CHECKOUT:
sstat = "Needs Checkout";
break;
+#ifdef SERVER_SUPPORT
+ case T_PATCH:
+ sstat = "Needs Patch";
+ break;
+#endif
case T_CONFLICT:
sstat = "Unresolved Conflict";
break;
@@ -143,6 +173,10 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
(void) printf (" Working revision:\tNo entry for %s\n", file);
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
(void) printf (" Working revision:\tNew file!\n");
+#ifdef SERVER_SUPPORT
+ else if (server_active)
+ (void) printf (" Working revision:\t%s\n", vers->vn_user);
+#endif
else
(void) printf (" Working revision:\t%s\t%s\n", vers->vn_user,
vers->ts_rcs);
@@ -181,17 +215,17 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
}
}
}
- else
+ else if (!really_quiet)
(void) printf (" Sticky Tag:\t\t(none)\n");
if (edata->date)
(void) printf (" Sticky Date:\t\t%s\n", edata->date);
- else
+ else if (!really_quiet)
(void) printf (" Sticky Date:\t\t(none)\n");
if (edata->options && edata->options[0])
(void) printf (" Sticky Options:\t%s\n", edata->options);
- else
+ else if (!really_quiet)
(void) printf (" Sticky Options:\t(none)\n");
if (long_format && vers->srcfile)
diff --git a/gnu/usr.bin/cvs/cvs/tag.c b/gnu/usr.bin/cvs/cvs/tag.c
index fa7f162..55c8659 100644
--- a/gnu/usr.bin/cvs/cvs/tag.c
+++ b/gnu/usr.bin/cvs/cvs/tag.c
@@ -14,29 +14,57 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)tag.c 1.60 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)tag.c 1.60 94/09/30 $";
+USE(rcsid);
#endif
+static int check_fileproc PROTO((char *file, char *update_dir,
+ char *repository, List * entries,
+ List * srcfiles));
+static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
+static int pretag_proc PROTO((char *repository, char *filter));
+static void masterlist_delproc PROTO((Node *p));
+static void tag_delproc PROTO((Node *p));
+static int pretag_list_proc PROTO((Node *p, void *closure));
+
static Dtype tag_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int tag_fileproc PROTO((char *file, char *update_dir,
char *repository, List * entries,
List * srcfiles));
+static char *numtag;
+static char *date = NULL;
static char *symtag;
static int delete; /* adding a tag by default */
static int branch_mode; /* make an automagic "branch" tag */
static int local; /* recursive by default */
+static int force_tag_match = 1; /* force tag to match by default */
static int force_tag_move; /* don't force tag to move by default */
-static char *tag_usage[] =
+struct tag_info
+{
+ Ctype status;
+ char *rev;
+ char *tag;
+ char *options;
+};
+
+struct master_lists
{
- "Usage: %s %s [-QlRqF] [-b] [-d] tag [files...]\n",
- "\t-Q\tReally quiet.\n",
+ List *tlist;
+};
+
+static List *mtlist;
+static List *tlist;
+
+static const char *const tag_usage[] =
+{
+ "Usage: %s %s [-lRF] [-b] [-d] tag [files...]\n",
"\t-l\tLocal directory only, not recursive.\n",
"\t-R\tProcess directories recursively.\n",
- "\t-q\tSomewhat quiet.\n",
"\t-d\tDelete the given Tag.\n",
+ "\t-[rD]\tExisting tag or date.\n",
+ "\t-f\tForce a head revision if tag etc not found.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-F\tMove tag if it already exists\n",
NULL
@@ -45,7 +73,7 @@ static char *tag_usage[] =
int
tag (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int c;
int err = 0;
@@ -54,15 +82,20 @@ tag (argc, argv)
usage (tag_usage);
optind = 1;
- while ((c = getopt (argc, argv, "FQqlRdb")) != -1)
+ while ((c = getopt (argc, argv, "FQqlRdr:D:bf")) != -1)
{
switch (c)
{
case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
case 'l':
local = 1;
@@ -73,6 +106,17 @@ tag (argc, argv)
case 'd':
delete = 1;
break;
+ case 'r':
+ numtag = optarg;
+ break;
+ case 'D':
+ if (date)
+ free (date);
+ date = Make_Date (optarg);
+ break;
+ case 'f':
+ force_tag_match = 0;
+ break;
case 'b':
branch_mode = 1;
break;
@@ -98,13 +142,246 @@ tag (argc, argv)
error (0, 0, "warning: -b ignored with -d options");
RCS_check_tag (symtag);
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ /* We're the client side. Fire up the remote server. */
+ start_server ();
+
+ ign_setup ();
+
+ if (local)
+ send_arg("-l");
+ if (delete)
+ send_arg("-d");
+ if (branch_mode)
+ send_arg("-b");
+ if (force_tag_move)
+ send_arg("-F");
+
+ send_arg (symtag);
+
+#if 0
+ /* FIXME: We shouldn't have to send current files, but I'm not sure
+ whether it works. So send the files --
+ it's slower but it works. */
+ send_file_names (argc, argv);
+#else
+ send_files (argc, argv, local, 0);
+#endif
+ if (fprintf (to_server, "tag\n") < 0)
+ error (1, errno, "writing to server");
+ return get_responses_and_close ();
+ }
+#endif
+
+ /* check to make sure they are authorized to tag all the
+ specified files in the repository */
+
+ mtlist = getlist();
+ err = start_recursion (check_fileproc, check_filesdoneproc,
+ (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL,
+ argc, argv, local, W_LOCAL, 0, 1,
+ (char *) NULL, 1, 0);
+
+ if (err)
+ {
+ error (1, 0, "correct the above errors first!");
+ }
+
/* start the recursion processor */
- err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc,
- (int (*) ()) NULL, argc, argv, local,
+ err = start_recursion (tag_fileproc, (FILESDONEPROC) NULL, tag_dirproc,
+ (DIRLEAVEPROC) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
+ dellist(&mtlist);
+ return (err);
+}
+
+/* check file that is to be tagged */
+/* All we do here is add it to our list */
+
+static int
+check_fileproc(file, update_dir, repository, entries, srcfiles)
+ char *file;
+ char *update_dir;
+ char *repository;
+ List * entries;
+ List * srcfiles;
+{
+ char *xdir;
+ Node *p;
+ Vers_TS *vers;
+
+ if (update_dir[0] == '\0')
+ xdir = ".";
+ else
+ xdir = update_dir;
+ if ((p = findnode (mtlist, xdir)) != NULL)
+ {
+ tlist = ((struct master_lists *) p->data)->tlist;
+ }
+ else
+ {
+ struct master_lists *ml;
+
+ tlist = getlist ();
+ p = getnode ();
+ p->key = xstrdup (xdir);
+ p->type = UPDATE;
+ ml = (struct master_lists *)
+ xmalloc (sizeof (struct master_lists));
+ ml->tlist = tlist;
+ p->data = (char *) ml;
+ p->delproc = masterlist_delproc;
+ (void) addnode (mtlist, p);
+ }
+ /* do tlist */
+ p = getnode ();
+ p->key = xstrdup (file);
+ p->type = UPDATE;
+ p->delproc = tag_delproc;
+ vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
+ file, 0, 0, entries, srcfiles);
+ p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match, 0);
+ if (p->data != NULL)
+ {
+ int addit = 1;
+ char *oversion;
+
+ oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
+ if (oversion == NULL)
+ {
+ if (delete)
+ {
+ addit = 0;
+ }
+ }
+ else if (strcmp(oversion, p->data) == 0)
+ {
+ addit = 0;
+ }
+ else if (!force_tag_move)
+ {
+ addit = 0;
+ }
+ if (oversion != NULL)
+ {
+ free(oversion);
+ }
+ if (!addit)
+ {
+ free(p->data);
+ p->data = NULL;
+ }
+ }
+ freevers_ts(&vers);
+ (void) addnode (tlist, p);
+ return (0);
+}
+
+static int
+check_filesdoneproc(err, repos, update_dir)
+ int err;
+ char *repos;
+ char *update_dir;
+{
+ int n;
+ Node *p;
+
+ p = findnode(mtlist, update_dir);
+ if (p != NULL)
+ {
+ tlist = ((struct master_lists *) p->data)->tlist;
+ }
+ else
+ {
+ tlist = (List *) NULL;
+ }
+ if ((tlist == NULL) || (tlist->list->next == tlist->list))
+ {
+ return (err);
+ }
+ if ((n = Parse_Info(CVSROOTADM_TAGINFO, repos, pretag_proc, 1)) > 0)
+ {
+ error (0, 0, "Pre-tag check failed");
+ err += n;
+ }
return (err);
}
+static int
+pretag_proc(repository, filter)
+ char *repository;
+ char *filter;
+{
+ if (filter[0] == '/')
+ {
+ char *s, *cp;
+
+ s = xstrdup(filter);
+ for (cp=s; *cp; cp++)
+ {
+ if (isspace(*cp))
+ {
+ *cp = '\0';
+ break;
+ }
+ }
+ if (!isfile(s))
+ {
+ error (0, errno, "cannot find pre-tag filter '%s'", s);
+ free(s);
+ return (1);
+ }
+ free(s);
+ }
+ run_setup("%s %s %s %s",
+ filter,
+ symtag,
+ delete ? "del" : force_tag_move ? "mov" : "add",
+ repository);
+ walklist(tlist, pretag_list_proc, NULL);
+ return (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
+}
+
+static void
+masterlist_delproc(p)
+ Node *p;
+{
+ struct master_lists *ml;
+
+ ml = (struct master_lists *)p->data;
+ dellist(&ml->tlist);
+ free(ml);
+ return;
+}
+
+static void
+tag_delproc(p)
+ Node *p;
+{
+ if (p->data != NULL)
+ {
+ free(p->data);
+ p->data = NULL;
+ }
+ return;
+}
+
+static int
+pretag_list_proc(p, closure)
+ Node *p;
+ void *closure;
+{
+ if (p->data != NULL)
+ {
+ run_arg(p->key);
+ run_arg(p->data);
+ }
+ return (0);
+}
+
+
/*
* Called to tag a particular file (the currently checked out version is
* tagged with the specified tag - or the specified tag is deleted).
@@ -119,6 +396,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
List *srcfiles;
{
char *version, *oversion;
+ char *nversion = NULL;
char *rev;
Vers_TS *vers;
int retcode = 0;
@@ -126,6 +404,18 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
file, 0, 0, entries, srcfiles);
+ if ((numtag != NULL) || (date != NULL))
+ {
+ nversion = RCS_getversion(vers->srcfile,
+ numtag,
+ date,
+ force_tag_match, 0);
+ if (nversion == NULL)
+ {
+ freevers_ts (&vers);
+ return (0);
+ }
+ }
if (delete)
{
@@ -138,7 +428,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
* "rcs" to remove the tag... trust me.
*/
- version = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1);
+ version = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
if (version == NULL || vers->srcfile == NULL)
{
freevers_ts (&vers);
@@ -146,9 +436,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
}
free (version);
- run_setup ("%s%s -q -N%s", Rcsbin, RCS, symtag);
- run_arg (vers->srcfile->path);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_deltag(vers->srcfile->path, symtag, 1)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
@@ -175,7 +463,14 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
* If we are adding a tag, we need to know which version we have checked
* out and we'll tag that version.
*/
- version = vers->vn_user;
+ if (nversion == NULL)
+ {
+ version = vers->vn_user;
+ }
+ else
+ {
+ version = nversion;
+ }
if (version == NULL)
{
freevers_ts (&vers);
@@ -212,7 +507,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
* module -- which I have found to be a typical tagging operation.
*/
rev = branch_mode ? RCS_magicrev (vers->srcfile, version) : version;
- oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1);
+ oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
if (oversion != NULL)
{
int isbranch = RCS_isbranch (file, symtag, srcfiles);
@@ -245,9 +540,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
free (oversion);
}
- run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
- run_arg (vers->srcfile->path);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ if ((retcode = RCS_settag(vers->srcfile->path, symtag, rev)) != 0)
{
error (1, retcode == -1 ? errno : 0,
"failed to set tag %s to revision %s in %s",
@@ -266,6 +559,10 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
}
freevers_ts (&vers);
+ if (nversion != NULL)
+ {
+ free(nversion);
+ }
return (0);
}
diff --git a/gnu/usr.bin/cvs/cvs/update.c b/gnu/usr.bin/cvs/cvs/update.c
index 0a4f349..0dd0e1b 100644
--- a/gnu/usr.bin/cvs/cvs/update.c
+++ b/gnu/usr.bin/cvs/cvs/update.c
@@ -34,14 +34,26 @@
*/
#include "cvs.h"
+#ifdef CLIENT_SUPPORT
+#include "update.h"
+#endif
+#ifdef SERVER_SUPPORT
+#include "md5.h"
+#endif
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)update.c 1.95 94/10/22 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)update.c 1.95 94/10/22 $";
+USE(rcsid);
#endif
static int checkout_file PROTO((char *file, char *repository, List *entries,
List *srcfiles, Vers_TS *vers_ts, char *update_dir));
+#ifdef SERVER_SUPPORT
+static int patch_file PROTO((char *file, char *repository, List *entries,
+ List *srcfiles, Vers_TS *vers_ts, char *update_dir,
+ int *docheckout, struct stat *file_info,
+ unsigned char *checksum));
+#endif
static int isemptydir PROTO((char *dir));
static int merge_file PROTO((char *file, char *repository, List *entries,
Vers_TS *vers, char *update_dir));
@@ -51,11 +63,18 @@ static Dtype update_dirent_proc PROTO((char *dir, char *repository, char *update
static int update_dirleave_proc PROTO((char *dir, int err, char *update_dir));
static int update_file_proc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
+#ifndef CLIENT_SUPPORT
static int update_filesdone_proc PROTO((int err, char *repository, char *update_dir));
+#endif
static int write_letter PROTO((char *file, int letter, char *update_dir));
static void ignore_files PROTO((List * ilist, char *update_dir));
+#ifdef SERVER_SUPPORT
+static void join_file PROTO((char *file, List *srcfiles, Vers_TS *vers_ts,
+ char *update_dir, List *entries, char *repository));
+#else
static void join_file PROTO((char *file, List *srcfiles, Vers_TS *vers_ts,
char *update_dir, List *entries));
+#endif
static char *options = NULL;
static char *tag = NULL;
@@ -67,25 +86,32 @@ static int force_tag_match = 1;
static int update_build_dirs = 0;
static int update_prune_dirs = 0;
static int pipeout = 0;
+#ifdef SERVER_SUPPORT
+static int patches = 0;
+#endif
+#ifdef CLIENT_SUPPORT
+List *ignlist = (List *) NULL;
+#else
static List *ignlist = (List *) NULL;
+#endif
static time_t last_register_time;
-static char *update_usage[] =
+static const char *const update_usage[] =
{
- "Usage:\n %s %s [-APQdflRpq] [-k kopt] [-r rev|-D date] [-j rev] [-I ign] [files...]\n",
+ "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n",
+ " [-I ign] [-W spec] [files...]\n",
"\t-A\tReset any sticky tags/date/kopts.\n",
"\t-P\tPrune empty directories.\n",
- "\t-Q\tReally quiet.\n",
"\t-d\tBuild directories, like checkout does.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, no recursion.\n",
"\t-R\tProcess directories recursively.\n",
"\t-p\tSend updates to standard output.\n",
- "\t-q\tSomewhat quiet.\n",
"\t-k kopt\tUse RCS kopt -k option on checkout.\n",
"\t-r rev\tUpdate using specified revision/tag.\n",
"\t-D date\tSet date to update from.\n",
"\t-j rev\tMerge in changes made between current revision and rev.\n",
"\t-I ign\tMore files to ignore (! to reset).\n",
+ "\t-W spec\tWrappers specification line.\n",
NULL
};
@@ -95,7 +121,7 @@ static char *update_usage[] =
int
update (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
int c, err;
int local = 0; /* recursive by default */
@@ -105,10 +131,11 @@ update (argc, argv)
usage (update_usage);
ign_setup ();
+ wrap_setup ();
/* parse the args */
optind = 1;
- while ((c = getopt (argc, argv, "ApPflRQqdk:r:D:j:I:")) != -1)
+ while ((c = getopt (argc, argv, "ApPflRQqduk:r:D:j:I:W:")) != -1)
{
switch (c)
{
@@ -118,6 +145,9 @@ update (argc, argv)
case 'I':
ign_add (optarg, 0);
break;
+ case 'W':
+ wrap_add (optarg, 0);
+ break;
case 'k':
if (options)
free (options);
@@ -130,10 +160,15 @@ update (argc, argv)
local = 0;
break;
case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
case 'q':
- quiet = 1;
+#ifdef SERVER_SUPPORT
+ /* The CVS 1.5 client sends these options (in addition to
+ Global_option requests), so we must ignore them. */
+ if (!server_active)
+#endif
+ error (1, 0,
+ "-q or -Q must be specified before \"%s\"",
+ command_name);
break;
case 'd':
update_build_dirs = 1;
@@ -162,6 +197,14 @@ update (argc, argv)
else
join_rev1 = optarg;
break;
+ case 'u':
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ patches = 1;
+ else
+#endif
+ usage (update_usage);
+ break;
case '?':
default:
usage (update_usage);
@@ -171,6 +214,98 @@ update (argc, argv)
argc -= optind;
argv += optind;
+#ifdef CLIENT_SUPPORT
+ if (client_active)
+ {
+ /* The first pass does the regular update. If we receive at least
+ one patch which failed, we do a second pass and just fetch
+ those files whose patches failed. */
+ do
+ {
+ int status;
+
+ start_server ();
+
+ ign_setup ();
+
+ if (local)
+ send_arg("-l");
+ if (update_build_dirs)
+ send_arg("-d");
+ if (pipeout)
+ send_arg("-p");
+ if (!force_tag_match)
+ send_arg("-f");
+ if (aflag)
+ send_arg("-A");
+ if (update_prune_dirs)
+ send_arg("-P");
+ client_prune_dirs = update_prune_dirs;
+ option_with_arg ("-r", tag);
+ if (date)
+ client_senddate (date);
+ if (join_rev1)
+ option_with_arg ("-j", join_rev1);
+ if (join_rev2)
+ option_with_arg ("-j", join_rev2);
+
+ /* If the server supports the command "update-patches", that means
+ that it knows how to handle the -u argument to update, which
+ means to send patches instead of complete files. */
+ if (failed_patches == NULL)
+ {
+ struct request *rq;
+
+ for (rq = requests; rq->name != NULL; rq++)
+ {
+ if (strcmp (rq->name, "update-patches") == 0)
+ {
+ if (rq->status == rq_supported)
+ {
+ send_arg("-u");
+ }
+ break;
+ }
+ }
+ }
+
+ if (failed_patches == NULL)
+ send_files (argc, argv, local, aflag);
+ else
+ {
+ int i;
+
+ (void) printf ("%s client: refetching unpatchable files\n",
+ program_name);
+
+ if (toplevel_wd[0] != '\0'
+ && chdir (toplevel_wd) < 0)
+ {
+ error (1, errno, "could not chdir to %s", toplevel_wd);
+ }
+
+ for (i = 0; i < failed_patches_count; i++)
+ (void) unlink_file (failed_patches[i]);
+ send_files (failed_patches_count, failed_patches, local,
+ aflag);
+ }
+
+ failed_patches = NULL;
+ failed_patches_count = 0;
+
+ if (fprintf (to_server, "update\n") < 0)
+ error (1, errno, "writing to server");
+
+ status = get_responses_and_close ();
+ if (status != 0)
+ return status;
+
+ } while (failed_patches != NULL);
+
+ return 0;
+ }
+#endif
+
/*
* If we are updating the entire directory (for real) and building dirs
* as we go, we make sure there is no static entries file and write the
@@ -180,20 +315,30 @@ update (argc, argv)
{
if (update_build_dirs)
{
- if (unlink_file (CVSADM_ENTSTAT) < 0 && errno != ENOENT)
+ if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_clear_entstat (".", Name_Repository (NULL, NULL));
+#endif
}
/* keep the CVS/Tag file current with the specified arguments */
if (aflag || tag || date)
+ {
WriteTag ((char *) NULL, tag, date);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_sticky (".", Name_Repository (NULL, NULL), tag, date);
+#endif
+ }
}
/* look for files/dirs locally and in the repository */
which = W_LOCAL | W_REPOS;
/* look in the attic too if a tag or date is specified */
- if (tag != NULL || date != NULL)
+ if (tag != NULL || date != NULL || joining())
which |= W_ATTIC;
/* call the command line interface */
@@ -215,7 +360,7 @@ int
do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir)
int argc;
- char *argv[];
+ char **argv;
char *xoptions;
char *xtag;
char *xdate;
@@ -331,6 +476,9 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
case T_MODIFIED: /* locally modified */
case T_REMOVED: /* removed but not committed */
case T_CHECKOUT: /* needs checkout */
+#ifdef SERVER_SUPPORT
+ case T_PATCH: /* needs patch */
+#endif
retval = checkout_file (file, repository, entries, srcfiles,
vers, update_dir);
break;
@@ -356,8 +504,22 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
(void) write_letter (file, 'C', update_dir);
break;
case T_NEEDS_MERGE: /* needs merging */
- retval = merge_file (file, repository, entries,
- vers, update_dir);
+ if (noexec)
+ {
+ retval = 1;
+ (void) write_letter (file, 'C', update_dir);
+ }
+ else
+ {
+ if (wrap_merge_is_copy (file))
+ /* Should we be warning the user that we are
+ * overwriting the user's copy of the file? */
+ retval = checkout_file (file, repository, entries,
+ srcfiles, vers, update_dir);
+ else
+ retval = merge_file (file, repository, entries,
+ vers, update_dir);
+ }
break;
case T_MODIFIED: /* locally modified */
retval = 0;
@@ -370,9 +532,19 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
* If the timestamp has changed and no conflict indicators
* are found, it isn't a 'C' any more.
*/
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ retcode = vers->ts_conflict[0] != '=';
+ else {
+ filestamp = time_stamp (file);
+ retcode = strcmp (vers->ts_conflict, filestamp);
+ free (filestamp);
+ }
+#else
filestamp = time_stamp (file);
retcode = strcmp (vers->ts_conflict, filestamp);
free (filestamp);
+#endif
if (retcode)
{
@@ -380,10 +552,10 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
* If the timestamps differ, look for Conflict
* indicators to see if 'C' anyway.
*/
- run_setup ("%s -s", GREP);
+ run_setup ("%s", GREP);
run_arg (RCS_MERGE_PAT);
run_arg (file);
- retcode = run_exec (RUN_TTY, RUN_TTY,
+ retcode = run_exec (RUN_TTY, DEVNULL,
RUN_TTY,RUN_NORMAL);
if (retcode == -1)
{
@@ -413,9 +585,41 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
if (!retval)
retval = write_letter (file, 'M', update_dir);
break;
+#ifdef SERVER_SUPPORT
+ case T_PATCH: /* needs patch */
+ if (patches)
+ {
+ int docheckout;
+ struct stat file_info;
+ unsigned char checksum[16];
+
+ retval = patch_file (file, repository, entries, srcfiles,
+ vers, update_dir, &docheckout,
+ &file_info, checksum);
+ if (! docheckout)
+ {
+ if (server_active && retval == 0)
+ server_updated (file, update_dir, repository,
+ SERVER_PATCHED, &file_info,
+ checksum);
+ break;
+ }
+ }
+ /* Fall through. */
+ /* If we're not running as a server, just check the
+ file out. It's simpler and faster than starting up
+ two new processes (diff and patch). */
+ /* Fall through. */
+#endif
case T_CHECKOUT: /* needs checkout */
retval = checkout_file (file, repository, entries, srcfiles,
vers, update_dir);
+#ifdef SERVER_SUPPORT
+ if (server_active && retval == 0)
+ server_updated (file, update_dir, repository,
+ SERVER_UPDATED, (struct stat *) NULL,
+ (unsigned char *) NULL);
+#endif
break;
case T_ADDED: /* added but not committed */
retval = write_letter (file, 'A', update_dir);
@@ -425,6 +629,12 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
break;
case T_REMOVE_ENTRY: /* needs to be un-registered */
retval = scratch_file (file, repository, entries, update_dir);
+#ifdef SERVER_SUPPORT
+ if (server_active && retval == 0)
+ server_updated (file, update_dir, repository,
+ SERVER_UPDATED, (struct stat *) NULL,
+ (unsigned char *) NULL);
+#endif
break;
default: /* can't ever happen :-) */
error (0, 0,
@@ -436,7 +646,11 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
/* only try to join if things have gone well thus far */
if (retval == 0 && join_rev1)
+#ifdef SERVER_SUPPORT
+ join_file (file, srcfiles, vers, update_dir, entries, repository);
+#else
join_file (file, srcfiles, vers, update_dir, entries);
+#endif
/* if this directory has an ignore list, add this file to it */
if (ignlist)
@@ -458,7 +672,12 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
* update_filesdone_proc () is used
*/
/* ARGSUSED */
+#ifdef CLIENT_SUPPORT
+/* Also used by client.c */
+int
+#else
static int
+#endif
update_filesdone_proc (err, repository, update_dir)
int err;
char *repository;
@@ -472,17 +691,35 @@ update_filesdone_proc (err, repository, update_dir)
}
/* Clean up CVS admin dirs if we are export */
+#ifdef CLIENT_SUPPORT
+ /* In the client, we need to clean these up after we create them. Doing
+ it here might would clean up the user's previous contents even on
+ SIGINT which probably is bad. */
+ if (!client_active && strcmp (command_name, "export") == 0)
+#else
if (strcmp (command_name, "export") == 0)
+#endif
{
run_setup ("%s -fr", RM);
run_arg (CVSADM);
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
}
#ifdef CVSADM_ROOT
- else
+#ifdef SERVER_SUPPORT
+ else if (!server_active && !pipeout)
+#else
+ else if (!pipeout)
+#endif /* SERVER_SUPPORT */
{
/* If there is no CVS/Root file, add one */
+#ifdef CLIENT_SUPPORT
+ if (!isfile (CVSADM_ROOT)
+ /* but only if we want it */
+ && ! (getenv ("CVS_IGNORE_REMOTE_ROOT") && strchr (CVSroot, ':'))
+ )
+#else /* No CLIENT_SUPPORT */
if (!isfile (CVSADM_ROOT))
+#endif /* No CLIENT_SUPPORT */
Create_Root( (char *) NULL, CVSroot );
}
#endif /* CVSADM_ROOT */
@@ -528,7 +765,7 @@ update_dirent_proc (dir, repository, update_dir)
{
/* otherwise, create the dir and appropriate adm files */
make_directory (dir);
- Create_Admin (dir, repository, tag, date);
+ Create_Admin (dir, update_dir, repository, tag, date);
}
}
@@ -543,13 +780,23 @@ update_dirent_proc (dir, repository, update_dir)
char tmp[PATH_MAX];
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
- if (unlink_file (tmp) < 0 && errno != ENOENT)
+ if (unlink_file (tmp) < 0 && ! existence_error (errno))
error (1, errno, "cannot remove file %s", tmp);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_clear_entstat (update_dir, repository);
+#endif
}
/* keep the CVS/Tag file current with the specified arguments */
if (aflag || tag || date)
+ {
WriteTag (dir, tag, date);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ server_set_sticky (update_dir, repository, tag, date);
+#endif
+ }
/* initialize the ignore list for this directory */
ignlist = getlist ();
@@ -599,43 +846,7 @@ update_dirleave_proc (dir, err, update_dir)
free (repository);
}
- /* Clean up CVS admin dirs if we are export */
- if (strcmp (command_name, "export") == 0)
- {
- run_setup ("%s -fr", RM);
- run_arg (CVSADM);
- (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
- }
-#ifdef CVSADM_ROOT
- else
- {
- /* If there is no CVS/Root file, add one */
- if (!isreadable (CVSADM_ROOT))
- {
- if (isfile (CVSADM_ROOT))
- {
- error (0, 0, "bad permissions %s/%s deleteing it", update_dir,
- CVSADM_ROOT);
- if (unlink_file (CVSADM_ROOT) == -1)
- {
- error (0, errno, "delete failed for %s/%s",
- update_dir, CVSADM_ROOT);
- }
- }
- Create_Root( (char *) NULL, CVSroot );
- }
- else
- {
- char *root = Name_Root( (char *) NULL, update_dir);
-
- if (root == NULL)
- Create_Root( (char *) NULL, CVSroot );
- else
- free (root); /* all is well, release the storage */
- }
- }
-#endif /* CVSADM_ROOT */
-
+ /* FIXME: chdir ("..") loses with symlinks. */
/* Prune empty dirs on the way out - if necessary */
(void) chdir ("..");
if (update_prune_dirs && isemptydir (dir))
@@ -667,8 +878,7 @@ isemptydir (dir)
while ((dp = readdir (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") != 0 && strcmp (dp->d_name, "..") != 0 &&
- strcmp (dp->d_name, CVSADM) != 0 &&
- strcmp (dp->d_name, OCVSADM) != 0)
+ strcmp (dp->d_name, CVSADM) != 0)
{
(void) closedir (dirp);
return (0);
@@ -709,6 +919,9 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
char backup[PATH_MAX];
int set_time, retval = 0;
int retcode = 0;
+#ifdef DEATH_SUPPORT
+ int file_is_dead;
+#endif
/* don't screw with backup files if we're going to stdout */
if (!pipeout)
@@ -720,7 +933,13 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
(void) unlink_file (backup);
}
- run_setup ("%s%s -q -r%s %s", Rcsbin, RCS_CO, vers_ts->vn_rcs,
+#ifdef DEATH_SUPPORT
+ file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
+
+ if (!file_is_dead) {
+#endif
+
+ run_setup ("%s%s -q -r%s %s", Rcsbin, RCS_CO, vers_ts->vn_tag,
vers_ts->options);
/*
@@ -749,15 +968,49 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
if (!pipeout)
run_arg (file);
+#ifdef DEATH_SUPPORT
+ }
+ if (file_is_dead || (retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
+#else
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
+#endif
(pipeout ? (RUN_NORMAL|RUN_REALLY) : RUN_NORMAL))) == 0)
{
if (!pipeout)
{
Vers_TS *xvers_ts;
+#ifdef DEATH_SUPPORT
+ int resurrecting;
+
+ resurrecting = 0;
+ if (file_is_dead && joining())
+ {
+ /* when joining, we need to get dead files checked
+ out. Try harder. */
+ run_setup ("%s%s -q -r%s %s", Rcsbin, RCS_CO, vers_ts->vn_rcs,
+ vers_ts->options);
+
+ run_arg ("-f");
+ run_arg (vers_ts->srcfile->path);
+ run_arg (file);
+ if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
+ {
+ error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
+ "could not check out %s", file);
+ (void) unlink_file (backup);
+ return (retcode);
+ }
+ file_is_dead = 0;
+ resurrecting = 1;
+ }
+
+ if (cvswrite == TRUE && !file_is_dead)
+ xchmod (file, 1);
+#else /* No DEATH_SUPPORT */
if (cvswrite == TRUE)
xchmod (file, 1);
+#endif /* No DEATH_SUPPORT */
/* set the time from the RCS file iff it was unknown before */
if (vers_ts->vn_user == NULL ||
@@ -768,16 +1021,64 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
else
set_time = 0;
+ wrap_fromcvs_process_file (file);
+
xvers_ts = Version_TS (repository, options, tag, date, file,
force_tag_match, set_time, entries, srcfiles);
if (strcmp (xvers_ts->options, "-V4") == 0)
xvers_ts->options[0] = '\0';
+ /* If no keyword expansion was specified on command line,
+ use whatever was in the file. This is how we tell the client
+ whether a file is binary. */
+ if (xvers_ts->options[0] == '\0')
+ {
+ if (vers_ts->srcfile->expand != NULL)
+ {
+ free (xvers_ts->options);
+ xvers_ts->options =
+ xmalloc (strlen (vers_ts->srcfile->expand) + 3);
+ strcpy (xvers_ts->options, "-k");
+ strcat (xvers_ts->options, vers_ts->srcfile->expand);
+ }
+ }
(void) time (&last_register_time);
+#ifdef DEATH_SUPPORT
+ if (file_is_dead)
+ {
+ if (xvers_ts->vn_user != NULL)
+ {
+ if (update_dir[0] == '\0')
+ error (0, 0,
+ "warning: %s is not (any longer) pertinent",
+ file);
+ else
+ error (0, 0,
+ "warning: %s/%s is not (any longer) pertinent",
+ update_dir, file);
+ }
+ Scratch_Entry (entries, file);
+ if (unlink_file (file) < 0 && ! existence_error (errno))
+ {
+ if (update_dir[0] == '\0')
+ error (0, errno, "cannot remove %s", file);
+ else
+ error (0, errno, "cannot remove %s/%s", update_dir,
+ file);
+ }
+ }
+ else
+ Register (entries, file,
+ resurrecting ? "0" : xvers_ts->vn_rcs,
+ xvers_ts->ts_user, xvers_ts->options,
+ xvers_ts->tag, xvers_ts->date,
+ (char *)0); /* Clear conflict flag on fresh checkout */
+#else /* No DEATH_SUPPORT */
Register (entries, file, xvers_ts->vn_rcs, xvers_ts->ts_user,
xvers_ts->options, xvers_ts->tag, xvers_ts->date,
(char *)0); /* Clear conflict flag on fresh checkout */
+#endif /* No DEATH_SUPPORT */
/* fix up the vers structure, in case it is used by join */
if (join_rev1)
@@ -797,7 +1098,11 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
freevers_ts (&xvers_ts);
+#ifdef DEATH_SUPPORT
+ if (!really_quiet && !file_is_dead)
+#else
if (!really_quiet)
+#endif
{
if (update_dir[0])
(void) printf ("U %s/%s\n", update_dir, file);
@@ -825,6 +1130,226 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
return (retval);
}
+#ifdef SERVER_SUPPORT
+/* Patch a file. Runs rcsdiff. This is only done when running as the
+ * server. The hope is that the diff will be smaller than the file
+ * itself.
+ */
+static int
+patch_file (file, repository, entries, srcfiles, vers_ts, update_dir,
+ docheckout, file_info, checksum)
+ char *file;
+ char *repository;
+ List *entries;
+ List *srcfiles;
+ Vers_TS *vers_ts;
+ char *update_dir;
+ int *docheckout;
+ struct stat *file_info;
+ unsigned char *checksum;
+{
+ char backup[PATH_MAX];
+ char file1[PATH_MAX];
+ char file2[PATH_MAX];
+ int retval = 0;
+ int retcode = 0;
+ int fail;
+ FILE *e;
+
+ *docheckout = 0;
+
+ if (pipeout || joining ())
+ {
+ *docheckout = 1;
+ return 0;
+ }
+
+ (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, file);
+ if (isfile (file))
+ rename_file (file, backup);
+ else
+ (void) unlink_file (backup);
+
+ (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, file);
+ (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, file);
+
+ fail = 0;
+
+ /* We need to check out both revisions first, to see if either one
+ has a trailing newline. Because of this, we don't use rcsdiff,
+ but just use diff. */
+ run_setup ("%s%s -q -p -r%s %s %s", Rcsbin, RCS_CO, vers_ts->vn_user,
+ vers_ts->options, vers_ts->srcfile->path);
+ if (run_exec (RUN_TTY, file1, RUN_TTY, RUN_NORMAL) != 0)
+ fail = 1;
+ else
+ {
+ e = fopen (file1, "r");
+ if (e == NULL)
+ fail = 1;
+ else
+ {
+ if (fseek (e, (long) -1, SEEK_END) == 0
+ && getc (e) != '\n')
+ {
+ fail = 1;
+ }
+ fclose (e);
+ }
+ }
+
+ if (! fail)
+ {
+ /* Check it out into file, and then move to file2, so that we
+ can get the right modes into *FILE_INFO. We can't check it
+ out directly into file2 because co doesn't understand how
+ to do that. */
+ run_setup ("%s%s -q -r%s %s %s %s", Rcsbin, RCS_CO, vers_ts->vn_rcs,
+ vers_ts->options, vers_ts->srcfile->path, file);
+ if (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
+ fail = 1;
+ else
+ {
+ if (!isreadable (file))
+ {
+ /* File is dead. */
+ fail = 1;
+ }
+ else
+ {
+ rename_file (file, file2);
+ if (cvswrite == TRUE)
+ xchmod (file2, 1);
+ e = fopen (file2, "r");
+ if (e == NULL)
+ fail = 1;
+ else
+ {
+ struct MD5Context context;
+ int nl;
+ unsigned char buf[8192];
+ unsigned len;
+
+ nl = 0;
+
+ /* Compute the MD5 checksum and make sure there is
+ a trailing newline. */
+ MD5Init (&context);
+ while ((len = fread (buf, 1, sizeof buf, e)) != 0)
+ {
+ nl = buf[len - 1] == '\n';
+ MD5Update (&context, buf, len);
+ }
+ MD5Final (checksum, &context);
+
+ if (ferror (e) || ! nl)
+ {
+ fail = 1;
+ }
+
+ fclose (e);
+ }
+ }
+ }
+ }
+
+ if (! fail)
+ {
+ /* FIXME: This whole thing with diff/patch is rather more
+ convoluted than necessary (lots of forks and execs, need to
+ worry about versions of diff and patch, etc.). Also, we
+ send context lines which aren't needed (in the rare case in
+ which the diff doesn't apply, the checksum would catches it).
+ Solution perhaps is to librarify the RCS routines which apply
+ deltas or something equivalent. */
+ /* This is -c, not -u, because we have no way of knowing which
+ DIFF is in use. */
+ run_setup ("%s -c %s %s", DIFF, file1, file2);
+
+ /* A retcode of 0 means no differences. 1 means some differences. */
+ if ((retcode = run_exec (RUN_TTY, file, RUN_TTY, RUN_NORMAL)) != 0
+ && retcode != 1)
+ {
+ fail = 1;
+ }
+ else
+ {
+#define BINARY "Binary"
+ char buf[sizeof BINARY];
+ unsigned int c;
+
+ /* Check the diff output to make sure patch will be handle it. */
+ e = fopen (file, "r");
+ if (e == NULL)
+ error (1, errno, "could not open diff output file %s", file);
+ c = fread (buf, 1, sizeof BINARY - 1, e);
+ buf[c] = '\0';
+ if (strcmp (buf, BINARY) == 0)
+ {
+ /* These are binary files. We could use diff -a, but
+ patch can't handle that. */
+ fail = 1;
+ }
+ fclose (e);
+ }
+ }
+
+ if (! fail)
+ {
+ Vers_TS *xvers_ts;
+
+ /* This stuff is just copied blindly from checkout_file. I
+ don't really know what it does. */
+ xvers_ts = Version_TS (repository, options, tag, date, file,
+ force_tag_match, 0, entries, srcfiles);
+ if (strcmp (xvers_ts->options, "-V4") == 0)
+ xvers_ts->options[0] = '\0';
+
+ Register (entries, file, xvers_ts->vn_rcs,
+ xvers_ts->ts_user, xvers_ts->options,
+ xvers_ts->tag, xvers_ts->date, NULL);
+
+ if (stat (file2, file_info) < 0)
+ error (1, errno, "could not stat %s", file2);
+
+ /* If this is really Update and not Checkout, recode history */
+ if (strcmp (command_name, "update") == 0)
+ history_write ('P', update_dir, xvers_ts->vn_rcs, file,
+ repository);
+
+ freevers_ts (&xvers_ts);
+
+ if (!really_quiet)
+ {
+ if (update_dir[0])
+ (void) printf ("P %s/%s\n", update_dir, file);
+ else
+ (void) printf ("P %s\n", file);
+ }
+ }
+ else
+ {
+ int old_errno = errno; /* save errno value over the rename */
+
+ if (isfile (backup))
+ rename_file (backup, file);
+
+ if (retcode != 0 && retcode != 1)
+ error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
+ "could not diff %s", file);
+
+ *docheckout = 1;
+ retval = retcode;
+ }
+
+ (void) unlink_file (backup);
+ (void) unlink_file (file1);
+ (void) unlink_file (file2);
+
+ return (retval);
+}
+#endif
+
/*
* Several of the types we process only print a bit of information consisting
* of a single letter and the name.
@@ -878,16 +1403,9 @@ merge_file (file, repository, entries, vers, update_dir)
copy_file (file, backup);
xchmod (file, 1);
- /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */
- run_setup ("%s%s %s -r%s -r%s", Rcsbin, RCS_RCSMERGE, vers->options,
- vers->vn_user, vers->vn_rcs);
- run_arg (vers->srcfile->path);
- status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
- if (status != 0
-#ifdef HAVE_RCS5
- && status != 1
-#endif
- )
+ status = RCS_merge(vers->srcfile->path,
+ vers->options, vers->vn_user, vers->vn_rcs);
+ if (status != 0 && status != 1)
{
error (0, status == -1 ? errno : 0,
"could not merge revision %s of %s", vers->vn_user, user);
@@ -919,7 +1437,19 @@ merge_file (file, repository, entries, vers, update_dir)
vers->vn_user = xstrdup (vers->vn_rcs);
}
- if (!xcmp (backup, file))
+#ifdef SERVER_SUPPORT
+ /* Send the new contents of the file before the message. If we
+ wanted to be totally correct, we would have the client write
+ the message only after the file has safely been written. */
+ if (server_active)
+ {
+ server_copy_file (file, update_dir, repository, backup);
+ server_updated (file, update_dir, repository, SERVER_MERGED,
+ (struct stat *) NULL, (unsigned char *) NULL);
+ }
+#endif
+
+ if (!noexec && !xcmp (backup, file))
{
printf ("%s already contains the differences between %s and %s\n",
user, vers->vn_user, vers->vn_rcs);
@@ -927,12 +1457,7 @@ merge_file (file, repository, entries, vers, update_dir)
return (0);
}
- /* possibly run GREP to see if there appear to be conflicts in the file */
- run_setup ("%s -s", GREP);
- run_arg (RCS_MERGE_PAT);
- run_arg (file);
- if (status == 1 ||
- (retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) == 0)
+ if (status == 1)
{
if (!noexec)
error (0, 0, "conflicts found in %s", user);
@@ -961,7 +1486,12 @@ merge_file (file, repository, entries, vers, update_dir)
* (-j option)
*/
static void
+#ifdef SERVER_SUPPORT
+join_file (file, srcfiles, vers, update_dir, entries, repository)
+ char *repository;
+#else
join_file (file, srcfiles, vers, update_dir, entries)
+#endif
char *file;
List *srcfiles;
Vers_TS *vers;
@@ -985,6 +1515,14 @@ join_file (file, srcfiles, vers, update_dir, entries)
jdate1 = date_rev1;
jdate2 = date_rev2;
+ if (wrap_merge_is_copy (file))
+ {
+ /* FIXME: Should be including update_dir in message. */
+ error (0, 0,
+ "Cannot merge %s because it is a merge-by-copy file.", file);
+ return;
+ }
+
/* determine if we need to do anything at all */
if (vers->srcfile == NULL ||
vers->srcfile->path == NULL)
@@ -1003,9 +1541,38 @@ join_file (file, srcfiles, vers, update_dir, entries)
jdate1 = NULL;
}
+ /* The file in the working directory doesn't exist in CVS/Entries.
+ FIXME: Shouldn't this case result in additional processing (if
+ the file was added going from rev1 to rev2, then do the equivalent
+ of a "cvs add")? (yes; easier said than done.. :-) */
+ if (vers->vn_user == NULL)
+ {
+ /* No merge possible YET. */
+ if (jdate2 != NULL)
+ error (0, 0,
+ "file %s is present in revision %s as of %s",
+ file, jrev2, jdate2);
+ else
+ error (0, 0,
+ "file %s is present in revision %s",
+ file, jrev2);
+ return;
+ }
+
+ /* Fix for bug CVS/193:
+ * Used to dump core if the file had been removed on the current branch.
+ */
+ if (strcmp(vers->vn_user, "0") == 0)
+ {
+ error(0, 0,
+ "file %s has been deleted",
+ file);
+ return;
+ }
+
/* convert the second rev spec, walking branches and dates. */
- rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1);
+ rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, 0);
if (rev2 == NULL)
{
if (!quiet)
@@ -1018,14 +1585,14 @@ join_file (file, srcfiles, vers, update_dir, entries)
error (0, 0,
"cannot find revision %s in file %s",
jrev2, file);
- return;
}
+ return;
}
-
- /* skip joining identical revs or if the file is not present */
- if (vers->vn_user == NULL ||
- strcmp (rev2, vers->vn_user) == 0) /* no merge necessary */
+
+ /* skip joining identical revs */
+ if (strcmp (rev2, vers->vn_user) == 0)
{
+ /* No merge necessary. */
free (rev2);
return;
}
@@ -1037,6 +1604,9 @@ join_file (file, srcfiles, vers, update_dir, entries)
greatest common ancestor of both the join rev, and the
checked out rev. */
+ /* FIXME: What is this check for '!' about? If it is legal to
+ have '!' in the first character of vn_user, it isn't
+ documented at struct vers_ts in cvs.h. */
tst = vers->vn_user;
if (*tst == '!')
{
@@ -1054,7 +1624,7 @@ join_file (file, srcfiles, vers, update_dir, entries)
abort();
}
- tst = RCS_gettag (vers->srcfile, rev2, 1);
+ tst = RCS_gettag (vers->srcfile, rev2, 1, 0);
if (tst == NULL)
{
/* this should not be possible. */
@@ -1077,10 +1647,10 @@ join_file (file, srcfiles, vers, update_dir, entries)
/* otherwise, convert the first rev spec, walking branches and
dates. */
- rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1);
- if (rev1 == NULL
- && !quiet)
+ rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, 0);
+ if (rev1 == NULL)
{
+ if (!quiet) {
if (jdate1 != NULL)
error (0, 0,
"cannot find revision %s as of %s in file %s",
@@ -1089,7 +1659,8 @@ join_file (file, srcfiles, vers, update_dir, entries)
error (0, 0,
"cannot find revision %s in file %s",
jrev1, file);
- return;
+ }
+ return;
}
}
@@ -1100,7 +1671,7 @@ join_file (file, srcfiles, vers, update_dir, entries)
/* special handling when two revisions are specified */
if (join_rev1 && join_rev2)
{
- rev = RCS_getversion (vers->srcfile, join_rev2, date_rev2, 1);
+ rev = RCS_getversion (vers->srcfile, join_rev2, date_rev2, 1, 0);
if (rev == NULL)
{
if (!quiet && date_rev2 == NULL)
@@ -1109,7 +1680,7 @@ join_file (file, srcfiles, vers, update_dir, entries)
return;
}
- baserev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1);
+ baserev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1, 0);
if (baserev == NULL)
{
if (!quiet && date_rev1 == NULL)
@@ -1137,7 +1708,7 @@ join_file (file, srcfiles, vers, update_dir, entries)
}
else
{
- rev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1);
+ rev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1, 0);
if (rev == NULL)
return;
if (strcmp (rev, vers->vn_user) == 0) /* no merge necessary */
@@ -1172,6 +1743,20 @@ join_file (file, srcfiles, vers, update_dir, entries)
#endif
/* OK, so we have two revisions; continue on */
+
+#ifdef SERVER_SUPPORT
+ if (server_active && !isreadable (file))
+ {
+ int retcode;
+ /* The file is up to date. Need to check out the current contents. */
+ run_setup ("%s%s -q -r%s", Rcsbin, RCS_CO, vers->vn_user);
+ run_arg (vers->srcfile->path);
+ retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+ if (retcode != 0)
+ error (1, retcode == -1 ? errno : 0,
+ "failed to check out %s file", file);
+ }
+#endif
/*
* The users currently modified file is moved to a backup file name
@@ -1198,16 +1783,8 @@ join_file (file, srcfiles, vers, update_dir, entries)
#endif
#endif
- /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */
- run_setup ("%s%s %s -r%s -r%s", Rcsbin, RCS_RCSMERGE, options,
- rev1, rev2);
- run_arg (vers->srcfile->path);
- status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
- if (status != 0
-#ifdef HAVE_RCS5
- && status != 1
-#endif
- )
+ status = RCS_merge (vers->srcfile->path, options, rev1, rev2);
+ if (status != 0 && status != 1)
{
error (0, status == -1 ? errno : 0,
"could not merge revision %s of %s", rev2, user);
@@ -1218,8 +1795,17 @@ join_file (file, srcfiles, vers, update_dir, entries)
free (rev1);
free (rev2);
-#ifdef HAVE_RCS5
+#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
{
char *cp = 0;
@@ -1230,9 +1816,15 @@ join_file (file, srcfiles, vers, update_dir, entries)
if (cp)
free(cp);
}
-#endif
- return;
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ server_copy_file (file, update_dir, repository, backup);
+ server_updated (file, update_dir, repository, SERVER_MERGED,
+ (struct stat *) NULL, (unsigned char *) NULL);
+ }
+#endif
}
/*
@@ -1261,6 +1853,8 @@ ignore_files (ilist, update_dir)
return;
ign_add_file (CVSDOTIGNORE, 1);
+ wrap_add_file (CVSDOTWRAPPER, 1);
+
while ((dp = readdir (dirp)) != NULL)
{
file = dp->d_name;
diff --git a/gnu/usr.bin/cvs/cvs/vers_ts.c b/gnu/usr.bin/cvs/cvs/vers_ts.c
index 0bc1242..ebb7ca8 100644
--- a/gnu/usr.bin/cvs/cvs/vers_ts.c
+++ b/gnu/usr.bin/cvs/cvs/vers_ts.c
@@ -9,11 +9,13 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)vers_ts.c 1.45 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)vers_ts.c 1.45 94/10/07 $";
+USE(rcsid);
#endif
-#define ctime(X) do not use ctime, please
+#ifdef SERVER_SUPPORT
+static void time_stamp_server PROTO((char *, Vers_TS *));
+#endif
/*
* Fill in and return a Vers_TS structure "user" is the name of the local
@@ -136,16 +138,39 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
/* squirrel away the rcsdata pointer for others */
vers_ts->srcfile = rcsdata;
+#ifndef DEATH_SUPPORT
+ /* (is this indeed death support? I haven't looked carefully). */
/* get RCS version number into vn_rcs (if appropriate) */
if (((vers_ts->tag || vers_ts->date) && force_tag_match) ||
((rcsdata->flags & VALID) && (rcsdata->flags & INATTIC) == 0))
{
+#endif
if (vers_ts->tag && strcmp (vers_ts->tag, TAG_BASE) == 0)
+ {
vers_ts->vn_rcs = xstrdup (vers_ts->vn_user);
+ vers_ts->vn_tag = xstrdup (vers_ts->vn_user);
+ }
else
+ {
vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
- vers_ts->date, force_tag_match);
+ vers_ts->date, force_tag_match, 1);
+ if (vers_ts->vn_rcs == NULL)
+ vers_ts->vn_tag = NULL;
+ else
+ {
+ char *colon = strchr (vers_ts->vn_rcs, ':');
+ if (colon)
+ {
+ vers_ts->vn_tag = xstrdup (colon+1);
+ *colon = '\0';
+ }
+ else
+ vers_ts->vn_tag = xstrdup (vers_ts->vn_rcs);
+ }
+ }
+#ifndef DEATH_SUPPORT
}
+#endif
/*
* If the source control file exists and has the requested revision,
@@ -167,12 +192,81 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
/* get user file time-stamp in ts_user */
if (entries != (List *) NULL)
{
- vers_ts->ts_user = time_stamp (user);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ time_stamp_server (user, vers_ts);
+ else
+#endif
+ vers_ts->ts_user = time_stamp (user);
}
return (vers_ts);
}
+#ifdef SERVER_SUPPORT
+
+/* Set VERS_TS->TS_USER to time stamp for FILE. */
+
+/* Separate these out to keep the logic below clearer. */
+#define mark_lost(V) ((V)->ts_user = 0)
+#define mark_unchanged(V) ((V)->ts_user = xstrdup ((V)->ts_rcs))
+
+static void
+time_stamp_server (file, vers_ts)
+ char *file;
+ Vers_TS *vers_ts;
+{
+ struct stat sb;
+ char *cp;
+
+ if (stat (file, &sb) < 0)
+ {
+ if (! existence_error (errno))
+ error (1, errno, "cannot stat temp file");
+ if (use_unchanged)
+ {
+ /* Missing file means lost or unmodified; check entries
+ file to see which.
+
+ XXX FIXME - If there's no entries file line, we
+ wouldn't be getting the file at all, so consider it
+ lost. I don't know that that's right, but it's not
+ clear to me that either choice is. Besides, would we
+ have an RCS string in that case anyways? */
+ if (vers_ts->entdata == NULL)
+ mark_lost (vers_ts);
+ else if (vers_ts->entdata->timestamp
+ && vers_ts->entdata->timestamp[0] == '=')
+ mark_unchanged (vers_ts);
+ else
+ mark_lost (vers_ts);
+ }
+ else
+ {
+ /* Missing file in the temp directory means that the file
+ was not modified. */
+ mark_unchanged (vers_ts);
+ }
+ }
+ else if (sb.st_mtime == 0)
+ {
+ if (use_unchanged)
+ /* We shouldn't reach this case any more! */
+ abort ();
+
+ /* Special code used by server.c to indicate the file was lost. */
+ mark_lost (vers_ts);
+ }
+ else
+ {
+ vers_ts->ts_user = xmalloc (25);
+ cp = asctime (gmtime (&sb.st_mtime)); /* copy in the modify time */
+ cp[24] = 0;
+ (void) strcpy (vers_ts->ts_user, cp);
+ }
+}
+
+#endif /* SERVER_SUPPORT */
/*
* Gets the time-stamp for the file "file" and returns it in space it
* allocates
@@ -213,6 +307,8 @@ freevers_ts (versp)
free ((*versp)->vn_user);
if ((*versp)->vn_rcs)
free ((*versp)->vn_rcs);
+ if ((*versp)->vn_tag)
+ free ((*versp)->vn_tag);
if ((*versp)->ts_user)
free ((*versp)->ts_user);
if ((*versp)->ts_rcs)
diff --git a/gnu/usr.bin/cvs/cvsbug/Makefile b/gnu/usr.bin/cvs/cvsbug/Makefile
new file mode 100644
index 0000000..2117dda
--- /dev/null
+++ b/gnu/usr.bin/cvs/cvsbug/Makefile
@@ -0,0 +1,25 @@
+# $Id: Makefile,v 1.2 1995/07/25 00:31:51 bde Exp $
+
+MAN8= cvsbug.8
+
+CLEANFILES+= cvsbug
+
+.SUFFIXES: .sh
+
+all: cvsbug
+
+.sh:
+ echo > ver cvs-`sed < ${.CURDIR}/../lib/version.c \
+ -e '/version_string/!d' \
+ -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
+ -e q`
+ sed -e "s,xVERSIONx,`cat ver`,g" ${.CURDIR}/$@.sh > $@
+
+
+afterinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ cvsbug ${DESTDIR}${BINDIR}/cvsbug
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
+
diff --git a/gnu/usr.bin/cvs/cvsinit/Makefile b/gnu/usr.bin/cvs/cvsinit/Makefile
index 870fb77..8cc2d0a 100644
--- a/gnu/usr.bin/cvs/cvsinit/Makefile
+++ b/gnu/usr.bin/cvs/cvsinit/Makefile
@@ -1,8 +1,27 @@
-# $Id: Makefile,v 1.1 1994/10/22 04:51:39 nate Exp $
+# $Id: Makefile,v 1.2 1995/07/25 00:31:51 bde Exp $
+
+MAN8= cvsinit.8
+
+EXAMPDIR= /usr/share/examples/cvs
+CLEANFILES+= cvsinit
+
+.SUFFIXES: .sh
+
+all: cvsinit
+
+.sh:
+ echo > ver \
+ cvs-`sed < ${.CURDIR}/../lib/version.c \
+ -e '/version_string/!d' \
+ -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
+ -e q`
+ sed -e 's,xLIBDIRx,$(EXAMPDIR),g' \
+ -e "s,xVERSIONx,`cat ver`,g" ${.CURDIR}/$@.sh > $@
afterinstall:
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
- ${.CURDIR}/cvsinit.sh ${DESTDIR}${BINDIR}/cvsinit
+ cvsinit ${DESTDIR}${BINDIR}/cvsinit
.include "../../Makefile.inc"
.include <bsd.prog.mk>
+
diff --git a/gnu/usr.bin/cvs/cvsinit/cvsinit.sh b/gnu/usr.bin/cvs/cvsinit/cvsinit.sh
index 1c117cb..49c5451 100644
--- a/gnu/usr.bin/cvs/cvsinit/cvsinit.sh
+++ b/gnu/usr.bin/cvs/cvsinit/cvsinit.sh
@@ -1,17 +1,28 @@
#! /bin/sh
:
#
+#ident "@(#)cvs:$Name: $:$Id: cvsinit.sh,v 1.7 1995/11/14 23:44:18 woods Exp $"
# Copyright (c) 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 1.4 kit.
-#
-# $CVSid: @(#)cvsinit.sh 1.1 94/10/22 $
-#
-# This script should be run once to help you setup your site for CVS.
+
+# This script should be run for each repository you create to help you
+# setup your site for CVS. You may also run it to update existing
+# repositories if you install a new version of CVS.
# this line is edited by Makefile when creating cvsinit.inst
-CVSLIB="/usr/src/gnu/usr.bin/cvs"
+CVSLIB="xLIBDIRx"
+
+CVS_VERSION="xVERSIONx"
+
+# All purpose usage message, also suffices for --help and --version.
+if test $# -gt 0; then
+ echo "cvsinit version $CVS_VERSION"
+ echo "usage: $0"
+ echo "(set CVSROOT to the repository that you want to initialize)"
+ exit 0
+fi
# Make sure that the CVSROOT variable is set
if [ "x$CVSROOT" = x ]; then
@@ -23,17 +34,16 @@ if [ "x$CVSROOT" = x ]; then
echo "plenty of free space."
echo ""
echo "Please enter the full path for your CVSROOT source repository:"
- read CVSROOT
+ read CVSROOT junk
+ unset junk
remind_cvsroot=yes
else
- echo "Using $CVSROOT as the source repository."
remind_cvsroot=no
fi
-echo ""
# Now, create the $CVSROOT if it is not already there
if [ ! -d $CVSROOT ]; then
- echo "Hmmm... $CVSROOT does not exist; trying to make it..."
+ echo "Creating $CVSROOT..."
path=
for comp in `echo $CVSROOT | sed -e 's,/, ,g'`; do
path=$path/$comp
@@ -42,7 +52,7 @@ if [ ! -d $CVSROOT ]; then
fi
done
else
- echo "Good... $CVSROOT already exists."
+ true
fi
# Next, check for $CVSROOT/CVSROOT
@@ -52,81 +62,63 @@ if [ ! -d $CVSROOT/CVSROOT ]; then
echo "I will rename it to $CVSROOT/CVSROOT for you..."
mv $CVSROOT/CVSROOT.adm $CVSROOT/CVSROOT
else
- echo "Making the $CVSROOT/CVSROOT directory..."
+ echo "Creating the $CVSROOT/CVSROOT directory..."
mkdir $CVSROOT/CVSROOT
fi
else
- echo "Wow!... so does $CVSROOT/CVSROOT."
+ true
fi
-echo ""
if [ ! -d $CVSROOT/CVSROOT ]; then
- echo "You still don't have a $CVSROOT/CVSROOT directory."
+ echo "Unable to create $CVSROOT/CVSROOT."
echo "I give up."
exit 1
fi
-# Create the special *info files within $CVSROOT/CVSROOT
+# Create the special control files and templates within $CVSROOT/CVSROOT
-# Trump up a simple modules file, if one doesn't exist
-if [ -f $CVSROOT/CVSROOT/modules,v ]; then
- if [ ! -f $CVSROOT/CVSROOT/modules ]; then
- echo "You have a $CVSROOT/CVSROOT/modules,v file,"
- echo "But no $CVSROOT/CVSROOT/modules file. This is OK."
- echo "I'll checkout a fresh copy..."
- (cd $CVSROOT/CVSROOT; co -q modules)
- echo ""
- fi
-else
- if [ -f $CVSROOT/CVSROOT/modules ]; then
- echo "You have a $CVSROOT/CVSROOT/modules file,"
- echo "But no $CVSROOT/CVSROOT/modules,v file."
- echo "I'll create one for you, but otherwise leave it alone..."
- else
- echo "The $CVSROOT/CVSROOT/modules file does not exist."
- echo "Making a simple one for you..."
- cat > $CVSROOT/CVSROOT/modules <<"HERE"
-#
-# The CVS modules file
-#
-# Three different line formats are valid:
-# key -a aliases...
-# key [options] directory
-# key [options] directory files...
-#
-# Where "options" are composed of:
-# -i prog Run "prog" on "cvs commit" from top-level of module.
-# -o prog Run "prog" on "cvs checkout" of module.
-# -t prog Run "prog" on "cvs rtag" of module.
-# -u prog Run "prog" on "cvs update" of module.
-# -d dir Place module in directory "dir" instead of module name.
-# -l Top-level directory only -- do not recurse.
-#
-# And "directory" is a path to a directory relative to $CVSROOT.
-#
-# The "-a" option specifies an alias. An alias is interpreted as if
-# everything on the right of the "-a" had been typed on the command line.
-#
-# You can encode a module within a module by using the special '&'
-# character to interpose another module into the current module. This
-# can be useful for creating a module that consists of many directories
-# spread out over the entire source repository.
-#
+EXAMPLES="checkoutlist commitinfo cvswrappers editinfo loginfo modules
+rcsinfo rcstemplate taginfo wrap unwrap"
-# Convenient aliases
-world -a .
-
-# CVSROOT support; run mkmodules whenever anything changes.
-CVSROOT -i mkmodules CVSROOT
-modules -i mkmodules CVSROOT modules
-loginfo -i mkmodules CVSROOT loginfo
-commitinfo -i mkmodules CVSROOT commitinfo
-rcsinfo -i mkmodules CVSROOT rcsinfo
-editinfo -i mkmodules CVSROOT editinfo
-
-# Add other modules here...
-HERE
+NEWSAMPLE=false
+for info in $EXAMPLES; do
+ if [ -f $CVSROOT/CVSROOT/${info},v ]; then
+ if [ ! -f $CVSROOT/CVSROOT/$info ]; then
+ echo "Checking out $CVSROOT/CVSROOT/$info"
+ echo " from $CVSROOT/CVSROOT/${info},v..."
+ (cd $CVSROOT/CVSROOT; co -q $info)
+ fi
+ else
+ NEWSAMPLE=true
+ if [ -f $CVSROOT/CVSROOT/$info ]; then
+ echo "Checking in $CVSROOT/CVSROOT/${info},v"
+ echo " from $CVSROOT/CVSROOT/$info..."
+ else
+ echo "Creating a sample $CVSROOT/CVSROOT/$info file..."
+ case $info in
+ modules)
+ sed -n -e '/END_REQUIRED_CONTENT/q' \
+ -e p $CVSLIB/examples/modules > $CVSROOT/CVSROOT/modules
+ ;;
+ rcstemplate)
+ cp $CVSLIB/examples/$info $CVSROOT/CVSROOT/$info
+ ;;
+ wrap|unwrap)
+ cp $CVSLIB/examples/$info $CVSROOT/CVSROOT/$info
+ chmod +x $CVSROOT/CVSROOT/$info
+ ;;
+ *)
+ # comment out everything in all the other examples....
+ sed -e 's/^\([^#]\)/#\1/' $CVSLIB/examples/$info > $CVSROOT/CVSROOT/$info
+ ;;
+ esac
+ fi
+ (cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m"initial checkin of $info" $info)
fi
- (cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m'initial checkin of modules' modules)
+done
+
+if $NEWSAMPLE ; then
+ echo "NOTE: You may wish to check out the CVSROOT module and edit any new"
+ echo "configuration files to match your local requirements."
echo ""
fi
@@ -138,86 +130,18 @@ if grep CVSROOT.adm $CVSROOT/CVSROOT/modules >/dev/null 2>&1; then
echo ""
fi
-# loginfo, like modules, is special-cased
-if [ -f $CVSROOT/CVSROOT/loginfo,v ]; then
- if [ ! -f $CVSROOT/CVSROOT/loginfo ]; then
- echo "You have a $CVSROOT/CVSROOT/loginfo,v file,"
- echo "But no $CVSROOT/CVSROOT/loginfo file. This is OK."
- echo "I'll checkout a fresh copy..."
- (cd $CVSROOT/CVSROOT; co -q loginfo)
- echo ""
- fi
-else
- if [ -f $CVSROOT/CVSROOT/loginfo ]; then
- echo "You have a $CVSROOT/CVSROOT/loginfo file,"
- echo "But no $CVSROOT/CVSROOT/loginfo,v file."
- echo "I'll create one for you, but otherwise leave it alone..."
- else
- echo "The $CVSROOT/CVSROOT/loginfo file does not exist."
- echo "Making a simple one for you..."
- # try to find perl; use fancy log script if we can
- for perlpath in `echo $PATH | sed -e 's/:/ /g'` x; do
- if [ -f $perlpath/perl -a -r $CVSLIB/contrib/log.pl ]; then
- echo "#!$perlpath/perl" > $CVSROOT/CVSROOT/log.pl
- cat $CVSLIB/contrib/log.pl >> $CVSROOT/CVSROOT/log.pl
- chmod 755 $CVSROOT/CVSROOT/log.pl
- cp $CVSLIB/examples/loginfo $CVSROOT/CVSROOT/loginfo
- break
- fi
- done
- if [ $perlpath = x -o ! -r $CVSLIB/contrib/log.pl ]; then
- # we did not find perl anywhere, so make a simple loginfo file
- cat > $CVSROOT/CVSROOT/loginfo <<"HERE"
-#
-# The "loginfo" file is used to control where "cvs commit" log information
-# is sent. The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT. If a match is found, then the remainder of the line is a filter
-# program that should expect log information on its standard input.
+# These files are generated from the contrib files.
+# FIXME: Is it really wise to overwrite possible local changes like this?
+# Normal folks will keep these up to date by modifying the source in
+# their CVS module and re-installing CVS, but is everyone OK with that?
#
-# The filter program may use one and only one % modifier (ala printf). If
-# %s is specified in the filter program, a brief title is included (enclosed
-# in single quotes) showing the modified file names.
#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
+CONTRIBS="log commit_prep log_accum cln_hist"
#
-# If the name ALL appears as a regular expression it is always used
-# in addition to the first matching regex or DEFAULT.
-#
-DEFAULT (echo ""; echo $USER; date; cat) >> $CVSROOT/CVSROOT/commitlog
-HERE
- fi
- fi
- (cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m'initial checkin of loginfo' loginfo)
- echo ""
-fi
-
-# The remaining files are generated from the examples files.
-for info in commitinfo rcsinfo editinfo; do
- if [ -f $CVSROOT/CVSROOT/${info},v ]; then
- if [ ! -f $CVSROOT/CVSROOT/$info ]; then
- echo "You have a $CVSROOT/CVSROOT/${info},v file,"
- echo "But no $CVSROOT/CVSROOT/$info file. This is OK."
- echo "I'll checkout a fresh copy..."
- (cd $CVSROOT/CVSROOT; co -q $info)
- echo ""
- fi
- else
- if [ -f $CVSROOT/CVSROOT/$info ]; then
- echo "You have a $CVSROOT/CVSROOT/$info file,"
- echo "But no $CVSROOT/CVSROOT/${info},v file."
- echo "I'll create one for you, but otherwise leave it alone..."
- (cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m"initial checkin of $info" $info)
- else
- echo "The $CVSROOT/CVSROOT/$info file does not exist."
- if [ -r $CVSLIB/examples/$info ]; then
- echo "Making a simple one for you..."
- sed -e 's/^\([^#]\)/#\1/' $CVSLIB/examples/$info > $CVSROOT/CVSROOT/$info
- fi
- fi
- echo ""
- fi
+for contrib in $CONTRIBS; do
+ echo "Copying the new version of '${contrib}'"
+ echo " to $CVSROOT/CVSROOT for you..."
+ cp $CVSLIB/contrib/$contrib $CVSROOT/CVSROOT/$contrib
done
# XXX - also add a stub for the cvsignore file
@@ -226,16 +150,12 @@ done
if [ ! -f $CVSROOT/CVSROOT/history ]; then
echo "Enabling CVS history logging..."
touch $CVSROOT/CVSROOT/history
- echo ""
+ chmod g+w $CVSROOT/CVSROOT/history
+ echo "(Remove $CVSROOT/CVSROOT/history to disable.)"
fi
# finish up by running mkmodules
echo "All done! Running 'mkmodules' as my final step..."
mkmodules $CVSROOT/CVSROOT
-# and, if necessary, remind them about setting CVSROOT
-if [ $remind_cvsroot = yes ]; then
- echo "Remember to set the CVSROOT environment variable in your login script"
-fi
-
exit 0
diff --git a/gnu/usr.bin/cvs/doc/Makefile b/gnu/usr.bin/cvs/doc/Makefile
index a0cdc97..874cc46 100644
--- a/gnu/usr.bin/cvs/doc/Makefile
+++ b/gnu/usr.bin/cvs/doc/Makefile
@@ -1,3 +1,5 @@
-INFO = cvs
+# $Id$
+
+INFO = cvs cvsclient
.include <bsd.info.mk>
diff --git a/gnu/usr.bin/cvs/examples/Makefile b/gnu/usr.bin/cvs/examples/Makefile
index dbc997e..1855b78 100644
--- a/gnu/usr.bin/cvs/examples/Makefile
+++ b/gnu/usr.bin/cvs/examples/Makefile
@@ -1,17 +1,18 @@
-# $Id: Makefile,v 1.1 1995/04/08 17:50:48 nate Exp $
+# $Id: Makefile,v 1.2 1995/07/25 00:31:56 bde Exp $
-CVSFILES= commitinfo loginfo rcsinfo editinfo modules
+CVSFILES= checkoutlist commitinfo cvswrappers editinfo loginfo modules \
+ rcsinfo rcstemplate taginfo unwrap wrap
EXAMPDIR = /usr/share/examples/cvs
NOMAN = noman
+NOOBJ = noobj
all clean:
@echo -n
install:
- cd ${.CURDIR}; \
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ${CVSFILES} \
- ${DESTDIR}${EXAMPDIR}
+ ${DESTDIR}${EXAMPDIR}/examples
.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cvs/lib/Makefile b/gnu/usr.bin/cvs/lib/Makefile
index af510b6..aeab066 100644
--- a/gnu/usr.bin/cvs/lib/Makefile
+++ b/gnu/usr.bin/cvs/lib/Makefile
@@ -1,10 +1,12 @@
-# $Id: Makefile,v 1.25 1995/03/22 19:39:45 nate Exp $
+# $Id: Makefile,v 1.8 1995/03/31 07:55:28 nate Exp $
LIB = cvs
NOPROFILE= yes
-CFLAGS += -I${.CURDIR} -I${.CURDIR}/../cvs -DHAVE_CONFIG_H -DHAVE_TIMEZONE
-SRCS = argmatch.c error.c getdate.y getopt.c getopt1.c fnmatch.c myndbm.c \
- hash.c sighandle.c strippath.c stripslash.c subr.c version.c yesno.c
+CFLAGS += -I${.CURDIR} -I${.CURDIR}/../cvs -DHAVE_CONFIG_H
+SRCS = argmatch.c error.c filesubr.c getdate.y getline.c \
+ getopt.c getopt1.c hash.c md5.c myndbm.c run.c save-cwd.c \
+ sighandle.c strippath.c stripslash.c subr.c version.c \
+ xgetwd.c yesno.c
CLEANFILES+= getdate.c y.tab.h
@@ -12,3 +14,4 @@ install:
@echo -n
.include <bsd.lib.mk>
+
diff --git a/gnu/usr.bin/cvs/lib/argmatch.c b/gnu/usr.bin/cvs/lib/argmatch.c
index 327a27d..cc360ee 100644
--- a/gnu/usr.bin/cvs/lib/argmatch.c
+++ b/gnu/usr.bin/cvs/lib/argmatch.c
@@ -21,6 +21,8 @@
#include "config.h"
#endif
+#include <sys/types.h>
+
#include <stdio.h>
#ifdef STDC_HEADERS
#include <string.h>
@@ -39,7 +41,7 @@ argmatch (arg, optlist)
char **optlist;
{
int i; /* Temporary index in OPTLIST. */
- int arglen; /* Length of ARG. */
+ size_t arglen; /* Length of ARG. */
int matchind = -1; /* Index of first nonexact match. */
int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
diff --git a/gnu/usr.bin/cvs/lib/getopt.c b/gnu/usr.bin/cvs/lib/getopt.c
index 446a8e4..f1d8dfa 100644
--- a/gnu/usr.bin/cvs/lib/getopt.c
+++ b/gnu/usr.bin/cvs/lib/getopt.c
@@ -47,6 +47,10 @@
#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
@@ -494,7 +498,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
- if (nameend - nextchar == strlen (p->name))
+ if (nameend - nextchar == (int) strlen (p->name))
{
/* Exact match found. */
pfound = p;
diff --git a/gnu/usr.bin/cvs/lib/hash.c b/gnu/usr.bin/cvs/lib/hash.c
index afc554d..8ac9323 100644
--- a/gnu/usr.bin/cvs/lib/hash.c
+++ b/gnu/usr.bin/cvs/lib/hash.c
@@ -10,8 +10,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)hash.c 1.19 94/09/23 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)hash.c 1.19 94/09/23 $";
+USE(rcsid);
#endif
/* global caches */
@@ -23,7 +23,7 @@ static void freenode_mem PROTO((Node * p));
/* hash function */
static int
hashp (key)
- char *key;
+ const char *key;
{
unsigned int h = 0;
unsigned int g;
@@ -254,7 +254,7 @@ addnode (list, p)
Node *
findnode (list, key)
List *list;
- char *key;
+ const char *key;
{
Node *head, *p;
@@ -277,7 +277,7 @@ findnode (list, key)
int
walklist (list, proc, closure)
List *list;
- int (*proc) ();
+ int (*proc) PROTO ((Node *, void *));
void *closure;
{
Node *head, *p;
@@ -298,7 +298,7 @@ walklist (list, proc, closure)
void
sortlist (list, comp)
List *list;
- int (*comp) ();
+ int (*comp) PROTO ((const Node *, const Node *));
{
Node *head, *remain, *p, *q;
@@ -363,7 +363,8 @@ nodetypestring (type)
return("<trash>");
}
-int
+static int printnode PROTO ((Node *, void *));
+static int
printnode (node, closure)
Node *node;
void *closure;
diff --git a/gnu/usr.bin/cvs/lib/hash.h b/gnu/usr.bin/cvs/lib/hash.h
index 8e10e81..e30511a 100644
--- a/gnu/usr.bin/cvs/lib/hash.h
+++ b/gnu/usr.bin/cvs/lib/hash.h
@@ -44,23 +44,12 @@ struct list
};
typedef struct list List;
-struct entnode
-{
- char *version;
- char *timestamp;
- char *options;
- char *tag;
- char *date;
- char *conflict;
-};
-typedef struct entnode Entnode;
-
List *getlist PROTO((void));
-Node *findnode PROTO((List * list, char *key));
+Node *findnode PROTO((List * list, const char *key));
Node *getnode PROTO((void));
int addnode PROTO((List * list, Node * p));
-int walklist PROTO((List * list, int PROTO((*proc)) PROTO((Node *n, void *closure)), void *closure));
+int walklist PROTO((List * list, int (*)(Node *n, void *closure), void *closure));
void dellist PROTO((List ** listp));
void delnode PROTO((Node * p));
void freenode PROTO((Node * p));
-void sortlist PROTO((List * list, int PROTO((*comp))()));
+void sortlist PROTO((List * list, int (*)(const Node *, const Node *)));
diff --git a/gnu/usr.bin/cvs/lib/myndbm.c b/gnu/usr.bin/cvs/lib/myndbm.c
index 33ef49c..fef3265 100644
--- a/gnu/usr.bin/cvs/lib/myndbm.c
+++ b/gnu/usr.bin/cvs/lib/myndbm.c
@@ -18,8 +18,8 @@
#ifdef MY_NDBM
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)myndbm.c 1.7 94/09/23 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)myndbm.c 1.7 94/09/23 $";
+USE(rcsid);
#endif
static void mydbm_load_file ();
diff --git a/gnu/usr.bin/cvs/lib/subr.c b/gnu/usr.bin/cvs/lib/subr.c
index d3d40b1..228581c 100644
--- a/gnu/usr.bin/cvs/lib/subr.c
+++ b/gnu/usr.bin/cvs/lib/subr.c
@@ -11,248 +11,11 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $";
+USE(rcsid);
#endif
-#ifdef _MINIX
-#undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
-#endif
-
-#ifdef HAVE_VPRINTF
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#include <stdarg.h>
-#define VA_START(args, lastarg) va_start(args, lastarg)
-#else
-#include <varargs.h>
-#define VA_START(args, lastarg) va_start(args)
-#endif
-#else
-#define va_alist a1, a2, a3, a4, a5, a6, a7, a8
-#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-#endif
-
-/*
- * I don't know of a convenient way to test this at configure time, or else
- * I'd certainly do it there.
- */
-#if defined(NeXT)
-#define LOSING_TMPNAM_FUNCTION
-#ifndef _POSIX_SOURCE
-/*
- * NeXT doesn't define these without _POSIX_SOURCE,
- * but that changes a lot of things.
- */
-#define WEXITSTATUS(x) ((x).w_retcode)
-#define WTERMSIG(x) ((x).w_termsig)
-#endif
-#endif
-
-static void run_add_arg PROTO((char *s));
-static void run_init_prog PROTO((void));
-
extern char *getlogin ();
-extern char *strtok ();
-
-/*
- * Copies "from" to "to". mallocs a buffer large enough to hold the entire
- * file and does one read/one write to do the copy. This is reasonable,
- * since source files are typically not too large.
- */
-void
-copy_file (from, to)
- char *from;
- char *to;
-{
- struct stat sb;
- struct utimbuf t;
- int fdin, fdout;
- char *buf;
-
- if (trace)
- (void) fprintf (stderr, "-> copy(%s,%s)\n", from, to);
- if (noexec)
- return;
-
- if ((fdin = open (from, O_RDONLY)) < 0)
- error (1, errno, "cannot open %s for copying", from);
- if (fstat (fdin, &sb) < 0)
- error (1, errno, "cannot fstat %s", from);
- if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
- error (1, errno, "cannot create %s for copying", to);
- if (sb.st_size > 0)
- {
- buf = xmalloc ((int) sb.st_size);
- if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size)
- error (1, errno, "cannot read file %s for copying", from);
- if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size
-#ifdef HAVE_FSYNC
- || fsync (fdout) == -1
-#endif
- )
- {
- error (1, errno, "cannot write file %s for copying", to);
- }
- free (buf);
- }
- (void) close (fdin);
- if (close (fdout) < 0)
- error (1, errno, "cannot close %s", to);
-
- /* now, set the times for the copied file to match those of the original */
- memset ((char *) &t, 0, sizeof (t));
- t.actime = sb.st_atime;
- t.modtime = sb.st_mtime;
- (void) utime (to, &t);
-}
-
-/* FIXME-krp: these functions would benefit from caching the char * &
- stat buf. */
-
-/*
- * Returns non-zero if the argument file is a directory, or is a symbolic
- * link which points to a directory.
- */
-int
-isdir (file)
- char *file;
-{
- struct stat sb;
-
- if (stat (file, &sb) < 0)
- return (0);
- return (S_ISDIR (sb.st_mode));
-}
-
-/*
- * Returns non-zero if the argument file is a symbolic link.
- */
-int
-islink (file)
- char *file;
-{
-#ifdef S_ISLNK
- struct stat sb;
-
- if (lstat (file, &sb) < 0)
- return (0);
- return (S_ISLNK (sb.st_mode));
-#else
- return (0);
-#endif
-}
-
-/*
- * Returns non-zero if the argument file exists.
- */
-int
-isfile (file)
- char *file;
-{
- struct stat sb;
-
- if (stat (file, &sb) < 0)
- return (0);
- return (1);
-}
-
-/*
- * Returns non-zero if the argument file is readable.
- * XXX - must be careful if "cvs" is ever made setuid!
- */
-int
-isreadable (file)
- char *file;
-{
- return (access (file, R_OK) != -1);
-}
-
-/*
- * Returns non-zero if the argument file is writable
- * XXX - muct be careful if "cvs" is ever made setuid!
- */
-int
-iswritable (file)
- char *file;
-{
- return (access (file, W_OK) != -1);
-}
-
-/*
- * Open a file and die if it fails
- */
-FILE *
-open_file (name, mode)
- char *name;
- char *mode;
-{
- FILE *fp;
-
- if ((fp = fopen (name, mode)) == NULL)
- error (1, errno, "cannot open %s", name);
- return (fp);
-}
-
-/*
- * Open a file if allowed and return.
- */
-FILE *
-Fopen (name, mode)
- char *name;
- char *mode;
-{
- if (trace)
- (void) fprintf (stderr, "-> fopen(%s,%s)\n", name, mode);
- if (noexec)
- return (NULL);
-
- return (fopen (name, mode));
-}
-
-/*
- * Make a directory and die if it fails
- */
-void
-make_directory (name)
- char *name;
-{
- struct stat buf;
-
- if (stat (name, &buf) == 0 && (!S_ISDIR (buf.st_mode)))
- error (0, 0, "%s already exists but is not a directory", name);
- if (!noexec && mkdir (name, 0777) < 0)
- error (1, errno, "cannot make directory %s", name);
-}
-
-/*
- * Make a path to the argument directory, printing a message if something
- * goes wrong.
- */
-void
-make_directories (name)
- char *name;
-{
- char *cp;
-
- if (noexec)
- return;
-
- if (mkdir (name, 0777) == 0 || errno == EEXIST)
- return;
- if (errno != ENOENT)
- {
- error (0, errno, "cannot make path to %s", name);
- return;
- }
- if ((cp = strrchr (name, '/')) == NULL)
- return;
- *cp = '\0';
- make_directories (name);
- *cp++ = '/';
- if (*cp == '\0')
- return;
- (void) mkdir (name, 0777);
-}
/*
* malloc some data and die if it fails
@@ -263,7 +26,14 @@ xmalloc (bytes)
{
char *cp;
- if ((cp = malloc (bytes)) == NULL)
+ /* Parts of CVS try to xmalloc zero bytes and then free it. Some
+ systems have a malloc which returns NULL for zero byte
+ allocations but a free which can't handle NULL, so compensate. */
+ if (bytes == 0)
+ bytes = 1;
+
+ cp = malloc (bytes);
+ if (cp == NULL)
error (1, 0, "can not allocate %lu bytes", (unsigned long) bytes);
return (cp);
}
@@ -295,7 +65,7 @@ xrealloc (ptr, bytes)
*/
char *
xstrdup (str)
- char *str;
+ const char *str;
{
char *s;
@@ -306,143 +76,16 @@ xstrdup (str)
return (s);
}
-/*
- * Change the mode of a file, either adding write permissions, or removing
- * all write permissions. Adding write permissions honors the current umask
- * setting.
- */
+/* Remove trailing newlines from STRING, destructively. */
void
-xchmod (fname, writable)
- char *fname;
- int writable;
+strip_trailing_newlines (str)
+ char *str;
{
- struct stat sb;
- mode_t mode, oumask;
+ int len;
+ len = strlen (str) - 1;
- if (stat (fname, &sb) < 0)
- {
- if (!noexec)
- error (0, errno, "cannot stat %s", fname);
- return;
- }
- if (writable)
- {
- oumask = umask (0);
- (void) umask (oumask);
- mode = sb.st_mode | ((S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask);
- }
- else
- {
- mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH);
- }
-
- if (trace)
- (void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, mode);
- if (noexec)
- return;
-
- if (chmod (fname, mode) < 0)
- error (0, errno, "cannot change mode of file %s", fname);
-}
-
-/*
- * Rename a file and die if it fails
- */
-void
-rename_file (from, to)
- char *from;
- char *to;
-{
- if (trace)
- (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
- if (noexec)
- return;
-
- if (rename (from, to) < 0)
- error (1, errno, "cannot rename file %s to %s", from, to);
-}
-
-/*
- * link a file, if possible.
- */
-int
-link_file (from, to)
- char *from, *to;
-{
- if (trace)
- (void) fprintf (stderr, "-> link(%s,%s)\n", from, to);
- if (noexec)
- return (0);
-
- return (link (from, to));
-}
-
-/*
- * unlink a file, if possible.
- */
-int
-unlink_file (f)
- char *f;
-{
- if (trace)
- (void) fprintf (stderr, "-> unlink(%s)\n", f);
- if (noexec)
- return (0);
-
- return (unlink (f));
-}
-
-/*
- * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
- *
- * mallocs a buffer large enough to hold the entire file and does two reads to
- * load the buffer and calls memcmp to do the cmp. This is reasonable, since
- * source files are typically not too large.
- */
-
-/* richfix: this *could* exploit mmap. */
-
-int
-xcmp (file1, file2)
- char *file1;
- char *file2;
-{
- register char *buf1, *buf2;
- struct stat sb;
- off_t size;
- int ret, fd1, fd2;
-
- if ((fd1 = open (file1, O_RDONLY)) < 0)
- error (1, errno, "cannot open file %s for comparing", file1);
- if ((fd2 = open (file2, O_RDONLY)) < 0)
- error (1, errno, "cannot open file %s for comparing", file2);
- if (fstat (fd1, &sb) < 0)
- error (1, errno, "cannot fstat %s", file1);
- size = sb.st_size;
- if (fstat (fd2, &sb) < 0)
- error (1, errno, "cannot fstat %s", file2);
- if (size == sb.st_size)
- {
- if (size == 0)
- ret = 0;
- else
- {
- buf1 = xmalloc ((int) size);
- buf2 = xmalloc ((int) size);
- if (read (fd1, buf1, (int) size) != (int) size)
- error (1, errno, "cannot read file %s for comparing", file1);
- if (read (fd2, buf2, (int) size) != (int) size)
- error (1, errno, "cannot read file %s for comparing", file2);
- ret = memcmp(buf1, buf2, (int) size);
- free (buf1);
- free (buf2);
- }
- }
- else
- ret = 1;
- (void) close (fd1);
- (void) close (fd2);
- return (ret);
+ while (str[len] == '\n')
+ str[len--] = '\0';
}
/*
@@ -451,7 +94,7 @@ xcmp (file1, file2)
void
free_names (pargc, argv)
int *pargc;
- char *argv[];
+ char **argv;
{
register int i;
@@ -470,7 +113,7 @@ free_names (pargc, argv)
void
line2argv (pargc, argv, line)
int *pargc;
- char *argv[];
+ char **argv;
char *line;
{
char *cp;
@@ -488,14 +131,13 @@ line2argv (pargc, argv, line)
*/
int
numdots (s)
- char *s;
+ const char *s;
{
- char *cp;
int dots = 0;
- for (cp = s; *cp; cp++)
+ for (; *s; s++)
{
- if (*cp == '.')
+ if (*s == '.')
dots++;
}
return (dots);
@@ -518,394 +160,18 @@ getcaller ()
if (uid == (uid_t) 0)
{
/* super-user; try getlogin() to distinguish */
- if (((name = getenv("LOGNAME")) || (name = getenv("USER")) ||
- (name = getlogin ())) && *name)
+ if (((name = getlogin ()) || (name = getenv("LOGNAME")) ||
+ (name = getenv("USER"))) && *name)
return (name);
}
if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
{
- (void) sprintf (uidname, "uid%d", (unsigned long) uid);
+ (void) sprintf (uidname, "uid%lu", (unsigned long) uid);
return (uidname);
}
return (pw->pw_name);
}
-/*
- * To exec a program under CVS, first call run_setup() to setup any initial
- * arguments. The options to run_setup are essentially like printf(). The
- * arguments will be parsed into whitespace separated words and added to the
- * global run_argv list.
- *
- * Then, optionally call run_arg() for each additional argument that you'd like
- * to pass to the executed program.
- *
- * Finally, call run_exec() to execute the program with the specified arguments.
- * The execvp() syscall will be used, so that the PATH is searched correctly.
- * File redirections can be performed in the call to run_exec().
- */
-static char *run_prog;
-static char **run_argv;
-static int run_argc;
-static int run_argc_allocated;
-
-/* VARARGS */
-#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
-void
-run_setup (char *fmt,...)
-#else
-void
-run_setup (fmt, va_alist)
- char *fmt;
- va_dcl
-
-#endif
-{
-#ifdef HAVE_VPRINTF
- va_list args;
-
-#endif
- char *cp;
- int i;
-
- run_init_prog ();
-
- /* clean out any malloc'ed values from run_argv */
- for (i = 0; i < run_argc; i++)
- {
- if (run_argv[i])
- {
- free (run_argv[i]);
- run_argv[i] = (char *) 0;
- }
- }
- run_argc = 0;
-
- /* process the varargs into run_prog */
-#ifdef HAVE_VPRINTF
- VA_START (args, fmt);
- (void) vsprintf (run_prog, fmt, args);
- va_end (args);
-#else
- (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif
-
- /* put each word into run_argv, allocating it as we go */
- for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
- run_add_arg (cp);
-}
-
-void
-run_arg (s)
- char *s;
-{
- run_add_arg (s);
-}
-
-/* VARARGS */
-#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
-void
-run_args (char *fmt,...)
-#else
-void
-run_args (fmt, va_alist)
- char *fmt;
- va_dcl
-
-#endif
-{
-#ifdef HAVE_VPRINTF
- va_list args;
-
-#endif
-
- run_init_prog ();
-
- /* process the varargs into run_prog */
-#ifdef HAVE_VPRINTF
- VA_START (args, fmt);
- (void) vsprintf (run_prog, fmt, args);
- va_end (args);
-#else
- (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif
-
- /* and add the (single) argument to the run_argv list */
- run_add_arg (run_prog);
-}
-
-static void
-run_add_arg (s)
- char *s;
-{
- /* allocate more argv entries if we've run out */
- if (run_argc >= run_argc_allocated)
- {
- run_argc_allocated += 50;
- run_argv = (char **) xrealloc ((char *) run_argv,
- run_argc_allocated * sizeof (char **));
- }
-
- if (s)
- run_argv[run_argc++] = xstrdup (s);
- else
- run_argv[run_argc] = (char *) 0;/* not post-incremented on purpose! */
-}
-
-static void
-run_init_prog ()
-{
- /* make sure that run_prog is allocated once */
- if (run_prog == (char *) 0)
- run_prog = xmalloc (10 * 1024); /* 10K of args for _setup and _arg */
-}
-
-int
-run_exec (stin, stout, sterr, flags)
- char *stin;
- char *stout;
- char *sterr;
- int flags;
-{
- int shin, shout, sherr;
- int mode_out, mode_err;
-#if defined(NeXT) && !defined(_POSIX_SOURCE)
- union wait status;
-#else
- int status;
-#endif
- int rc = -1;
- int rerrno = 0;
- int pid, w;
-
-#ifdef POSIX
- sigset_t sigset_mask, sigset_omask;
- struct sigaction act, iact, qact;
-
-#else
-#ifdef BSD_SIGNALS
- int mask;
- struct sigvec vec, ivec, qvec;
-
-#else
- RETSIGTYPE (*istat) (), (*qstat) ();
-#endif
-#endif
-
- if (trace)
- {
- (void) fprintf (stderr, "-> system(");
- run_print (stderr);
- (void) fprintf (stderr, ")\n");
- }
- if (noexec && (flags & RUN_REALLY) == 0)
- return (0);
-
- /* make sure that we are null terminated, since we didn't calloc */
- run_add_arg ((char *) 0);
-
- /* setup default file descriptor numbers */
- shin = 0;
- shout = 1;
- sherr = 2;
-
- /* set the file modes for stdout and stderr */
- mode_out = mode_err = O_WRONLY | O_CREAT;
- mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
- mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
-
- if (stin && (shin = open (stin, O_RDONLY)) == -1)
- {
- rerrno = errno;
- error (0, errno, "cannot open %s for reading (prog %s)",
- stin, run_argv[0]);
- goto out0;
- }
- if (stout && (shout = open (stout, mode_out, 0666)) == -1)
- {
- rerrno = errno;
- error (0, errno, "cannot open %s for writing (prog %s)",
- stout, run_argv[0]);
- goto out1;
- }
- if (sterr && (flags & RUN_COMBINED) == 0)
- {
- if ((sherr = open (sterr, mode_err, 0666)) == -1)
- {
- rerrno = errno;
- error (0, errno, "cannot open %s for writing (prog %s)",
- sterr, run_argv[0]);
- goto out2;
- }
- }
-
- /* Make sure we don't flush this twice, once in the subprocess. */
- fflush (stdout);
- fflush (stderr);
-
- /* The output files, if any, are now created. Do the fork and dups */
-#ifdef HAVE_VFORK
- pid = vfork ();
-#else
- pid = fork ();
-#endif
- if (pid == 0)
- {
- if (shin != 0)
- {
- (void) dup2 (shin, 0);
- (void) close (shin);
- }
- if (shout != 1)
- {
- (void) dup2 (shout, 1);
- (void) close (shout);
- }
- if (flags & RUN_COMBINED)
- (void) dup2 (1, 2);
- else if (sherr != 2)
- {
- (void) dup2 (sherr, 2);
- (void) close (sherr);
- }
-
- /* dup'ing is done. try to run it now */
- (void) execvp (run_argv[0], run_argv);
- error (0, errno, "cannot exec %s", run_argv[0]);
- _exit (127);
- }
- else if (pid == -1)
- {
- rerrno = errno;
- goto out;
- }
-
- /* the parent. Ignore some signals for now */
-#ifdef POSIX
- if (flags & RUN_SIGIGNORE)
- {
- act.sa_handler = SIG_IGN;
- (void) sigemptyset (&act.sa_mask);
- act.sa_flags = 0;
- (void) sigaction (SIGINT, &act, &iact);
- (void) sigaction (SIGQUIT, &act, &qact);
- }
- else
- {
- (void) sigemptyset (&sigset_mask);
- (void) sigaddset (&sigset_mask, SIGINT);
- (void) sigaddset (&sigset_mask, SIGQUIT);
- (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
- }
-#else
-#ifdef BSD_SIGNALS
- if (flags & RUN_SIGIGNORE)
- {
- memset ((char *) &vec, 0, sizeof (vec));
- vec.sv_handler = SIG_IGN;
- (void) sigvec (SIGINT, &vec, &ivec);
- (void) sigvec (SIGQUIT, &vec, &qvec);
- }
- else
- mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
-#else
- istat = signal (SIGINT, SIG_IGN);
- qstat = signal (SIGQUIT, SIG_IGN);
-#endif
-#endif
-
- /* wait for our process to die and munge return status */
-#ifdef POSIX
- while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
- ;
-#else
- while ((w = wait (&status)) != pid)
- {
- if (w == -1 && errno != EINTR)
- break;
- }
-#endif
- if (w == -1)
- {
- rc = -1;
- rerrno = errno;
- }
- else if (WIFEXITED (status))
- rc = WEXITSTATUS (status);
- else if (WIFSIGNALED (status))
- {
- if (WTERMSIG (status) == SIGPIPE)
- error (1, 0, "broken pipe");
- rc = 2;
- }
- else
- rc = 1;
-
- /* restore the signals */
-#ifdef POSIX
- if (flags & RUN_SIGIGNORE)
- {
- (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
- (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
- }
- else
- (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
-#else
-#ifdef BSD_SIGNALS
- if (flags & RUN_SIGIGNORE)
- {
- (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
- (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
- }
- else
- (void) sigsetmask (mask);
-#else
- (void) signal (SIGINT, istat);
- (void) signal (SIGQUIT, qstat);
-#endif
-#endif
-
- /* cleanup the open file descriptors */
- out:
- if (sterr)
- (void) close (sherr);
- out2:
- if (stout)
- (void) close (shout);
- out1:
- if (stin)
- (void) close (shin);
-
- out0:
- if (rerrno)
- errno = rerrno;
- return (rc);
-}
-
-void
-run_print (fp)
- FILE *fp;
-{
- int i;
-
- for (i = 0; i < run_argc; i++)
- {
- (void) fprintf (fp, "%s", run_argv[i]);
- if (i != run_argc - 1)
- (void) fprintf (fp, " ");
- }
-}
-
-FILE *
-Popen (cmd, mode)
- char *cmd, *mode;
-{
- if (trace)
- (void) fprintf (stderr, "-> Popen(%s,%s)\n", cmd, mode);
- if (noexec)
- return (NULL);
- return (popen (cmd, mode));
-}
-
#ifdef lint
#ifndef __GNUC__
/* ARGSUSED */
@@ -1031,19 +297,26 @@ gca (rev1, rev2)
return (xstrdup (gca));
}
-#ifdef LOSING_TMPNAM_FUNCTION
-char *tmpnam(char *s)
+/*
+ * Sanity checks and any required fix-up on message passed to RCS via '-m'.
+ * RCS 5.7 requires that a non-total-whitespace, non-null message be provided
+ * with '-m'.
+ */
+char *
+make_message_rcslegal (message)
+ char *message;
{
- static char value[L_tmpnam+1];
+ if ((message == NULL) || (*message == '\0') || isspace (*message))
+ {
+ char *t;
+
+ if (message)
+ for (t = message; *t; t++)
+ if (!isspace (*t))
+ return message;
- if (s){
- strcpy(s,"/tmp/cvsXXXXXX");
- mktemp(s);
- return s;
- }else{
- strcpy(value,"/tmp/cvsXXXXXX");
- mktemp(s);
- return value;
+ return "*** empty log message ***\n";
}
+
+ return message;
}
-#endif
diff --git a/gnu/usr.bin/cvs/lib/system.h b/gnu/usr.bin/cvs/lib/system.h
index 1f35065..20539de 100644
--- a/gnu/usr.bin/cvs/lib/system.h
+++ b/gnu/usr.bin/cvs/lib/system.h
@@ -17,45 +17,162 @@
/* $CVSid: @(#)system.h 1.18 94/09/25 $ */
+#ifdef __GNUC__
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#else
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+/* AIX alloca decl has to be the first thing in the file, bletch! */
+ #pragma alloca
+#else /* not _AIX */
+#ifdef ALLOCA_IN_STDLIB
+ /* then we need do nothing */
+#else
+char *alloca ();
+#endif /* not ALLOCA_IN_STDLIB */
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */
+#endif /* not __GNUS__ */
+
#include <sys/types.h>
#include <sys/stat.h>
-#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
-#ifndef mode_t
-#define mode_t unsigned short
-#endif
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISREG
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISSOCK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
#endif
+
+/* Not all systems have S_IFMT, but we probably want to use it if we
+ do. See ChangeLog for a more detailed discussion. */
+
#if !defined(S_ISBLK) && defined(S_IFBLK)
-#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# if defined(S_IFMT)
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# else
+# define S_ISBLK(m) ((m) & S_IFBLK)
+# endif
#endif
+
#if !defined(S_ISCHR) && defined(S_IFCHR)
-#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# if defined(S_IFMT)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# else
+# define S_ISCHR(m) ((m) & S_IFCHR)
+# endif
#endif
+
#if !defined(S_ISDIR) && defined(S_IFDIR)
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# if defined(S_IFMT)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# else
+# define S_ISDIR(m) ((m) & S_IFDIR)
+# endif
#endif
+
#if !defined(S_ISREG) && defined(S_IFREG)
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+# if defined(S_IFMT)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+# else
+# define S_ISREG(m) ((m) & S_IFREG)
+# endif
#endif
+
#if !defined(S_ISFIFO) && defined(S_IFIFO)
-#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# if defined(S_IFMT)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) ((m) & S_IFIFO)
+# endif
#endif
+
#if !defined(S_ISLNK) && defined(S_IFLNK)
-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# if defined(S_IFMT)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# else
+# define S_ISLNK(m) ((m) & S_IFLNK)
+# endif
#endif
+
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
-#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# if defined(S_IFMT)
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+# define S_ISSOCK(m) ((m) & S_IFSOCK)
+# endif
#endif
+
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
-#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
-#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+# if defined(S_IFMT)
+# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+# else
+# define S_ISMPB(m) ((m) & S_IFMPB)
+# define S_ISMPC(m) ((m) & S_IFMPC)
+# endif
#endif
+
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
-#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+# if defined(S_IFMT)
+# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+# else
+# define S_ISNWK(m) ((m) & S_IFNWK)
+# endif
#endif
+
#if !defined(HAVE_MKFIFO)
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
#endif
+#ifdef NEED_DECOY_PERMISSIONS /* OS/2, really */
+
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#define S_IXUSR S_IEXEC
+#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+#define S_IRGRP S_IREAD
+#define S_IWGRP S_IWRITE
+#define S_IXGRP S_IEXEC
+#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#define S_IROTH S_IREAD
+#define S_IWOTH S_IWRITE
+#define S_IXOTH S_IEXEC
+#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+
+#else /* ! NEED_DECOY_PERMISSIONS */
+
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define S_IXUSR 0100
+/* Read, write, and execute by owner. */
+#define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)
+
+#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */
+#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */
+#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */
+/* Read, write, and execute by group. */
+#define S_IRWXG (S_IRWXU >> 3)
+
+#define S_IROTH (S_IRGRP >> 3) /* Read by others. */
+#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */
+#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */
+/* Read, write, and execute by others. */
+#define S_IRWXO (S_IRWXG >> 3)
+#endif /* !def S_IRUSR */
+#endif /* NEED_DECOY_PERMISSIONS */
+
#if defined(POSIX) || defined(HAVE_UNISTD_H)
#include <unistd.h>
#include <limits.h>
@@ -63,25 +180,38 @@
off_t lseek ();
#endif
-#ifdef TM_IN_SYS_TIME
-#include <sys/time.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
#else
-#include <time.h>
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
#endif
-#ifndef HAVE_SYS_TIMEB_H
+#ifdef timezone
+#undef timezone /* needed for sgi */
+#endif
+
+#ifdef HAVE_SYS_TIMEB_H
+#include <sys/timeb.h>
+#else
struct timeb {
time_t time; /* Seconds since the epoch */
unsigned short millitm; /* Field not used */
-#ifdef timezone
- short tzone;
-#else
short timezone;
-#endif
short dstflag; /* Field not used */
};
-#else
-#include <sys/timeb.h>
#endif
#if !defined(HAVE_FTIME) && !defined(HAVE_TIMEZONE)
@@ -106,10 +236,17 @@ extern long timezone;
** PATH_MAX in terms of MAXPATHLEN.
** 3. If neither is defined, include limits.h and check for
** PATH_MAX again.
+** 3.1 If we now have PATHSIZE, define PATH_MAX in terms of that.
+** and ignore the rest. Since _POSIX_PATH_MAX (checked for
+** next) is the *most* restrictive (smallest) value, if we
+** trust _POSIX_PATH_MAX, several of our buffers are too small.
** 4. If PATH_MAX is still not defined but _POSIX_PATH_MAX is,
** then define PATH_MAX in terms of _POSIX_PATH_MAX.
** 5. And if even _POSIX_PATH_MAX doesn't exist just put in
** a reasonable value.
+** *. All in all, this is an excellent argument for using pathconf()
+** when at all possible. Or better yet, dynamically allocate
+** our buffers and use getcwd() not getwd().
**
** This works on:
** Sun Sparc 10 SunOS 4.1.3 & Solaris 1.2
@@ -118,12 +255,16 @@ extern long timezone;
** IBM RS6000 AIX 3.2
** Dec Alpha OSF 1 ????
** Intel 386 BSDI BSD/386
+** Intel 386 SCO OpenServer Release 5
** Apollo Domain 10.4
** NEC SVR4
*/
-/* On MOST systems this will get you MAXPATHLEN */
+/* On MOST systems this will get you MAXPATHLEN.
+ Windows NT doesn't have this file, tho. */
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
#ifndef PATH_MAX
# ifdef MAXPATHLEN
@@ -131,20 +272,28 @@ extern long timezone;
# else
# include <limits.h>
# ifndef PATH_MAX
-# ifdef _POSIX_PATH_MAX
-# define PATH_MAX _POSIX_PATH_MAX
-# else
-# define PATH_MAX 1024
-# endif /* _POSIX_PATH_MAX */
-# endif /* PATH_MAX */
+# ifdef PATHSIZE
+# define PATH_MAX PATHSIZE
+# else /* no PATHSIZE */
+# ifdef _POSIX_PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+# else
+# define PATH_MAX 1024
+# endif /* no _POSIX_PATH_MAX */
+# endif /* no PATHSIZE */
+# endif /* no PATH_MAX */
# endif /* MAXPATHLEN */
#endif /* PATH_MAX */
-
-
-#ifdef HAVE_UTIME_H
+/* The NeXT (without _POSIX_SOURCE, which we don't want) has a utime.h
+ which doesn't define anything. It would be cleaner to have configure
+ check for struct utimbuf, but for now I'm checking NeXT here (so I don't
+ have to debug the configure check across all the machines). */
+#if defined (HAVE_UTIME_H) && !defined (NeXT)
#include <utime.h>
+#elif defined (HAVE_SYS_UTIME_H)
+# include <sys/utime.h>
#else
#ifndef ALTOS
struct utimbuf
@@ -179,12 +328,31 @@ int utime ();
#define bzero(s, n) memset ((s), 0, (n))
#endif /* bzero */
-#else /* not STDC_HJEADERS and not HAVE_STRING_H */
+#else /* not STDC_HEADERS and not HAVE_STRING_H */
#include <strings.h>
/* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
#include <errno.h>
+
+/* Not all systems set the same error code on a non-existent-file
+ error. This tries to ask the question somewhat portably.
+ On systems that don't have ENOTEXIST, this should behave just like
+ x == ENOENT. "x" is probably errno, of course. */
+
+#ifdef ENOTEXIST
+# ifdef EOS2ERR
+# define existence_error(x) \
+ (((x) == ENOTEXIST) || ((x) == ENOENT) || ((x) == EOS2ERR))
+# else
+# define existence_error(x) \
+ (((x) == ENOTEXIST) || ((x) == ENOENT))
+# endif
+#else
+# define existence_error(x) ((x) == ENOENT)
+#endif
+
+
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
@@ -201,6 +369,29 @@ char *getcwd ();
char *getwd ();
#endif
+/* check for POSIX signals */
+#if defined(HAVE_SIGACTION) && defined(HAVE_SIGPROCMASK)
+# define POSIX_SIGNALS
+#endif
+
+/* MINIX 1.6 doesn't properly support sigaction */
+#if defined(_MINIX)
+# undef POSIX_SIGNALS
+#endif
+
+/* If !POSIX, try for BSD.. Reason: 4.4BSD implements these as wrappers */
+#if !defined(POSIX_SIGNALS)
+# if defined(HAVE_SIGVEC) && defined(HAVE_SIGSETMASK) && defined(HAVE_SIGBLOCK)
+# define BSD_SIGNALS
+# endif
+#endif
+
+/* Under OS/2, this must be included _after_ stdio.h; that's why we do
+ it here. */
+#ifdef USE_OWN_TCPIP_H
+#include "tcpip.h"
+#endif
+
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#else
@@ -220,23 +411,22 @@ char *getwd ();
#define R_OK 4
#endif
-/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
-#if defined(DIRENT) || defined(_POSIX_VERSION)
-#include <dirent.h>
-#define NLENGTH(dirent) (strlen((dirent)->d_name))
-#else /* not (DIRENT or _POSIX_VERSION) */
-#define dirent direct
-#define NLENGTH(dirent) ((dirent)->d_namlen)
-#ifdef HAVE_SYS_NDIR_H
-#include <sys/ndir.h>
-#endif
-#ifdef HAVE_SYS_DIR_H
-#include <sys/dir.h>
-#endif
-#ifdef HAVE_NDIR_H
-#include <ndir.h>
-#endif
-#endif /* not (DIRENT or _POSIX_VERSION) */
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
/* Convert B 512-byte blocks to kilobytes if K is nonzero,
otherwise return it unchanged. */
@@ -260,3 +450,47 @@ char *getwd ();
#define S_IWOTH 0000002 /* write permission, other */
#endif
+/* Under MS-DOS and its derivatives (like Windows NT), mkdir takes only one
+ argument; permission is handled very differently on those systems than in
+ in Unix. So we leave such systems a hook on which they can hang their
+ own definitions. */
+#ifndef CVS_MKDIR
+#define CVS_MKDIR mkdir
+#endif
+
+/* Some file systems are case-insensitive. If FOLD_FN_CHAR is
+ #defined, it maps the character C onto its "canonical" form. In a
+ case-insensitive system, it would map all alphanumeric characters
+ to lower case. Under Windows NT, / and \ are both path component
+ separators, so FOLD_FN_CHAR would map them both to /. */
+#ifndef FOLD_FN_CHAR
+#define FOLD_FN_CHAR(c) (c)
+#define fnfold(filename) (filename)
+#define fncmp strcmp
+#endif
+
+/* Different file systems have different path component separators.
+ For the VMS port we might need to abstract further back than this. */
+#ifndef ISDIRSEP
+#define ISDIRSEP(c) ((c) == '/')
+#endif
+
+
+/* On some systems, lines in text files should be terminated with CRLF,
+ not just LF, and the read and write routines do this translation
+ for you. LINES_CRLF_TERMINATED is #defined on such systems.
+ - OPEN_BINARY is the flag to pass to the open function for
+ untranslated I/O.
+ - FOPEN_BINARY_READ is the string to pass to fopen to get
+ untranslated reading.
+ - FOPEN_BINARY_WRITE is the string to pass to fopen to get
+ untranslated writing. */
+#if LINES_CRLF_TERMINATED
+#define OPEN_BINARY (O_BINARY)
+#define FOPEN_BINARY_READ ("rb")
+#define FOPEN_BINARY_WRITE ("wb")
+#else
+#define OPEN_BINARY (0)
+#define FOPEN_BINARY_READ ("r")
+#define FOPEN_BINARY_WRITE ("w")
+#endif
diff --git a/gnu/usr.bin/cvs/lib/version.c b/gnu/usr.bin/cvs/lib/version.c
index 071b112..2eb66cd 100644
--- a/gnu/usr.bin/cvs/lib/version.c
+++ b/gnu/usr.bin/cvs/lib/version.c
@@ -13,8 +13,22 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)version.c 1.15 94/10/03 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)version.c 1.15 94/10/03 $";
+USE(rcsid);
#endif
-char *version_string = "\nConcurrent Versions System (CVS) 1.4 Alpha-2\n";
+char *version_string = "\nConcurrent Versions System (CVS) 1.6.3";
+
+#ifdef CLIENT_SUPPORT
+#ifdef SERVER_SUPPORT
+char *config_string = " (client/server)\n";
+#else
+char *config_string = " (client)\n";
+#endif
+#else
+#ifdef SERVER_SUPPORT
+char *config_string = " (server)\n";
+#else
+char *config_string = "\n";
+#endif
+#endif
diff --git a/gnu/usr.bin/cvs/mkmodules/Makefile b/gnu/usr.bin/cvs/mkmodules/Makefile
index f37930b..78c2bb9 100644
--- a/gnu/usr.bin/cvs/mkmodules/Makefile
+++ b/gnu/usr.bin/cvs/mkmodules/Makefile
@@ -1,8 +1,8 @@
-# $Id: Makefile,v 1.25 1995/03/22 19:39:45 nate Exp $
+# $Id: Makefile,v 1.5 1995/03/31 07:55:30 nate Exp $
PROG = mkmodules
SRCS = mkmodules.c
-CFLAGS+= -I${.CURDIR}/../cvs -I${.CURDIR}/../lib -DHAVE_CONFIG_H -DHAVE_TIMEZONE
+CFLAGS+= -I${.CURDIR}/../cvs -I${.CURDIR}/../lib -DHAVE_CONFIG_H
DPADD+= ${LIBCVS}
LDADD+= -lcvs
diff --git a/gnu/usr.bin/cvs/mkmodules/mkmodules.c b/gnu/usr.bin/cvs/mkmodules/mkmodules.c
index d5611de..9b0e7bd 100644
--- a/gnu/usr.bin/cvs/mkmodules/mkmodules.c
+++ b/gnu/usr.bin/cvs/mkmodules/mkmodules.c
@@ -14,8 +14,8 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "$CVSid: @(#)mkmodules.c 1.45 94/09/30 $";
-USE(rcsid)
+static const char rcsid[] = "$CVSid: @(#)mkmodules.c 1.45 94/09/30 $";
+USE(rcsid);
#endif
#ifndef DBLKSIZ
@@ -25,6 +25,7 @@ USE(rcsid)
char *program_name, *command_name;
char *Rcsbin = RCSBIN_DFLT;
+char *CVSroot = CVSROOT_DFLT;
int noexec = 0; /* Here only to satisfy use in subr.c */
int trace = 0; /* Here only to satisfy use in subr.c */
@@ -42,9 +43,8 @@ static void write_dbmfile PROTO((char *temp));
int
main (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
- extern char *getenv ();
char temp[PATH_MAX];
char *cp, *last, *fname;
#ifdef MY_NDBM
@@ -64,19 +64,20 @@ main (argc, argv)
"a %s file can be used to validate log messages"},
{CVSROOTADM_COMMITINFO,
"a %s file can be used to configure 'cvs commit' checking"},
+ {CVSROOTADM_TAGINFO,
+ "a %s file can be used to configure 'cvs tag' checking"},
{CVSROOTADM_IGNORE,
"a %s file can be used to specify files to ignore"},
{CVSROOTADM_CHECKOUTLIST,
"a %s file can specify extra CVSROOT files to auto-checkout"},
+ {CVSROOTADM_WRAPPER,
+ "a %s file can be used to specify files to treat as wrappers"},
{NULL, NULL}};
/*
* Just save the last component of the path for error messages
*/
- if ((program_name = strrchr (argv[0], '/')) == NULL)
- program_name = argv[0];
- else
- program_name++;
+ program_name = last_component (argv[0]);
if (argc != 2)
mkmodules_usage ();
@@ -164,9 +165,15 @@ main (argc, argv)
/*
* File format:
* [<whitespace>]<filename><whitespace><error message><end-of-line>
+ *
+ * comment lines begin with '#'
*/
- for (; fgets (line, sizeof (line), fp) != NULL;)
+ while (fgets (line, sizeof (line), fp) != NULL)
{
+ /* skip lines starting with # */
+ if (line[0] == '#')
+ continue;
+
if ((last = strrchr (line, '\n')) != NULL)
*last = '\0'; /* strip the newline */
@@ -329,12 +336,14 @@ write_dbmfile (temp)
(void) fclose (fp);
if (err)
{
- char dotdir[50], dotpag[50];
+ char dotdir[50], dotpag[50], dotdb[50];
(void) sprintf (dotdir, "%s.dir", temp);
(void) sprintf (dotpag, "%s.pag", temp);
+ (void) sprintf (dotdb, "%s.db", temp);
(void) unlink_file (dotdir);
(void) unlink_file (dotpag);
+ (void) unlink_file (dotdb);
error (1, 0, "DBM creation failed; correct above errors");
}
}
@@ -343,29 +352,36 @@ static void
rename_dbmfile (temp)
char *temp;
{
- char newdir[50], newpag[50];
- char dotdir[50], dotpag[50];
- char bakdir[50], bakpag[50];
+ char newdir[50], newpag[50], newdb[50];
+ char dotdir[50], dotpag[50], dotdb[50];
+ char bakdir[50], bakpag[50], bakdb[50];
(void) sprintf (dotdir, "%s.dir", CVSROOTADM_MODULES);
(void) sprintf (dotpag, "%s.pag", CVSROOTADM_MODULES);
+ (void) sprintf (dotdb, "%s.db", CVSROOTADM_MODULES);
(void) sprintf (bakdir, "%s%s.dir", BAKPREFIX, CVSROOTADM_MODULES);
(void) sprintf (bakpag, "%s%s.pag", BAKPREFIX, CVSROOTADM_MODULES);
+ (void) sprintf (bakdb, "%s%s.db", BAKPREFIX, CVSROOTADM_MODULES);
(void) sprintf (newdir, "%s.dir", temp);
(void) sprintf (newpag, "%s.pag", temp);
+ (void) sprintf (newdb, "%s.db", temp);
(void) chmod (newdir, 0666);
(void) chmod (newpag, 0666);
+ (void) chmod (newdb, 0666);
/* don't mess with me */
SIG_beginCrSect ();
(void) unlink_file (bakdir); /* rm .#modules.dir .#modules.pag */
(void) unlink_file (bakpag);
+ (void) unlink_file (bakdb);
(void) rename (dotdir, bakdir); /* mv modules.dir .#modules.dir */
(void) rename (dotpag, bakpag); /* mv modules.pag .#modules.pag */
+ (void) rename (dotdb, bakdb); /* mv modules.db .#modules.db */
(void) rename (newdir, dotdir); /* mv "temp".dir modules.dir */
(void) rename (newpag, dotpag); /* mv "temp".pag modules.pag */
+ (void) rename (newdb, dotdb); /* mv "temp".db modules.db */
/* OK -- make my day */
SIG_endCrSect ();
@@ -403,6 +419,14 @@ Lock_Cleanup ()
{
}
+int server_active = 0;
+
+void
+server_cleanup (sig)
+ int sig;
+{
+}
+
static void
mkmodules_usage ()
{
OpenPOWER on IntegriCloud