summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cvs/src
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cvs/src')
-rw-r--r--gnu/usr.bin/cvs/src/Makefile.in679
-rw-r--r--gnu/usr.bin/cvs/src/checkout.c125
-rw-r--r--gnu/usr.bin/cvs/src/client.c343
-rw-r--r--gnu/usr.bin/cvs/src/commit.c84
-rw-r--r--gnu/usr.bin/cvs/src/cvs.h56
-rw-r--r--gnu/usr.bin/cvs/src/cvsbug.sh526
-rw-r--r--gnu/usr.bin/cvs/src/ignore.c42
-rw-r--r--gnu/usr.bin/cvs/src/import.c28
-rw-r--r--gnu/usr.bin/cvs/src/lock.c22
-rw-r--r--gnu/usr.bin/cvs/src/main.c217
-rw-r--r--gnu/usr.bin/cvs/src/mkmodules.c10
-rw-r--r--gnu/usr.bin/cvs/src/parseinfo.c10
-rw-r--r--gnu/usr.bin/cvs/src/patch.c51
-rw-r--r--gnu/usr.bin/cvs/src/rcs.c240
-rw-r--r--gnu/usr.bin/cvs/src/rcscmds.c8
-rw-r--r--gnu/usr.bin/cvs/src/recurse.c24
-rw-r--r--gnu/usr.bin/cvs/src/root.c488
-rw-r--r--gnu/usr.bin/cvs/src/rtag.c764
-rw-r--r--gnu/usr.bin/cvs/src/server.c445
-rw-r--r--gnu/usr.bin/cvs/src/update.c131
20 files changed, 1873 insertions, 2420 deletions
diff --git a/gnu/usr.bin/cvs/src/Makefile.in b/gnu/usr.bin/cvs/src/Makefile.in
index 833d35780eb..c80deab8794 100644
--- a/gnu/usr.bin/cvs/src/Makefile.in
+++ b/gnu/usr.bin/cvs/src/Makefile.in
@@ -1,6 +1,20 @@
+# Makefile.in generated automatically by automake 1.4e from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
# Makefile for GNU CVS program.
-# Do not use this makefile directly, but only from `../Makefile'.
-# Copyright (C) 1986, 1988-1990 Free Software Foundation, Inc.
+# Copyright (C) 1986, 1988-1990, 2000 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -12,185 +26,584 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-SHELL = /bin/sh
-srcdir = @srcdir@
+srcdir = @srcdir@
top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-
+VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
-# Where to install the executables.
bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
-# Where to put the system-wide .cvsrc file
-datadir = $(prefix)/share
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
-# Where to put the manual pages.
-mandir = @mandir@
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
-# Use cp if you don't have install.
INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+AMTAR = @AMTAR@
+AWK = @AWK@
+CC = @CC@
+CSH = @CSH@
+DEPDIR = @DEPDIR@
+ETAGS = @ETAGS@
+ETAGS_INCLUDE_OPTION = @ETAGS_INCLUDE_OPTION@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTALL_STRIP_PROGRAM_ENV = @INSTALL_STRIP_PROGRAM_ENV@
+KRB4 = @KRB4@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL = @PERL@
+PR = @PR@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+ROFF = @ROFF@
+STRIP = @STRIP@
+TEXI2DVI = @TEXI2DVI@
+VERSION = @VERSION@
+YACC = @YACC@
+_am_include = @_am_include@
+_am_quote = @_am_quote@
+includeopt = @includeopt@
+install_sh = @install_sh@
-LIBS = @LIBS@
-
-SOURCES = add.c admin.c buffer.c checkin.c checkout.c classify.c client.c \
-commit.c create_adm.c cvsrc.c diff.c edit.c entries.c error.c expand_path.c \
-fileattr.c find_names.c hardlink.c hash.c history.c ignore.c import.c \
-lock.c log.c login.c logmsg.c main.c mkmodules.c modules.c myndbm.c no_diff.c \
-parseinfo.c patch.c rcs.c rcscmds.c recurse.c release.c remove.c repos.c \
-root.c rtag.c scramble.c server.c status.c subr.c filesubr.c run.c \
-tag.c update.c watch.c wrapper.c vers_ts.c version.c zlib.c
+SHELL = /bin/sh
-OBJECTS = add.o admin.o buffer.o checkin.o checkout.o classify.o client.o \
-commit.o create_adm.o cvsrc.o diff.o edit.o entries.o expand_path.o \
-fileattr.o find_names.o hardlink.o hash.o history.o ignore.o import.o \
-lock.o log.o login.o logmsg.o main.o mkmodules.o modules.o myndbm.o no_diff.o \
-parseinfo.o patch.o rcs.o rcscmds.o recurse.o release.o remove.o repos.o \
-root.o rtag.o scramble.o server.o status.o tag.o update.o \
-watch.o wrapper.o vers_ts.o \
-subr.o filesubr.o run.o version.o error.o zlib.o
+# $(includeopt) is CVS specific and set by configure
+# FIXME - This includes line is dependant on its order. This means there is
+# some namespace hackery going on that maybe shouldn't be. Long term fix is to
+# try and remove naming ocnflicts and fix Automake to allow particular includes
+# to be attached only to particular object files. Short term fix is either or.
+INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/diff -I$(top_srcdir)/zlib $(includeopt)
+
+bin_PROGRAMS = cvs
+bin_SCRIPTS = cvsbug
+
+# The cvs executable
+cvs_SOURCES = \
+ add.c \
+ admin.c \
+ annotate.c \
+ buffer.c \
+ checkin.c \
+ checkout.c \
+ classify.c \
+ client.c \
+ commit.c \
+ create_adm.c \
+ cvsrc.c diff.c \
+ edit.c \
+ entries.c \
+ error.c \
+ expand_path.c \
+ fileattr.c \
+ filesubr.c \
+ find_names.c \
+ hardlink.c \
+ hash.c \
+ history.c \
+ ignore.c \
+ import.c \
+ lock.c \
+ log.c \
+ login.c \
+ logmsg.c \
+ main.c \
+ mkmodules.c \
+ modules.c \
+ myndbm.c \
+ no_diff.c \
+ parseinfo.c \
+ patch.c \
+ rcs.c \
+ rcscmds.c \
+ recurse.c \
+ release.c \
+ remove.c \
+ repos.c \
+ root.c \
+ run.c \
+ scramble.c \
+ server.c \
+ status.c \
+ subr.c \
+ tag.c \
+ update.c \
+ vers_ts.c \
+ watch.c \
+ wrapper.c \
+ zlib.c \
+ buffer.h \
+ client.h \
+ cvs.h \
+ edit.h \
+ error.h \
+ fileattr.h \
+ hardlink.h \
+ hash.h \
+ myndbm.h \
+ rcs.h \
+ server.h \
+ update.h \
+ watch.h
+
+cvs_LDADD = \
+ ../diff/libdiff.a \
+ ../lib/libcvs.a \
+ ../zlib/libz.a \
+ version.o
+
+cvs_EXTRA_DIST = version.c
+
+# extra clean targets
+# wish this could be distclean-hdr-local but it's not part of automake
+DISTCLEANFILES = options.h-SAVED check.log check.plog
+
+# General
+EXTRA_DIST = \
+ $(cvs_EXTRA_DIST) \
+ .cvsignore \
+ ChangeLog-9194 \
+ ChangeLog-9395 \
+ ChangeLog-96 \
+ ChangeLog-97 \
+ build_src.com \
+ sanity.sh \
+ version.c \
+ version.c.in
+
+EXEEXT =
+OBJEXT = o
+subdir = src
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h options.h
+CONFIG_CLEAN_FILES = cvsbug
+bin_PROGRAMS = cvs$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS)
+
+am_cvs_OBJECTS = add.$(OBJEXT) admin.$(OBJEXT) annotate.$(OBJEXT) \
+ buffer.$(OBJEXT) checkin.$(OBJEXT) checkout.$(OBJEXT) \
+ classify.$(OBJEXT) client.$(OBJEXT) commit.$(OBJEXT) \
+ create_adm.$(OBJEXT) cvsrc.$(OBJEXT) diff.$(OBJEXT) \
+ edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
+ expand_path.$(OBJEXT) fileattr.$(OBJEXT) filesubr.$(OBJEXT) \
+ find_names.$(OBJEXT) hardlink.$(OBJEXT) hash.$(OBJEXT) \
+ history.$(OBJEXT) ignore.$(OBJEXT) import.$(OBJEXT) \
+ lock.$(OBJEXT) log.$(OBJEXT) login.$(OBJEXT) logmsg.$(OBJEXT) \
+ main.$(OBJEXT) mkmodules.$(OBJEXT) modules.$(OBJEXT) \
+ myndbm.$(OBJEXT) no_diff.$(OBJEXT) parseinfo.$(OBJEXT) \
+ patch.$(OBJEXT) rcs.$(OBJEXT) rcscmds.$(OBJEXT) \
+ recurse.$(OBJEXT) release.$(OBJEXT) remove.$(OBJEXT) \
+ repos.$(OBJEXT) root.$(OBJEXT) run.$(OBJEXT) scramble.$(OBJEXT) \
+ server.$(OBJEXT) status.$(OBJEXT) subr.$(OBJEXT) tag.$(OBJEXT) \
+ update.$(OBJEXT) vers_ts.$(OBJEXT) watch.$(OBJEXT) \
+ wrapper.$(OBJEXT) zlib.$(OBJEXT)
+cvs_OBJECTS = $(am_cvs_OBJECTS)
+cvs_DEPENDENCIES = ../diff/libdiff.a ../lib/libcvs.a ../zlib/libz.a \
+ version.o
+cvs_LDFLAGS =
+SCRIPTS = $(bin_SCRIPTS)
+
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CFLAGS = @CFLAGS@
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-HEADERS = buffer.h cvs.h rcs.h hardlink.h hash.h myndbm.h \
- update.h server.h client.h error.h fileattr.h edit.h watch.h
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -I.
+DEFS = @DEFS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+DIST_SOURCES = $(cvs_SOURCES)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/add.Po $(DEPDIR)/admin.Po \
+@AMDEP_TRUE@ $(DEPDIR)/annotate.Po $(DEPDIR)/buffer.Po \
+@AMDEP_TRUE@ $(DEPDIR)/checkin.Po $(DEPDIR)/checkout.Po \
+@AMDEP_TRUE@ $(DEPDIR)/classify.Po $(DEPDIR)/client.Po \
+@AMDEP_TRUE@ $(DEPDIR)/commit.Po $(DEPDIR)/create_adm.Po \
+@AMDEP_TRUE@ $(DEPDIR)/cvsrc.Po $(DEPDIR)/diff.Po \
+@AMDEP_TRUE@ $(DEPDIR)/edit.Po $(DEPDIR)/entries.Po \
+@AMDEP_TRUE@ $(DEPDIR)/error.Po $(DEPDIR)/expand_path.Po \
+@AMDEP_TRUE@ $(DEPDIR)/fileattr.Po $(DEPDIR)/filesubr.Po \
+@AMDEP_TRUE@ $(DEPDIR)/find_names.Po $(DEPDIR)/hardlink.Po \
+@AMDEP_TRUE@ $(DEPDIR)/hash.Po $(DEPDIR)/history.Po \
+@AMDEP_TRUE@ $(DEPDIR)/ignore.Po $(DEPDIR)/import.Po \
+@AMDEP_TRUE@ $(DEPDIR)/lock.Po $(DEPDIR)/log.Po \
+@AMDEP_TRUE@ $(DEPDIR)/login.Po $(DEPDIR)/logmsg.Po \
+@AMDEP_TRUE@ $(DEPDIR)/main.Po $(DEPDIR)/mkmodules.Po \
+@AMDEP_TRUE@ $(DEPDIR)/modules.Po $(DEPDIR)/myndbm.Po \
+@AMDEP_TRUE@ $(DEPDIR)/no_diff.Po $(DEPDIR)/parseinfo.Po \
+@AMDEP_TRUE@ $(DEPDIR)/patch.Po $(DEPDIR)/rcs.Po \
+@AMDEP_TRUE@ $(DEPDIR)/rcscmds.Po $(DEPDIR)/recurse.Po \
+@AMDEP_TRUE@ $(DEPDIR)/release.Po $(DEPDIR)/remove.Po \
+@AMDEP_TRUE@ $(DEPDIR)/repos.Po $(DEPDIR)/root.Po \
+@AMDEP_TRUE@ $(DEPDIR)/run.Po $(DEPDIR)/scramble.Po \
+@AMDEP_TRUE@ $(DEPDIR)/server.Po $(DEPDIR)/status.Po \
+@AMDEP_TRUE@ $(DEPDIR)/subr.Po $(DEPDIR)/tag.Po \
+@AMDEP_TRUE@ $(DEPDIR)/update.Po $(DEPDIR)/vers_ts.Po \
+@AMDEP_TRUE@ $(DEPDIR)/watch.Po $(DEPDIR)/wrapper.Po \
+@AMDEP_TRUE@ $(DEPDIR)/zlib.Po
+DIST_COMMON = ./stamp-h2.in ChangeLog Makefile.am Makefile.in cvsbug.in \
+ options.h.in
+SOURCES = $(cvs_SOURCES)
+OBJECTS = $(am_cvs_OBJECTS)
+
+all: options.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && \
+ CONFIG_HEADERS= CONFIG_LINKS= \
+ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+
+options.h: stamp-h2
+ @if test ! -f $@; then \
+ rm -f stamp-h2; \
+ $(MAKE) stamp-h2; \
+ else :; fi
+stamp-h2: $(srcdir)/options.h.in $(top_builddir)/config.status
+ @rm -f stamp-h2 stamp-h2T
+ @echo timestamp > stamp-h2T 2> /dev/null
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=src/options.h \
+ $(SHELL) ./config.status
+ @mv stamp-h2T stamp-h2
+$(srcdir)/options.h.in: $(srcdir)/./stamp-h2.in
+ @if test ! -f $@; then \
+ rm -f $(srcdir)/./stamp-h2.in; \
+ $(MAKE) $(srcdir)/./stamp-h2.in; \
+ else :; fi
+$(srcdir)/./stamp-h2.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/acconfig.h
+ @rm -f $(srcdir)/./stamp-h2.in $(srcdir)/./stamp-h2.inT
+ @echo timestamp > $(srcdir)/./stamp-h2.inT 2> /dev/null
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @mv $(srcdir)/./stamp-h2.inT $(srcdir)/./stamp-h2.in
+
+distclean-hdr:
+ -rm -f options.h
+cvsbug: $(top_builddir)/config.status cvsbug.in
+ cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \
+ else :; fi; \
+ done
-TAGFILES = $(HEADERS) options.h.in $(SOURCES)
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+ rm -f $(DESTDIR)$(bindir)/$$f; \
+ done
-DISTFILES = .cvsignore Makefile.in \
- ChangeLog ChangeLog-97 ChangeLog-96 ChangeLog-9395 ChangeLog-9194 \
- sanity.sh cvsbug.sh $(TAGFILES) build_src.com
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+cvs$(EXEEXT): $(cvs_OBJECTS) $(cvs_DEPENDENCIES)
+ @rm -f cvs$(EXEEXT)
+ $(LINK) $(cvs_LDFLAGS) $(cvs_OBJECTS) $(cvs_LDADD) $(LIBS)
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ f="`echo $$p|sed '$(transform)'`"; \
+ if test -f $$p; then \
+ echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/$$f"; \
+ $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/$$f; \
+ elif test -f $(srcdir)/$$p; then \
+ echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/$$f"; \
+ $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/$$f; \
+ else :; fi; \
+ done
-PROGS = cvs cvsbug
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ f="`echo $$p|sed '$(transform)'`"; \
+ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+ rm -f $(DESTDIR)$(bindir)/$$f; \
+ done
-DEFS = @DEFS@ @includeopt@
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) options.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+ unique=`for i in $$list @CONFIG@; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)options.h.in$$unique$(LISP)$$tags" \
+ || $(ETAGS) $(ETAGS_ARGS) $$tags options.h.in $$unique $(LISP)
+
+GTAGS:
+ here=`CDPATH=: && cd $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $$here
+
+distclean-tags:
+ -rm -f TAGS ID
+
+@_am_include@ @_am_quote@$(DEPDIR)/add.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/admin.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/annotate.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/buffer.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/checkin.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/checkout.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/classify.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/client.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/commit.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/create_adm.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/cvsrc.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/diff.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/edit.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/entries.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/error.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/expand_path.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/fileattr.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/filesubr.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/find_names.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/hardlink.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/hash.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/history.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/ignore.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/import.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/lock.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/log.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/login.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/logmsg.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/main.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/mkmodules.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/modules.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/myndbm.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/no_diff.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/parseinfo.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/patch.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/rcs.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/rcscmds.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/recurse.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/release.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/remove.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/repos.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/root.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/run.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/scramble.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/server.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/status.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/subr.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/tag.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/update.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/vers_ts.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/watch.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/wrapper.Po@_am_quote@
+@_am_include@ @_am_quote@$(DEPDIR)/zlib.Po@_am_quote@
+
+distclean-depend:
+ -rm -rf $(DEPDIR)
+
+CCDEPMODE = @CCDEPMODE@
-CC = @CC@
-CFLAGS = @CFLAGS@
-CPPFLAGS =
-LDFLAGS = @LDFLAGS@
-ZLIB = @ZLIB@
+.c.o:
+ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c -o $@ `cygpath -w $<`
+
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pR $$d/$$file $(distdir) \
+ || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(PROGRAMS) $(SCRIPTS) options.h
-INCLUDES = -I. -I.. -I$(srcdir) -I$(top_srcdir)/lib
-ZLIB_INCLUDES = @ZLIB_INCLUDES@
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(bindir)
-.c.o:
- $(CC) $(CPPFLAGS) $(INCLUDES) $(DEFS) $(CFLAGS) -c $<
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
-all: Makefile $(PROGS)
-.PHONY: all
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-saber_cvs:
- @cd ..; $(MAKE) saber SUBDIRS=src
+installcheck: installcheck-am
-lint:
- @cd ..; $(MAKE) lint SUBDIRS=src
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_PROGRAM_ENV='$(INSTALL_STRIP_PROGRAM_ENV)' install
-install: installdirs
- @for prog in $(PROGS); do \
- echo Installing $$prog in $(bindir); \
- $(INSTALL_PROGRAM) $$prog $(bindir)/$$prog ; \
- done
+mostlyclean-generic:
-installdirs:
- $(SHELL) $(top_srcdir)/mkinstalldirs $(bindir)
+clean-generic:
-.PHONY: install installdirs
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-installcheck:
- $(SHELL) $(srcdir)/sanity.sh $(bindir)/cvs
-.PHONY: installcheck
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f Makefile.in
+clean: clean-am
-check: all
- $(SHELL) $(srcdir)/sanity.sh `pwd`/cvs
-.PHONY: check
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
-# I'm not sure there is any remaining reason for this to be separate from
-# `make check'.
-remotecheck: all
- $(SHELL) $(srcdir)/sanity.sh -r `pwd`/cvs
-.PHONY: remotecheck
+distclean: distclean-am
-tags: $(TAGFILES)
- ctags $(TAGFILES)
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-hdr distclean-tags
-TAGS: $(TAGFILES)
- etags `for i in $(TAGFILES); do echo $(srcdir)/$$i; done`
+dvi:
-ls:
- @echo $(DISTFILES)
-.PHONY: ls
+dvi-am:
-clean:
- rm -f $(PROGS) *.o core check.log check.plog
-.PHONY: clean
+info:
-distclean: clean
- rm -f tags TAGS Makefile options.h
-.PHONY: distclean
+info-am:
-realclean: distclean
-.PHONY: realclean
+install-data-am:
-dist-dir:
- mkdir ${DISTDIR}
- for i in ${DISTFILES}; do \
- ln $(srcdir)/$${i} ${DISTDIR}; \
- done
-.PHONY: dist-dir
+install-exec-am: install-binPROGRAMS install-binSCRIPTS
-# Linking rules.
+install-info:
-$(PROGS): ../lib/libcvs.a ../diff/libdiff.a
+install-man:
-cvs: $(OBJECTS)
- $(CC) $(OBJECTS) ../lib/libcvs.a ../diff/libdiff.a $(ZLIB) $(LIBS) $(LDFLAGS) -o $@
+installcheck-am:
-xlint: $(SOURCES)
- files= ; \
- for i in $(SOURCES) ; do \
- files="$$files $(srcdir)/$$i" ; \
- done ; \
- sh -c "lint $(DEFS) $(INCLUDES) $$files | grep -v \"possible pointer alignment problem\" \
- | grep -v \"argument closure unused\""
+maintainer-clean: maintainer-clean-am
-saber: $(SOURCES)
- # load $(CFLAGS) $(SOURCES)
- # load ../lib/libcvs.a $(LIBS)
+maintainer-clean-am: distclean-am maintainer-clean-generic
-cvsbug: cvsbug.sh $(srcdir)/version.c
- echo > .fname \
- cvs-`sed < $(srcdir)/version.c \
- -e '/version_string/!d' \
- -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
- -e q`
- sed -e 's,xDATADIRx,$(datadir)/cvs,g' \
- -e "s,xVERSIONx,`cat .fname`,g" $(srcdir)/$@.sh > $@-t
- rm -f .fname
- mv $@-t $@
- chmod a+x $@
+mostlyclean: mostlyclean-am
-# Compilation rules.
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
-$(OBJECTS): $(HEADERS) options.h
+uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS
-rcscmds.o: rcscmds.c $(top_srcdir)/diff/diffrun.h
- $(CC) $(CPPFLAGS) $(INCLUDES) -I$(top_srcdir)/diff $(DEFS) $(CFLAGS) -c $(srcdir)/rcscmds.c
+.PHONY: all all-am check check-am check-local clean clean-binPROGRAMS \
+ clean-generic distclean distclean-compile distclean-depend \
+ distclean-generic distclean-hdr distclean-tags distdir dvi \
+ dvi-am info info-am install install-am install-binPROGRAMS \
+ install-binSCRIPTS install-data install-data-am install-exec \
+ install-exec-am install-info install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic tags uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-binSCRIPTS
-zlib.o: zlib.c
- $(CC) $(CPPFLAGS) $(INCLUDES) ${ZLIB_INCLUDES} $(DEFS) $(CFLAGS) -c $(srcdir)/zlib.c
-subdir = src
-Makefile: ../config.status Makefile.in
- cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+check-local:
+ $(SHELL) $(srcdir)/sanity.sh `pwd`/cvs
-options.h: ../config.status options.h.in
- cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+.PHONY: remotecheck
+remotecheck: all
+ $(SHELL) $(srcdir)/sanity.sh -r `pwd`/cvs
-#../config.status: ../configure
-# cd .. ; $(SHELL) config.status --recheck
+# version.c
+# - build this here so that we can distribute it
+# - version.c needs to be updated only once, since it depends on
+# configure.in, not on the results of a 'configure' run.
+# - It is guaranteed (with GNU Make) that when the version in configure.in
+# is changed, acversion.m4 is built only after the new version number is
+# propagated to the Makefile. (Libtool uses the same guarantee.)
+# - need the explicit version.o dependency or else make won't match
+# $(srcdir)/version.c when looking for a dependency for version.c
+version.o: $(srcdir)/version.c
+$(srcdir)/version.c: $(srcdir)/version.c.in $(top_srcdir)/configure.in
+ sed 's,@VERSION\@,$(VERSION),g' $(srcdir)/version.c.in >$(srcdir)/version.tc
+ mv $(srcdir)/version.tc $(srcdir)/version.c
+
+# for backwards compatibility with the old makefiles
+.PHONY: realclean
+realclean: maintainer-clean
-#../configure: ../configure.in
-# cd $(top_srcdir) ; autoconf
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gnu/usr.bin/cvs/src/checkout.c b/gnu/usr.bin/cvs/src/checkout.c
index 1a66b5be6f9..86dc9510eb0 100644
--- a/gnu/usr.bin/cvs/src/checkout.c
+++ b/gnu/usr.bin/cvs/src/checkout.c
@@ -44,7 +44,7 @@ static int checkout_proc PROTO((int argc, char **argv, char *where,
static const char *const checkout_usage[] =
{
- "Usage:\n %s %s [-ANPRcflnps] [-r rev | -D date] [-d dir]\n",
+ "Usage:\n %s %s [-ANPRcflnps] [-r rev] [-D date] [-d dir]\n",
" [-j rev1] [-j rev2] [-k kopt] modules...\n",
"\t-A\tReset any sticky tags/date/kopts.\n",
"\t-N\tDon't shorten module paths if -d specified.\n",
@@ -59,7 +59,7 @@ static const char *const checkout_usage[] =
"\t-r rev\tCheck out revision or tag. (implies -P) (is sticky)\n",
"\t-D date\tCheck out revisions as of date. (implies -P) (is sticky)\n",
"\t-d dir\tCheck out into dir instead of module name.\n",
- "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
+ "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
"\t-j rev\tMerge in changes made between current revision and rev.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
@@ -67,7 +67,7 @@ static const char *const checkout_usage[] =
static const char *const export_usage[] =
{
- "Usage: %s %s [-NRfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n",
+ "Usage: %s %s [-NRfln] [-r rev] [-D date] [-d dir] [-k kopt] module...\n",
"\t-N\tDon't shorten module paths if -d specified.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, not recursive\n",
@@ -190,7 +190,7 @@ checkout (argc, argv)
shorten = 1;
break;
case 's':
- status = 1;
+ cat = status = 1;
break;
case 'f':
force_tag_match = 0;
@@ -223,10 +223,10 @@ checkout (argc, argv)
if (shorten == -1)
shorten = 0;
- if ((cat || status) && argc != 0)
+ if (cat && argc != 0)
error (1, 0, "-c and -s must not get any arguments");
- if (!(cat || status) && argc == 0)
+ if (!cat && argc == 0)
error (1, 0, "must specify at least one module or directory");
if (where && pipeout)
@@ -248,12 +248,12 @@ checkout (argc, argv)
}
#endif
- if (!safe_location()) {
+ if (!cat && !safe_location()) {
error(1, 0, "Cannot check out files into the repository itself");
}
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
int expand_modules;
@@ -269,7 +269,7 @@ checkout (argc, argv)
below in !expand_modules), those files (CVS/Checkin.prog
or CVS/Update.prog) don't get created. Grrr. */
- expand_modules = (!cat && !status && !pipeout
+ expand_modules = (!cat && !pipeout
&& supported_request ("expand-modules"));
if (expand_modules)
@@ -296,7 +296,7 @@ checkout (argc, argv)
if (checkout_prune_dirs && m_type == CHECKOUT)
send_arg("-P");
client_prune_dirs = checkout_prune_dirs;
- if (cat)
+ if (cat && !status)
send_arg("-c");
if (where != NULL)
option_with_arg ("-d", where);
@@ -329,7 +329,7 @@ checkout (argc, argv)
}
#endif /* CLIENT_SUPPORT */
- if (cat || status)
+ if (cat)
{
cat_module (status);
if (options)
@@ -367,7 +367,7 @@ checkout (argc, argv)
for (i = 0; i < argc; i++)
err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
- where, shorten, local, run_module_prog,
+ where, shorten, local, run_module_prog, !pipeout,
(char *) NULL);
close_module (db);
if (options)
@@ -391,13 +391,13 @@ safe_location ()
/* FIXME-arbitrary limit: should be retrying this like xgetwd.
But how does readlink let us know that the buffer was too small?
(by returning sizeof hardpath - 1?). */
- x = readlink(CVSroot_directory, hardpath, sizeof hardpath - 1);
+ x = readlink(current_parsed_root->directory, hardpath, sizeof hardpath - 1);
#else
x = -1;
#endif
if (x == -1)
{
- strcpy(hardpath, CVSroot_directory);
+ strcpy(hardpath, current_parsed_root->directory);
}
else
{
@@ -466,8 +466,8 @@ build_one_dir (repository, dirpath, sticky)
error (1, 0, "there is no repository %s", repository);
if (Create_Admin (".", dirpath, repository,
- sticky ? (char *) NULL : tag,
- sticky ? (char *) NULL : date,
+ sticky ? tag : (char *) NULL,
+ sticky ? date : (char *) NULL,
/* FIXME? This is a guess. If it is important
for nonbranch to be set correctly here I
@@ -529,11 +529,11 @@ checkout_proc (argc, argv, where_orig, mwhere, mfile, shorten,
/* Set up the repository (maybe) for the bottom directory.
Allocate more space than we need so we don't need to keep
reallocating this string. */
- repository = xmalloc (strlen (CVSroot_directory)
+ repository = xmalloc (strlen (current_parsed_root->directory)
+ strlen (argv[0])
+ (mfile == NULL ? 0 : strlen (mfile))
+ 10);
- (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
+ (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
Sanitize_Repository_Name (repository);
@@ -709,11 +709,11 @@ checkout_proc (argc, argv, where_orig, mwhere, mfile, shorten,
struct dir_to_build *head;
char *reposcopy;
- if (strncmp (repository, CVSroot_directory,
- strlen (CVSroot_directory)) != 0)
+ if (strncmp (repository, current_parsed_root->directory,
+ strlen (current_parsed_root->directory)) != 0)
error (1, 0, "\
internal error: %s doesn't start with %s in checkout_proc",
- repository, CVSroot_directory);
+ repository, current_parsed_root->directory);
/* We always create at least one directory, which corresponds to
the entire strings for WHERE and REPOSITORY. */
@@ -798,7 +798,7 @@ internal error: %s doesn't start with %s in checkout_proc",
bar -> Emptydir (generated dir -- not in repos)
baz -> quux (finally!) */
- if (strcmp (reposcopy, CVSroot_directory) == 0)
+ if (strcmp (reposcopy, current_parsed_root->directory) == 0)
{
/* We can't walk up past CVSROOT. Instead, the
repository should be Emptydir. */
@@ -806,55 +806,30 @@ internal error: %s doesn't start with %s in checkout_proc",
}
else
{
- if ((where_orig != NULL)
- && (strcmp (new->dirpath, where_orig) == 0))
- {
- /* It's the case that the user specified a
- * destination directory with the "-d" flag. The
- * repository in this directory should be "."
- * since the user's command is equivalent to:
- *
- * cd <dir>; cvs co blah */
-
- strcpy (reposcopy, CVSroot_directory);
- goto allocate_repos;
- }
- else if (mwhere != NULL)
- {
- /* This is a generated directory, so point to
- CVSNULLREPOS. */
-
- new->repository = emptydir_name ();
- }
- else
- {
- /* It's a directory in the repository! */
+ /* It's a directory in the repository! */
- char *rp;
+ char *rp;
- /* We'll always be below CVSROOT, but check for
- paranoia's sake. */
- rp = strrchr (reposcopy, '/');
- if (rp == NULL)
- error (1, 0,
- "internal error: %s doesn't contain a slash",
- reposcopy);
+ /* We'll always be below CVSROOT, but check for
+ paranoia's sake. */
+ rp = strrchr (reposcopy, '/');
+ if (rp == NULL)
+ error (1, 0,
+ "internal error: %s doesn't contain a slash",
+ reposcopy);
- *rp = '\0';
-
- allocate_repos:
- new->repository = xmalloc (strlen (reposcopy) + 5);
- (void) strcpy (new->repository, reposcopy);
+ *rp = '\0';
+ new->repository = xmalloc (strlen (reposcopy) + 5);
+ (void) strcpy (new->repository, reposcopy);
- if (strcmp (reposcopy, CVSroot_directory) == 0)
- {
- /* Special case -- the repository name needs
- to be "/path/to/repos/." (the trailing dot
- is important). We might be able to get rid
- of this after the we check out the other
- code that handles repository names. */
- (void) strcat (new->repository, "/.");
- }
+ if (strcmp (reposcopy, current_parsed_root->directory) == 0)
+ {
+ /* Special case -- the repository name needs
+ to be "/path/to/repos/." (the trailing dot
+ is important). We might be able to get rid
+ of this after the we check out the other
+ code that handles repository names. */
+ (void) strcat (new->repository, "/.");
}
}
}
@@ -866,7 +841,7 @@ internal error: %s doesn't start with %s in checkout_proc",
int where_is_absolute = isabsolute (where);
/* The top-level CVSADM directory should always be
- CVSroot_directory. Create it, but only if WHERE is
+ current_parsed_root->directory. Create it, but only if WHERE is
relative. If WHERE is absolute, our current directory
may not have a thing to do with where the sources are
being checked out. If it does, build_dirs_and_chdir
@@ -880,7 +855,7 @@ internal error: %s doesn't start with %s in checkout_proc",
{
/* It may be argued that we shouldn't set any sticky
bits for the top-level repository. FIXME? */
- build_one_dir (CVSroot_directory, ".", argc <= 1);
+ build_one_dir (current_parsed_root->directory, ".", argc <= 1);
#ifdef SERVER_SUPPORT
/* We _always_ want to have a top-level admin
@@ -892,7 +867,7 @@ internal error: %s doesn't start with %s in checkout_proc",
will be ignored on the client side. */
if (server_active)
- server_clear_entstat (".", CVSroot_directory);
+ server_clear_entstat (".", current_parsed_root->directory);
#endif
}
@@ -1033,7 +1008,7 @@ internal error: %s doesn't start with %s in checkout_proc",
force_tag_match, 0 /* !local */ ,
1 /* update -d */ , aflag, checkout_prune_dirs,
pipeout, which, join_rev1, join_rev2,
- preload_update_dir);
+ preload_update_dir, m_type == CHECKOUT);
goto out;
}
@@ -1089,7 +1064,7 @@ internal error: %s doesn't start with %s in checkout_proc",
err += do_update (argc - 1, argv + 1, options, tag, date,
force_tag_match, local_specified, 1 /* update -d */,
aflag, checkout_prune_dirs, pipeout, which, join_rev1,
- join_rev2, preload_update_dir);
+ join_rev2, preload_update_dir, m_type == CHECKOUT);
out:
free (preload_update_dir);
preload_update_dir = oldupdate;
@@ -1121,11 +1096,11 @@ emptydir_name ()
{
char *repository;
- repository = xmalloc (strlen (CVSroot_directory)
+ repository = xmalloc (strlen (current_parsed_root->directory)
+ sizeof (CVSROOTADM)
+ sizeof (CVSNULLREPOS)
- + 10);
- (void) sprintf (repository, "%s/%s/%s", CVSroot_directory,
+ + 3);
+ (void) sprintf (repository, "%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSNULLREPOS);
if (!isfile (repository))
{
diff --git a/gnu/usr.bin/cvs/src/client.c b/gnu/usr.bin/cvs/src/client.c
index c82896ab21c..999beb31f3b 100644
--- a/gnu/usr.bin/cvs/src/client.c
+++ b/gnu/usr.bin/cvs/src/client.c
@@ -32,6 +32,7 @@
# else /* No winsock.h */
# include <sys/socket.h>
# include <netinet/in.h>
+# include <arpa/inet.h>
# include <netdb.h>
# endif /* No winsock.h */
#endif
@@ -77,19 +78,7 @@ static Key_schedule sched;
#ifdef HAVE_GSSAPI
-#ifdef HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif
-#ifdef HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#endif
-#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
-#include <gssapi/gssapi_generic.h>
-#endif
-
-#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
-#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
-#endif
+# include "xgssapi.h"
/* This is needed for GSSAPI encryption. */
static gss_ctx_id_t gcontext;
@@ -97,7 +86,7 @@ static gss_ctx_id_t gcontext;
static int connect_to_gserver PROTO((int, struct hostent *));
#endif /* HAVE_GSSAPI */
-
+
static void add_prune_candidate PROTO((char *));
/* All the commands. */
@@ -198,7 +187,7 @@ arg_should_not_be_sent_to_server (arg)
4) the argument lies within one of the paths in
dirs_sent_to_server.
- 4) */
+ */
if (list_isempty (dirs_sent_to_server))
return 0; /* always send it */
@@ -270,8 +259,8 @@ arg_should_not_be_sent_to_server (arg)
*/
#if 0
/* Now check the value for root. */
- if (this_root && current_root
- && (strcmp (this_root, current_root) != 0))
+ if (this_root && current_parsed_root
+ && (strcmp (this_root, current_parsed_root->original) != 0))
{
/* Don't send this, since the CVSROOTs don't match. */
free (this_root);
@@ -1285,6 +1274,32 @@ warning: server is not creating directories one at a time");
if ( CVS_CHDIR (dir_name) < 0)
error (1, errno, "could not chdir to %s", dir_name);
}
+ else if (!isdir (CVSADM))
+ {
+ /*
+ * Put repository in CVS/Repository. For historical
+ * (pre-CVS/Root) reasons, this is an absolute pathname,
+ * but what really matters is the part of it which is
+ * relative to cvsroot.
+ */
+ char *repo;
+
+ if (reposdirname_absolute)
+ repo = reposdirname;
+ else
+ {
+ repo = xmalloc (strlen (reposdirname)
+ + strlen (toplevel_repos)
+ + 10);
+ strcpy (repo, toplevel_repos);
+ strcat (repo, "/");
+ strcat (repo, reposdirname);
+ }
+
+ Create_Admin (".", ".", repo, (char *)NULL, (char *)NULL, 0, 1, 1);
+ if (repo != reposdirname)
+ free (repo);
+ }
if (strcmp (command_name, "export") != 0)
{
@@ -2290,7 +2305,7 @@ static int
is_cvsroot_level (pathname)
char *pathname;
{
- if (strcmp (toplevel_repos, CVSroot_directory) != 0)
+ if (strcmp (toplevel_repos, current_parsed_root->directory) != 0)
return 0;
return strchr (pathname, '/') == NULL;
@@ -2930,14 +2945,14 @@ send_a_repository (dir, repository, update_dir)
from REPOSITORY. If the path elements don't exist
in REPOSITORY, or the removal of those path
elements mean that we "step above"
- CVSroot_directory, set toplevel_repos to
- CVSroot_directory. */
+ current_parsed_root->directory, set toplevel_repos to
+ current_parsed_root->directory. */
if ((repository_len > update_dir_len)
&& (strcmp (repository + repository_len - update_dir_len,
update_dir) == 0)
- /* TOPLEVEL_REPOS shouldn't be above CVSroot_directory */
+ /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
&& ((repository_len - update_dir_len)
- > strlen (CVSroot_directory)))
+ > strlen (current_parsed_root->directory)))
{
/* The repository name contains UPDATE_DIR. Set
toplevel_repos to the repository name without
@@ -2951,7 +2966,7 @@ send_a_repository (dir, repository, update_dir)
}
else
{
- toplevel_repos = xstrdup (CVSroot_directory);
+ toplevel_repos = xstrdup (current_parsed_root->directory);
}
}
}
@@ -3009,7 +3024,7 @@ client_expand_modules (argc, argv, local)
for (i = 0; i < argc; ++i)
send_arg (argv[i]);
- send_a_repository ("", CVSroot_directory, "");
+ send_a_repository ("", current_parsed_root->directory, "");
send_to_server ("expand-modules\012", 0);
@@ -3047,13 +3062,13 @@ client_send_expansions (local, where, build_dirs)
if (isfile (argv[0]))
send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS : 0);
}
- send_a_repository ("", CVSroot_directory, "");
+ send_a_repository ("", current_parsed_root->directory, "");
}
void
client_nonexpanded_setup ()
{
- send_a_repository ("", CVSroot_directory, "");
+ send_a_repository ("", current_parsed_root->directory, "");
}
/* Receive a cvswrappers line from the server; it must be a line
@@ -3568,7 +3583,8 @@ get_responses_and_close ()
{
if (shutdown (server_fd, 1) < 0)
error (1, 0, "shutting down connection to %s: %s",
- CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
+ current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO));
+ server_fd = -1;
/*
* This test will always be true because we dup the descriptor
*/
@@ -3577,7 +3593,7 @@ get_responses_and_close ()
if (fclose (to_server_fp) != 0)
error (1, errno,
"closing down connection to %s",
- CVSroot_hostname);
+ current_parsed_root->hostname);
}
}
else
@@ -3595,15 +3611,15 @@ get_responses_and_close ()
#endif /* START_RSH_WITH_POPEN_RW */
{
error (1, errno, "closing connection to %s",
- CVSroot_hostname);
+ current_parsed_root->hostname);
}
}
if (! buf_empty_p (from_server)
|| getc (from_server_fp) != EOF)
- error (0, 0, "dying gasps from %s unexpected", CVSroot_hostname);
+ error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname);
else if (ferror (from_server_fp))
- error (0, errno, "reading from %s", CVSroot_hostname);
+ error (0, errno, "reading from %s", current_parsed_root->hostname);
fclose (from_server_fp);
#endif /* SHUTDOWN_SERVER */
@@ -3620,8 +3636,7 @@ get_responses_and_close ()
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- while (time ((time_t *) NULL) == last_register_time)
- sleep (1);
+ sleep_past (last_register_time);
}
return errs;
@@ -3645,7 +3660,8 @@ supported_request (name)
return 0;
}
-
+
+
#if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS)
static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *,
unsigned int));
@@ -3674,22 +3690,86 @@ init_sockaddr (name, hostname, port)
#endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) */
-#ifdef AUTH_CLIENT_SUPPORT
-static int auth_server_port_number PROTO ((void));
+#ifdef AUTH_CLIENT_SUPPORT
+
+/* Generic function to do port number lookup tasks.
+ *
+ * In order of precedence, will return:
+ * getenv (envname), if defined
+ * getservbyname (portname), if defined
+ * defaultport
+ */
static int
-auth_server_port_number ()
+get_port_number (envname, portname, defaultport)
+ const char *envname;
+ const char *portname;
+ int defaultport;
{
- struct servent *s = getservbyname ("cvspserver", "tcp");
+ struct servent *s;
+ char *port_s;
- if (s)
+ if (envname && (port_s = getenv (envname)))
+ {
+ int port = atoi (port_s);
+ if (port <= 0)
+ {
+ error (0, 0, "%s must be a positive integer! If you", envname);
+ error (0, 0, "are trying to force a connection via ssh, please");
+ error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
+ error (1, 0, "variable.");
+ }
+ return port;
+ }
+ else if (portname && (s = getservbyname (portname, "tcp")))
return ntohs (s->s_port);
else
- return CVS_AUTH_PORT;
+ return defaultport;
+}
+
+
+
+/* get the port number for a client to connect to based on the port
+ * and method of a cvsroot_t.
+ *
+ * we do this here instead of in parse_cvsroot so that we can keep network
+ * code confined to a localized area and also to delay the lookup until the
+ * last possible moment so it remains possible to run cvs client commands that
+ * skip opening connections to the server (i.e. skip network operations entirely)
+ *
+ * and yes, I know none of the the commands do that now, but here's to planning
+ * for the future, eh? cheers.
+ *
+ * FIXME - We could cache the port lookup safely right now as we never change
+ * it for a single root on the fly, but we'd have to un'const some other
+ * functions
+ */
+int
+get_cvs_port_number (root)
+ const cvsroot_t *root;
+{
+
+ if (root->port) return root->port;
+
+ switch (root->method)
+ {
+ case gserver_method:
+ case pserver_method:
+ return get_port_number ("CVS_CLIENT_PORT", "cvspserver", CVS_AUTH_PORT);
+#ifdef HAVE_KERBEROS
+ case kserver_method:
+ return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
+#endif
+ default:
+ error(1, EINVAL, "internal error: get_cvs_port_number called for invalid connection method (%s)",
+ method_names[root->method]);
+ break;
+ }
}
+
/* Read a line from socket SOCK. Result does not include the
terminating linefeed. This is only used by the authentication
protocol, which we call before we set up all the buffering stuff.
@@ -3717,7 +3797,7 @@ recv_line (sock, resultp)
int n;
n = recv (sock, &ch, 1, 0);
if (n <= 0)
- error (1, 0, "recv() from server %s: %s", CVSroot_hostname,
+ error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
n == 0 ? "EOF" : SOCK_STRERROR (SOCK_ERRNO));
if (ch == '\012')
@@ -3755,11 +3835,15 @@ connect_to_forked_server (tofdp, fromfdp)
command[0] = getenv ("CVS_SERVER");
if (! command[0])
- command[0] = "cvs";
+ command[0] = program_path;
command[1] = "server";
command[2] = NULL;
+ if (trace)
+ {
+ fprintf (stderr, " -> Forking server: %s %s\n", command[0], command[1]);
+ }
if (! piped_child (command, tofdp, fromfdp))
error (1, 0, "could not fork server process");
}
@@ -3787,20 +3871,29 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
int tofd, fromfd;
#endif
int port_number;
+ char *username; /* the username we use to connect */
struct sockaddr_in client_sai;
struct hostent *hostinfo;
- char no_passwd = 0; /* gets set if no password found */
+ char no_passwd = 0; /* gets set if no password found */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
}
- port_number = auth_server_port_number ();
- hostinfo = init_sockaddr (&client_sai, CVSroot_hostname, port_number);
+ port_number = get_cvs_port_number (current_parsed_root);
+ hostinfo = init_sockaddr (&client_sai, current_parsed_root->hostname, port_number);
+ if (trace)
+ {
+ fprintf (stderr, " -> Connecting to %s(%s):%d\n",
+ current_parsed_root->hostname,
+ inet_ntoa (client_sai.sin_addr), port_number);
+ }
if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai))
< 0)
- error (1, 0, "connect to %s:%d failed: %s", CVSroot_hostname,
+ error (1, 0, "connect to %s(%s):%d failed: %s",
+ current_parsed_root->hostname,
+ inet_ntoa (client_sai.sin_addr),
port_number, SOCK_STRERROR (SOCK_ERRNO));
/* Run the authorization mini-protocol before anything else. */
@@ -3808,7 +3901,12 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
{
#ifdef HAVE_GSSAPI
if (! connect_to_gserver (sock, hostinfo))
+ {
+ error (0, 0,
+ "authorization failed: server %s rejected access to %s",
+ current_parsed_root->hostname, current_parsed_root->directory);
goto rejected;
+ }
#else
error (1, 0, "This client does not support GSSAPI authentication");
#endif
@@ -3816,11 +3914,9 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
else
{
char *begin = NULL;
- char *repository = CVSroot_directory;
- char *username = CVSroot_username;
char *password = NULL;
char *end = NULL;
-
+
if (verify_only)
{
begin = "BEGIN VERIFICATION REQUEST\012";
@@ -3834,7 +3930,8 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
/* Get the password, probably from ~/.cvspass. */
password = get_cvs_password ();
-
+ username = current_parsed_root->username ? current_parsed_root->username : getcaller();
+
/* Send the empty string by default. This is so anonymous CVS
access doesn't require client to have done "cvs login". */
if (password == NULL)
@@ -3848,7 +3945,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
/* Send the data the server needs. */
- if (send (sock, repository, strlen (repository), 0) < 0)
+ if (send (sock, current_parsed_root->directory, strlen (current_parsed_root->directory), 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
if (send (sock, "\012", 1, 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
@@ -3879,7 +3976,29 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
if (strcmp (read_buf, "I HATE YOU") == 0)
{
- /* Authorization not granted. */
+ /* Authorization not granted.
+ *
+ * This is a little confusing since we can reach this while loop in GSSAPI
+ * mode, but if GSSAPI authentication failed, we already jumped to the
+ * rejected label (there is no case where the connect_to_gserver function
+ * can return 1 and we will not receive "I LOVE YOU" from the server, barring
+ * broken connections and garbled messages, of course).
+ *
+ * i.e. This is a pserver specific error message and shoiuld be since
+ * GSSAPI doesn't use username.
+ */
+ error (0, 0,
+ "authorization failed: server %s rejected access to %s for user %s",
+ current_parsed_root->hostname, current_parsed_root->directory, username);
+
+ /* Output a special error message if authentication was attempted
+ with no password -- the user should be made aware that they may
+ have missed a step. */
+ if (no_passwd)
+ {
+ error (0, 0,
+ "used empty password; try \"cvs login\" with a real password");
+ }
goto rejected;
}
else if (strncmp (read_buf, "E ", 2) == 0)
@@ -3917,15 +4036,15 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
{
error (0, 0,
"unrecognized auth response from %s: %s",
- CVSroot_hostname, read_buf);
+ current_parsed_root->hostname, read_buf);
error (1, 0,
"shutdown() failed, server %s: %s",
- CVSroot_hostname,
+ current_parsed_root->hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
error (1, 0,
"unrecognized auth response from %s: %s",
- CVSroot_hostname, read_buf);
+ current_parsed_root->hostname, read_buf);
}
free (read_buf);
}
@@ -3934,7 +4053,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
if (verify_only)
{
if (shutdown (sock, 2) < 0)
- error (0, 0, "shutdown() failed, server %s: %s", CVSroot_hostname,
+ error (0, 0, "shutdown() failed, server %s: %s", current_parsed_root->hostname,
SOCK_STRERROR (SOCK_ERRNO));
return;
}
@@ -3959,24 +4078,11 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
return;
rejected:
- error (0, 0,
- "authorization failed: server %s rejected access to %s for user %s",
- CVSroot_hostname, CVSroot_directory, CVSroot_username);
-
- /* Output a special error message if authentication was attempted
- with no password -- the user should be made aware that they may
- have missed a step. */
- if (no_passwd)
- {
- error (0, 0,
- "used empty password; try \"cvs login\" with a real password");
- }
-
if (shutdown (sock, 2) < 0)
{
error (0, 0,
"shutdown() failed (server %s): %s",
- CVSroot_hostname,
+ current_parsed_root->hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
@@ -3984,8 +4090,9 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
}
#endif /* AUTH_CLIENT_SUPPORT */
-
-#if HAVE_KERBEROS
+
+
+#ifdef HAVE_KERBEROS
/* This function has not been changed to deal with NO_SOCKET_TO_FD
(i.e., systems on which sockets cannot be converted to file
@@ -4007,42 +4114,26 @@ start_tcp_server (tofdp, fromfdp)
if (s < 0)
error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
- /* Get CVS_CLIENT_PORT or look up cvs/tcp with CVS_PORT as default */
- portenv = getenv ("CVS_CLIENT_PORT");
- if (portenv != NULL)
- {
- port = atoi (portenv);
- if (port <= 0)
- {
- error (0, 0, "CVS_CLIENT_PORT must be a positive number! If you");
- error (0, 0, "are trying to force a connection via ssh, please");
- error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
- error (1, 0, "variable.");
- }
- if (trace)
- fprintf(stderr, "Using TCP port %d to contact server.\n", port);
- }
- else
- {
- struct servent *sp;
-
- sp = getservbyname ("cvs", "tcp");
- if (sp == NULL)
- port = CVS_PORT;
- else
- port = ntohs (sp->s_port);
- }
+ port = get_cvs_port_number (current_parsed_root);
- hp = init_sockaddr (&sin, CVSroot_hostname, port);
+ hp = init_sockaddr (&sin, current_parsed_root->hostname, port);
hname = xmalloc (strlen (hp->h_name) + 1);
strcpy (hname, hp->h_name);
+ if (trace)
+ {
+ fprintf (stderr, " -> Connecting to %s(%s):%d\n",
+ current_parsed_root->hostname,
+ inet_ntoa (client_sai.sin_addr), port);
+ }
+
if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
- error (1, 0, "connect to %s:%d failed: %s", CVSroot_hostname,
+ error (1, 0, "connect to %s(%s):%d failed: %s",
+ current_parsed_root->hostname,
+ inet_ntoa (client_sai.sin_addr),
port, SOCK_STRERROR (SOCK_ERRNO));
-#ifdef HAVE_KERBEROS
{
const char *realm;
struct sockaddr_in laddr;
@@ -4067,7 +4158,6 @@ start_tcp_server (tofdp, fromfdp)
krb_get_err_text (status));
memcpy (kblock, cred.session, sizeof (C_Block));
}
-#endif /* HAVE_KERBEROS */
server_fd = s;
close_on_exec (server_fd);
@@ -4096,9 +4186,10 @@ recv_bytes (sock, buf, need)
int got;
got = recv (sock, buf, need, 0);
- if (got < 0)
- error (1, 0, "recv() from server %s: %s", CVSroot_hostname,
- SOCK_STRERROR (SOCK_ERRNO));
+ if (got <= 0)
+ error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
+ got == 0 ? "EOF" : SOCK_STRERROR (SOCK_ERRNO));
+
buf += got;
need -= got;
}
@@ -4191,11 +4282,11 @@ connect_to_gserver (sock, hostinfo)
got = recv (sock, buf + 2, sizeof buf - 2, 0);
if (got < 0)
error (1, 0, "recv() from server %s: %s",
- CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
+ current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO));
buf[got + 2] = '\0';
if (buf[got + 1] == '\n')
buf[got + 1] = '\0';
- error (1, 0, "error from server %s: %s", CVSroot_hostname,
+ error (1, 0, "error from server %s: %s", current_parsed_root->hostname,
buf);
}
@@ -4247,7 +4338,7 @@ start_server ()
(*really* slow on a 14.4kbps link); the clean way to have a CVS
which supports several ways of connecting is with access methods. */
- switch (CVSroot_method)
+ switch (current_parsed_root->method)
{
#ifdef AUTH_CLIENT_SUPPORT
@@ -4264,7 +4355,7 @@ start_server ()
break;
#endif
-#if HAVE_GSSAPI
+#ifdef HAVE_GSSAPI
case gserver_method:
/* GSSAPI authentication is handled by the pserver. */
connect_to_pserver (&tofd, &fromfd, 0, 1);
@@ -4283,8 +4374,8 @@ start_server ()
case server_method:
#if defined(START_SERVER)
START_SERVER (&tofd, &fromfd, getcaller (),
- CVSroot_username, CVSroot_hostname,
- CVSroot_directory);
+ current_parsed_root->username, current_parsed_root->hostname,
+ current_parsed_root->directory);
# if defined (START_SERVER_RETURNS_SOCKET) && defined (NO_SOCKET_TO_FD)
/* This is a system on which we can only write to a socket
using send/recv. Therefore its START_SERVER needs to
@@ -4415,7 +4506,7 @@ the :server: access method is not supported by this port of CVS");
if (!rootless)
{
send_to_server ("Root ", 0);
- send_to_server (CVSroot_directory, 0);
+ send_to_server (current_parsed_root->directory, 0);
send_to_server ("\012", 1);
}
@@ -4545,7 +4636,7 @@ the :server: access method is not supported by this port of CVS");
on encryption, bomb out; don't let the user think the data
is being encrypted when it is not. */
#ifdef HAVE_KERBEROS
- if (CVSroot_method == kserver_method)
+ if (current_parsed_root->method == kserver_method)
{
if (! supported_request ("Kerberos-encrypt"))
error (1, 0, "This server does not support encryption");
@@ -4560,7 +4651,7 @@ the :server: access method is not supported by this port of CVS");
else
#endif /* HAVE_KERBEROS */
#ifdef HAVE_GSSAPI
- if (CVSroot_method == gserver_method)
+ if (current_parsed_root->method == gserver_method)
{
if (! supported_request ("Gssapi-encrypt"))
error (1, 0, "This server does not support encryption");
@@ -4633,7 +4724,7 @@ the :server: access method is not supported by this port of CVS");
ability to decrypt the data stream is itself a form of
authentication. */
#ifdef HAVE_GSSAPI
- if (CVSroot_method == gserver_method)
+ if (current_parsed_root->method == gserver_method)
{
if (! supported_request ("Gssapi-authenticate"))
error (1, 0,
@@ -4740,13 +4831,13 @@ start_rsh_server (tofdp, fromfdp)
#endif /* RSH_NEEDS_BINARY_FLAG */
/* Then we strcat more things on the end one by one. */
- if (CVSroot_username != NULL)
+ if (current_parsed_root->username != NULL)
{
rsh_argv[i++] = "-l";
- rsh_argv[i++] = CVSroot_username;
+ rsh_argv[i++] = current_parsed_root->username;
}
- rsh_argv[i++] = CVSroot_hostname;
+ rsh_argv[i++] = current_parsed_root->hostname;
rsh_argv[i++] = cvs_server;
rsh_argv[i++] = "server";
@@ -4756,6 +4847,8 @@ start_rsh_server (tofdp, fromfdp)
if (trace)
{
fprintf (stderr, " -> Starting server: ");
+ for (i = 0; rsh_argv[i]; i++)
+ fprintf (stderr, "%s ", rsh_argv[i]);
putc ('\n', stderr);
}
@@ -4793,7 +4886,7 @@ start_rsh_server (tofdp, fromfdp)
versions of rsh that grab switches out of the middle of the
command (they're calling the GNU getopt routines incorrectly). */
command = xmalloc (strlen (cvs_server)
- + strlen (CVSroot_directory)
+ + strlen (current_parsed_root->directory)
+ 50);
/* If you are running a very old (Nov 3, 1994, before 1.5)
@@ -4807,15 +4900,15 @@ start_rsh_server (tofdp, fromfdp)
char **p = argv;
*p++ = cvs_rsh;
- *p++ = CVSroot_hostname;
+ *p++ = current_parsed_root->hostname;
/* If the login names differ between client and server
* pass it on to rsh.
*/
- if (CVSroot_username != NULL)
+ if (current_parsed_root->username != NULL)
{
*p++ = "-l";
- *p++ = CVSroot_username;
+ *p++ = current_parsed_root->username;
}
*p++ = command;
@@ -5542,7 +5635,7 @@ send_files (argc, argv, local, aflag, flags)
* latter case; I don't think toplevel_repos matters for the
* former.
*/
- toplevel_repos = xstrdup (CVSroot_directory);
+ toplevel_repos = xstrdup (current_parsed_root->directory);
send_repository ("", toplevel_repos, ".");
}
@@ -5661,7 +5754,7 @@ client_import_done ()
*/
/* FIXME: "can't happen" now that we call client_import_setup
at the beginning. */
- toplevel_repos = xstrdup (CVSroot_directory);
+ toplevel_repos = xstrdup (current_parsed_root->directory);
send_repository ("", toplevel_repos, ".");
}
@@ -5841,9 +5934,9 @@ client_senddate (date)
void
send_init_command ()
{
- /* This is here because we need the CVSroot_directory variable. */
+ /* This is here because we need the current_parsed_root->directory variable. */
send_to_server ("init ", 0);
- send_to_server (CVSroot_directory, 0);
+ send_to_server (current_parsed_root->directory, 0);
send_to_server ("\012", 0);
}
diff --git a/gnu/usr.bin/cvs/src/commit.c b/gnu/usr.bin/cvs/src/commit.c
index 1c1f71c48a3..149da7cb74d 100644
--- a/gnu/usr.bin/cvs/src/commit.c
+++ b/gnu/usr.bin/cvs/src/commit.c
@@ -85,13 +85,13 @@ static time_t last_register_time;
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",
- "\t-R\tProcess directories recursively.\n",
- "\t-l\tLocal directory only (not recursive).\n",
- "\t-f\tForce the file to be committed; disables recursion.\n",
- "\t-F file\tRead the log message from file.\n",
- "\t-m msg\tLog message.\n",
- "\t-r rev\tCommit to this branch or trunk revision.\n",
+ " -n Do not run the module program (if any).\n",
+ " -R Process directories recursively.\n",
+ " -l Local directory only (not recursive).\n",
+ " -f Force the file to be committed; disables recursion.\n",
+ " -F logfile Read the log message from file.\n",
+ " -m msg Log message.\n",
+ " -r rev Commit to this branch or trunk revision.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
@@ -344,7 +344,7 @@ commit (argc, argv)
if (geteuid () == (uid_t) 0
# ifdef CLIENT_SUPPORT
/* Who we are on the client side doesn't affect logging. */
- && !client_active
+ && !current_parsed_root->isremote
# endif
)
{
@@ -432,7 +432,7 @@ commit (argc, argv)
}
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
struct find_data find_args;
@@ -591,8 +591,7 @@ commit (argc, argv)
char *fname;
FILE *fp;
- fname = cvs_temp_name ();
- fp = CVS_FOPEN (fname, "w+");
+ fp = cvs_temp_file (&fname);
if (fp == NULL)
error (1, 0, "cannot create temporary file %s", fname);
if (fwrite (saved_message, 1, strlen (saved_message), fp)
@@ -601,6 +600,7 @@ commit (argc, argv)
if (fclose (fp) < 0)
error (0, errno, "cannot close temporary file %s", fname);
error (0, 0, "saving log message in %s", fname);
+ free (fname);
}
return err;
}
@@ -615,7 +615,7 @@ commit (argc, argv)
wrap_setup ();
- lock_tree_for_write (argc, argv, local, aflag);
+ lock_tree_for_write (argc, argv, local, W_LOCAL, aflag);
/*
* Set up the master update list and hard link list
@@ -663,11 +663,15 @@ commit (argc, argv)
Lock_Cleanup ();
dellist (&mulist);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ return err;
+#endif
+
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- while (time ((time_t *) NULL) == last_register_time)
- sleep (1);
+ sleep_past (last_register_time);
}
return (err);
@@ -778,7 +782,7 @@ check_fileproc (callerdat, finfo)
struct commit_info *ci;
struct logfile_info *li;
- size_t cvsroot_len = strlen (CVSroot_directory);
+ size_t cvsroot_len = strlen (current_parsed_root->directory);
if (!finfo->repository)
{
@@ -786,7 +790,7 @@ check_fileproc (callerdat, finfo)
return (1);
}
- if (strncmp (finfo->repository, CVSroot_directory, cvsroot_len) == 0
+ if (strncmp (finfo->repository, current_parsed_root->directory, cvsroot_len) == 0
&& ISDIRSEP (finfo->repository[cvsroot_len])
&& strncmp (finfo->repository + cvsroot_len + 1,
CVSROOTADM,
@@ -810,9 +814,7 @@ check_fileproc (callerdat, finfo)
switch (status)
{
case T_CHECKOUT:
-#ifdef SERVER_SUPPORT
case T_PATCH:
-#endif
case T_NEEDS_MERGE:
case T_CONFLICT:
case T_REMOVE_ENTRY:
@@ -829,7 +831,7 @@ check_fileproc (callerdat, finfo)
* Also,
* - if status is T_REMOVED, can't have a numeric tag
* - if status is T_ADDED, rcs file must not exist unless on
- * a branch
+ * a branch or head is dead
* - if status is T_ADDED, can't have a non-trunk numeric rev
* - if status is T_MODIFIED and a Conflict marker exists, don't
* allow the commit if timestamp is identical or if we find
@@ -926,29 +928,17 @@ warning: file `%s' seems to still contain conflict indicators",
{
if (vers->tag == NULL)
{
- char *rcs;
-
- rcs = xmalloc (strlen (finfo->repository)
- + strlen (finfo->file)
- + sizeof RCSEXT
- + 5);
-
- /* Don't look in the attic; if it exists there we
- will move it back out in checkaddfile. */
- sprintf(rcs, "%s/%s%s", finfo->repository, finfo->file,
- RCSEXT);
- if (isreadable (rcs))
+ if (finfo->rcs != NULL &&
+ !RCS_isdead (finfo->rcs, finfo->rcs->head))
{
error (0, 0,
"cannot add file `%s' when RCS file `%s' already exists",
- finfo->fullname, rcs);
+ finfo->fullname, finfo->rcs->path);
freevers_ts (&vers);
- free (rcs);
return (1);
}
- free (rcs);
}
- if (vers->tag && isdigit ((unsigned char) *vers->tag) &&
+ else if (isdigit ((unsigned char) *vers->tag) &&
numdots (vers->tag) > 1)
{
error (0, 0,
@@ -1311,6 +1301,12 @@ commit_fileproc (callerdat, finfo)
/* find the max major rev number in this directory */
maxrev = 0;
(void) walklist (finfo->entries, findmaxrev, NULL);
+ if (finfo->rcs->head) {
+ /* resurrecting: include dead revision */
+ int thisrev = atoi (finfo->rcs->head);
+ if (thisrev > maxrev)
+ maxrev = thisrev;
+ }
if (maxrev == 0)
maxrev = 1;
xrev = xmalloc (20);
@@ -1430,12 +1426,12 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
{
char *p;
- if (strncmp (CVSroot_directory, repository,
- strlen (CVSroot_directory)) != 0)
+ if (strncmp (current_parsed_root->directory, repository,
+ strlen (current_parsed_root->directory)) != 0)
error (0, 0,
"internal error: repository (%s) doesn't begin with root (%s)",
- repository, CVSroot_directory);
- p = repository + strlen (CVSroot_directory);
+ repository, current_parsed_root->directory);
+ p = repository + strlen (current_parsed_root->directory);
if (*p == '/')
++p;
if (strcmp ("CVSROOT", p) == 0
@@ -1596,19 +1592,13 @@ findmaxrev (p, closure)
Node *p;
void *closure;
{
- char *cp;
int thisrev;
Entnode *entdata;
entdata = (Entnode *) p->data;
if (entdata->type != ENT_FILE)
return (0);
- cp = strchr (entdata->version, '.');
- if (cp != NULL)
- *cp = '\0';
thisrev = atoi (entdata->version);
- if (cp != NULL)
- *cp = '.';
if (thisrev > maxrev)
maxrev = thisrev;
return (0);
@@ -1956,10 +1946,8 @@ checkaddfile (file, repository, tag, options, rcsnode)
Attic. */
if (!(rcsfile->flags & INATTIC))
{
- error (0, 0, "internal error: confused about attic for %s",
+ error (0, 0, "warning: expected %s to be in Attic",
rcsfile->path);
- retval = 1;
- goto out;
}
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
diff --git a/gnu/usr.bin/cvs/src/cvs.h b/gnu/usr.bin/cvs/src/cvs.h
index 40892ceb3fb..961e02c5240 100644
--- a/gnu/usr.bin/cvs/src/cvs.h
+++ b/gnu/usr.bin/cvs/src/cvs.h
@@ -316,7 +316,7 @@ typedef struct entnode Entnode;
/* The type of request that is being done in do_module() */
enum mtype
{
- CHECKOUT, TAG, PATCH, EXPORT
+ CHECKOUT, TAG, PATCH, EXPORT, MISC
};
/*
@@ -369,28 +369,34 @@ extern char *RCS_citag;
/* Access method specified in CVSroot. */
typedef enum {
- local_method, server_method, pserver_method, kserver_method, gserver_method,
+ null_method, local_method, server_method, pserver_method, kserver_method, gserver_method,
ext_method, fork_method
} CVSmethod;
extern char *method_names[]; /* change this in root.c if you change
the enum above */
+typedef struct cvsroot_s {
+ char *original; /* the complete source CVSroot string */
+ CVSmethod method; /* one of the enum values above */
+ char *username; /* the username or NULL if method == local */
+ char *password; /* the username or NULL if method == local */
+ char *hostname; /* the hostname or NULL if method == local */
+ int port; /* the port or zero if method == local */
+ char *directory; /* the directory name */
+#ifdef CLIENT_SUPPORT
+ unsigned char isremote; /* nonzero if we are doing remote access */
+#endif /* CLIENT_SUPPORT */
+} cvsroot_t;
+
/* This global variable holds the global -d option. It is NULL if -d
was not used, which means that we must get the CVSroot information
from the CVSROOT environment variable or from a CVS/Root file. */
extern char *CVSroot_cmdline;
-extern char *CVSroot_original; /* the active, complete CVSroot string */
-extern int client_active; /* nonzero if we are doing remote access */
-extern CVSmethod CVSroot_method; /* one of the enum values above */
-extern char *CVSroot_username; /* the username or NULL if method == local */
-extern char *CVSroot_hostname; /* the hostname or NULL if method == local */
-extern char *CVSroot_directory; /* the directory name */
-
/* These variables keep track of all of the CVSROOT directories that
have been seen by the client and the current one of those selected. */
extern List *root_directories;
-extern char *current_root;
+extern cvsroot_t *current_parsed_root;
extern char *emptydir_name PROTO ((void));
extern int safe_location PROTO ((void));
@@ -426,8 +432,9 @@ extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile,
char *rev1, char *rev2,
char *label1, char *label2,
char *workfile));
-extern int diff_exec PROTO ((char *file1, char *file2, char *options,
- char *out));
+extern int diff_exec PROTO ((char *file1, char *file2,
+ char *label1, char *label2,
+ char *options, char *out));
extern int diff_execv PROTO ((char *file1, char *file2,
char *label1, char *label2,
char *options, char *out));
@@ -447,15 +454,18 @@ void Subdir_Deregister PROTO((List *, const char *, const char *));
char *Make_Date PROTO((char *rawdate));
char *date_from_time_t PROTO ((time_t));
-void date_to_internet PROTO ((char *, char *));
+void date_to_internet PROTO ((char *, const char *));
+void date_to_tm PROTO ((struct tm *, const char *));
+void tm_to_internet PROTO ((char *, const struct tm *));
char *Name_Repository PROTO((char *dir, char *update_dir));
char *Short_Repository PROTO((char *repository));
void Sanitize_Repository_Name PROTO((char *repository));
char *Name_Root PROTO((char *dir, char *update_dir));
-int parse_cvsroot PROTO((char *CVSroot));
-void set_local_cvsroot PROTO((char *dir));
+void free_cvsroot_t PROTO((cvsroot_t *root_in));
+cvsroot_t *parse_cvsroot PROTO((char *root));
+cvsroot_t *local_cvsroot PROTO((char *dir));
void Create_Root PROTO((char *dir, char *rootdir));
void root_allow_add PROTO ((char *));
void root_allow_free PROTO ((void));
@@ -469,6 +479,7 @@ char *time_stamp PROTO((char *file));
void *xmalloc PROTO((size_t bytes));
void *xrealloc PROTO((void *ptr, size_t bytes));
void expand_string PROTO ((char **, size_t *, size_t));
+void allocate_and_strcat PROTO ((char **, size_t *, const char *));
char *xstrdup PROTO((const char *str));
void strip_trailing_newlines PROTO((char *str));
int pathname_levels PROTO ((char *path));
@@ -491,6 +502,7 @@ char *xreadlink PROTO((const char *link));
char *last_component PROTO((char *path));
char *get_homedir PROTO ((void));
char *cvs_temp_name PROTO ((void));
+FILE *cvs_temp_file PROTO ((char **filename));
int numdots PROTO((const char *s));
char *increment_revnum PROTO ((const char *));
@@ -514,7 +526,8 @@ void Lock_Cleanup PROTO((void));
/* Writelock an entire subtree, well the part specified by ARGC, ARGV, LOCAL,
and AFLAG, anyway. */
-void lock_tree_for_write PROTO ((int argc, char **argv, int local, int aflag));
+void lock_tree_for_write PROTO ((int argc, char **argv, int local, int which,
+ int aflag));
/* See lock.c for description. */
extern void lock_dir_for_write PROTO ((char *));
@@ -551,7 +564,6 @@ void make_directories PROTO((const char *name));
void make_directory PROTO((const char *name));
extern int mkdir_if_needed PROTO ((char *name));
void rename_file PROTO((const char *from, const char *to));
-char *backup_file PROTO((const char *file, const char *suffix));
/* Expand wildcards in each element of (ARGC,ARGV). This is according to the
files which exist in the current directory, and accordingly to OS-specific
conventions regarding wildcard syntax. It might be desirable to change the
@@ -631,7 +643,8 @@ extern int init PROTO ((int argc, char **argv));
int do_module PROTO((DBM * db, char *mname, enum mtype m_type, char *msg,
CALLBACKPROC callback_proc, char *where, int shorten,
- int local_specified, int run_module_prog, char *extra_arg));
+ int local_specified, int run_module_prog, int build_dirs,
+ char *extra_arg));
void history_write PROTO((int type, char *update_dir, char *revs, char *name,
char *repository));
int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
@@ -649,7 +662,10 @@ char *make_message_rcslegal PROTO((char *message));
extern int file_has_markers PROTO ((const struct file_info *));
extern void get_file PROTO ((const char *, const char *, const char *,
char **, size_t *, size_t *));
+extern char *shell_escape PROTO((char *buf, const char *str));
+char *backup_file PROTO((const char *file, const char *suffix));
extern void resolve_symlink PROTO ((char **filename));
+void sleep_past PROTO ((time_t desttime));
/* flags for run_exec(), the fast system() for CVS */
#define RUN_NORMAL 0x0000 /* no special behaviour */
@@ -779,9 +795,7 @@ 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;
@@ -871,6 +885,8 @@ char *descramble PROTO ((char *str));
#ifdef AUTH_CLIENT_SUPPORT
char *get_cvs_password PROTO((void));
+int get_cvs_port_number PROTO((const cvsroot_t *root));
+char *normalize_cvsroot PROTO((const cvsroot_t *root));
#endif /* AUTH_CLIENT_SUPPORT */
extern void tag_check_valid PROTO ((char *, int, char **, int, int, char *));
diff --git a/gnu/usr.bin/cvs/src/cvsbug.sh b/gnu/usr.bin/cvs/src/cvsbug.sh
deleted file mode 100644
index ee3b7bb5cd8..00000000000
--- a/gnu/usr.bin/cvs/src/cvsbug.sh
+++ /dev/null
@@ -1,526 +0,0 @@
-#! /bin/sh
-# Submit a problem report to a GNATS site.
-# Copyright (C) 1993 Free Software Foundation, Inc.
-# Contributed by Brendan Kehoe (brendan@cygnus.com), based on a
-# version written by Heinz G. Seidl (hgs@ide.com).
-#
-# This file is part of GNU GNATS.
-# Modified by Berliner for CVS.
-#
-# GNU GNATS is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU GNATS 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.
-
-# The version of this send-pr.
-VERSION=3.2
-
-# The submitter-id for your site.
-SUBMITTER=net
-
-## # Where the GNATS directory lives, if at all.
-## [ -z "$GNATS_ROOT" ] &&
-## GNATS_ROOT=/usr/local/lib/gnats/gnats-db
-
-# The default mail address for PR submissions.
-GNATS_ADDR=bug-cvs@gnu.org
-
-## # Where the gnats category tree lives.
-## DATADIR=/usr/local/lib
-
-## # If we've been moved around, try using GCC_EXEC_PREFIX.
-## [ ! -d $DATADIR/gnats -a -d "$GCC_EXEC_PREFIX" ] && DATADIR=${GCC_EXEC_PREFIX}..
-
-# The default release for this host.
-DEFAULT_RELEASE="xVERSIONx"
-
-# The default organization.
-DEFAULT_ORGANIZATION="net"
-
-## # The default site to look for.
-## GNATS_SITE=unknown
-
-## # Newer config information?
-## [ -f ${GNATS_ROOT}/gnats-adm/config ] && . ${GNATS_ROOT}/gnats-adm/config
-
-# What mailer to use. This must come after the config file, since it is
-# host-dependent.
-if [ -f /usr/sbin/sendmail ]; then
- MAIL_AGENT="/usr/sbin/sendmail -oi -t"
-else
- MAIL_AGENT="/usr/lib/sendmail -oi -t"
-fi
-MAILER=`echo $MAIL_AGENT | sed -e 's, .*,,'`
-if [ ! -f "$MAILER" ] ; then
- echo "$COMMAND: Cannot file mail program \"$MAILER\"."
- echo "$COMMAND: Please fix the MAIL_AGENT entry in the $COMMAND file."
- exit 1
-fi
-
-if test "`echo -n foo`" = foo ; then
- ECHON=bsd
-elif test "`echo 'foo\c'`" = foo ; then
- ECHON=sysv
-else
- ECHON=none
-fi
-
-if [ $ECHON = bsd ] ; then
- ECHON1="echo -n"
- ECHON2=
-elif [ $ECHON = sysv ] ; then
- ECHON1=echo
- ECHON2='\c'
-else
- ECHON1=echo
- ECHON2=
-fi
-
-#
-
-[ -z "$TMPDIR" ] && TMPDIR=/tmp
-
-TEMP=$TMPDIR/p$$
-BAD=$TMPDIR/pbad$$
-REF=$TMPDIR/pf$$
-
-if [ -z "$LOGNAME" -a -n "$USER" ]; then
- LOGNAME=$USER
-fi
-
-FROM="$LOGNAME"
-REPLY_TO="$LOGNAME"
-
-# Find out the name of the originator of this PR.
-if [ -n "$NAME" ]; then
- ORIGINATOR="$NAME"
-elif [ -f $HOME/.fullname ]; then
- ORIGINATOR="`sed -e '1q' $HOME/.fullname`"
-elif [ -f /bin/domainname ]; then
- if [ "`/bin/domainname`" != "" -a -f /usr/bin/ypcat ]; then
- # Must use temp file due to incompatibilities in quoting behavior
- # and to protect shell metacharacters in the expansion of $LOGNAME
- /usr/bin/ypcat passwd 2>/dev/null | cat - /etc/passwd | grep "^$LOGNAME:" |
- cut -f5 -d':' | sed -e 's/,.*//' > $TEMP
- ORIGINATOR="`cat $TEMP`"
- rm -f $TEMP
- fi
-fi
-
-if [ "$ORIGINATOR" = "" ]; then
- grep "^$LOGNAME:" /etc/passwd | cut -f5 -d':' | sed -e 's/,.*//' > $TEMP
- ORIGINATOR="`cat $TEMP`"
- rm -f $TEMP
-fi
-
-if [ -n "$ORGANIZATION" ]; then
- if [ -f "$ORGANIZATION" ]; then
- ORGANIZATION="`cat $ORGANIZATION`"
- fi
-else
- if [ -n "$DEFAULT_ORGANIZATION" ]; then
- ORGANIZATION="$DEFAULT_ORGANIZATION"
- elif [ -f $HOME/.organization ]; then
- ORGANIZATION="`cat $HOME/.organization`"
- elif [ -f $HOME/.signature ]; then
- ORGANIZATION="`cat $HOME/.signature`"
- fi
-fi
-
-# If they don't have a preferred editor set, then use
-if [ -z "$VISUAL" ]; then
- if [ -z "$EDITOR" ]; then
- EDIT=vi
- else
- EDIT="$EDITOR"
- fi
-else
- EDIT="$VISUAL"
-fi
-
-# Find out some information.
-SYSTEM=`( [ -f /bin/uname ] && /bin/uname -a ) || \
- ( [ -f /usr/bin/uname ] && /usr/bin/uname -a ) || echo ""`
-ARCH=`[ -f /bin/arch ] && /bin/arch`
-MACHINE=`[ -f /bin/machine ] && /bin/machine`
-
-COMMAND=`echo $0 | sed -e 's,.*/,,'`
-## USAGE="Usage: $COMMAND [-PVL] [-t address] [-f filename] [--request-id]
-USAGE="Usage: $COMMAND [-PVL]
-[--version]"
-REMOVE=
-BATCH=
-
-while [ $# -gt 0 ]; do
- case "$1" in
- -r) ;; # Ignore for backward compat.
-## -t | --to) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
-## shift ; GNATS_ADDR="$1"
-## EXPLICIT_GNATS_ADDR=true
-## ;;
-## -f | --file) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
-## shift ; IN_FILE="$1"
-## if [ "$IN_FILE" != "-" -a ! -r "$IN_FILE" ]; then
-## echo "$COMMAND: cannot read $IN_FILE"
-## exit 1
-## fi
-## ;;
- -b | --batch) BATCH=true ;;
- -p | -P | --print) PRINT=true ;;
- -L | --list) FORMAT=norm ;;
- -l | -CL | --lisp) FORMAT=lisp ;;
-## --request-id) REQUEST_ID=true ;;
- -h | --help) echo "$USAGE"; exit 0 ;;
- -V | --version) echo "$VERSION"; exit 0 ;;
- -*) echo "$USAGE" ; exit 1 ;;
- *) echo "$USAGE" ; exit 1
-## if [ -z "$USER_GNATS_SITE" ]; then
-## if [ ! -r "$DATADIR/gnats/$1" ]; then
-## echo "$COMMAND: the GNATS site $1 does not have a categories list."
-## exit 1
-## else
-## # The site name is the alias they'll have to have created.
-## USER_GNATS_SITE=$1
-## fi
-## else
-## echo "$USAGE" ; exit 1
-## fi
- ;;
- esac
- shift
-done
-
-if [ -n "$USER_GNATS_SITE" ]; then
- GNATS_SITE=$USER_GNATS_SITE
- GNATS_ADDR=$USER_GNATS_SITE-gnats
-fi
-
-if [ "$SUBMITTER" = "unknown" -a -z "$REQUEST_ID" -a -z "$IN_FILE" ]; then
- cat << '__EOF__'
-It seems that send-pr is not installed with your unique submitter-id.
-You need to run
-
- install-sid YOUR-SID
-
-where YOUR-SID is the identification code you received with `send-pr'.
-`send-pr' will automatically insert this value into the template field
-`>Submitter-Id'. If you've downloaded `send-pr' from the Net, use `net'
-for this value. If you do not know your id, run `send-pr --request-id' to
-get one from your support site.
-__EOF__
- exit 1
-fi
-
-## if [ -r "$DATADIR/gnats/$GNATS_SITE" ]; then
-## CATEGORIES=`grep -v '^#' $DATADIR/gnats/$GNATS_SITE | sort`
-## else
-## echo "$COMMAND: could not read $DATADIR/gnats/$GNATS_SITE for categories list."
-## exit 1
-## fi
-CATEGORIES="contrib cvs doc pcl-cvs portability"
-
-if [ -z "$CATEGORIES" ]; then
- echo "$COMMAND: the categories list for $GNATS_SITE was empty!"
- exit 1
-fi
-
-case "$FORMAT" in
- lisp) echo "$CATEGORIES" | \
- awk 'BEGIN {printf "( "}
- {printf "(\"%s\") ",$0}
- END {printf ")\n"}'
- exit 0
- ;;
- norm) l=`echo "$CATEGORIES" | \
- awk 'BEGIN {max = 0; }
- { if (length($0) > max) { max = length($0); } }
- END {print max + 1;}'`
- c=`expr 70 / $l`
- if [ $c -eq 0 ]; then c=1; fi
- echo "$CATEGORIES" | \
- awk 'BEGIN {print "Known categories:"; i = 0 }
- { printf ("%-'$l'.'$l's", $0); if ((++i % '$c') == 0) { print "" } }
- END { print ""; }'
- exit 0
- ;;
-esac
-
-ORIGINATOR_C='<name of the PR author (one line)>'
-ORGANIZATION_C='<organization of PR author (multiple lines)>'
-CONFIDENTIAL_C='<[ yes | no ] (one line)>'
-SYNOPSIS_C='<synopsis of the problem (one line)>'
-SEVERITY_C='<[ non-critical | serious | critical ] (one line)>'
-PRIORITY_C='<[ low | medium | high ] (one line)>'
-CATEGORY_C='<name of the product (one line)>'
-CLASS_C='<[ sw-bug | doc-bug | change-request | support ] (one line)>'
-RELEASE_C='<release number or tag (one line)>'
-ENVIRONMENT_C='<machine, os, target, libraries (multiple lines)>'
-DESCRIPTION_C='<precise description of the problem (multiple lines)>'
-HOW_TO_REPEAT_C='<code/input/activities to reproduce the problem (multiple lines)>'
-FIX_C='<how to correct or work around the problem, if known (multiple lines)>'
-
-# Catch some signals. ($xs kludge needed by Sun /bin/sh)
-xs=0
-trap 'rm -f $REF $TEMP; exit $xs' 0
-trap 'echo "$COMMAND: Aborting ..."; rm -f $REF $TEMP; xs=1; exit' 1 2 3 13 15
-
-# If they told us to use a specific file, then do so.
-if [ -n "$IN_FILE" ]; then
- if [ "$IN_FILE" = "-" ]; then
- # The PR is coming from the standard input.
- if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
- sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" > $TEMP
- else
- cat > $TEMP
- fi
- else
- # Use the file they named.
- if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
- sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" $IN_FILE > $TEMP
- else
- cat $IN_FILE > $TEMP
- fi
- fi
-else
-
- if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
- # If their PR_FORM points to a bogus entry, then bail.
- if [ ! -f "$PR_FORM" -o ! -r "$PR_FORM" -o ! -s "$PR_FORM" ]; then
- echo "$COMMAND: can't seem to read your template file (\`$PR_FORM'), ignoring PR_FORM"
- sleep 1
- PRINT_INTERN=bad_prform
- fi
- fi
-
- if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
- cp $PR_FORM $TEMP ||
- ( echo "$COMMAND: could not copy $PR_FORM" ; xs=1; exit )
- else
- for file in $TEMP $REF ; do
- cat > $file << '__EOF__'
-SEND-PR: -*- send-pr -*-
-SEND-PR: Lines starting with `SEND-PR' will be removed automatically, as
-SEND-PR: will all comments (text enclosed in `<' and `>').
-SEND-PR:
-SEND-PR: Choose from the following categories:
-SEND-PR:
-__EOF__
-
- # Format the categories so they fit onto lines.
- l=`echo "$CATEGORIES" | \
- awk 'BEGIN {max = 0; }
- { if (length($0) > max) { max = length($0); } }
- END {print max + 1;}'`
- c=`expr 61 / $l`
- if [ $c -eq 0 ]; then c=1; fi
- echo "$CATEGORIES" | \
- awk 'BEGIN {printf "SEND-PR: "; i = 0 }
- { printf ("%-'$l'.'$l's", $0);
- if ((++i % '$c') == 0) { printf "\nSEND-PR: " } }
- END { printf "\nSEND-PR:\n"; }' >> $file
-
- cat >> $file << __EOF__
-To: $GNATS_ADDR
-Subject:
-From: $FROM
-Reply-To: $REPLY_TO
-X-send-pr-version: $VERSION
-
-
->Submitter-Id: $SUBMITTER
->Originator: $ORIGINATOR
->Organization:
-${ORGANIZATION-$ORGANIZATION_C}
->Confidential: $CONFIDENTIAL_C
->Synopsis: $SYNOPSIS_C
->Severity: $SEVERITY_C
->Priority: $PRIORITY_C
->Category: $CATEGORY_C
->Class: $CLASS_C
->Release: ${DEFAULT_RELEASE-$RELEASE_C}
->Environment:
- $ENVIRONMENT_C
-`[ -n "$SYSTEM" ] && echo System: $SYSTEM`
-`[ -n "$ARCH" ] && echo Architecture: $ARCH`
-`[ -n "$MACHINE" ] && echo Machine: $MACHINE`
->Description:
- $DESCRIPTION_C
->How-To-Repeat:
- $HOW_TO_REPEAT_C
->Fix:
- $FIX_C
-__EOF__
- done
- fi
-
- if [ "$PRINT" = true -o "$PRINT_INTERN" = true ]; then
- cat $TEMP
- xs=0; exit
- fi
-
- chmod u+w $TEMP
- if [ -z "$REQUEST_ID" ]; then
- eval $EDIT $TEMP
- else
- ed -s $TEMP << '__EOF__'
-/^Subject/s/^Subject:.*/Subject: request for a customer id/
-/^>Category/s/^>Category:.*/>Category: send-pr/
-w
-q
-__EOF__
- fi
-
- if cmp -s $REF $TEMP ; then
- echo "$COMMAND: problem report not filled out, therefore not sent"
- xs=1; exit
- fi
-fi
-
-#
-# Check the enumeration fields
-
-# This is a "sed-subroutine" with one keyword parameter
-# (with workaround for Sun sed bug)
-#
-SED_CMD='
-/$PATTERN/{
-s|||
-s|<.*>||
-s|^[ ]*||
-s|[ ]*$||
-p
-q
-}'
-
-
-while [ -z "$REQUEST_ID" ]; do
- CNT=0
-
- # 1) Confidential
- #
- PATTERN=">Confidential:"
- CONFIDENTIAL=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$CONFIDENTIAL" in
- ""|yes|no) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$CONFIDENTIAL' is not a valid value for \`Confidential'." ;;
- esac
- #
- # 2) Severity
- #
- PATTERN=">Severity:"
- SEVERITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$SEVERITY" in
- ""|non-critical|serious|critical) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$SEVERITY' is not a valid value for \`Severity'."
- esac
- #
- # 3) Priority
- #
- PATTERN=">Priority:"
- PRIORITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$PRIORITY" in
- ""|low|medium|high) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$PRIORITY' is not a valid value for \`Priority'."
- esac
- #
- # 4) Category
- #
- PATTERN=">Category:"
- CATEGORY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- FOUND=
- for C in $CATEGORIES
- do
- if [ "$C" = "$CATEGORY" ]; then FOUND=true ; break ; fi
- done
- if [ -n "$FOUND" ]; then
- CNT=`expr $CNT + 1`
- else
- if [ -z "$CATEGORY" ]; then
- echo "$COMMAND: you must include a Category: field in your report."
- else
- echo "$COMMAND: \`$CATEGORY' is not a known category."
- fi
- fi
- #
- # 5) Class
- #
- PATTERN=">Class:"
- CLASS=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$CLASS" in
- ""|sw-bug|doc-bug|change-request|support) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$CLASS' is not a valid value for \`Class'."
- esac
-
- [ $CNT -lt 5 -a -z "$BATCH" ] &&
- echo "Errors were found with the problem report."
-
- while true; do
- if [ -z "$BATCH" ]; then
- $ECHON1 "a)bort, e)dit or s)end? $ECHON2"
- read input
- else
- if [ $CNT -eq 5 ]; then
- input=s
- else
- input=a
- fi
- fi
- case "$input" in
- a*)
- if [ -z "$BATCH" ]; then
- echo "$COMMAND: the problem report remains in $BAD and is not sent."
- mv $TEMP $BAD
- else
- echo "$COMMAND: the problem report is not sent."
- fi
- xs=1; exit
- ;;
- e*)
- eval $EDIT $TEMP
- continue 2
- ;;
- s*)
- break 2
- ;;
- esac
- done
-done
-#
-# Remove comments and send the problem report
-# (we have to use patterns, where the comment contains regex chars)
-#
-# /^>Originator:/s;$ORIGINATOR;;
-sed -e "
-/^SEND-PR:/d
-/^>Organization:/,/^>[A-Za-z-]*:/s;$ORGANIZATION_C;;
-/^>Confidential:/s;<.*>;;
-/^>Synopsis:/s;$SYNOPSIS_C;;
-/^>Severity:/s;<.*>;;
-/^>Priority:/s;<.*>;;
-/^>Category:/s;$CATEGORY_C;;
-/^>Class:/s;<.*>;;
-/^>Release:/,/^>[A-Za-z-]*:/s;$RELEASE_C;;
-/^>Environment:/,/^>[A-Za-z-]*:/s;$ENVIRONMENT_C;;
-/^>Description:/,/^>[A-Za-z-]*:/s;$DESCRIPTION_C;;
-/^>How-To-Repeat:/,/^>[A-Za-z-]*:/s;$HOW_TO_REPEAT_C;;
-/^>Fix:/,/^>[A-Za-z-]*:/s;$FIX_C;;
-" $TEMP > $REF
-
-if $MAIL_AGENT < $REF; then
- echo "$COMMAND: problem report sent"
- xs=0; exit
-else
- echo "$COMMAND: mysterious mail failure."
- if [ -z "$BATCH" ]; then
- echo "$COMMAND: the problem report remains in $BAD and is not sent."
- mv $REF $BAD
- else
- echo "$COMMAND: the problem report is not sent."
- fi
- xs=1; exit
-fi
diff --git a/gnu/usr.bin/cvs/src/ignore.c b/gnu/usr.bin/cvs/src/ignore.c
index ebcdf853754..b04d10e932b 100644
--- a/gnu/usr.bin/cvs/src/ignore.c
+++ b/gnu/usr.bin/cvs/src/ignore.c
@@ -68,13 +68,13 @@ ign_setup ()
processing, and only if !ign_inhibit_server), letting the server
know about the files and letting it decide whether to ignore
them based on CVSROOOTADM_IGNORE. */
- if (!client_active)
+ if (!current_parsed_root->isremote)
#endif
{
- char *file = xmalloc (strlen (CVSroot_directory) + sizeof (CVSROOTADM)
+ char *file = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
+ sizeof (CVSROOTADM_IGNORE) + 10);
/* Then add entries found in repository, if it exists */
- (void) sprintf (file, "%s/%s/%s", CVSroot_directory,
+ (void) sprintf (file, "%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSROOTADM_IGNORE);
ign_add_file (file, 0);
free (file);
@@ -379,6 +379,8 @@ ignore_files (ilist, entries, update_dir, proc)
struct stat sb;
char *file;
char *xdir;
+ List *files;
+ Node *p;
/* Set SUBDIRS if we have subdirectory information in ENTRIES. */
if (entries == NULL)
@@ -407,14 +409,16 @@ ignore_files (ilist, entries, update_dir, proc)
ign_add_file (CVSDOTIGNORE, 1);
wrap_add_file (CVSDOTWRAPPER, 1);
- errno = 0;
- while ((dp = readdir (dirp)) != NULL)
+ /* Make a list for the files. */
+ files = getlist ();
+
+ while (errno = 0, (dp = CVS_READDIR (dirp)) != NULL)
{
file = dp->d_name;
if (strcmp (file, ".") == 0 || strcmp (file, "..") == 0)
- goto continue_loop;
+ continue;
if (findnode_fn (ilist, file) != NULL)
- goto continue_loop;
+ continue;
if (subdirs)
{
Node *node;
@@ -435,14 +439,14 @@ ignore_files (ilist, entries, update_dir, proc)
dir = isdir (p);
free (p);
if (dir)
- goto continue_loop;
+ continue;
}
}
/* We could be ignoring FIFOs and other files which are neither
regular files nor directories here. */
if (ign_name (file))
- goto continue_loop;
+ continue;
if (
#ifdef DT_DIR
@@ -469,7 +473,7 @@ ignore_files (ilist, entries, update_dir, proc)
if (isdir (temp))
{
free (temp);
- goto continue_loop;
+ continue;
}
free (temp);
}
@@ -484,16 +488,22 @@ ignore_files (ilist, entries, update_dir, proc)
#endif
)
{
- goto continue_loop;
+ continue;
}
#endif
- }
+ }
- (*proc) (file, xdir);
- continue_loop:
- errno = 0;
+ p = getnode ();
+ p->type = FILES;
+ p->key = xstrdup (file);
+ (void) addnode (files, p);
}
if (errno != 0)
error (0, errno, "error reading current directory");
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
+
+ sortlist (files, fsortcmp);
+ for (p = files->list->next; p != files->list; p = p->next)
+ (*proc) (p->key, xdir);
+ dellist (&files);
}
diff --git a/gnu/usr.bin/cvs/src/import.c b/gnu/usr.bin/cvs/src/import.c
index 3387914fb02..833c74e2434 100644
--- a/gnu/usr.bin/cvs/src/import.c
+++ b/gnu/usr.bin/cvs/src/import.c
@@ -171,16 +171,17 @@ import (argc, argv)
if (! isabsolute (argv[0])
&& pathname_levels (argv[0]) == 0)
{
- if (CVSroot_directory == NULL)
+ if (current_parsed_root == NULL)
{
error (0, 0, "missing CVSROOT environment variable\n");
error (1, 0, "Set it or specify the '-d' option to %s.",
program_name);
}
- repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0])
- + 10);
- (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
- repos_len = strlen (CVSroot_directory);
+ repository = xmalloc (strlen (current_parsed_root->directory)
+ + strlen (argv[0])
+ + 2);
+ (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
+ repos_len = strlen (current_parsed_root->directory);
}
else
{
@@ -207,7 +208,7 @@ import (argc, argv)
*cp = '\0';
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
/* For rationale behind calling start_server before do_editor, see
commit.c */
@@ -236,7 +237,7 @@ import (argc, argv)
}
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
int err;
@@ -290,8 +291,7 @@ import (argc, argv)
make_directories (repository);
/* Create the logfile that will be logged upon completion */
- tmpfile = cvs_temp_name ();
- if ((logfp = CVS_FOPEN (tmpfile, "w+")) == NULL)
+ if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
error (1, errno, "cannot create temporary file `%s'", tmpfile);
/* On systems where we can unlink an open file, do so, so it will go
away no matter how we exit. FIXME-maybe: Should be checking for
@@ -425,7 +425,7 @@ import_descend (message, vtag, targc, targv)
else
{
errno = 0;
- while ((dp = readdir (dirp)) != NULL)
+ while ((dp = CVS_READDIR (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
goto one_more_time_boys;
@@ -476,7 +476,7 @@ import_descend (message, vtag, targc, targv)
else
{
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
err += client_process_import_file (message, dp->d_name,
vtag, targc, targv,
repository,
@@ -496,7 +496,7 @@ import_descend (message, vtag, targc, targv)
error (0, errno, "cannot read directory");
++err;
}
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
}
if (dirlist != NULL)
@@ -1567,7 +1567,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
}
#ifdef CLIENT_SUPPORT
- if (!quiet && !client_active)
+ if (!quiet && !current_parsed_root->isremote)
#else
if (!quiet)
#endif
@@ -1582,7 +1582,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
goto out;
}
#ifdef CLIENT_SUPPORT
- if (!client_active && !isdir (repository))
+ if (!current_parsed_root->isremote && !isdir (repository))
#else
if (!isdir (repository))
#endif
diff --git a/gnu/usr.bin/cvs/src/lock.c b/gnu/usr.bin/cvs/src/lock.c
index b0c75ab3d93..72f7adbfaed 100644
--- a/gnu/usr.bin/cvs/src/lock.c
+++ b/gnu/usr.bin/cvs/src/lock.c
@@ -172,12 +172,13 @@ lock_name (repository, name)
/* The interesting part of the repository is the part relative
to CVSROOT. */
- assert (CVSroot_directory != NULL);
- assert (strncmp (repository, CVSroot_directory,
- strlen (CVSroot_directory)) == 0);
- short_repos = repository + strlen (CVSroot_directory) + 1;
+ assert (current_parsed_root != NULL);
+ assert (current_parsed_root->directory != NULL);
+ assert (strncmp (repository, current_parsed_root->directory,
+ strlen (current_parsed_root->directory)) == 0);
+ short_repos = repository + strlen (current_parsed_root->directory) + 1;
- if (strcmp (repository, CVSroot_directory) == 0)
+ if (strcmp (repository, current_parsed_root->directory) == 0)
short_repos = ".";
else
assert (short_repos[-1] == '/');
@@ -633,7 +634,7 @@ again:
error (1, 0, "cannot open directory %s", repository);
errno = 0;
- while ((dp = readdir (dirp)) != NULL)
+ while ((dp = CVS_READDIR (dirp)) != NULL)
{
if (CVS_FNMATCH (CVSRFLPAT, dp->d_name, 0) == 0)
{
@@ -654,7 +655,7 @@ again:
*/
if (now >= (sb.st_ctime + CVSLCKAGE) && CVS_UNLINK (line) != -1)
{
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
free (line);
goto again;
}
@@ -680,7 +681,7 @@ again:
if (errno != 0)
error (0, errno, "error reading directory %s", repository);
- closedir (dirp);
+ CVS_CLOSEDIR (dirp);
return (ret);
}
@@ -890,10 +891,11 @@ lock_filesdoneproc (callerdat, err, repository, update_dir, entries)
}
void
-lock_tree_for_write (argc, argv, local, aflag)
+lock_tree_for_write (argc, argv, local, which, aflag)
int argc;
char **argv;
int local;
+ int which;
int aflag;
{
int err;
@@ -904,7 +906,7 @@ lock_tree_for_write (argc, argv, local, aflag)
lock_tree_list = getlist ();
err = start_recursion ((FILEPROC) NULL, lock_filesdoneproc,
(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, argc,
- argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0);
+ argv, local, which, aflag, 0, (char *) NULL, 0);
sortlist (lock_tree_list, fsortcmp);
if (Writer_Lock (lock_tree_list) != 0)
error (1, 0, "lock failed - giving up");
diff --git a/gnu/usr.bin/cvs/src/main.c b/gnu/usr.bin/cvs/src/main.c
index 40a0f3bba2c..96fc22fe406 100644
--- a/gnu/usr.bin/cvs/src/main.c
+++ b/gnu/usr.bin/cvs/src/main.c
@@ -66,8 +66,12 @@ char *Editor = EDITOR_DFLT;
List *root_directories = NULL;
/* We step through the above values. This variable is set to reflect
- the currently active value. */
-char *current_root = NULL;
+ * the currently active value.
+ *
+ * Now static. FIXME - this variable should be removable (well, localizable)
+ * with a little more work.
+ */
+static char *current_root = NULL;
static const struct cmd
@@ -98,47 +102,50 @@ static const struct cmd
char *nick2;
int (*func) (); /* Function takes (argc, argv) arguments. */
+ unsigned long attr; /* Attributes. */
} cmds[] =
{
- { "add", "ad", "new", add },
- { "admin", "adm", "rcs", admin },
- { "annotate", "ann", NULL, annotate },
- { "checkout", "co", "get", checkout },
- { "commit", "ci", "com", commit },
- { "diff", "di", "dif", diff },
- { "edit", NULL, NULL, edit },
- { "editors", NULL, NULL, editors },
- { "export", "exp", "ex", checkout },
- { "history", "hi", "his", history },
- { "import", "im", "imp", import },
- { "init", NULL, NULL, init },
+ { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR },
+ { "checkout", "co", "get", checkout, 0 },
+ { "commit", "ci", "com", commit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "diff", "di", "dif", diff, CVS_CMD_USES_WORK_DIR },
+ { "edit", NULL, NULL, edit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "editors", NULL, NULL, editors, CVS_CMD_USES_WORK_DIR },
+ { "export", "exp", "ex", checkout, CVS_CMD_USES_WORK_DIR },
+ { "history", "hi", "his", history, CVS_CMD_USES_WORK_DIR },
+ { "import", "im", "imp", import, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR | CVS_CMD_IGNORE_ADMROOT},
+ { "init", NULL, NULL, init, CVS_CMD_MODIFIES_REPOSITORY },
#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- { "kserver", NULL, NULL, server }, /* placeholder */
+ { "kserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
#endif
- { "log", "lo", "rlog", cvslog },
+ { "log", "lo", NULL, cvslog, CVS_CMD_USES_WORK_DIR },
#ifdef AUTH_CLIENT_SUPPORT
- { "login", "logon", "lgn", login },
- { "logout", NULL, NULL, logout },
+ { "login", "logon", "lgn", login, 0 },
+ { "logout", NULL, NULL, logout, 0 },
#endif /* AUTH_CLIENT_SUPPORT */
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- { "pserver", NULL, NULL, server }, /* placeholder */
+ { "pserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
#endif
- { "rdiff", "patch", "pa", patch },
- { "release", "re", "rel", release },
- { "remove", "rm", "delete", cvsremove },
- { "rtag", "rt", "rfreeze", rtag },
+ { "rannotate","rann", "ra", annotate, 0 },
+ { "rdiff", "patch", "pa", patch, 0 },
+ { "release", "re", "rel", release, 0 },
+ { "remove", "rm", "delete", cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "rlog", "rl", NULL, cvslog, 0 },
+ { "rtag", "rt", "rfreeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY },
#ifdef SERVER_SUPPORT
- { "server", NULL, NULL, server },
+ { "server", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
#endif
- { "status", "st", "stat", cvsstatus },
- { "tag", "ta", "freeze", cvstag },
- { "unedit", NULL, NULL, unedit },
- { "update", "up", "upd", update },
- { "version", "ve", "ver", version },
- { "watch", NULL, NULL, watch },
- { "watchers", NULL, NULL, watchers },
- { NULL, NULL, NULL, NULL },
+ { "status", "st", "stat", cvsstatus, CVS_CMD_USES_WORK_DIR },
+ { "tag", "ta", "freeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "unedit", NULL, NULL, unedit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "update", "up", "upd", update, CVS_CMD_USES_WORK_DIR },
+ { "version", "ve", "ver", version, 0 },
+ { "watch", NULL, NULL, watch, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
+ { "watchers", NULL, NULL, watchers, CVS_CMD_USES_WORK_DIR },
+ { NULL, NULL, NULL, NULL, 0 },
};
static const char *const usg[] =
@@ -213,9 +220,11 @@ static const char *const cmd_usage[] =
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
" pserver Password server mode\n",
#endif
+ " rannotate Show last revision where each line of module was modified\n",
" rdiff Create 'patch' format diffs between releases\n",
" release Indicate that a Module is no longer in use\n",
" remove Remove an entry from the repository\n",
+ " rlog Print out history information for a module\n",
" rtag Add a symbolic tag to a module\n",
#ifdef SERVER_SUPPORT
" server Server mode\n",
@@ -224,6 +233,7 @@ static const char *const cmd_usage[] =
" tag Add a symbolic tag to checked out version of files\n",
" unedit Undo an edit command\n",
" update Bring work tree in sync with repository\n",
+ " version Show current CVS version(s)\n",
" watch Set watches\n",
" watchers See who is watching a file\n",
"(Specify the --help option for a list of other help options)\n",
@@ -318,51 +328,14 @@ unsigned long int
lookup_command_attribute (cmd_name)
char *cmd_name;
{
- unsigned long int ret = 0;
-
- if (strcmp (cmd_name, "import") != 0)
- {
- ret |= CVS_CMD_IGNORE_ADMROOT;
- }
-
-
- /* The following commands do not use a checked-out working
- directory. We conservatively assume that everything else does.
- Feel free to add to this list if you are _certain_ something
- something doesn't use the WD. */
- if ((strcmp (cmd_name, "checkout") != 0) &&
- (strcmp (cmd_name, "init") != 0) &&
- (strcmp (cmd_name, "login") != 0) &&
- (strcmp (cmd_name, "logout") != 0) &&
- (strcmp (cmd_name, "rdiff") != 0) &&
- (strcmp (cmd_name, "release") != 0) &&
- (strcmp (cmd_name, "rtag") != 0))
- {
- ret |= CVS_CMD_USES_WORK_DIR;
- }
-
+ const struct cmd *cm;
- /* The following commands do not modify the repository; we
- conservatively assume that everything else does. Feel free to
- add to this list if you are _certain_ something is safe. */
- if ((strcmp (cmd_name, "annotate") != 0) &&
- (strcmp (cmd_name, "checkout") != 0) &&
- (strcmp (cmd_name, "diff") != 0) &&
- (strcmp (cmd_name, "rdiff") != 0) &&
- (strcmp (cmd_name, "update") != 0) &&
- (strcmp (cmd_name, "editors") != 0) &&
- (strcmp (cmd_name, "export") != 0) &&
- (strcmp (cmd_name, "history") != 0) &&
- (strcmp (cmd_name, "log") != 0) &&
- (strcmp (cmd_name, "noop") != 0) &&
- (strcmp (cmd_name, "watchers") != 0) &&
- (strcmp (cmd_name, "release") != 0) &&
- (strcmp (cmd_name, "status") != 0))
+ for (cm = cmds; cm->fullname; cm++)
{
- ret |= CVS_CMD_MODIFIES_REPOSITORY;
+ if (strcmp (cmd_name, cm->fullname) == 0)
+ break;
}
-
- return ret;
+ return cm->attr;
}
@@ -581,7 +554,7 @@ main (argc, argv)
version (0, (char **) NULL);
(void) fputs ("\n", stdout);
(void) fputs ("\
-Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
+Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
Jeff Polk, and other authors\n", stdout);
(void) fputs ("\n", stdout);
(void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
@@ -612,6 +585,8 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
if (CVSroot_cmdline != NULL)
free (CVSroot_cmdline);
CVSroot_cmdline = xstrdup (optarg);
+ if (free_CVSroot)
+ free (CVSroot);
CVSroot = xstrdup (optarg);
free_CVSroot = 1;
cvs_update_env = 1; /* need to update environment */
@@ -687,15 +662,6 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
else
command_name = cm->fullname; /* Global pointer for later use */
- /* This should probably remain a warning, rather than an error,
- for quite a while. For one thing the version of VC distributed
- with GNU emacs 19.34 invokes 'cvs rlog' instead of 'cvs log'. */
- if (strcmp (argv[0], "rlog") == 0)
- {
- error (0, 0, "warning: the rlog command is deprecated");
- error (0, 0, "use the synonymous log command instead");
- }
-
if (help)
{
argc = -1; /* some functions only check for this */
@@ -844,8 +810,7 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
specify a different repository than the one we are
importing to. */
- if ((lookup_command_attribute (command_name)
- & CVS_CMD_IGNORE_ADMROOT)
+ if (!(cm->attr & CVS_CMD_IGNORE_ADMROOT)
/* -d overrides CVS/Root, so don't give an error if the
latter points to a nonexistent repository. */
@@ -937,25 +902,29 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
variable. Parse it to see if we're supposed to do
remote accesses or use a special access method. */
- if (parse_cvsroot (current_root))
+ if (current_parsed_root != NULL)
+ free_cvsroot_t (current_parsed_root);
+ if ((current_parsed_root = parse_cvsroot (current_root)) == NULL)
error (1, 0, "Bad CVSROOT.");
if (trace)
- error (0, 0, "notice: main loop with CVSROOT=%s",
- current_root);
+ fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",
+ CLIENT_SERVER_STR, current_root);
/*
* Check to see if the repository exists.
*/
- if (!client_active)
+#ifdef CLIENT_SUPPORT
+ if (!current_parsed_root->isremote)
+#endif /* CLIENT_SUPPORT */
{
char *path;
int save_errno;
- path = xmalloc (strlen (CVSroot_directory)
+ path = xmalloc (strlen (current_parsed_root->directory)
+ sizeof (CVSROOTADM)
+ 20);
- (void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
+ (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
if (readonlyfs == 0 && !isaccessible (path, R_OK | X_OK))
{
save_errno = errno;
@@ -1000,7 +969,7 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
&& !server_active
#endif
#ifdef CLIENT_SUPPORT
- && !client_active
+ && !current_parsed_root->isremote
#endif
)
{
@@ -1008,11 +977,15 @@ Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
already printed an error. We keep going. Why? Because
if we didn't, then there would be no way to check in a new
CVSROOT/config file to fix the broken one! */
- parse_config (CVSroot_directory);
+ parse_config (current_parsed_root->directory);
}
#ifdef CLIENT_SUPPORT
- if (client_active)
+ /* Need to check for current_parsed_root != NULL here since
+ * we could still be in server mode before the server function
+ * gets called below and sets the root
+ */
+ if (current_parsed_root != NULL && current_parsed_root->isremote)
{
/* Create a new list for directory names that we've
sent to the server. */
@@ -1130,31 +1103,55 @@ date_from_time_t (unixtime)
void
date_to_internet (dest, source)
char *dest;
- char *source;
+ const char *source;
{
- int year, month, day, hour, minute, second;
+ struct tm date;
- /* Just to reiterate, these strings are from RFC822 and do not vary
- according to locale. */
- static const char *const month_names[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ date_to_tm (&date, source);
+ tm_to_internet (dest, &date);
+}
+void
+date_to_tm (dest, source)
+ struct tm *dest;
+ const char *source;
+{
if (sscanf (source, SDATEFORM,
- &year, &month, &day, &hour, &minute, &second)
- != 6)
+ &dest->tm_year, &dest->tm_mon, &dest->tm_mday,
+ &dest->tm_hour, &dest->tm_min, &dest->tm_sec)
+ != 6)
/* Is there a better way to handle errors here? I made this
non-fatal in case we are called from the code which can't
deal with fatal errors. */
error (0, 0, "internal error: bad date %s", source);
- /* Always send a four digit year. */
- if (year < 100)
- year += 1900;
+ if (dest->tm_year > 100)
+ dest->tm_year -= 1900;
+
+ dest->tm_mon -= 1;
+}
+
+/* Convert a date to RFC822/1123 format. This is used in contexts like
+ dates to send in the protocol; it should not vary based on locale or
+ other such conventions for users. We should have another routine which
+ does that kind of thing.
- sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", day,
- month < 1 || month > 12 ? "???" : month_names[month - 1],
- year, hour, minute, second);
+ The SOURCE date is a pointer to a struct tm. DEST should point to
+ storage managed by the caller, at least MAXDATELEN characters. */
+void
+tm_to_internet (dest, source)
+ char *dest;
+ const struct tm *source;
+{
+ /* Just to reiterate, these strings are from RFC822 and do not vary
+ according to locale. */
+ static const char *const month_names[] =
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", source->tm_mday,
+ source->tm_mon < 0 || source->tm_mon > 11 ? "???" : month_names[source->tm_mon],
+ source->tm_year + 1900, source->tm_hour, source->tm_min, source->tm_sec);
}
void
diff --git a/gnu/usr.bin/cvs/src/mkmodules.c b/gnu/usr.bin/cvs/src/mkmodules.c
index a18a161c815..e252536efd6 100644
--- a/gnu/usr.bin/cvs/src/mkmodules.c
+++ b/gnu/usr.bin/cvs/src/mkmodules.c
@@ -857,7 +857,7 @@ init (argc, argv)
usage (init_usage);
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
start_server ();
@@ -871,12 +871,10 @@ init (argc, argv)
old cvsinit.sh script did. Few utilities do that, and a
non-existent parent directory is as likely to be a typo as something
which needs to be created. */
- mkdir_if_needed (CVSroot_directory);
+ mkdir_if_needed (current_parsed_root->directory);
- adm = xmalloc (strlen (CVSroot_directory) + sizeof (CVSROOTADM) + 10);
- strcpy (adm, CVSroot_directory);
- strcat (adm, "/");
- strcat (adm, CVSROOTADM);
+ adm = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM) + 2);
+ sprintf (adm, "%s/%s", current_parsed_root->directory, CVSROOTADM);
mkdir_if_needed (adm);
/* This is needed because we pass "fileptr->filename" not "info"
diff --git a/gnu/usr.bin/cvs/src/parseinfo.c b/gnu/usr.bin/cvs/src/parseinfo.c
index 6d5b481ec49..9d501ffcb53 100644
--- a/gnu/usr.bin/cvs/src/parseinfo.c
+++ b/gnu/usr.bin/cvs/src/parseinfo.c
@@ -37,7 +37,7 @@ Parse_Info (infofile, repository, callproc, all)
char *cp, *exp, *value, *srepos, bad;
const char *regex_err;
- if (CVSroot_original == NULL)
+ if (current_parsed_root == NULL)
{
/* XXX - should be error maybe? */
error (0, 0, "CVSROOT variable not set");
@@ -45,11 +45,11 @@ Parse_Info (infofile, repository, callproc, all)
}
/* find the info file and open it */
- infopath = xmalloc (strlen (CVSroot_directory)
+ infopath = xmalloc (strlen (current_parsed_root->directory)
+ strlen (infofile)
+ sizeof (CVSROOTADM)
- + 10);
- (void) sprintf (infopath, "%s/%s/%s", CVSroot_directory,
+ + 3);
+ (void) sprintf (infopath, "%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, infofile);
fp_info = CVS_FOPEN (infopath, "r");
if (fp_info == NULL)
@@ -204,7 +204,7 @@ Parse_Info (infofile, repository, callproc, all)
KEYWORD=VALUE. There is currently no way to have a multi-line
VALUE (would be nice if there was, probably).
- CVSROOT is the $CVSROOT directory (CVSroot_directory might not be
+ CVSROOT is the $CVSROOT directory (current_parsed_root->directory might not be
set yet).
Returns 0 for success, negative value for failure. Call
diff --git a/gnu/usr.bin/cvs/src/patch.c b/gnu/usr.bin/cvs/src/patch.c
index 9aa26f3342e..5a208776abc 100644
--- a/gnu/usr.bin/cvs/src/patch.c
+++ b/gnu/usr.bin/cvs/src/patch.c
@@ -12,6 +12,7 @@
* release as either a date or a revision number.
*/
+#include <assert.h>
#include "cvs.h"
#include "getline.h"
@@ -189,7 +190,7 @@ patch (argc, argv)
options = xstrdup ("");
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
/* We're the client side. Fire up the remote server. */
start_server ();
@@ -252,7 +253,7 @@ patch (argc, argv)
db = open_module ();
for (i = 0; i < argc; i++)
err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
- (char *) NULL, 0, 0, 0, (char *) NULL);
+ (char *) NULL, 0, 0, 0, 0, (char *) NULL);
close_module (db);
free (options);
patch_cleanup ();
@@ -282,11 +283,11 @@ patch_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
char *repository;
char *where;
- repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile)) + 30);
- (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
- where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile))
- + 10);
+ repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
+ + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
+ (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
+ where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
+ + 1);
(void) strcpy (where, argv[0]);
/* if mfile isn't null, we need to set up to do only part of the module */
@@ -307,7 +308,7 @@ patch_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
}
/* take care of the rest */
- path = xmalloc (strlen (repository) + strlen (mfile) + 5);
+ path = xmalloc (strlen (repository) + strlen (mfile) + 2);
(void) sprintf (path, "%s/%s", repository, mfile);
if (isdir (path))
{
@@ -502,10 +503,15 @@ patch_fileproc (callerdat, finfo)
}
/* Create 3 empty files. I'm not really sure there is any advantage
- to doing so now rather than just waiting until later. */
- tmpfile1 = cvs_temp_name ();
- fp1 = CVS_FOPEN (tmpfile1, "w+");
- if (fp1 == NULL)
+ * to doing so now rather than just waiting until later.
+ *
+ * There is - cvs_temp_file opens the file so that it can guarantee that
+ * we have exclusive write access to the file. Unfortunately we spoil that
+ * by closing it and reopening it again. Of course any better solution
+ * requires that the RCS functions accept open file pointers rather than
+ * simple file names.
+ */
+ if ((fp1 = cvs_temp_file (&tmpfile1)) == NULL)
{
error (0, errno, "cannot create temporary file %s", tmpfile1);
ret = 1;
@@ -514,9 +520,7 @@ patch_fileproc (callerdat, finfo)
else
if (fclose (fp1) < 0)
error (0, errno, "warning: cannot close %s", tmpfile1);
- tmpfile2 = cvs_temp_name ();
- fp2 = CVS_FOPEN (tmpfile2, "w+");
- if (fp2 == NULL)
+ if ((fp2 = cvs_temp_file (&tmpfile2)) == NULL)
{
error (0, errno, "cannot create temporary file %s", tmpfile2);
ret = 1;
@@ -525,9 +529,7 @@ patch_fileproc (callerdat, finfo)
else
if (fclose (fp2) < 0)
error (0, errno, "warning: cannot close %s", tmpfile2);
- tmpfile3 = cvs_temp_name ();
- fp3 = CVS_FOPEN (tmpfile3, "w+");
- if (fp3 == NULL)
+ if ((fp3 = cvs_temp_file (&tmpfile3)) == NULL)
{
error (0, errno, "cannot create temporary file %s", tmpfile3);
ret = 1;
@@ -580,7 +582,7 @@ patch_fileproc (callerdat, finfo)
(void) utime (tmpfile2, &t);
}
- switch (diff_exec (tmpfile1, tmpfile2, unidiff ? "-u" : "-c", tmpfile3))
+ switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, unidiff ? "-u" : "-c", tmpfile3))
{
case -1: /* fork/wait failure */
error (1, errno, "fork for diff failed on %s", rcs);
@@ -643,13 +645,14 @@ failed to read diff file header %s for %s: end of file", tmpfile3, rcs);
goto out;
}
}
- if (CVSroot_directory != NULL)
+ assert (current_parsed_root != NULL);
+ assert (current_parsed_root->directory != NULL);
{
- strippath = xmalloc (strlen (CVSroot_directory) + 10);
- (void) sprintf (strippath, "%s/", CVSroot_directory);
+ strippath = xmalloc (strlen (current_parsed_root->directory) + 2);
+ (void) sprintf (strippath, "%s/", current_parsed_root->directory);
}
- else
- strippath = xstrdup (REPOS_STRIP);
+ /*else
+ strippath = xstrdup (REPOS_STRIP); */
if (strncmp (rcs, strippath, strlen (strippath)) == 0)
rcs += strlen (strippath);
free (strippath);
diff --git a/gnu/usr.bin/cvs/src/rcs.c b/gnu/usr.bin/cvs/src/rcs.c
index 3719e5561a5..52fdb8100e9 100644
--- a/gnu/usr.bin/cvs/src/rcs.c
+++ b/gnu/usr.bin/cvs/src/rcs.c
@@ -92,11 +92,6 @@ static void expand_keywords PROTO((RCSNode *, RCSVers *, const char *,
size_t, char **, size_t *));
static void cmp_file_buffer PROTO((void *, const char *, size_t));
-enum rcs_delta_op {RCS_ANNOTATE, RCS_FETCH};
-static void RCS_deltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *, char *,
- enum rcs_delta_op, char **, size_t *,
- char **, size_t *));
-
/* Routines for reading, parsing and writing RCS files. */
static RCSVers *getdelta PROTO ((struct rcsbuffer *, char *, char **,
char **));
@@ -2126,7 +2121,7 @@ RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
* -- If tag is a branch tag, returns the branch number, not
* the revision of the head of the branch.
* If tag or revision is not valid or does not exist in file,
- * exit with error.
+ * return NULL.
*/
char *
RCS_tag2rev (rcs, tag)
@@ -2205,9 +2200,8 @@ RCS_tag2rev (rcs, tag)
if (rev)
return rev;
- error (1, 0, "tag `%s' does not exist", tag);
- /* NOT REACHED -- error (1 ... ) does not return here */
- return 0;
+ /* Trust the caller to print warnings. */
+ return NULL;
}
/*
@@ -4157,7 +4151,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
whether it should be considered an error for `dest' to exist
at this point. If so, the unlink call should be removed and
`symlink' should signal the error. -twp) */
- if (unlink (dest) < 0 && !existence_error (errno))
+ if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
error (1, errno, "cannot remove %s", dest);
if (symlink (info->data, dest) < 0)
error (1, errno, "cannot create symbolic link from %s to %s",
@@ -4327,7 +4321,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
/* Unlink `dest', just in case. It's okay if this provokes a
ENOENT error. */
- if (unlink (dest) < 0 && existence_error (errno))
+ if (CVS_UNLINK (dest) < 0 && existence_error (errno))
error (1, errno, "cannot remove %s", dest);
if (mknod (dest, special_file, devnum) < 0)
error (1, errno, "could not create special file %s",
@@ -5270,7 +5264,7 @@ workfile);
memset (commitpt->text, 0, sizeof (Deltatext));
bufsize = 0;
- switch (diff_exec (workfile, tmpfile, diffopts, changefile))
+ switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile))
{
case 0:
case 1:
@@ -5318,7 +5312,7 @@ workfile);
/* This file is not being inserted at the head, but on a side
branch somewhere. Make a diff from the previous revision
to the working file. */
- switch (diff_exec (tmpfile, workfile, diffopts, changefile))
+ switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile))
{
case 0:
case 1:
@@ -5698,7 +5692,7 @@ RCS_setbranch (rcs, rev)
int
RCS_lock (rcs, rev, lock_quiet)
RCSNode *rcs;
- const char *rev;
+ char *rev;
int lock_quiet;
{
List *locks;
@@ -5717,32 +5711,16 @@ RCS_lock (rcs, rev, lock_quiet)
/* A revision number of NULL means lock the head or default branch. */
if (rev == NULL)
xrev = RCS_head (rcs);
-
- /* If rev is a branch number, lock the latest revision on that
- branch. I think that if the branch doesn't exist, it's
- okay to return 0 -- that just means that the branch is new,
- so we don't need to lock it anyway. -twp */
- else if (RCS_nodeisbranch (rcs, rev))
- {
- xrev = RCS_getbranch (rcs, (char *) rev, 1);
- if (xrev == NULL)
- {
- if (!lock_quiet)
- error (0, 0, "%s: branch %s absent", rcs->path, rev);
- return 1;
- }
- }
-
- if (xrev == NULL)
- xrev = xstrdup (rev);
+ else
+ xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
/* Make sure that the desired revision exists. Technically,
we can update the locks list without even checking this,
but RCS 5.7 did this. And it can't hurt. */
- if (findnode (rcs->versions, xrev) == NULL)
+ if (xrev == NULL || findnode (rcs->versions, xrev) == NULL)
{
if (!lock_quiet)
- error (0, 0, "%s: revision %s absent", rcs->path, xrev);
+ error (0, 0, "%s: revision %s absent", rcs->path, rev);
free (xrev);
return 1;
}
@@ -5808,7 +5786,7 @@ RCS_lock (rcs, rev, lock_quiet)
int
RCS_unlock (rcs, rev, unlock_quiet)
RCSNode *rcs;
- const char *rev;
+ char *rev;
int unlock_quiet;
{
Node *lock;
@@ -5858,20 +5836,15 @@ RCS_unlock (rcs, rev, unlock_quiet)
return 0; /* no lock found, ergo nothing to do */
xrev = xstrdup (lock->key);
}
- else if (RCS_nodeisbranch (rcs, rev))
+ else
{
- /* If rev is a branch number, unlock the latest revision on that
- branch. */
- xrev = RCS_getbranch (rcs, (char *) rev, 1);
+ xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
if (xrev == NULL)
{
- error (0, 0, "%s: branch %s absent", rcs->path, rev);
+ error (0, 0, "%s: revision %s absent", rcs->path, rev);
return 1;
}
}
- else
- /* REV is an exact revision number. */
- xrev = xstrdup (rev);
lock = findnode (RCS_getlocks (rcs), xrev);
if (lock == NULL)
@@ -6393,7 +6366,7 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
goto delrev_done;
outfile = cvs_temp_name();
- status = diff_exec (beforefile, afterfile, "-an", outfile);
+ status = diff_exec (beforefile, afterfile, NULL, NULL, "-an", outfile);
if (status == 2)
{
@@ -7032,7 +7005,7 @@ rcs_change_text (name, textbuf, textlen, diffbuf, difflen, retbuf, retlen)
On error, give a fatal error. */
-static void
+void
RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
RCSNode *rcs;
FILE *fp;
@@ -8391,138 +8364,6 @@ RCS_abandon (rcs)
rcs->flags |= PARTIAL;
}
-
-/* Annotate command. In rcs.c for historical reasons (from back when
- what is now RCS_deltas was part of annotate_fileproc). */
-
-/* Options from the command line. */
-
-static int force_tag_match = 1;
-static char *tag = NULL;
-static char *date = NULL;
-
-static int annotate_fileproc PROTO ((void *callerdat, struct file_info *));
-
-static int
-annotate_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- FILE *fp = NULL;
- struct rcsbuffer *rcsbufp = NULL;
- struct rcsbuffer rcsbuf;
- char *version;
-
- if (finfo->rcs == NULL)
- return (1);
-
- if (finfo->rcs->flags & PARTIAL)
- {
- RCS_reparsercsfile (finfo->rcs, &fp, &rcsbuf);
- rcsbufp = &rcsbuf;
- }
-
- version = RCS_getversion (finfo->rcs, tag, date, force_tag_match,
- (int *) NULL);
- if (version == NULL)
- return 0;
-
- /* Distinguish output for various files if we are processing
- several files. */
- cvs_outerr ("Annotations for ", 0);
- cvs_outerr (finfo->fullname, 0);
- cvs_outerr ("\n***************\n", 0);
-
- RCS_deltas (finfo->rcs, fp, rcsbufp, version, RCS_ANNOTATE, NULL,
- NULL, NULL, NULL);
- free (version);
- return 0;
-}
-
-static const char *const annotate_usage[] =
-{
- "Usage: %s %s [-lRf] [-r rev|-D date] [files...]\n",
- "\t-l\tLocal directory only, no recursion.\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-f\tUse head revision if tag/date not found.\n",
- "\t-r rev\tAnnotate file as of specified revision/tag.\n",
- "\t-D date\tAnnotate file as of specified date.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-/* Command to show the revision, date, and author where each line of a
- file was modified. */
-
-int
-annotate (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0;
- int c;
-
- if (argc == -1)
- usage (annotate_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+lr:D:fR")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'r':
- tag = optarg;
- break;
- case 'D':
- date = Make_Date (optarg);
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case '?':
- default:
- usage (annotate_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CLIENT_SUPPORT
- if (client_active)
- {
- start_server ();
- ign_setup ();
-
- if (local)
- send_arg ("-l");
- if (!force_tag_match)
- send_arg ("-f");
- option_with_arg ("-r", tag);
- if (date)
- client_senddate (date);
- send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
- send_file_names (argc, argv, SEND_EXPAND_WILD);
- send_to_server ("annotate\012", 0);
- return get_responses_and_close ();
- }
-#endif /* CLIENT_SUPPORT */
-
- if (tag != NULL)
- tag_check_valid (tag, argc, argv, local, 0, "");
-
- return start_recursion (annotate_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, 1, (char *)NULL,
- 1);
-}
-
/*
* For a given file with full pathname PATH and revision number REV,
* produce a file label suitable for passing to diff. The default
@@ -8532,6 +8373,11 @@ annotate (argc, argv)
*
* The date and time used are the revision's last checkin date and time.
* If REV is NULL, use the working copy's mtime instead.
+ *
+ * /dev/null is not statted but assumed to have been created on the Epoch.
+ * At least using the POSIX.2 definition of patch, this should cause creation
+ * of files on platforms such as Windoze where the null IO device isn't named
+ * /dev/null to be parsed by patch properly.
*/
char *
make_file_label (path, rev, rcs)
@@ -8539,37 +8385,45 @@ make_file_label (path, rev, rcs)
char *rev;
RCSNode *rcs;
{
- char datebuf[MAXDATELEN];
+ char datebuf[MAXDATELEN + 1];
char *label;
- char *file;
- file = last_component (path);
label = (char *) xmalloc (strlen (path)
- + (rev == NULL ? 0 : strlen (rev))
- + 50);
+ + (rev == NULL ? 0 : strlen (rev) + 1)
+ + MAXDATELEN
+ + 2);
if (rev)
{
- char *date;
+ char date[MAXDATELEN + 1];
+ /* revs cannot be attached to /dev/null ... duh. */
+ assert (strcmp(DEVNULL, path));
RCS_getrevtime (rcs, rev, datebuf, 0);
- date = printable_date (datebuf);
+ (void) date_to_internet (date, datebuf);
(void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
- free (date);
}
else
{
struct stat sb;
- struct tm *wm;
+ struct tm *wm = NULL;
- if (CVS_STAT (file, &sb) < 0)
- error (0, 1, "could not get info for `%s'", path);
+ if (strcmp(DEVNULL, path))
+ {
+ char *file = last_component (path);
+ if (CVS_STAT (file, &sb) < 0)
+ error (0, 1, "could not get info for `%s'", path);
+ else
+ wm = gmtime (&sb.st_mtime);
+ }
else
{
- wm = gmtime (&sb.st_mtime);
- (void) sprintf (datebuf, "%04d/%02d/%02d %02d:%02d:%02d",
- wm->tm_year + 1900, wm->tm_mon + 1,
- wm->tm_mday, wm->tm_hour,
- wm->tm_min, wm->tm_sec);
+ time_t t = 0;
+ wm = gmtime(&t);
+ }
+
+ if (wm)
+ {
+ (void) tm_to_internet (datebuf, wm);
(void) sprintf (label, "-L%s\t%s", path, datebuf);
}
}
diff --git a/gnu/usr.bin/cvs/src/rcscmds.c b/gnu/usr.bin/cvs/src/rcscmds.c
index ab94e407bd7..43be16839df 100644
--- a/gnu/usr.bin/cvs/src/rcscmds.c
+++ b/gnu/usr.bin/cvs/src/rcscmds.c
@@ -530,9 +530,11 @@ RCS file: ", 0);
message on stderr. */
int
-diff_exec (file1, file2, options, out)
+diff_exec (file1, file2, label1, label2, options, out)
char *file1;
char *file2;
+ char *label1;
+ char *label2;
char *options;
char *out;
{
@@ -575,6 +577,10 @@ diff_exec (file1, file2, options, out)
/* The first word in this string is used only for error reporting. */
sprintf (args, "diff %s", options);
call_diff_setup (args);
+ if (label1)
+ call_diff_arg (label1);
+ if (label2)
+ call_diff_arg (label2);
call_diff_arg (file1);
call_diff_arg (file2);
free (args);
diff --git a/gnu/usr.bin/cvs/src/recurse.c b/gnu/usr.bin/cvs/src/recurse.c
index 1cb2fbbf35d..2235193d1cb 100644
--- a/gnu/usr.bin/cvs/src/recurse.c
+++ b/gnu/usr.bin/cvs/src/recurse.c
@@ -157,10 +157,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
#ifdef CLIENT_SUPPORT
if (!just_subdirs
&& CVSroot_cmdline == NULL
- && client_active)
+ && current_parsed_root->isremote)
{
char *root = Name_Root (NULL, update_dir);
- if (root && strcmp (root, current_root) != 0)
+ if (root && strcmp (root, current_parsed_root->original) != 0)
/* We're skipping this directory because it is for
a different root. Therefore, we just want to
do the subdirectories only. Processing files would
@@ -204,7 +204,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
program_name);
}
#ifdef CLIENT_SUPPORT
- else if (client_active && server_started)
+ else if (current_parsed_root->isremote && server_started)
{
/* In the the case "cvs update foo bar baz", a call to
send_file_names in update.c will have sent the
@@ -290,7 +290,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
{
if ((which & W_LOCAL) && isdir (CVSADM)
#ifdef CLIENT_SUPPORT
- && !client_active
+ && !current_parsed_root->isremote
#endif
)
{
@@ -363,8 +363,8 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
/* FIXME (njc): in the multiroot case, we don't want to send
argument commands for those top-level directories which do
not contain any subdirectories which have files checked out
- from current_root. If we do, and two repositories have a
- module with the same name, nasty things could happen.
+ from current_parsed_root->original. If we do, and two repositories
+ have a module with the same name, nasty things could happen.
This is hard. Perhaps we should send the Argument commands
later in this procedure, after we've had a chance to notice
@@ -440,7 +440,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
"Directory xxx" command, which forces the server to descend
and serve the files there. client.c (send_file_names) has
also been modified to send only those arguments which are
- appropriate to current_root.
+ appropriate to current_parsed_root->original.
*/
@@ -599,8 +599,9 @@ do_recursion (frame)
}
- process_this_directory = (strcmp (current_root, this_root) == 0);
-
+ process_this_directory =
+ (strcmp (current_parsed_root->original, this_root) == 0);
+
free (this_root);
}
}
@@ -710,7 +711,7 @@ do_recursion (frame)
place (server_notify). For local, we can't do them here--we don't
have writelocks in place, and there is no way to get writelocks
here. */
- if (client_active)
+ if (current_parsed_root->isremote)
notify_check (repository, update_dir);
#endif /* CLIENT_SUPPORT */
@@ -1024,7 +1025,8 @@ but CVS uses %s for its own purposes; skipping %s directory",
}
- process_this_directory = (strcmp (current_root, this_root) == 0);
+ process_this_directory = (strcmp (current_parsed_root->original, this_root) == 0);
+
free (this_root);
}
}
diff --git a/gnu/usr.bin/cvs/src/root.c b/gnu/usr.bin/cvs/src/root.c
index 1c92b1561e8..08dab3e94a6 100644
--- a/gnu/usr.bin/cvs/src/root.c
+++ b/gnu/usr.bin/cvs/src/root.c
@@ -12,11 +12,11 @@
#include "cvs.h"
#include "getline.h"
-/* Printable names for things in the CVSroot_method enum variable.
+/* Printable names for things in the current_parsed_root->method enum variable.
Watch out if the enum is changed in cvs.h! */
char *method_names[] = {
- "local", "server (ssh)", "pserver", "kserver", "gserver", "ext", "fork"
+ "undefined", "local", "server (ssh)", "pserver", "kserver", "gserver", "ext", "fork"
};
#ifndef DEBUG
@@ -265,12 +265,16 @@ error 0 Server configuration missing --allow-root in inetd.conf\n");
return 0;
}
+
+
/* This global variable holds the global -d option. It is NULL if -d
was not used, which means that we must get the CVSroot information
from the CVSROOT environment variable or from a CVS/Root file. */
char *CVSroot_cmdline;
+
+
/* Parse a CVSROOT variable into its constituent parts -- method,
* username, hostname, directory. The prototypical CVSROOT variable
* looks like:
@@ -280,50 +284,103 @@ char *CVSroot_cmdline;
* Some methods may omit fields; local, for example, doesn't need user
* and host.
*
- * Returns zero on success, non-zero on failure. */
+ * Returns pointer to new cvsroot_t on success, NULL on failure. */
-char *CVSroot_original = NULL; /* the CVSroot that was passed in */
-int client_active; /* nonzero if we are doing remote access */
-CVSmethod CVSroot_method; /* one of the enum values defined in cvs.h */
-char *CVSroot_username; /* the username or NULL if method == local */
-char *CVSroot_hostname; /* the hostname or NULL if method == local */
-char *CVSroot_directory; /* the directory name */
+cvsroot_t *current_parsed_root = NULL;
-int
-parse_cvsroot (CVSroot)
- char *CVSroot;
+
+
+/* allocate and initialize a cvsroot_t
+ *
+ * We must initialize the strings to NULL so we know later what we should
+ * free
+ *
+ * Some of the other zeroes remain meaningful as, "never set, use default",
+ * or the like
+ */
+static cvsroot_t *
+new_cvsroot_t ()
{
- static int cvsroot_parsed = 0;
- char *cvsroot_copy, *cvsroot_save, *p;
- int check_hostname;
+ cvsroot_t *newroot;
+
+ /* gotta store it somewhere */
+ newroot = xmalloc(sizeof(cvsroot_t));
+
+ newroot->original = NULL;
+ newroot->method = null_method;
+ newroot->username = NULL;
+ newroot->password = NULL;
+ newroot->hostname = NULL;
+ newroot->port = 0;
+ newroot->directory = NULL;
+#ifdef CLIENT_SUPPORT
+ newroot->isremote = 0;
+#endif /* CLIENT_SUPPORT */
- /* Don't go through the trouble twice. */
- if (cvsroot_parsed)
+ return newroot;
+}
+
+
+
+/* Dispose of a cvsroot_t and its component parts */
+void
+free_cvsroot_t (root)
+ cvsroot_t *root;
+{
+ if (root->original != NULL)
+ free (root->original);
+ if (root->username != NULL)
+ free (root->username);
+ if (root->password != NULL)
{
- error (0, 0, "WARNING (parse_cvsroot): someone called me twice!\n");
- return 0;
+ /* I like to be paranoid */
+ memset (root->password, 0, strlen (root->password));
+ free (root->password);
}
+ if (root->hostname != NULL)
+ free (root->hostname);
+ if (root->directory != NULL)
+ free (root->directory);
+ free (root);
+}
+
- if (CVSroot_original != NULL)
- free (CVSroot_original);
- if (CVSroot_directory != NULL)
- free (CVSroot_directory);
- if (CVSroot_username != NULL)
- free (CVSroot_username);
- if (CVSroot_hostname != NULL)
- free (CVSroot_hostname);
- CVSroot_original = xstrdup (CVSroot);
- cvsroot_save = cvsroot_copy = xstrdup (CVSroot);
+/*
+ * parse a CVSROOT string to allocate and return a new cvsroot_t structure
+ */
+cvsroot_t *
+parse_cvsroot (root_in)
+ char *root_in;
+{
+ cvsroot_t *newroot; /* the new root to be returned */
+ char *cvsroot_save; /* what we allocated so we can dispose
+ * it when finished */
+ char *firstslash; /* save where the path spec starts
+ * while we parse
+ * [[user][:password]@]host[:[port]]
+ */
+ char *cvsroot_copy, *p, *q; /* temporary pointers for parsing */
+ char *new_hostname;
+ int check_hostname, no_port, no_password;
+
+ /* allocate some space */
+ newroot = new_cvsroot_t();
+
+ /* save the original string */
+ newroot->original = xstrdup (root_in);
+
+ /* and another copy we can munge while parsing */
+ cvsroot_save = cvsroot_copy = xstrdup (root_in);
if (*cvsroot_copy == ':')
{
char *method = ++cvsroot_copy;
/* Access method specified, as in
- * "cvs -d :pserver:user@host:/path",
+ * "cvs -d :(gserver|kserver|pserver):[[user][:password]@]host[:[port]]/path",
+ * "cvs -d [:(ext|server):][[user]@]host[:]/path",
* "cvs -d :local:e:\path",
- * "cvs -d :kserver:user@host:/path", or
* "cvs -d :fork:/path".
* We need to get past that part of CVSroot before parsing the
* rest of it.
@@ -331,9 +388,9 @@ parse_cvsroot (CVSroot)
if (! (p = strchr (method, ':')))
{
- error (0, 0, "bad CVSroot: %s", CVSroot);
+ error (0, 0, "bad CVSroot: %s", root_in);
free (cvsroot_save);
- return 1;
+ goto error_exit;
}
*p = '\0';
cvsroot_copy = ++p;
@@ -341,24 +398,24 @@ parse_cvsroot (CVSroot)
/* Now we have an access method -- see if it's valid. */
if (strcmp (method, "local") == 0)
- CVSroot_method = local_method;
+ newroot->method = local_method;
else if (strcmp (method, "pserver") == 0)
- CVSroot_method = pserver_method;
+ newroot->method = pserver_method;
else if (strcmp (method, "kserver") == 0)
- CVSroot_method = kserver_method;
+ newroot->method = kserver_method;
else if (strcmp (method, "gserver") == 0)
- CVSroot_method = gserver_method;
+ newroot->method = gserver_method;
else if (strcmp (method, "server") == 0)
- CVSroot_method = server_method;
+ newroot->method = server_method;
else if (strcmp (method, "ext") == 0)
- CVSroot_method = ext_method;
+ newroot->method = ext_method;
else if (strcmp (method, "fork") == 0)
- CVSroot_method = fork_method;
+ newroot->method = fork_method;
else
{
- error (0, 0, "unknown method in CVSroot: %s", CVSroot);
+ error (0, 0, "unknown method in CVSroot: %s", root_in);
free (cvsroot_save);
- return 1;
+ goto error_exit;
}
}
else
@@ -367,183 +424,348 @@ parse_cvsroot (CVSroot)
SERVER_METHOD/EXT_METHOD if the string contains a colon or
LOCAL_METHOD otherwise. */
- CVSroot_method = ((strchr (cvsroot_copy, ':'))
-#ifdef RSH_NOT_TRANSPARENT
+ newroot->method = ((*cvsroot_copy != '/' && strchr (cvsroot_copy, '/'))
+/*#ifdef RSH_NOT_TRANSPARENT
? server_method
-#else
+#else*/
? ext_method
-#endif
+/*#endif*/
: local_method);
}
- client_active = (CVSroot_method != local_method);
-
- /* Check for username/hostname if we're not LOCAL_METHOD. */
+#ifdef CLIENT_SUPPORT
+ newroot->isremote = (newroot->method != local_method);
+#endif /* CLIENT_SUPPORT */
- CVSroot_username = NULL;
- CVSroot_hostname = NULL;
- if ((CVSroot_method != local_method)
- && (CVSroot_method != fork_method))
+ if ((newroot->method != local_method)
+ && (newroot->method != fork_method))
{
- /* Check to see if there is a username in the string. */
+ /* split the string into [[user][:password]@]host[:[port]] & /path
+ *
+ * this will allow some characters such as '@' & ':' to remain unquoted
+ * in the path portion of the spec
+ */
+ if ((p = strchr (cvsroot_copy, '/')) == NULL)
+ {
+ error (0, 0, "CVSROOT (\"%s\")", root_in);
+ error (0, 0, "requires a path spec");
+ error (0, 0, ":(gserver|kserver|pserver):[[user][:password]@]host[:[port]]/path");
+ error (0, 0, "[:(ext|server):][[user]@]host[:]/path");
+ free (cvsroot_save);
+ goto error_exit;
+ }
+ firstslash = p; /* == NULL if '/' not in string */
+ *p = '\0';
+ /* Check to see if there is a username[:password] in the string. */
if ((p = strchr (cvsroot_copy, '@')) != NULL)
{
*p = '\0';
- CVSroot_username = xstrdup (cvsroot_copy);
+ /* check for a password */
+ if ((q = strchr (cvsroot_copy, ':')) != NULL)
+ {
+ *q = '\0';
+ newroot->password = xstrdup (++q);
+ /* Don't check for *newroot->password == '\0' since
+ * a user could conceivably wish to specify a blank password
+ * (newroot->password == NULL means to use the
+ * password from .cvspass)
+ */
+ }
+
+ /* copy the username */
+ if (*cvsroot_copy != '\0')
+ /* a blank username is impossible, so leave it NULL in that
+ * case so we know to use the default username
+ */
+ newroot->username = xstrdup (cvsroot_copy);
+
cvsroot_copy = ++p;
- if (*CVSroot_username == '\0')
- CVSroot_username = NULL;
}
+ new_hostname = NULL;
if (*cvsroot_copy == '[')
{
p = strchr(cvsroot_copy, ']');
if (p != NULL)
{
*p = '\0';
- CVSroot_hostname = xstrdup (cvsroot_copy+1);
+ new_hostname = xstrdup (cvsroot_copy+1);
*p++ = ']';
if (*p == ':')
- cvsroot_copy = p+1;
+ cvsroot_copy = p;
}
}
- else if ((p = strchr (cvsroot_copy, ':')) != NULL)
+
+ /* now deal with host[:[port]] */
+
+ /* the port */
+ if ((p = strchr (cvsroot_copy, ':')) != NULL)
{
- *p = '\0';
- CVSroot_hostname = xstrdup (cvsroot_copy);
- cvsroot_copy = ++p;
-
- if (*CVSroot_hostname == '\0')
- CVSroot_hostname = NULL;
+ *p++ = '\0';
+ if (strlen(p))
+ {
+ q = p;
+ if (*q == '-') q++;
+ while (*q)
+ {
+ if (!isdigit(*q++))
+ {
+ error(0, 0, "CVSROOT (\"%s\")", root_in);
+ error(0, 0, "may only specify a positive, non-zero, integer port (not \"%s\").",
+ p);
+ error(0, 0, "perhaps you entered a relative pathname?");
+ free (cvsroot_save);
+ if (new_hostname != NULL)
+ free (new_hostname);
+ goto error_exit;
+ }
+ }
+ if ((newroot->port = atoi (p)) <= 0)
+ {
+ error (0, 0, "CVSROOT (\"%s\")", root_in);
+ error(0, 0, "may only specify a positive, non-zero, integer port (not \"%s\").",
+ p);
+ error(0, 0, "perhaps you entered a relative pathname?");
+ if (new_hostname != NULL)
+ free (new_hostname);
+ free (cvsroot_save);
+ goto error_exit;
+ }
+ }
}
+
+ /* copy host */
+ if (new_hostname != NULL)
+ newroot->hostname = new_hostname;
+ else if (*cvsroot_copy != '\0')
+ /* blank hostnames are invalid, but for now leave the field NULL
+ * and catch the error during the sanity checks later
+ */
+ newroot->hostname = xstrdup (cvsroot_copy);
+
+ /* restore the '/' */
+ cvsroot_copy = firstslash;
+ *cvsroot_copy = '/';
}
- CVSroot_directory = xstrdup(cvsroot_copy);
+ /* parse the path for all methods */
+ newroot->directory = xstrdup(cvsroot_copy);
free (cvsroot_save);
+ /*
+ * Do various sanity checks.
+ */
+
#if ! defined (CLIENT_SUPPORT) && ! defined (DEBUG)
- if (CVSroot_method != local_method)
+ if (newroot->method != local_method)
{
- error (0, 0, "Your CVSROOT is set for a remote access method");
- error (0, 0, "but your CVS executable doesn't support it");
- error (0, 0, "(%s)", CVSroot);
- return 1;
+ error (0, 0, "CVSROOT \"%s\"", root_in);
+ error (0, 0, "is set for a remote access method but your");
+ error (0, 0, "CVS executable doesn't support it");
+ goto error_exit;
}
#endif
-
- /* Do various sanity checks. */
- if (CVSroot_username && ! CVSroot_hostname)
+#if ! defined (SERVER_SUPPORT) && ! defined (DEBUG)
+ if (newroot->method == fork_method)
+ {
+ error (0, 0, "CVSROOT \"%s\"", root_in);
+ error (0, 0, "is set to use the :fork: access method but your");
+ error (0, 0, "CVS executable doesn't support it");
+ goto error_exit;
+ }
+#endif
+
+ if (newroot->username && ! newroot->hostname)
{
- error (0, 0, "missing hostname in CVSROOT: %s", CVSroot);
- return 1;
+ error (0, 0, "missing hostname in CVSROOT: \"%s\"", root_in);
+ goto error_exit;
}
check_hostname = 0;
- switch (CVSroot_method)
+ no_password = 0;
+ no_port = 0;
+ switch (newroot->method)
{
case local_method:
- if (CVSroot_username || CVSroot_hostname)
+ if (newroot->username || newroot->hostname)
{
error (0, 0, "can't specify hostname and username in CVSROOT");
+ error (0, 0, "(\"%s\")", root_in);
error (0, 0, "when using local access method");
- error (0, 0, "(%s)", CVSroot);
- return 1;
+ goto error_exit;
}
/* cvs.texinfo has always told people that CVSROOT must be an
absolute pathname. Furthermore, attempts to use a relative
pathname produced various errors (I couldn't get it to work),
so there would seem to be little risk in making this a fatal
error. */
- if (!isabsolute (CVSroot_directory))
- error (1, 0, "CVSROOT %s must be an absolute pathname",
- CVSroot_directory);
+ if (!isabsolute (newroot->directory))
+ {
+ error (0, 0, "CVSROOT \"%s\" must be an absolute pathname",
+ newroot->directory);
+ goto error_exit;
+ }
+ no_port = 1;
+ no_password = 1;
break;
case fork_method:
/* We want :fork: to behave the same as other remote access
methods. Therefore, don't check to see that the repository
name is absolute -- let the server do it. */
- if (CVSroot_username || CVSroot_hostname)
+ if (newroot->username || newroot->hostname)
{
error (0, 0, "can't specify hostname and username in CVSROOT");
+ error (0, 0, "(\"%s\")", root_in);
error (0, 0, "when using fork access method");
- error (0, 0, "(%s)", CVSroot);
- return 1;
+ goto error_exit;
+ }
+ if (!isabsolute (newroot->directory))
+ {
+ error (0, 0, "CVSROOT \"%s\" must be an absolute pathname",
+ newroot->directory);
+ goto error_exit;
}
+ no_port = 1;
+ no_password = 1;
break;
case kserver_method:
#ifndef HAVE_KERBEROS
- error (0, 0, "Your CVSROOT is set for a kerberos access method");
- error (0, 0, "but your CVS executable doesn't support it");
- error (0, 0, "(%s)", CVSroot);
- return 1;
+ error (0, 0, "CVSROOT \"%s\"", root_in);
+ error (0, 0, "is set for a kerberos access method but your");
+ error (0, 0, "CVS executable doesn't support it");
+ goto error_exit;
#else
check_hostname = 1;
break;
#endif
case gserver_method:
#ifndef HAVE_GSSAPI
- error (0, 0, "Your CVSROOT is set for a GSSAPI access method");
- error (0, 0, "but your CVS executable doesn't support it");
- error (0, 0, "(%s)", CVSroot);
- return 1;
+ error (0, 0, "CVSROOT \"%s\"", root_in);
+ error (0, 0, "is set for a GSSAPI access method but your");
+ error (0, 0, "CVS executable doesn't support it");
+ goto error_exit;
#else
check_hostname = 1;
break;
#endif
case server_method:
case ext_method:
+ no_port = 1;
+ no_password = 1;
+ check_hostname = 1;
+ break;
case pserver_method:
check_hostname = 1;
break;
}
- if (check_hostname)
+ if (no_password && newroot->password)
+ {
+ error (0, 0, "CVSROOT password specification is only valid for");
+ error (0, 0, "pserver connection method.");
+ goto error_exit;
+ }
+
+ if (check_hostname && !newroot->hostname)
{
- if (! CVSroot_hostname)
+ error (0, 0, "didn't specify hostname in CVSROOT: %s", root_in);
+ goto error_exit;
+ }
+
+ if (no_port && newroot->port)
{
- error (0, 0, "didn't specify hostname in CVSROOT: %s", CVSroot);
- return 1;
+ error (0, 0, "CVSROOT port specification is only valid for gserver, kserver,");
+ error (0, 0, "and pserver connection methods.");
+ goto error_exit;
}
- }
- if (*CVSroot_directory == '\0')
+ if (*newroot->directory == '\0')
{
- error (0, 0, "missing directory in CVSROOT: %s", CVSroot);
- return 1;
+ error (0, 0, "missing directory in CVSROOT: %s", root_in);
+ goto error_exit;
}
/* Hooray! We finally parsed it! */
- return 0;
+ return newroot;
+
+error_exit:
+ free_cvsroot_t (newroot);
+ return NULL;
}
-/* Set up the global CVSroot* variables as if we're using the local
- repository DIR. */
-void
-set_local_cvsroot (dir)
+#ifdef AUTH_CLIENT_SUPPORT
+/* Use root->username, root->hostname, root->port, and root->directory
+ * to create a normalized CVSROOT fit for the .cvspass file
+ *
+ * username defaults to the result of getcaller()
+ * port defaults to the result of get_cvs_port_number()
+ *
+ * FIXME - we could cache the canonicalized version of a root inside the
+ * cvsroot_t, but we'd have to un'const the input here and stop expecting the
+ * caller to be responsible for our return value
+ */
+char *
+normalize_cvsroot (root)
+ const cvsroot_t *root;
+{
+ char *cvsroot_canonical;
+ char *p, *hostname, *username;
+ char port_s[64];
+
+ /* get the appropriate port string */
+ sprintf (port_s, "%d", get_cvs_port_number (root));
+
+ /* use a lower case hostname since we know hostnames are case insensitive */
+ /* Some logic says we should be tacking our domain name on too if it isn't
+ * there already, but for now this works. Reverse->Forward lookups are
+ * almost certainly too much since that would make CVS immune to some of
+ * the DNS trickery that makes life easier for sysadmins when they want to
+ * move a repository or the like
+ */
+ p = hostname = xstrdup(root->hostname);
+ while (*p)
+ {
+ *p = tolower(*p);
+ p++;
+ }
+
+ /* get the username string */
+ username = root->username ? root->username : getcaller();
+ cvsroot_canonical = xmalloc ( strlen(username)
+ + strlen(hostname) + strlen(port_s)
+ + strlen(root->directory) + 12);
+ sprintf (cvsroot_canonical, ":pserver:%s@%s:%s%s",
+ username, hostname, port_s, root->directory);
+
+ free (hostname);
+ return cvsroot_canonical;
+}
+#endif /* AUTH_CLIENT_SUPPORT */
+
+
+
+/* allocate and return a cvsroot_t structure set up as if we're using the local
+ * repository DIR. */
+cvsroot_t *
+local_cvsroot (dir)
char *dir;
{
- if (CVSroot_original != NULL)
- free (CVSroot_original);
- CVSroot_original = xstrdup(dir);
- CVSroot_method = local_method;
- if (CVSroot_directory != NULL)
- free (CVSroot_directory);
- CVSroot_directory = xstrdup(dir);
- if (CVSroot_username != NULL)
- free (CVSroot_username);
- CVSroot_username = NULL;
- if (CVSroot_hostname != NULL)
- free (CVSroot_hostname);
- CVSroot_hostname = NULL;
- client_active = 0;
+ cvsroot_t *newroot = new_cvsroot_t();
+
+ newroot->original = xstrdup(dir);
+ newroot->method = local_method;
+ newroot->directory = xstrdup(dir);
+
+ return newroot;
}
+
#ifdef DEBUG
/* This is for testing the parsing function. Use
@@ -553,7 +775,6 @@ set_local_cvsroot (dir)
#include <stdio.h>
-char *CVSroot;
char *program_name = "testing";
char *command_name = "parse_cvsroot"; /* XXX is this used??? */
@@ -567,13 +788,6 @@ error_exit PROTO ((void))
exit (1);
}
-char *
-xstrdup (str)
- const char *str;
-{
- return strdup (str);
-}
-
int
isabsolute (dir)
const char *dir;
@@ -594,18 +808,18 @@ main (argc, argv)
exit (2);
}
- if (parse_cvsroot (argv[1]))
+ if ((current_parsed_root = parse_cvsroot (argv[1])) == NULL)
{
fprintf (stderr, "%s: Parsing failed.\n", program_name);
exit (1);
}
printf ("CVSroot: %s\n", argv[1]);
- printf ("CVSroot_method: %s\n", method_names[CVSroot_method]);
- printf ("CVSroot_username: %s\n",
- CVSroot_username ? CVSroot_username : "NULL");
- printf ("CVSroot_hostname: %s\n",
- CVSroot_hostname ? CVSroot_hostname : "NULL");
- printf ("CVSroot_directory: %s\n", CVSroot_directory);
+ printf ("current_parsed_root->method: %s\n", method_names[current_parsed_root->method]);
+ printf ("current_parsed_root->username: %s\n",
+ current_parsed_root->username ? current_parsed_root->username : "NULL");
+ printf ("current_parsed_root->hostname: %s\n",
+ current_parsed_root->hostname ? current_parsed_root->hostname : "NULL");
+ printf ("current_parsed_root->directory: %s\n", current_parsed_root->directory);
exit (0);
/* NOTREACHED */
diff --git a/gnu/usr.bin/cvs/src/rtag.c b/gnu/usr.bin/cvs/src/rtag.c
deleted file mode 100644
index bc14d8819cb..00000000000
--- a/gnu/usr.bin/cvs/src/rtag.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright (c) 1992, Brian Berliner and Jeff Polk
- * Copyright (c) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Rtag
- *
- * Add or delete a symbolic name to an RCS file, or a collection of RCS files.
- * Uses the modules database, if necessary.
- */
-
-#include "cvs.h"
-
-static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int check_filesdoneproc PROTO ((void *callerdat, int err,
- char *repos, char *update_dir,
- List *entries));
-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 ((void *callerdat, char *dir,
- char *repos, char *update_dir,
- List *entries));
-static int rtag_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int rtag_filesdoneproc PROTO ((void *callerdat, int err,
- char *repos, char *update_dir,
- List *entries));
-static int rtag_proc PROTO((int argc, 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 numtag_validated = 0;
-static int delete_flag; /* adding a tag by default */
-static int attic_too; /* remove tag from Attic files */
-static int branch_mode; /* make an automagic "branch" tag */
-static char *date;
-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 const char *const rtag_usage[] =
-{
- "Usage: %s %s [-aflRnF] [-b] [-d] [-r rev|-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-d\tDelete the given Tag.\n",
- "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
- "\t-r rev\tExisting revision/tag.\n",
- "\t-D\tExisting date.\n",
- "\t-F\tMove tag if it already exists\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-rtag (argc, argv)
- int argc;
- char **argv;
-{
- register int i;
- int c;
- DBM *db;
- int run_module_prog = 1;
- int err = 0;
-
- if (argc == -1)
- usage (rtag_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+FanfQqlRdbr:D:")) != -1)
- {
- switch (c)
- {
- case 'a':
- attic_too = 1;
- break;
- case 'n':
- run_module_prog = 0;
- break;
- 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 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'd':
- delete_flag = 1;
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case 'b':
- branch_mode = 1;
- break;
- case 'r':
- numtag = optarg;
- break;
- case 'D':
- if (date)
- free (date);
- date = Make_Date (optarg);
- break;
- case 'F':
- force_tag_move = 1;
- break;
- case '?':
- default:
- usage (rtag_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 2)
- usage (rtag_usage);
- symtag = argv[0];
- argc--;
- argv++;
-
- if (date && numtag)
- error (1, 0, "-r and -D options are mutually exclusive");
- if (delete_flag && branch_mode)
- 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 (!force_tag_match)
- send_arg ("-f");
- if (local)
- send_arg("-l");
- if (delete_flag)
- 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]);
- }
-
- send_to_server ("rtag\012", 0);
- return get_responses_and_close ();
- }
-#endif
-
- db = open_module ();
- for (i = 0; i < argc; i++)
- {
- /* XXX last arg should be repository, but doesn't make sense here */
- history_write ('T', (delete_flag ? "D" : (numtag ? numtag :
- (date ? date : "A"))), symtag, argv[i], "");
- err += do_module (db, argv[i], TAG,
- delete_flag ? "Untagging" : "Tagging",
- rtag_proc, (char *) NULL, 0, 0, run_module_prog,
- symtag);
- }
- close_module (db);
- return (err);
-}
-
-/*
- * callback proc for doing the real work of tagging
- */
-/* ARGSUSED */
-static int
-rtag_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
- mname, msg)
- int argc;
- char **argv;
- char *xwhere;
- char *mwhere;
- char *mfile;
- int shorten;
- int local_specified;
- char *mname;
- char *msg;
-{
- /* Begin section which is identical to patch_proc--should this
- be abstracted out somehow? */
- char *myargv[2];
- int err = 0;
- int which;
- char *repository;
- char *where;
-
- repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile)) + 30);
- (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
- where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile))
- + 10);
- (void) strcpy (where, argv[0]);
-
- /* if mfile isn't null, we need to set up to do only part of the module */
- if (mfile != NULL)
- {
- char *cp;
- char *path;
-
- /* if the portion of the module is a path, put the dir part on repos */
- if ((cp = strrchr (mfile, '/')) != NULL)
- {
- *cp = '\0';
- (void) strcat (repository, "/");
- (void) strcat (repository, mfile);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- mfile = cp + 1;
- }
-
- /* take care of the rest */
- path = xmalloc (strlen (repository) + strlen (mfile) + 5);
- (void) sprintf (path, "%s/%s", repository, mfile);
- if (isdir (path))
- {
- /* directory means repository gets the dir tacked on */
- (void) strcpy (repository, path);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- }
- else
- {
- myargv[0] = argv[0];
- myargv[1] = mfile;
- argc = 2;
- argv = myargv;
- }
- free (path);
- }
-
- /* cd to the starting repository */
- if ( CVS_CHDIR (repository) < 0)
- {
- error (0, errno, "cannot chdir to %s", repository);
- free (repository);
- return (1);
- }
- free (repository);
- /* End section which is identical to patch_proc. */
-
- if (delete_flag || attic_too || (force_tag_match && numtag))
- which = W_REPOS | W_ATTIC;
- else
- which = W_REPOS;
-
- if (numtag != NULL && !numtag_validated)
- {
- tag_check_valid (numtag, argc - 1, argv + 1, local, 0, NULL);
- numtag_validated = 1;
- }
-
- /* 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, NULL,
- argc - 1, argv + 1, local, which, 0, 1,
- where, 1);
-
- if (err)
- {
- error (1, 0, "correct the above errors first!");
- }
-
- /* start the recursion processor */
- err = start_recursion (rtag_fileproc, rtag_filesdoneproc, rtag_dirproc,
- (DIRLEAVEPROC) NULL, NULL,
- argc - 1, argv + 1, local,
- which, 0, 0, where, 1);
- free (where);
- 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 (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *xdir;
- Node *p;
- Vers_TS *vers;
-
- if (finfo->update_dir[0] == '\0')
- xdir = ".";
- else
- xdir = finfo->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 (finfo->file);
- p->type = UPDATE;
- p->delproc = tag_delproc;
- vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
- p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match,
- (int *) NULL);
- if (p->data != NULL)
- {
- int addit = 1;
- char *oversion;
-
- oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (oversion == NULL)
- {
- if (delete_flag)
- {
- /* Deleting a tag which did not exist is a noop and
- should not be logged. */
- addit = 0;
- }
- }
- else if (delete_flag)
- {
- free (p->data);
- p->data = xstrdup (oversion);
- }
- 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 (callerdat, err, repos, update_dir, entries)
- void *callerdat;
- int err;
- char *repos;
- char *update_dir;
- List *entries;
-{
- 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 ((unsigned char) *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 (filter);
- run_arg (symtag);
- run_arg (delete_flag ? "del" : force_tag_move ? "mov" : "add");
- run_arg (repository);
- walklist(tlist, pretag_list_proc, NULL);
- return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL));
-}
-
-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.
- */
-/* ARGSUSED */
-static int
-rtag_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- RCSNode *rcsfile;
- char *version, *rev;
- int retcode = 0;
-
- /* Lock the directory if it is not already locked. We might be
- able to rely on rtag_dirproc for this. */
-
- /* It would be nice to provide consistency with respect to
- commits; however CVS lacks the infrastructure to do that (see
- Concurrency in cvs.texinfo and comment in do_recursion). We
- can and will prevent simultaneous tag operations from
- interfering with each other, by write locking each directory as
- we enter it, and unlocking it as we leave it. */
-
- lock_dir_for_write (finfo->repository);
-
- /* find the parsed RCS data */
- if ((rcsfile = finfo->rcs) == NULL)
- return (1);
-
- /*
- * For tagging an RCS file which is a symbolic link, you'd best be
- * running with RCS 5.6, since it knows how to handle symbolic links
- * correctly without breaking your link!
- */
-
- if (delete_flag)
- return (rtag_delete (rcsfile));
-
- /*
- * If we get here, we are adding a tag. But, if -a was specified, we
- * need to check to see if a -r or -D option was specified. If neither
- * was specified and the file is in the Attic, remove the tag.
- */
- if (attic_too && (!numtag && !date))
- {
- if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC))
- return (rtag_delete (rcsfile));
- }
-
- version = RCS_getversion (rcsfile, numtag, date, force_tag_match,
- (int *) NULL);
- if (version == NULL)
- {
- /* If -a specified, clean up any old tags */
- if (attic_too)
- (void) rtag_delete (rcsfile);
-
- if (!quiet && !force_tag_match)
- {
- error (0, 0, "cannot find tag `%s' in `%s'",
- numtag ? numtag : "head", rcsfile->path);
- return (1);
- }
- return (0);
- }
- if (numtag
- && isdigit ((unsigned char) *numtag)
- && strcmp (numtag, version) != 0)
- {
-
- /*
- * We didn't find a match for the numeric tag that was specified, but
- * that's OK. just pass the numeric tag on to rcs, to be tagged as
- * specified. Could get here if one tried to tag "1.1.1" and there
- * was a 1.1.1 branch with some head revision. In this case, we want
- * the tag to reference "1.1.1" and not the revision at the head of
- * the branch. Use a symbolic tag for that.
- */
- rev = branch_mode ? RCS_magicrev (rcsfile, version) : numtag;
- retcode = RCS_settag(rcsfile, symtag, numtag);
- if (retcode == 0)
- RCS_rewrite (rcsfile, NULL, NULL);
- }
- else
- {
- char *oversion;
-
- /*
- * As an enhancement for the case where a tag is being re-applied to
- * a large body of a module, make one extra call to RCS_getversion to
- * see if the tag is already set in the RCS file. If so, check to
- * see if it needs to be moved. If not, do nothing. This will
- * likely save a lot of time when simply moving the tag to the
- * "current" head revisions of a module -- which I have found to be a
- * typical tagging operation.
- */
- rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
- oversion = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (oversion != NULL)
- {
- int isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
-
- /*
- * if versions the same and neither old or new are branches don't
- * have to do anything
- */
- if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
- {
- free (oversion);
- free (version);
- return (0);
- }
-
- if (!force_tag_move)
- {
- /* we're NOT going to move the tag */
- (void) printf ("W %s", finfo->fullname);
-
- (void) printf (" : %s already exists on %s %s",
- symtag, isbranch ? "branch" : "version",
- oversion);
- (void) printf (" : NOT MOVING tag to %s %s\n",
- branch_mode ? "branch" : "version", rev);
- free (oversion);
- free (version);
- return (0);
- }
- free (oversion);
- }
- retcode = RCS_settag(rcsfile, symtag, rev);
- if (retcode == 0)
- RCS_rewrite (rcsfile, NULL, NULL);
- }
-
- if (retcode != 0)
- {
- error (1, retcode == -1 ? errno : 0,
- "failed to set tag `%s' to revision `%s' in `%s'",
- symtag, rev, rcsfile->path);
- if (branch_mode)
- free (rev);
- free (version);
- return (1);
- }
- if (branch_mode)
- free (rev);
- free (version);
- return (0);
-}
-
-/*
- * If -d is specified, "force_tag_match" is set, so that this call to
- * RCS_getversion() will return a NULL version string if the symbolic
- * tag does not exist in the RCS file.
- *
- * If the -r flag was used, numtag is set, and we only delete the
- * symtag from files that have numtag.
- *
- * This is done here because it's MUCH faster than just blindly calling
- * "rcs" to remove the tag... trust me.
- */
-static int
-rtag_delete (rcsfile)
- RCSNode *rcsfile;
-{
- char *version;
- int retcode;
-
- if (numtag)
- {
- version = RCS_getversion (rcsfile, numtag, (char *) NULL, 1,
- (int *) NULL);
- if (version == NULL)
- return (0);
- free (version);
- }
-
- version = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (version == NULL)
- return (0);
- free (version);
-
- if ((retcode = RCS_deltag(rcsfile, symtag)) != 0)
- {
- if (!quiet)
- error (0, retcode == -1 ? errno : 0,
- "failed to remove tag `%s' from `%s'", symtag,
- rcsfile->path);
- return (1);
- }
- RCS_rewrite (rcsfile, NULL, NULL);
- return (0);
-}
-
-/* Clear any lock we may hold on the current directory. */
-
-static int
-rtag_filesdoneproc (callerdat, err, repos, update_dir, entries)
- void *callerdat;
- int err;
- char *repos;
- char *update_dir;
- List *entries;
-{
- Lock_Cleanup ();
-
- return (err);
-}
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-rtag_dirproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- char *dir;
- char *repos;
- char *update_dir;
- List *entries;
-{
- if (ignore_directory (update_dir))
- {
- /* print the warm fuzzy message */
- if (!quiet)
- error (0, 0, "Ignoring %s", update_dir);
- return R_SKIP_ALL;
- }
-
- if (!quiet)
- error (0, 0, "%s %s", delete_flag ? "Untagging" : "Tagging",
- update_dir);
- return (R_PROCESS);
-}
-
-
-
diff --git a/gnu/usr.bin/cvs/src/server.c b/gnu/usr.bin/cvs/src/server.c
index c55c416d484..eae6ae95004 100644
--- a/gnu/usr.bin/cvs/src/server.c
+++ b/gnu/usr.bin/cvs/src/server.c
@@ -16,50 +16,19 @@
#include "getline.h"
#include "buffer.h"
-#ifdef SERVER_SUPPORT
-
-#ifdef HAVE_WINSOCK_H
-#include <winsock.h>
-#endif
-
-#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_KERBEROS
-# include <netinet/in.h>
-# include <krb.h>
-# ifndef HAVE_KRB_GET_ERR_TEXT
-# define krb_get_err_text(status) krb_err_txt[status]
-# endif
-
-/* Information we need if we are going to use Kerberos encryption. */
-static C_Block kblock;
-static Key_schedule sched;
-
-#endif
-
-#ifdef HAVE_GSSAPI
-
-#include <netdb.h>
-
-#ifdef HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif
-#ifdef HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#endif
-#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
-#include <gssapi/gssapi_generic.h>
-#endif
-
-#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
-#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
-#endif
-
+#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
+# ifdef HAVE_GSSAPI
+/* This stuff isn't included solely with SERVER_SUPPORT since some of these
+ * functions (encryption & the like) get compiled with or without server
+ * support.
+ *
+ * FIXME - They should be in a different file.
+ */
+# include <netdb.h>
+# include "xgssapi.h"
/* We use Kerberos 5 routines to map the GSSAPI credential to a user
name. */
-#include <krb5.h>
+# include <krb5.h>
/* We need this to wrap data. */
static gss_ctx_id_t gcontext;
@@ -69,37 +38,46 @@ static void gserver_authenticate_connection PROTO((void));
/* Whether we are already wrapping GSSAPI communication. */
static int cvs_gssapi_wrapping;
-# ifdef ENCRYPTION
+# ifdef ENCRYPTION
/* Whether to encrypt GSSAPI communication. We use a global variable
like this because we use the same buffer type (gssapi_wrap) to
handle both authentication and encryption, and we don't want
multiple instances of that buffer in the communication stream. */
int cvs_gssapi_encrypt;
-# endif
+# endif
+# endif /* HAVE_GSSAPI */
+#endif /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */
+#ifdef SERVER_SUPPORT
+
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
#endif
-/* for select */
-#include <sys/types.h>
-#ifdef HAVE_SYS_BSDTYPES_H
-#include <sys/bsdtypes.h>
+#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
+#include <sys/socket.h>
#endif
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
#endif
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#ifdef HAVE_KERBEROS
+# include <netinet/in.h>
+# include <krb.h>
+# ifndef HAVE_KRB_GET_ERR_TEXT
+# define krb_get_err_text(status) krb_err_txt[status]
+# endif
+
+/* Information we need if we are going to use Kerberos encryption. */
+static C_Block kblock;
+static Key_schedule sched;
+
#endif
+/* for select */
+#include "xselect.h"
+
#ifndef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
#endif
@@ -112,18 +90,16 @@ int cvs_gssapi_encrypt;
#define blocking_error(err) ((err) == EAGAIN)
#endif
-#ifdef AUTH_SERVER_SUPPORT
-#ifdef HAVE_GETSPNAM
-#include <shadow.h>
-#endif
-#endif /* AUTH_SERVER_SUPPORT */
-
/* For initgroups(). */
#if HAVE_INITGROUPS
#include <grp.h>
#endif /* HAVE_INITGROUPS */
-
-#ifdef AUTH_SERVER_SUPPORT
+
+# ifdef AUTH_SERVER_SUPPORT
+
+# ifdef HAVE_GETSPNAM
+# include <shadow.h>
+# endif
/* The cvs username sent by the client, which might or might not be
the same as the system username the server eventually switches to
@@ -139,7 +115,7 @@ static char *Pserver_Repos = NULL;
CVSROOT/config. */
int system_auth = 1;
-#endif /* AUTH_SERVER_SUPPORT */
+# endif /* AUTH_SERVER_SUPPORT */
/* While processing requests, this buffer accumulates data to be sent to
@@ -420,10 +396,10 @@ create_adm_p (base_dir, dir)
differently. */
char *empty;
- empty = malloc (strlen (CVSroot_directory)
+ empty = malloc (strlen (current_parsed_root->directory)
+ sizeof (CVSROOTADM)
+ sizeof (CVSNULLREPOS)
- + 10);
+ + 3);
if (! empty)
{
retval = ENOMEM;
@@ -431,7 +407,7 @@ create_adm_p (base_dir, dir)
}
/* Create the directory name. */
- (void) sprintf (empty, "%s/%s/%s", CVSroot_directory,
+ (void) sprintf (empty, "%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSNULLREPOS);
/* Create the directory if it doesn't exist. */
@@ -597,10 +573,16 @@ print_error (status)
int status;
{
char *msg;
+ char tmpstr[80];
+
buf_output0 (buf_to_net, "error ");
msg = strerror (status);
- if (msg)
- buf_output0 (buf_to_net, msg);
+ if (msg == NULL)
+ {
+ sprintf (tmpstr, "unknown error %d", status);
+ msg = tmpstr;
+ }
+ buf_output0 (buf_to_net, msg);
buf_append_char (buf_to_net, '\n');
buf_flush (buf_to_net, 0);
@@ -767,7 +749,7 @@ serve_root (arg)
new connection. Doing this would cause interoperability
headaches, so it should be a different request, if there is
any reason why such a feature is needed. */
- if (CVSroot_directory != NULL)
+ if (current_parsed_root != NULL)
{
if (alloc_pending (80 + strlen (arg)))
sprintf (pending_error_text,
@@ -790,21 +772,24 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"",
}
}
#endif
- set_local_cvsroot (arg);
+
+ if (current_parsed_root != NULL)
+ free_cvsroot_t (current_parsed_root);
+ current_parsed_root = local_cvsroot (arg);
/* For pserver, this will already have happened, and the call will do
nothing. But for rsh, we need to do it now. */
- parse_config (CVSroot_directory);
+ parse_config (current_parsed_root->directory);
- path = malloc (strlen (CVSroot_directory)
+ path = malloc (strlen (current_parsed_root->directory)
+ sizeof (CVSROOTADM)
- + 10);
+ + 2);
if (path == NULL)
{
pending_error = ENOMEM;
return;
}
- (void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
+ (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
if (readonlyfs == 0 && !isaccessible (path, R_OK | X_OK))
{
int save_errno = errno;
@@ -815,13 +800,13 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"",
free (path);
#ifdef HAVE_PUTENV
- env = malloc (strlen (CVSROOT_ENV) + strlen (CVSroot_directory) + 1 + 1);
+ env = malloc (strlen (CVSROOT_ENV) + strlen (current_parsed_root->directory) + 2);
if (env == NULL)
{
pending_error = ENOMEM;
return;
}
- (void) sprintf (env, "%s=%s", CVSROOT_ENV, CVSroot_directory);
+ (void) sprintf (env, "%s=%s", CVSROOT_ENV, current_parsed_root->directory);
(void) putenv (env);
/* do not free env, as putenv has control of it */
#endif
@@ -864,14 +849,14 @@ server_pathname_check (path)
static int outside_root PROTO ((char *));
/* Is file or directory REPOS an absolute pathname within the
- CVSroot_directory? If yes, return 0. If no, set pending_error
+ current_parsed_root->directory? If yes, return 0. If no, set pending_error
and return 1. */
static int
outside_root (repos)
char *repos;
{
size_t repos_len = strlen (repos);
- size_t root_len = strlen (CVSroot_directory);
+ size_t root_len = strlen (current_parsed_root->directory);
/* I think isabsolute (repos) should always be true, and that
any RELATIVE_REPOS stuff should only be in CVS/Repository
@@ -886,15 +871,15 @@ E protocol error: %s is not absolute", repos);
}
if (repos_len < root_len
- || strncmp (CVSroot_directory, repos, root_len) != 0)
+ || strncmp (current_parsed_root->directory, repos, root_len) != 0)
{
not_within:
- if (alloc_pending (strlen (CVSroot_directory)
+ if (alloc_pending (strlen (current_parsed_root->directory)
+ strlen (repos)
+ 80))
sprintf (pending_error_text, "\
E protocol error: directory '%s' not within root '%s'",
- repos, CVSroot_directory);
+ repos, current_parsed_root->directory);
return 1;
}
if (repos_len > root_len)
@@ -1097,8 +1082,9 @@ dirswitch (dir, repos)
(e.g., an entry like ``world -a .'') by putting /. at the end
of the Repository file, so we do the same. */
if (strcmp (dir, ".") == 0
- && CVSroot_directory != NULL
- && strcmp (CVSroot_directory, repos) == 0)
+ && current_parsed_root != NULL
+ && current_parsed_root->directory != NULL
+ && strcmp (current_parsed_root->directory, repos) == 0)
{
if (fprintf (f, "/.") < 0)
{
@@ -2428,6 +2414,9 @@ error ENOMEM Virtual memory exhausted.\n";
/* If this gives an error, not much we could do. syslog() it? */
write (STDOUT_FILENO, msg, sizeof (msg) - 1);
+#ifdef HAVE_SYSLOG_H
+ syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted");
+#endif
error_exit ();
}
@@ -2485,13 +2474,13 @@ check_command_legal_p (cmd_name)
int found_it = 0;
/* else */
- flen = strlen (CVSroot_directory)
+ flen = strlen (current_parsed_root->directory)
+ strlen (CVSROOTADM)
+ strlen (CVSROOTADM_READERS)
+ 3;
fname = xmalloc (flen);
- (void) sprintf (fname, "%s/%s/%s", CVSroot_directory,
+ (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSROOTADM_READERS);
fp = fopen (fname, "r");
@@ -2537,13 +2526,13 @@ check_command_legal_p (cmd_name)
/* Now check the writers file. */
- flen = strlen (CVSroot_directory)
+ flen = strlen (current_parsed_root->directory)
+ strlen (CVSROOTADM)
+ strlen (CVSROOTADM_WRITERS)
+ 3;
fname = xmalloc (flen);
- (void) sprintf (fname, "%s/%s/%s", CVSroot_directory,
+ (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSROOTADM_WRITERS);
fp = fopen (fname, "r");
@@ -2785,7 +2774,9 @@ error \n");
close (stderr_pipe[0]);
close (stderr_pipe[1]);
close (protocol_pipe[0]);
+ close_on_exec (protocol_pipe[1]);
#ifdef SERVER_FLOWCONTROL
+ close_on_exec (flowcontrol_pipe[0]);
close (flowcontrol_pipe[1]);
#endif /* SERVER_FLOWCONTROL */
@@ -2802,11 +2793,11 @@ error \n");
exitstatus = (*command) (argument_count, argument_vector);
/* Output any partial lines. If the client doesn't support
- "MT", we just throw out the partial line, like old versions
- of CVS did, since the protocol can't support this. */
- if (supported_response ("MT") && ! buf_empty_p (saved_output))
+ "MT", we go ahead and just tack on a newline since the
+ protocol doesn't support anything better. */
+ if (! buf_empty_p (saved_output))
{
- buf_output0 (protocol, "MT text ");
+ buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M ");
buf_append_buffer (protocol, saved_output);
buf_output (protocol, "\n", 1);
buf_send_counted (protocol);
@@ -2829,7 +2820,7 @@ error \n");
struct buffer *protocol_inbuf;
/* Number of file descriptors to check in select (). */
int num_to_check;
- int count_needed = 0;
+ int count_needed = 1;
#ifdef SERVER_FLOWCONTROL
int have_flowcontrolled = 0;
#endif /* SERVER_FLOWCONTROL */
@@ -2917,13 +2908,16 @@ error \n");
while (stdout_pipe[0] >= 0
|| stderr_pipe[0] >= 0
- || protocol_pipe[0] >= 0)
+ || protocol_pipe[0] >= 0
+ || count_needed <= 0)
{
fd_set readfds;
fd_set writefds;
int numfds;
#ifdef SERVER_FLOWCONTROL
int bufmemsize;
+ struct timeval *timeout_ptr;
+ struct timeval timeout;
/*
* See if we are swamping the remote client and filling our VM.
@@ -2944,8 +2938,24 @@ error \n");
FD_ZERO (&readfds);
FD_ZERO (&writefds);
+
+ if (count_needed <= 0)
+ {
+ /* there is data pending which was read from the protocol pipe
+ * so don't block if we don't find any data
+ */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timeout_ptr = &timeout;
+ }
+ else
+ {
+ /* block indefinately */
+ timeout_ptr = NULL;
+ }
+
if (! buf_empty_p (buf_to_net))
- FD_SET (STDOUT_FILENO, &writefds);
+ FD_SET (STDOUT_FILENO, &writefds);
if (stdout_pipe[0] >= 0)
{
@@ -2961,28 +2971,34 @@ error \n");
}
/* This process of selecting on the three pipes means that
- we might not get output in the same order in which it
- was written, thus producing the well-known
- "out-of-order" bug. If the child process uses
- cvs_output and cvs_outerr, it will send everything on
- the protocol_pipe and avoid this problem, so the
- solution is to use cvs_output and cvs_outerr in the
- child process. */
+ we might not get output in the same order in which it
+ was written, thus producing the well-known
+ "out-of-order" bug. If the child process uses
+ cvs_output and cvs_outerr, it will send everything on
+ the protocol_pipe and avoid this problem, so the
+ solution is to use cvs_output and cvs_outerr in the
+ child process. */
do {
/* This used to select on exceptions too, but as far
as I know there was never any reason to do that and
SCO doesn't let you select on exceptions on pipes. */
numfds = select (num_to_check, &readfds, &writefds,
- (fd_set *)0, (struct timeval *)NULL);
+ (fd_set *)0, timeout_ptr);
if (numfds < 0
- && errno != EINTR)
+ && errno != EINTR)
{
buf_output0 (buf_to_net, "E select failed\n");
print_error (errno);
goto error_exit;
}
} while (numfds < 0);
-
+
+ if (numfds == 0)
+ {
+ FD_ZERO (&readfds);
+ FD_ZERO (&writefds);
+ }
+
if (FD_ISSET (STDOUT_FILENO, &writefds))
{
/* What should we do with errors? syslog() them? */
@@ -2994,7 +3010,6 @@ error \n");
{
int status;
int count_read;
- int special;
status = buf_input_data (protocol_inbuf, &count_read);
@@ -3017,29 +3032,49 @@ error \n");
* have.
*/
count_needed -= count_read;
- while (count_needed <= 0)
- {
- count_needed = buf_copy_counted (buf_to_net,
+ }
+ /* this is still part of the protocol pipe procedure, but it is
+ * outside the above conditional so that unprocessed data can be
+ * left in the buffer and stderr/stdout can be read when a flush
+ * signal is received and control can return here without passing
+ * through the select code and maybe blocking
+ */
+ while (count_needed <= 0)
+ {
+ int special = 0;
+
+ count_needed = buf_copy_counted (buf_to_net,
protocol_inbuf,
&special);
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
+ /* What should we do with errors? syslog() them? */
+ buf_send_output (buf_to_net);
- /* If SPECIAL got set to -1, it means that the child
- wants us to flush the pipe. We don't want to block
- on the network, but we flush what we can. If the
- client supports the 'F' command, we send it. */
- if (special == -1)
+ /* If SPECIAL got set to <0, it means that the child
+ * wants us to flush the pipe & maybe stderr or stdout.
+ *
+ * After that we break to read stderr & stdout again before
+ * going back to the protocol pipe
+ *
+ * Upon breaking, count_needed = 0, so the next pass will only
+ * perform a non-blocking select before returning here to finish
+ * processing data we already read from the protocol buffer
+ */
+ if (special == -1)
+ {
+ cvs_flushout();
+ break;
+ }
+ if (special == -2)
+ {
+ /* If the client supports the 'F' command, we send it. */
+ if (supported_response ("F"))
{
- if (supported_response ("F"))
- {
- buf_append_char (buf_to_net, 'F');
- buf_append_char (buf_to_net, '\n');
- }
-
- cvs_flusherr ();
+ buf_append_char (buf_to_net, 'F');
+ buf_append_char (buf_to_net, '\n');
}
+ cvs_flusherr ();
+ break;
}
}
@@ -3426,6 +3461,11 @@ server_scratch (fname)
* two different cases. Using the last one which happens is almost
* surely correct; I haven't tracked down why they both happen (or
* even verified that they are for the same file).
+ *
+ * Don't know if this is what whoever wrote the above comment was
+ * talking about, but this can happen in the case where a join
+ * removes a file - the call to Register puts the '-vers' into the
+ * Entries file after the file is removed
*/
if (entries_line != NULL)
{
@@ -3585,6 +3625,15 @@ serve_log (arg)
}
static void
+serve_rlog (arg)
+ char *arg;
+{
+ /* Tell cvslog() to behave like rlog not log. */
+ command_name = "rlog";
+ do_cvs_command ("rlog", cvslog);
+}
+
+static void
serve_add (arg)
char *arg;
{
@@ -3623,7 +3672,9 @@ static void
serve_rtag (arg)
char *arg;
{
- do_cvs_command ("rtag", rtag);
+ /* Tell cvstag() to behave like rtag not tag. */
+ command_name = "rtag";
+ do_cvs_command ("rtag", cvstag);
}
static void
@@ -3747,7 +3798,10 @@ serve_init (arg)
/* Fall through to do_cvs_command which will return the
actual error. */
}
- set_local_cvsroot (arg);
+
+ if (current_parsed_root != NULL)
+ free_cvsroot_t (current_parsed_root);
+ current_parsed_root = local_cvsroot (arg);
do_cvs_command ("init", init);
}
@@ -3760,6 +3814,17 @@ serve_annotate (arg)
{
do_cvs_command ("annotate", annotate);
}
+
+static void serve_rannotate PROTO ((char *));
+
+static void
+serve_rannotate (arg)
+ char *arg;
+{
+ /* Tell annotate() to behave like rannotate not annotate. */
+ command_name = "rannotate";
+ do_cvs_command ("rannotate", annotate);
+}
static void
serve_co (arg)
@@ -4157,6 +4222,23 @@ CVS server internal error: unhandled case in server_updated");
output_dir (finfo->update_dir, finfo->repository);
buf_output0 (protocol, finfo->file);
buf_output (protocol, "\n", 1);
+ /* keep the vers structure up to date in case we do a join
+ * - if there isn't a file, it can't very well have a version number, can it?
+ *
+ * we do it here on the assumption that since we just told the client
+ * to remove the file/entry, it will, and we want to remember that.
+ * If it fails, that's the client's problem, not ours
+ */
+ if (vers && vers->vn_user != NULL)
+ {
+ free (vers->vn_user);
+ vers->vn_user = NULL;
+ }
+ if (vers && vers->ts_user != NULL)
+ {
+ free (vers->ts_user);
+ vers->ts_user = NULL;
+ }
}
else if (scratched_file == NULL && entries_line == NULL)
{
@@ -4490,7 +4572,7 @@ serve_expand_modules (arg)
for (i = 1; i < argument_count; i++)
err += do_module (db, argument_vector[i],
CHECKOUT, "Updating", expand_proc,
- NULL, 0, 0, 0,
+ NULL, 0, 0, 0, 0,
(char *) NULL);
close_module (db);
server_expanding = 0;
@@ -4691,6 +4773,7 @@ struct request requests[] =
REQ_LINE("update", serve_update, RQ_ESSENTIAL),
REQ_LINE("diff", serve_diff, 0),
REQ_LINE("log", serve_log, 0),
+ REQ_LINE("rlog", serve_rlog, 0),
REQ_LINE("add", serve_add, 0),
REQ_LINE("remove", serve_remove, 0),
REQ_LINE("update-patches", serve_ignore, 0),
@@ -4712,6 +4795,7 @@ struct request requests[] =
REQ_LINE("editors", serve_editors, 0),
REQ_LINE("init", serve_init, RQ_ROOTLESS),
REQ_LINE("annotate", serve_annotate, 0),
+ REQ_LINE("rannotate", serve_rannotate, 0),
REQ_LINE("noop", serve_noop, RQ_ROOTLESS),
REQ_LINE("version", serve_version, RQ_ROOTLESS),
REQ_LINE(NULL, NULL, 0)
@@ -4745,7 +4829,7 @@ serve_valid_requests (arg)
buf_flush (buf_to_net, 1);
}
-#ifdef sun
+#ifdef SUNOS_KLUDGE
/*
* Delete temporary files. SIG is the signal making this happen, or
* 0 if not called as a result of a signal.
@@ -4762,7 +4846,7 @@ static void wait_sig (sig)
command_pid_is_dead++;
errno = save_errno;
}
-#endif
+#endif /* SUNOS_KLUDGE */
void
server_cleanup (sig)
@@ -4806,7 +4890,7 @@ server_cleanup (sig)
/* What a bogus kludge. This disgusting code makes all kinds of
assumptions about SunOS, and is only for a bug in that system.
So only enable it on Suns. */
-#ifdef sun
+#ifdef SUNOS_KLUDGE
if (command_pid > 0)
{
/* To avoid crashes on SunOS due to bugs in SunOS tmpfs
@@ -4879,7 +4963,7 @@ server_cleanup (sig)
}
}
}
-#endif
+#endif /* SUNOS_KLUDGE */
CVS_CHDIR (Tmpdir);
/* Temporarily clear noexec, so that we clean up our temp directory
@@ -5017,19 +5101,25 @@ error ENOMEM Virtual memory exhausted.\n");
pending_error = status;
}
#ifndef CHMOD_BROKEN
- else
+ else if (chmod (server_temp_dir, S_IRWXU) < 0)
{
- if (chmod (server_temp_dir, S_IRWXU) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
+ int save_errno = errno;
+ if (alloc_pending (80 + strlen (server_temp_dir)))
+ sprintf (pending_error_text,
"E cannot change permissions on temporary directory %s",
- server_temp_dir);
- pending_error = save_errno;
- }
+ server_temp_dir);
+ pending_error = save_errno;
}
#endif
+ else if (CVS_CHDIR (server_temp_dir) < 0)
+ {
+ int save_errno = errno;
+ if (alloc_pending (80 + strlen (server_temp_dir)))
+ sprintf (pending_error_text,
+"E cannot change to temporary directory %s",
+ server_temp_dir);
+ pending_error = save_errno;
+ }
}
}
@@ -5125,7 +5215,7 @@ error ENOMEM Virtual memory exhausted.\n");
continue;
if (!(rq->flags & RQ_ROOTLESS)
- && CVSroot_directory == NULL)
+ && current_parsed_root == NULL)
{
/* For commands which change the way in which data
is sent and received, for example Gzip-stream,
@@ -5259,10 +5349,10 @@ error 0 %s: no such user\n", username);
#endif
#if HAVE_PUTENV
- /* Set LOGNAME and USER in the environment, in case they are
- already set to something else. */
+ /* Set LOGNAME, USER and CVS_USER in the environment, in case they
+ are already set to something else. */
{
- char *env;
+ char *env, *cvs_user;
env = xmalloc (sizeof "LOGNAME=" + strlen (username));
(void) sprintf (env, "LOGNAME=%s", username);
@@ -5271,6 +5361,11 @@ error 0 %s: no such user\n", username);
env = xmalloc (sizeof "USER=" + strlen (username));
(void) sprintf (env, "USER=%s", username);
(void) putenv (env);
+
+ cvs_user = NULL != CVS_Username ? CVS_Username : "";
+ env = xmalloc (sizeof "CVS_USER=" + strlen (cvs_user));
+ (void) sprintf (env, "CVS_USER=%s", cvs_user);
+ (void) putenv (env);
}
#endif /* HAVE_PUTENV */
}
@@ -5305,7 +5400,7 @@ check_repository_password (username, password, repository, host_user_ptr)
int found_it = 0;
int namelen;
- /* We don't use CVSroot_directory because it hasn't been set yet
+ /* We don't use current_parsed_root->directory because it hasn't been set yet
* -- our `repository' argument came from the authentication
* protocol, not the regular CVS protocol.
*/
@@ -5635,8 +5730,13 @@ pserver_authenticate_connection ()
{
int on = 1;
- (void) setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof on);
+ if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &on, sizeof on) < 0)
+ {
+#ifdef HAVE_SYSLOG_H
+ syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
+#endif
+ }
}
#endif
@@ -5692,13 +5792,13 @@ pserver_authenticate_connection ()
error (1, 0, "bad auth protocol end: %s", tmp);
}
if (!root_allow_ok (repository))
- /* Just give a generic I HATE YOU. This is because CVS 1.9.10
- and older clients do not support "error". Once more recent
- clients are more widespread, probably want to fix this (it is
- a real pain to track down why it isn't letting you in if it
- won't say why, and I am not convinced that the potential
- information disclosure to an attacker outweighs this). */
+ {
+ printf ("error 0 %s: no such repository\n", repository);
+#ifdef HAVE_SYSLOG_H
+ syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository);
+#endif
goto i_hate_you;
+ }
/* OK, now parse the config file, so we can use it to control how
to check passwords. If there was an error parsing the config
@@ -5714,6 +5814,13 @@ pserver_authenticate_connection ()
free (descrambled_password);
if (host_user == NULL)
{
+#ifdef HAVE_SYSLOG_H
+ syslog (LOG_DAEMON | LOG_NOTICE, "login failure (for %s)", repository);
+#ifdef LOG_AUTHPRIV
+ syslog (LOG_AUTHPRIV | LOG_NOTICE, "login failure by %s / %s (for %s)",
+ username, descrambled_password, repository);
+#endif
+#endif
i_hate_you:
printf ("I HATE YOU\n");
fflush (stdout);
@@ -5795,8 +5902,13 @@ error %s getpeername or getsockname failed\n", strerror (errno));
{
int on = 1;
- (void) setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof on);
+ if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &on, sizeof on) < 0)
+ {
+#ifdef HAVE_SYSLOG_H
+ syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
+#endif
+ }
}
#endif
@@ -6392,13 +6504,20 @@ cvs_flusherr ()
#ifdef SERVER_SUPPORT
if (error_use_protocol)
{
+ /* skip the actual stderr flush in this case since the parent process
+ * on the server should only be writing to stdout anyhow
+ */
/* Flush what we can to the network, but don't block. */
buf_flush (buf_to_net, 0);
}
else if (server_active)
{
+ /* make sure stderr is flushed before we send the flush count on the
+ * protocol pipe
+ */
+ fflush (stderr);
/* Send a special count to tell the parent to flush. */
- buf_send_special_count (protocol, -1);
+ buf_send_special_count (protocol, -2);
}
else
#endif
@@ -6424,7 +6543,13 @@ cvs_flushout ()
cvs_flushout replaces, setting stdout to line buffering in
main.c, didn't get called in the server child process. But
in the future it is quite plausible that we'll want to make
- this case work analogously to cvs_flusherr. */
+ this case work analogously to cvs_flusherr.
+
+ FIXME - DRP - I tried to implement this and triggered the following
+ error: "Protocol error: uncounted data discarded". I don't need
+ this feature right now, so I'm not going to bother with it yet.
+ */
+ buf_send_special_count (protocol, -1);
}
else
#endif
diff --git a/gnu/usr.bin/cvs/src/update.c b/gnu/usr.bin/cvs/src/update.c
index fc93e0da6a7..ec6e81831bd 100644
--- a/gnu/usr.bin/cvs/src/update.c
+++ b/gnu/usr.bin/cvs/src/update.c
@@ -58,7 +58,7 @@ static int patch_file PROTO ((struct file_info *finfo,
static void patch_file_write PROTO ((void *, const char *, size_t));
#endif
static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
-static int scratch_file PROTO((struct file_info *finfo));
+static int scratch_file PROTO((struct file_info *finfo, Vers_TS *vers));
static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir,
char *repository, char *update_dir,
List *entries));
@@ -99,6 +99,7 @@ static int force_tag_match = 1;
static int update_build_dirs = 0;
static int update_prune_dirs = 0;
static int pipeout = 0;
+static int dotemplate = 0;
#ifdef SERVER_SUPPORT
static int patches = 0;
static int rcs_diff_patches = 0;
@@ -107,7 +108,7 @@ static List *ignlist = (List *) NULL;
static time_t last_register_time;
static const char *const update_usage[] =
{
- "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n",
+ "Usage: %s %s [-APCdflRp] [-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",
@@ -117,7 +118,7 @@ static const char *const update_usage[] =
"\t-l\tLocal directory only, no recursion.\n",
"\t-R\tProcess directories recursively.\n",
"\t-p\tSend updates to standard output (avoids stickiness).\n",
- "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
+ "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
"\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
"\t-D date\tSet date to update from (is sticky).\n",
"\t-j rev\tMerge in changes made between current revision and rev.\n",
@@ -233,7 +234,7 @@ update (argc, argv)
argv += optind;
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (current_parsed_root->isremote)
{
int pass;
@@ -409,7 +410,7 @@ update (argc, argv)
/* call the command line interface */
err = do_update (argc, argv, options, tag, date, force_tag_match,
local, update_build_dirs, aflag, update_prune_dirs,
- pipeout, which, join_rev1, join_rev2, (char *) NULL);
+ pipeout, which, join_rev1, join_rev2, (char *) NULL, 1);
/* free the space Make_Date allocated if necessary */
if (date != NULL)
@@ -423,7 +424,8 @@ update (argc, argv)
*/
int
do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
- xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir)
+ xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir,
+ xdotemplate)
int argc;
char **argv;
char *xoptions;
@@ -439,6 +441,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
char *xjoin_rev1;
char *xjoin_rev2;
char *preload_update_dir;
+ int xdotemplate;
{
int err = 0;
char *cp;
@@ -452,6 +455,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
aflag = xaflag;
update_prune_dirs = xprune;
pipeout = xpipeout;
+ dotemplate = xdotemplate;
/* setup the join support */
join_rev1 = xjoin_rev1;
@@ -503,11 +507,15 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
argc, argv, local, which, aflag, 1,
preload_update_dir, 1);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ return err;
+#endif
+
/* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- while (time ((time_t *) NULL) == last_register_time)
- sleep (1);
+ sleep_past (last_register_time);
}
return (err);
@@ -575,9 +583,6 @@ update_fileproc (callerdat, finfo)
int retval;
Ctype status;
Vers_TS *vers;
- int resurrecting;
-
- resurrecting = 0;
status = Classify_File (finfo, tag, date, options, force_tag_match,
aflag, &vers, pipeout);
@@ -623,9 +628,7 @@ update_fileproc (callerdat, finfo)
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 (finfo, vers, 0, 0, 0);
break;
@@ -650,8 +653,12 @@ update_fileproc (callerdat, finfo)
write_letter (finfo, 'C');
break;
case T_NEEDS_MERGE: /* needs merging */
- retval = merge_file (finfo, vers);
- break;
+ if (! toss_local_changes)
+ {
+ retval = merge_file (finfo, vers);
+ break;
+ }
+ /* else FALL THROUGH */
case T_MODIFIED: /* locally modified */
retval = 0;
if (toss_local_changes)
@@ -731,8 +738,8 @@ update_fileproc (callerdat, finfo)
}
}
break;
-#ifdef SERVER_SUPPORT
case T_PATCH: /* needs patch */
+#ifdef SERVER_SUPPORT
if (patches)
{
int docheckout;
@@ -754,11 +761,11 @@ update_fileproc (callerdat, finfo)
break;
}
}
+#endif
/* If we're not running as a server, just check the
file out. It's simpler and faster than producing
and applying patches. */
/* Fall through. */
-#endif
case T_CHECKOUT: /* needs checkout */
retval = checkout_file (finfo, vers, 0, 0, 1);
break;
@@ -771,18 +778,7 @@ update_fileproc (callerdat, finfo)
retval = 0;
break;
case T_REMOVE_ENTRY: /* needs to be un-registered */
- retval = scratch_file (finfo);
-#ifdef SERVER_SUPPORT
- if (server_active && retval == 0)
- {
- if (vers->ts_user == NULL)
- server_scratch_entry_only ();
- server_updated (finfo, vers,
- SERVER_UPDATED, (mode_t) -1,
- (unsigned char *) NULL,
- (struct buffer *) NULL);
- }
-#endif
+ retval = scratch_file (finfo, vers);
break;
default: /* can't ever happen :-) */
error (0, 0,
@@ -797,7 +793,7 @@ update_fileproc (callerdat, finfo)
join_file (finfo, vers);
/* if this directory has an ignore list, add this file to it */
- if (ignlist)
+ if (ignlist && (status != T_UNKNOWN || vers->ts_user == NULL))
{
Node *p;
@@ -877,7 +873,7 @@ update_filesdone_proc (callerdat, err, repository, update_dir, entries)
{
/* If there is no CVS/Root file, add one */
if (!isfile (CVSADM_ROOT))
- Create_Root ((char *) NULL, CVSroot_original);
+ Create_Root ((char *) NULL, current_parsed_root->original);
}
return (err);
@@ -970,7 +966,7 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
via WriteTag. */
0,
0,
- 1);
+ dotemplate);
rewrite_tag = 1;
nonbranch = 0;
Subdir_Register (entries, (char *) NULL, dir);
@@ -1173,7 +1169,7 @@ isemptydir (dir, might_not_exist)
return (0);
}
errno = 0;
- while ((dp = readdir (dirp)) != NULL)
+ while ((dp = CVS_READDIR (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") != 0
&& strcmp (dp->d_name, "..") != 0)
@@ -1182,7 +1178,7 @@ isemptydir (dir, might_not_exist)
{
/* An entry other than the CVS directory. The directory
is certainly not empty. */
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
return (0);
}
else
@@ -1213,7 +1209,7 @@ isemptydir (dir, might_not_exist)
{
/* There are files that have been removed, but not
committed! Do not consider the directory empty. */
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
return (0);
}
}
@@ -1223,10 +1219,10 @@ isemptydir (dir, might_not_exist)
if (errno != 0)
{
error (0, errno, "cannot read directory %s", dir);
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
return (0);
}
- (void) closedir (dirp);
+ (void) CVS_CLOSEDIR (dirp);
return (1);
}
@@ -1234,13 +1230,46 @@ isemptydir (dir, might_not_exist)
* scratch the Entries file entry associated with a file
*/
static int
-scratch_file (finfo)
+scratch_file (finfo, vers)
struct file_info *finfo;
+ Vers_TS *vers;
{
history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
Scratch_Entry (finfo->entries, finfo->file);
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ if (vers->ts_user == NULL)
+ server_scratch_entry_only ();
+ server_updated (finfo, vers,
+ SERVER_UPDATED, (mode_t) -1,
+ (unsigned char *) NULL,
+ (struct buffer *) NULL);
+ }
+#endif
if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
error (0, errno, "unable to remove %s", finfo->fullname);
+ else
+#ifdef SERVER_SUPPORT
+ /* skip this step when the server is running since
+ * server_updated should have handled it */
+ if (!server_active)
+#endif
+ {
+ /* keep the vers structure up to date in case we do a join
+ * - if there isn't a file, it can't very well have a version number, can it?
+ */
+ if (vers->vn_user != NULL)
+ {
+ free (vers->vn_user);
+ vers->vn_user = NULL;
+ }
+ if (vers->ts_user != NULL)
+ {
+ free (vers->ts_user);
+ vers->ts_user = NULL;
+ }
+ }
return (0);
}
@@ -1744,7 +1773,7 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
diff_options = "-n";
}
- retcode = diff_exec (file1, file2, diff_options, finfo->file);
+ retcode = diff_exec (file1, file2, NULL, NULL, diff_options, finfo->file);
/* A retcode of 0 means no differences. 1 means some differences. */
if (retcode != 0
@@ -2120,6 +2149,17 @@ join_file (finfo, vers)
char *jdate1;
char *jdate2;
+ if (trace)
+ fprintf (stderr, "%s-> join_file(%s, %s%s%s%s, %s, %s)\n",
+ CLIENT_SERVER_STR,
+ finfo->file,
+ vers->tag ? vers->tag : "",
+ vers->tag ? " (" : "",
+ vers->vn_rcs ? vers->vn_rcs : "",
+ vers->tag ? ")" : "",
+ join_rev1 ? join_rev1 : "",
+ join_rev2 ? join_rev2 : "");
+
jrev1 = join_rev1;
jrev2 = join_rev2;
jdate1 = date_rev1;
@@ -2288,7 +2328,14 @@ join_file (finfo, vers)
for removal. FIXME: If we are doing a checkout, this has
the effect of first checking out the file, and then
removing it. It would be better to just register the
- removal. */
+ removal.
+
+ The same goes for a removal then an add. e.g.
+ cvs up -rbr -jbr2 could remove and readd the same file
+ */
+ /* save the rev since server_updated might invalidate it */
+ mrev = xmalloc (strlen (vers->vn_user) + 2);
+ sprintf (mrev, "-%s", vers->vn_user);
#ifdef SERVER_SUPPORT
if (server_active)
{
@@ -2297,8 +2344,6 @@ join_file (finfo, vers)
(unsigned char *) NULL, (struct buffer *) NULL);
}
#endif
- mrev = xmalloc (strlen (vers->vn_user) + 2);
- sprintf (mrev, "-%s", vers->vn_user);
Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
vers->options, vers->tag, vers->date, vers->ts_conflict);
free (mrev);
@@ -2341,6 +2386,7 @@ join_file (finfo, vers)
addition. */
if (vers->vn_user == NULL)
{
+ char *saved_options = options;
Vers_TS *xvers;
xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
@@ -2355,6 +2401,7 @@ join_file (finfo, vers)
/* FIXME: If checkout_file fails, we should arrange to
return a non-zero exit status. */
status = checkout_file (finfo, xvers, 1, 0, 1);
+ options = saved_options;
freevers_ts (&xvers);