|
|
|
|
Index: src/README.RSE
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: src/README.RSE
|
|
|
|
|
diff -N src/README.RSE
|
|
|
|
|
--- /dev/null 1 Jan 1970 00:00:00 -0000
|
|
|
|
|
+++ src/README.RSE 16 Feb 2002 12:35:28 -0000
|
|
|
|
|
@@ -0,0 +1,353 @@
|
|
|
|
|
+
|
|
|
|
|
+ CVS RSE Patches
|
|
|
|
|
+ ===============
|
|
|
|
|
+
|
|
|
|
|
+ This is the patched version of CVS from Ralf S. Engelschall
|
|
|
|
|
+ <rse@engelschall.com> - an enhanced version of the official
|
|
|
|
|
+ Cyclic/OpenAvenue's CVS version 1.11.1p1 (see http://www.cvshome.org/).
|
|
|
|
|
+
|
|
|
|
|
+ The following changes against the avendor CVS version are provided:
|
|
|
|
|
+ - support for .cvsrc files in $HOME _AND_ working and and its parent dirs
|
|
|
|
|
+ - support for $HOME/.cvsroot to alias roots and to support root mirrors
|
|
|
|
|
+ - support global but command specific options in .cvsrc files
|
|
|
|
|
+ - support for stand-alone external custom commands `cvs <command>'
|
|
|
|
|
+ - support for prolog and epilog hooks
|
|
|
|
|
+ - allow `verifymsg' hooks to _change_ the log message
|
|
|
|
|
+ - support `$LocalId$, a local keyword variant of `$Id$'
|
|
|
|
|
+ - support `$CVSHeader$, a variant of `$Header$', but without root path
|
|
|
|
|
+ - new `cvs -u' option in addition to `cvs -n' for _REAL_ read-only access
|
|
|
|
|
+ - support for additional `%x' variables on `loginfo' hook command lines
|
|
|
|
|
+ - support a `UMask=<mask>' variable in `$CVSROOT/CVSROOT/config'
|
|
|
|
|
+ - speeded up `cvs update' by sending whole file if smaller than the diff
|
|
|
|
|
+ - disabled keyword expansions during branch merges
|
|
|
|
|
+ - adjusted `cvs diff -rHEAD' to be consistent with other commands
|
|
|
|
|
+ - made `cvs diff' aware of removed/dead files in the trunk
|
|
|
|
|
+ - set `$LOGNAME' to the real user and not the CVS user
|
|
|
|
|
+ - support for `HistoryFile=<rel-path-under-CVSROOT>' variable in config.
|
|
|
|
|
+ - support for an `admininfo' hook to ACL `cvs admin' commands.
|
|
|
|
|
+ - support for an `importinfo' hook to ACL `cvs import' commands.
|
|
|
|
|
+ - support for a `-h<handle>' option to `cvs diff' for compressed time spec.
|
|
|
|
|
+ - use prefix 'T' ("touched/tagged") instead of 'U' ("updated") on `cvs import'
|
|
|
|
|
+ - allow `LockDir' configuration directive to use relative paths
|
|
|
|
|
+ - allow a hard-coded CVS super-user to override CVS user via $CVSUSER
|
|
|
|
|
+ - additional SetUID/SetGID support for `cvs server' situations.
|
|
|
|
|
+ - new `cvs pserverd' for running stand-alone pserver daemons
|
|
|
|
|
+ - new global --map-root=/oldpath:/newpath option for mapping root paths
|
|
|
|
|
+ - support for wildcards in CVSROOT/passwd files to decrease admin efforts
|
|
|
|
|
+ - various cosmetic changes
|
|
|
|
|
+
|
|
|
|
|
+ Some of my RSE functional patches are only useful for the server side,
|
|
|
|
|
+ others are also useful on the client side. All source patches to
|
|
|
|
|
+ *.[ch] files were entirely wrapped with ``#ifdef RSE_PATCH_<NAME> ...
|
|
|
|
|
+ #endif'' pairs. So, a particular patch is enabled by building CVS with
|
|
|
|
|
+ -DRSE_PATCH_<NAME>. All patches are enabled with -DRSE_PATCHES.
|
|
|
|
|
+
|
|
|
|
|
+ Ralf S. Engelschall
|
|
|
|
|
+ rse@engelschall.com
|
|
|
|
|
+ www.engelschall.com
|
|
|
|
|
+ ________________________________________________________________________
|
|
|
|
|
+
|
|
|
|
|
+ The following particular patches are available:
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CVSRC:
|
|
|
|
|
+ In addition to processing `$HOME/.cvsrc', process also `.cvsrc'
|
|
|
|
|
+ files in the current working directory and the parent directories of
|
|
|
|
|
+ the current working directory. This allows one to use for instance a
|
|
|
|
|
+ `commit -m ""' locally (as used for GNU Pth development where CVS is
|
|
|
|
|
+ only used for plain revision control and not for bookkeeping changes
|
|
|
|
|
+ or group communication - instead a plain manually edited ChangeLog
|
|
|
|
|
+ exists) or `commit -d <master>' (if working with a local repository
|
|
|
|
|
+ copy). Additionally this adds support for quoted strings inside
|
|
|
|
|
+ .cvsrc files.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CVSROOT:
|
|
|
|
|
+ This adds support for a new dot-file ~/.cvsroot which is used
|
|
|
|
|
+ optionally by CVS. It can be used by the user to configure a
|
|
|
|
|
+ nickname for a CVS repository root (the master location) plus a
|
|
|
|
|
+ possibly existing local repository copy (the slave location). An
|
|
|
|
|
+ entry in ~/.cvsroot is of the format ``<nickname> <master-path>
|
|
|
|
|
+ [<slave-path> [<sync-prog>]]''. Those entries can be either created
|
|
|
|
|
+ manually in ~/.cvsroot or with the `cvs root -e' command.
|
|
|
|
|
+
|
|
|
|
|
+ The idea is this: if a global `-d' option is used with <nickname> it is
|
|
|
|
|
+ automatically expanded to <master-path>. If no global `-d' option is used,
|
|
|
|
|
+ the CVS command is checked. If it is one of the commands which are known
|
|
|
|
|
+ to CVS to modify the repository, and the $CVSROOT or CVS/Root specify a
|
|
|
|
|
+ slave location, the repository is switched to the corresponding master
|
|
|
|
|
+ location (because modifications have to be performed there). If the
|
|
|
|
|
+ command is one of the commands which are known to CVS to NOT modify the
|
|
|
|
|
+ repository, and the $CVSROOT or CVS/Root specify a master location, the
|
|
|
|
|
+ repository is switched to the corresponding slave location (because the
|
|
|
|
|
+ slave location is faster than the master location per definition).
|
|
|
|
|
+
|
|
|
|
|
+ After a modifying operation, CVS can either run a synchronization job
|
|
|
|
|
+ automatically to bring slave in sync with master again or the user can run
|
|
|
|
|
+ `cvs root -s <nickname>' manually to perform this task.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_GLOBALOPTION:
|
|
|
|
|
+ RSE_PATCH_GLOBALOPTION_PARTLY:
|
|
|
|
|
+ By default, global options in `.cvsrc' files are specified with a
|
|
|
|
|
+ `cvs' prefix. These options then apply to _all_ cvs commands. If
|
|
|
|
|
+ RSE_PATCH_GLOBALOPTION is enabled, a second pass is done where all
|
|
|
|
|
+ global options are read with prefix `cvs/<command>' where <command>
|
|
|
|
|
+ is the official cvs command (for instance `commit' or `checkout',
|
|
|
|
|
+ even if `ci' or `co' are used on the command line). This is useful
|
|
|
|
|
+ for instance to override CVSROOT in commit commands if using a local
|
|
|
|
|
+ repository copy. The drawback of this feature is that it obviously
|
|
|
|
|
+ slows down cvs calls, because a second pass has to be done. But
|
|
|
|
|
+ usually this feature is intended only for use with `commit', `tag',
|
|
|
|
|
+ `rtag', `history', `admin', `import' and `rdiff' commands, so if
|
|
|
|
|
+ RSE_PATCH_GLOBALOPTION_PARTLY is additionally enabled, this second
|
|
|
|
|
+ pass is only done for those commands (which is the recommended use
|
|
|
|
|
+ of this feature).
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CUSTOMCMD:
|
|
|
|
|
+ This provides an additional global option `-C
|
|
|
|
|
+ <cmd-name>:<cmd-program>' which defines an additional CVS command
|
|
|
|
|
+ <cmd-name>. It is intended for use on `cvs' lines inside .cvsrc
|
|
|
|
|
+ files. The effect of having `cvs -Csync:$CVSROOT/CVSROOT/sync' in a
|
|
|
|
|
+ .cvsrc file is (and assuming $CVSROOT is /e/ossp/cvs) that if you
|
|
|
|
|
+ run `cvs sync <arg1> <arg2>', CVS executes `/e/ossp/cvs/CVSROOT/sync
|
|
|
|
|
+ <arg1> <arg2>'. So this is a way to externally extend CVS with
|
|
|
|
|
+ additional commands.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_PROLOGEPILOG:
|
|
|
|
|
+ Provides the two additional CVS options `-P <program>' and `-E
|
|
|
|
|
+ <program>' for running prolog and epilog programs before and
|
|
|
|
|
+ after the usual CVS processing. This is mainly intended as local
|
|
|
|
|
+ hooks for implicitly wrapping CVS commands (without having to
|
|
|
|
|
+ create slow wrapping shell scripts, etc.). Developers usually
|
|
|
|
|
+ use it to automatically start their RSYNC command to update the
|
|
|
|
|
+ local repository copy after a commit. The <program> is called
|
|
|
|
|
+ with four arguments: $1 is either `prolog' or `epilog' (useful
|
|
|
|
|
+ if one just wants to use a single hook program), $2 is the cvs
|
|
|
|
|
+ command (it is `commit' even `ci' is used, etc.), $3 is the current
|
|
|
|
|
+ working directory from which the cvs command was run and $4 is the
|
|
|
|
|
+ corresponding $CVSROOT variable.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_VERIFY:
|
|
|
|
|
+ This patch forces CVS to read in again the log messages after the
|
|
|
|
|
+ verification step (via the `verifymsg' hook) to allow the hook
|
|
|
|
|
+ script to actually _update_ the log message. This is useful for
|
|
|
|
|
+ stripping out unnecessary stuff, like not filled out custom fields
|
|
|
|
|
+ of the log template text.
|
|
|
|
|
+ [Origin: Peter Wemm, FreeBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_LOCALID:
|
|
|
|
|
+ Support a local keyword variant of `$Id$'. By default this is
|
|
|
|
|
+ `$LocalId$', but if -DRSE_PATCH_LOCALID_NAME=\"<name>\" is
|
|
|
|
|
+ additionally defined, then the keyword is `$<name>$'. Alternatively
|
|
|
|
|
+ one can define the name also in the `$CVSROOT/CVSROOT/config' file
|
|
|
|
|
+ with `LocalIdName=<name>'.
|
|
|
|
|
+ [Origin: NetBSD, OpenBSD, Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CVSHEADER:
|
|
|
|
|
+ Support the `$CVSHeader' variant of `$Header$' which has the
|
|
|
|
|
+ $CVSROOT prefix stripped of from the path. This is useful because
|
|
|
|
|
+ the prefix usually useless outside the server environment.
|
|
|
|
|
+ [Origin: FreeBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_NOLOCK:
|
|
|
|
|
+ Provide a `cvs -u' option in addition to `cvs -n' to force CVS to
|
|
|
|
|
+ not create any lock files in the repository. This is for supporting
|
|
|
|
|
+ read-only access to the repository. This is useful for working
|
|
|
|
|
+ with CVS repositories on CD-ROMs and for providing anonymous CVS
|
|
|
|
|
+ services.
|
|
|
|
|
+ [Origin: NetBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_EXTRAPERCENT:
|
|
|
|
|
+ This adds extra percent expansions to `loginfo' command lines:
|
|
|
|
|
+ `%o' to expand the operation (`A' = added, `M' = modified, `R' =
|
|
|
|
|
+ removed), `%t' to expand the tag, `%d' to expand the date.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_READDNEW:
|
|
|
|
|
+ If a file was re-added to the repository, log the revision in the
|
|
|
|
|
+ `commitlog' as `NONE' instead of the previous dead revision.
|
|
|
|
|
+ [Origin: NetBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CONFIGUMASK:
|
|
|
|
|
+ Provide a `UMask=<mask>' variable in `$CVSROOT/CVSROOT/config' which
|
|
|
|
|
+ overrides the umask of the CVS server process.
|
|
|
|
|
+ [Origin: OpenBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_FASTERUPDATE:
|
|
|
|
|
+ This speeds up `cvs update' by sending the whole file over the
|
|
|
|
|
+ network if it is smaller than the diff content. This is useful for
|
|
|
|
|
+ working remotely over slow Internet links.
|
|
|
|
|
+ [Origin: OpenBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_MERGENOKEYWORD:
|
|
|
|
|
+ This disables keyword expansions during branch merges which is
|
|
|
|
|
+ very useful in long-term branching. Without this the so-called
|
|
|
|
|
+ `spurious merging conflicts' occur because the keywords cause
|
|
|
|
|
+ spurious conflicts on every merge after the first (if those text
|
|
|
|
|
+ files have been modified on the trunk since the previous merge out
|
|
|
|
|
+ to the branch).
|
|
|
|
|
+ [Origin: Jay Sachs <jsachs@iclick.com>]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_DIFFHEAD:
|
|
|
|
|
+ This patch changes the behavior of `cvs diff -rHEAD' on branches.
|
|
|
|
|
+ HEAD here now behaves with as it does with all other CVS commands,
|
|
|
|
|
+ as a name for the head of the trunk (the old behavior of `cvs diff
|
|
|
|
|
+ -rHEAD' was to treat HEAD to mean the head of the branch, while all
|
|
|
|
|
+ the other commands already treated HEAD as the head of the trunk).
|
|
|
|
|
+ [Origin: Stephen Cameron <steve.cameron@compaq.com>]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_DEADAWARE:
|
|
|
|
|
+ This makes `cvs diff' aware of removed/dead files in the trunk
|
|
|
|
|
+ (HEAD), i.e., it doesn't complain if it didn't exist.
|
|
|
|
|
+ [Origin: FreeBSD]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_LOGNAME:
|
|
|
|
|
+ This is for SUID-based CVS servers and passes in `$LOGNAME' the real
|
|
|
|
|
+ user (first field in `$CVSROOT/CVSROOT/passwd') instead of the SUID
|
|
|
|
|
+ user (third field in `$CVSROOT/CVSROOT/passwd')
|
|
|
|
|
+ [Origin: Chris Cameron]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_HISTORYFILE:
|
|
|
|
|
+ This provides an additional `HistoryFile=<rel-path-under-CVSROOT>'
|
|
|
|
|
+ config variable which allows one to store the history file under a
|
|
|
|
|
+ different path.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_SMARTCONFIG:
|
|
|
|
|
+ This allows one to add custom configuration variables to
|
|
|
|
|
+ `$CVSROOT/CVSROOT/config' without having CVS complain about them and
|
|
|
|
|
+ fail with an error. This is useful to use the config file also for
|
|
|
|
|
+ storing config details for the various admin scripts.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_ADMININFO:
|
|
|
|
|
+ This adds the feature of an extra `$CVSROOT/CVSROOT/admininfo'
|
|
|
|
|
+ configuration file which can be used for access controlling `cvs
|
|
|
|
|
+ admin' commands similar to `cvs tag' (which is already done
|
|
|
|
|
+ with `taginfo') and `cvs commit' (which is already done with
|
|
|
|
|
+ `commitinfo'). The specified filters in this info file receive the
|
|
|
|
|
+ absolute repository directory as the first argument, followed by all
|
|
|
|
|
+ names of files in this directory on which the `cvs admin' command
|
|
|
|
|
+ should be performed. If the filter returns 0, the operation is
|
|
|
|
|
+ allowed. If it returns not 0, the operation is denied.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_IMPORTINFO:
|
|
|
|
|
+ This adds the feature of an extra `$CVSROOT/CVSROOT/importinfo'
|
|
|
|
|
+ configuration file which can be used for access controlling
|
|
|
|
|
+ `cvs import'. The specified filters in this info file receives
|
|
|
|
|
+ the following arguments: the vendor branch tag, the (absolute)
|
|
|
|
|
+ repository path which is the root of the import and then zero or
|
|
|
|
|
+ more relative file paths under this repository. If the filter
|
|
|
|
|
+ returns 0, the operation is allowed. If it returns not 0, the
|
|
|
|
|
+ operation is denied.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_HANDLE:
|
|
|
|
|
+ This adds a convinient `-h<handle>' option to `cvs diff'. `<handle>'
|
|
|
|
|
+ is a string of the format `[!]YYMMDDhhmmssoo' (YY=year, MM=month,
|
|
|
|
|
+ DD=day, hh=hour, mm=minute, ss=second, oo=offset) which internally
|
|
|
|
|
+ is expanded into two `-D' options. The first date is the equivalent
|
|
|
|
|
+ of `YYMMDDhhmmss', the second is the first plus `oo' seconds. If the
|
|
|
|
|
+ exclamation mark is used, the two dates are reversed. The intention
|
|
|
|
|
+ is that such a handle is a short form for a time range and can be
|
|
|
|
|
+ easily computed in a commit log mail. So the `-h' option can be used
|
|
|
|
|
+ to easily get the corresponding change diff for branch merging or
|
|
|
|
|
+ backing out. The only restriction is that time-overlapping commits
|
|
|
|
|
+ break the solution, of course. But in practice this is no real
|
|
|
|
|
+ problem.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_IMPORTTOUCH:
|
|
|
|
|
+ This prints the prefix 'T' (for "touched/tagged only") instead
|
|
|
|
|
+ of 'U' (for "updated") on `cvs import' if no modifications were
|
|
|
|
|
+ imported, i.e., no new revision is comitted. This way one can
|
|
|
|
|
+ distinguish those imports from the regular updated ones which also
|
|
|
|
|
+ print 'U' and which actually commit a new revision.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_RELLOCKDIR:
|
|
|
|
|
+ This allows the `LockDir' configuration directive to use relative
|
|
|
|
|
+ paths to $CVSROOT, because without this patch a relative path would
|
|
|
|
|
+ be relative to the current working directory (which is useless).
|
|
|
|
|
+ [Origin: Stefan Monnier <foo@acm.com>]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CVSUSER:
|
|
|
|
|
+ This allows the Unix user RSE_PATCH_CVSUSER_CALLER (per default
|
|
|
|
|
+ "ossp-cvs") to use the environment variable CVSUSER to override the
|
|
|
|
|
+ login name CVS uses to identify the caller. This is intended for use
|
|
|
|
|
+ with a CVS setuid wrapper program or for use manually by the CVS
|
|
|
|
|
+ administrator.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_SETXID:
|
|
|
|
|
+ This is a variant of CVS's SETXID_SUPPORT. It allows one to
|
|
|
|
|
+ setuid/setgid the CVS executable. Then CVS deletes these effective
|
|
|
|
|
+ uid/gid for all commands except for the "cvs server" command. For
|
|
|
|
|
+ this and only this it switches the real uid/gid to the effective
|
|
|
|
|
+ uid/gid. This way one can use the repository as a black-box. One
|
|
|
|
|
+ just has to be make sure that only :ext: (for remote) and :fork:
|
|
|
|
|
+ (for local) access is used.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_PSERVERD:
|
|
|
|
|
+ This adds an additional `cvs pserverd' command which is like `cvs
|
|
|
|
|
+ pserver' except that it uses own builtin TCP/IP socket listening and
|
|
|
|
|
+ forking facility. The advantages over using inetd are: pserverd can
|
|
|
|
|
+ listen to particular host addresses/ports (inetd always binds to all
|
|
|
|
|
+ interfaces of a host), it can optionally chroot(2) for a particular
|
|
|
|
|
+ user only (usually "anonymous"), it can optionally force the global
|
|
|
|
|
+ options -l -u for a particular user only (usually "anonymous"), it
|
|
|
|
|
+ can detach into background and run as a real daemon, etc.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_MAPROOT
|
|
|
|
|
+ This adds a global --map-root=/oldpath:/newpath option which
|
|
|
|
|
+ allows one to map virtual/incoming CVSROOT values to real ones.
|
|
|
|
|
+ For instance this can be used together with --allow-root and "cvs
|
|
|
|
|
+ pserverd" to map the intuitive virtual path to the physical path on
|
|
|
|
|
+ the host.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_HASHFUNC:
|
|
|
|
|
+ This replaces the obscure hash function in src/hash.c with D.J.Berstein's
|
|
|
|
|
+ popular "times 33" function which is faster to compute and still
|
|
|
|
|
+ distributes very well.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_ADDFILEATTR:
|
|
|
|
|
+ Let the default file attributes set on newly added files.
|
|
|
|
|
+ [Origin: Noel Yap]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_WILDPASSWD:
|
|
|
|
|
+ This allows wildcards ("*") in CVSROOT/passwd. That allows one to
|
|
|
|
|
+ just do "*:ULtgRLXo7NRxs:cvsuser" which would let absolutely anyone
|
|
|
|
|
+ use CVS provided they know the password. It would also let you do
|
|
|
|
|
+ things like "*:*:cvsuser" to let only authorized system users use
|
|
|
|
|
+ CVS using their system passwords.
|
|
|
|
|
+ [Larry Jones <larry.jones@sdrc.com>]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_CVSPID:
|
|
|
|
|
+ This provides an environment variable $CVSPID which contains the process
|
|
|
|
|
+ id of the parent CVS process. This is usually used inside scripts called
|
|
|
|
|
+ from *info files in order to have a unique session handle (for instance
|
|
|
|
|
+ for a common temporary directory "/tmp/cvs.foo.$CVSPID", etc).
|
|
|
|
|
+ [Origin: Rich Salz <rsalz@caveosystems.com>]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_BUGFIX:
|
|
|
|
|
+ This enabled various bugfixes which are still not present in the
|
|
|
|
|
+ official CVS version.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_COSMETICS:
|
|
|
|
|
+ This just enables some cosmetic changes to various output messages.
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
+ RSE_PATCH_COSMETICS_HARD:
|
|
|
|
|
+ This just enables more cosmetic changes to various output messages.
|
|
|
|
|
+ The difference is that these break "make check".
|
|
|
|
|
+ [Origin: Ralf S. Engelschall]
|
|
|
|
|
+
|
|
|
|
|
Index: src/add.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/add.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 add.c
|
|
|
|
|
--- src/add.c 19 Apr 2001 19:45:31 -0000 1.1.1.4
|
|
|
|
|
+++ src/add.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -798,6 +798,9 @@
|
|
|
|
|
li->type = T_TITLE;
|
|
|
|
|
li->tag = xstrdup (tag);
|
|
|
|
|
li->rev_old = li->rev_new = NULL;
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ li->date = NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
p->data = (char *) li;
|
|
|
|
|
(void) addnode (ulist, p);
|
|
|
|
|
Update_Logfile (rcsdir, message, (FILE *) NULL, ulist);
|
|
|
|
|
Index: src/admin.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/admin.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 admin.c
|
|
|
|
|
--- src/admin.c 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/admin.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -139,6 +139,161 @@
|
|
|
|
|
dat->av[dat->ac++] = newelt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_ADMININFO
|
|
|
|
|
+
|
|
|
|
|
+static List *admininfo_dlist;
|
|
|
|
|
+static List *admininfo_flist;
|
|
|
|
|
+
|
|
|
|
|
+static void admininfo_dlist_delproc(Node *);
|
|
|
|
|
+static int admininfo_info_runproc(char *, char *);
|
|
|
|
|
+static int admininfo_flist_runproc(Node *, void *);
|
|
|
|
|
+
|
|
|
|
|
+struct admininfo_dlist_st {
|
|
|
|
|
+ List *flist;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/* file callback function for recursive processing */
|
|
|
|
|
+static int
|
|
|
|
|
+admininfo_fileproc (
|
|
|
|
|
+ void *callerdat,
|
|
|
|
|
+ struct file_info *finfo)
|
|
|
|
|
+{
|
|
|
|
|
+ char *xdir;
|
|
|
|
|
+ Node *dnode;
|
|
|
|
|
+ Node *fnode;
|
|
|
|
|
+
|
|
|
|
|
+ /* determine current directory */
|
|
|
|
|
+ if (finfo->update_dir[0] == '\0')
|
|
|
|
|
+ xdir = ".";
|
|
|
|
|
+ else
|
|
|
|
|
+ xdir = finfo->update_dir;
|
|
|
|
|
+
|
|
|
|
|
+ /* find directory node in directory list */
|
|
|
|
|
+ if ((dnode = findnode(admininfo_dlist, xdir)) != NULL)
|
|
|
|
|
+ /* take already existing file list */
|
|
|
|
|
+ admininfo_flist = ((struct admininfo_dlist_st *)dnode->data)->flist;
|
|
|
|
|
+ else {
|
|
|
|
|
+ /* create a new file list */
|
|
|
|
|
+ struct admininfo_dlist_st *dlist;
|
|
|
|
|
+
|
|
|
|
|
+ admininfo_flist = getlist();
|
|
|
|
|
+
|
|
|
|
|
+ dlist = (struct admininfo_dlist_st *)xmalloc(sizeof(struct admininfo_dlist_st));
|
|
|
|
|
+ dlist->flist = admininfo_flist;
|
|
|
|
|
+
|
|
|
|
|
+ dnode = getnode();
|
|
|
|
|
+ dnode->type = UPDATE;
|
|
|
|
|
+ dnode->key = xstrdup(xdir);
|
|
|
|
|
+ dnode->data = (char *)dlist;
|
|
|
|
|
+ dnode->delproc = admininfo_dlist_delproc;
|
|
|
|
|
+
|
|
|
|
|
+ (void)addnode(admininfo_dlist, dnode);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* create new file node in file list */
|
|
|
|
|
+ fnode = getnode();
|
|
|
|
|
+ fnode->type = UPDATE;
|
|
|
|
|
+ fnode->key = xstrdup(finfo->file);
|
|
|
|
|
+ fnode->data = NULL;
|
|
|
|
|
+ fnode->delproc = NULL;
|
|
|
|
|
+ (void)addnode(admininfo_flist, fnode);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* delete a directory list node */
|
|
|
|
|
+static void
|
|
|
|
|
+admininfo_dlist_delproc(
|
|
|
|
|
+ Node *p)
|
|
|
|
|
+{
|
|
|
|
|
+ struct admininfo_dlist_st *dlist;
|
|
|
|
|
+
|
|
|
|
|
+ dlist = (struct admininfo_dlist_st *)p->data;
|
|
|
|
|
+ dellist(&dlist->flist);
|
|
|
|
|
+ free(dlist);
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* file callback function for recursive processing (when done) */
|
|
|
|
|
+static int
|
|
|
|
|
+admininfo_filesdoneproc(
|
|
|
|
|
+ void *callerdat,
|
|
|
|
|
+ int err,
|
|
|
|
|
+ char *repos,
|
|
|
|
|
+ char *update_dir,
|
|
|
|
|
+ List *entries)
|
|
|
|
|
+{
|
|
|
|
|
+ Node *dnode;
|
|
|
|
|
+ int n;
|
|
|
|
|
+
|
|
|
|
|
+ /* find file list for update directory */
|
|
|
|
|
+ if ((dnode = findnode(admininfo_dlist, update_dir)) != NULL)
|
|
|
|
|
+ admininfo_flist = ((struct admininfo_dlist_st *)dnode->data)->flist;
|
|
|
|
|
+ else
|
|
|
|
|
+ admininfo_flist = (List *)NULL;
|
|
|
|
|
+ if ( (admininfo_flist == NULL)
|
|
|
|
|
+ || (admininfo_flist->list->next == admininfo_flist->list))
|
|
|
|
|
+ return err;
|
|
|
|
|
+
|
|
|
|
|
+ /* parse and execute the admininfo configuration */
|
|
|
|
|
+ if ((n = Parse_Info(CVSROOTADM_ADMININFO, repos, admininfo_info_runproc, 1)) > 0) {
|
|
|
|
|
+ error(0, 0, "Pre-admin check failed");
|
|
|
|
|
+ err += n;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return err;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* admininfo configuration entry callback */
|
|
|
|
|
+static int
|
|
|
|
|
+admininfo_info_runproc(repository, filter)
|
|
|
|
|
+ char *repository;
|
|
|
|
|
+ char *filter;
|
|
|
|
|
+{
|
|
|
|
|
+ char *s, *cp;
|
|
|
|
|
+ int rv;
|
|
|
|
|
+
|
|
|
|
|
+ /* if possible, do an own check to make sure that filter really exists */
|
|
|
|
|
+ if (filter[0] == '/') {
|
|
|
|
|
+ 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-admin filter '%s'", s);
|
|
|
|
|
+ free(s);
|
|
|
|
|
+ return (1);
|
|
|
|
|
+ }
|
|
|
|
|
+ free(s);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* construct the filter command */
|
|
|
|
|
+ run_setup(filter);
|
|
|
|
|
+ run_arg(repository);
|
|
|
|
|
+ walklist(admininfo_flist, admininfo_flist_runproc, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ /* execute the filter command */
|
|
|
|
|
+ rv = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
|
|
|
|
+
|
|
|
|
|
+ return rv;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* file list callback for adding file as another program argument */
|
|
|
|
|
+static int
|
|
|
|
|
+admininfo_flist_runproc(
|
|
|
|
|
+ Node *p,
|
|
|
|
|
+ void *closure)
|
|
|
|
|
+{
|
|
|
|
|
+ if (p->key != NULL)
|
|
|
|
|
+ run_arg(p->key);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif /* RSE_PATCH_ADMININFO */
|
|
|
|
|
+
|
|
|
|
|
int
|
|
|
|
|
admin (argc, argv)
|
|
|
|
|
int argc;
|
|
|
|
|
@@ -505,6 +660,20 @@
|
|
|
|
|
#endif /* CLIENT_SUPPORT */
|
|
|
|
|
|
|
|
|
|
lock_tree_for_write (argc, argv, 0, W_LOCAL, 0);
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_ADMININFO
|
|
|
|
|
+ /* allow `CVSROOT/CVSROOT/admininfo' filters to check whether the
|
|
|
|
|
+ `cvs admin' operation is authorized for all the specified files
|
|
|
|
|
+ in the repository */
|
|
|
|
|
+ admininfo_dlist = getlist();
|
|
|
|
|
+ err = start_recursion(admininfo_fileproc, admininfo_filesdoneproc,
|
|
|
|
|
+ (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
|
|
|
|
|
+ argc, argv, 0, W_LOCAL, 0, 0, (char *)NULL, 1);
|
|
|
|
|
+ if (err) {
|
|
|
|
|
+ Lock_Cleanup();
|
|
|
|
|
+ error(1, 0, "correct above errors first!");
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
|
|
|
|
|
(DIRLEAVEPROC) NULL, (void *)&admin_data,
|
|
|
|
|
Index: src/checkin.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/checkin.c,v
|
|
|
|
|
retrieving revision 1.1.1.1
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.1 checkin.c
|
|
|
|
|
--- src/checkin.c 22 Feb 1998 19:46:46 -0000 1.1.1.1
|
|
|
|
|
+++ src/checkin.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -32,14 +32,27 @@
|
|
|
|
|
Vers_TS *vers;
|
|
|
|
|
int set_time;
|
|
|
|
|
char *tocvsPath = NULL;
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS_HARD
|
|
|
|
|
+ int flags;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* Hmm. This message goes to stdout and the "foo,v <-- foo"
|
|
|
|
|
message from "ci" goes to stderr. This doesn't make a whole
|
|
|
|
|
lot of sense, but making everything go to stdout can only be
|
|
|
|
|
gracefully achieved once RCS_checkin is librarified. */
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS_HARD
|
|
|
|
|
+ if (!really_quiet) {
|
|
|
|
|
+#endif
|
|
|
|
|
cvs_output ("Checking in ", 0);
|
|
|
|
|
cvs_output (finfo->fullname, 0);
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS_HARD
|
|
|
|
|
+ cvs_output ("\n", 0);
|
|
|
|
|
+#else
|
|
|
|
|
cvs_output (";\n", 0);
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS_HARD
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
tocvsPath = wrap_tocvs_process_file (finfo->file);
|
|
|
|
|
if (!noexec)
|
|
|
|
|
@@ -56,7 +69,14 @@
|
|
|
|
|
if (finfo->rcs == NULL)
|
|
|
|
|
finfo->rcs = RCS_parse (finfo->file, finfo->repository);
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS_HARD
|
|
|
|
|
+ flags = RCS_FLAGS_KEEPFILE;
|
|
|
|
|
+ if (really_quiet || quiet)
|
|
|
|
|
+ flags |= RCS_FLAGS_QUIET;
|
|
|
|
|
+ switch (RCS_checkin (finfo->rcs, NULL, message, rev, flags))
|
|
|
|
|
+#else
|
|
|
|
|
switch (RCS_checkin (finfo->rcs, NULL, message, rev, RCS_FLAGS_KEEPFILE))
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
case 0: /* everything normal */
|
|
|
|
|
|
|
|
|
|
@@ -118,6 +138,16 @@
|
|
|
|
|
vers->options, vers->tag, vers->date, (char *) 0);
|
|
|
|
|
history_write (type, NULL, vers->vn_rcs,
|
|
|
|
|
finfo->file, finfo->repository);
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_ADDFILEATTR
|
|
|
|
|
+ if (type == 'A') {
|
|
|
|
|
+ char *attr;
|
|
|
|
|
+ if ((attr = fileattr_getall(NULL)) != NULL) {
|
|
|
|
|
+ fileattr_setall(finfo->file, attr);
|
|
|
|
|
+ free(attr);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
if (tocvsPath)
|
|
|
|
|
if (unlink_file_dir (tocvsPath) < 0)
|
|
|
|
|
Index: src/checkout.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/checkout.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 checkout.c
|
|
|
|
|
--- src/checkout.c 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/checkout.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -179,7 +179,11 @@
|
|
|
|
|
case 'p':
|
|
|
|
|
pipeout = 1;
|
|
|
|
|
run_module_prog = 0; /* don't run module prog when piping */
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ noexec = nolock = 1; /* so no locks will be created */
|
|
|
|
|
+#else
|
|
|
|
|
noexec = 1; /* so no locks will be created */
|
|
|
|
|
+#endif
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
cat = 1;
|
|
|
|
|
Index: src/client.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/client.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 client.c
|
|
|
|
|
--- src/client.c 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/client.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -105,6 +105,9 @@
|
|
|
|
|
int status PROTO((int argc, char **argv));
|
|
|
|
|
int tag PROTO((int argc, char **argv));
|
|
|
|
|
int update PROTO((int argc, char **argv));
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+int list PROTO((int argc, char **argv));
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* All the response handling functions. */
|
|
|
|
|
static void handle_ok PROTO((char *, int));
|
|
|
|
|
@@ -251,14 +254,34 @@
|
|
|
|
|
this_root = Name_Root ((char *) NULL, (char *) NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ {
|
|
|
|
|
+ int cvsroot_alias;
|
|
|
|
|
+ cvsroot_type *e;
|
|
|
|
|
+
|
|
|
|
|
+ cvsroot_alias = 0;
|
|
|
|
|
+ if ((e = cvsroot_lookup(NULL, current_parsed_root->original, NULL)) != NULL)
|
|
|
|
|
+ if (strcmp(e->slavepath, this_root) == 0)
|
|
|
|
|
+ cvsroot_alias = 1;
|
|
|
|
|
+ if ((e = cvsroot_lookup(NULL, NULL, this_root)) != NULL)
|
|
|
|
|
+ if (strcmp(e->masterpath, current_parsed_root->original) == 0)
|
|
|
|
|
+ cvsroot_alias = 1;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* Now check the value for root. */
|
|
|
|
|
if (this_root && current_parsed_root
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ && !cvsroot_alias
|
|
|
|
|
+#endif
|
|
|
|
|
&& (strcmp (this_root, current_parsed_root->original) != 0))
|
|
|
|
|
{
|
|
|
|
|
/* Don't send this, since the CVSROOTs don't match. */
|
|
|
|
|
free (this_root);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
free (this_root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2704,6 +2727,9 @@
|
|
|
|
|
/* Add a directory name to the list of those sent to the
|
|
|
|
|
server. */
|
|
|
|
|
if (update_dir && (*update_dir != '\0')
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ /* FIXME: alternative to RSE_PATCH_CVSROOT?! */
|
|
|
|
|
+#endif
|
|
|
|
|
&& (strcmp (update_dir, ".") != 0)
|
|
|
|
|
&& (findnode (dirs_sent_to_server, update_dir) == NULL))
|
|
|
|
|
{
|
|
|
|
|
@@ -4546,6 +4572,18 @@
|
|
|
|
|
error (1, 0,
|
|
|
|
|
"This server does not support the global -n option.");
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (nolock && !noexec)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (have_global)
|
|
|
|
|
+ {
|
|
|
|
|
+ send_to_server ("Global_option -u\012", 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ error (1, 0,
|
|
|
|
|
+ "This server does not support the global -u option.");
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
if (quiet)
|
|
|
|
|
{
|
|
|
|
|
if (have_global)
|
|
|
|
|
Index: src/commit.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/commit.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 commit.c
|
|
|
|
|
--- src/commit.c 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/commit.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -296,6 +296,9 @@
|
|
|
|
|
data->type = status;
|
|
|
|
|
data->tag = xstrdup (vers->tag);
|
|
|
|
|
data->rev_old = data->rev_new = NULL;
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ data->date = xstrdup (vers->ts_user);
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
node->type = UPDATE;
|
|
|
|
|
node->delproc = update_delproc;
|
|
|
|
|
@@ -498,7 +501,11 @@
|
|
|
|
|
/* Run the user-defined script to verify/check information in
|
|
|
|
|
*the log message
|
|
|
|
|
*/
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ do_verify (&saved_message, (char *)NULL);
|
|
|
|
|
+#else
|
|
|
|
|
do_verify (saved_message, (char *)NULL);
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* We always send some sort of message, even if empty. */
|
|
|
|
|
/* FIXME: is that true? There seems to be some code in do_editor
|
|
|
|
|
@@ -986,7 +993,16 @@
|
|
|
|
|
xmalloc (sizeof (struct logfile_info)));
|
|
|
|
|
li->type = status;
|
|
|
|
|
li->tag = xstrdup (vers->tag);
|
|
|
|
|
+#ifdef RSE_PATCH_READDNEW
|
|
|
|
|
+ /* If the file was re-added, we want the revision in the commitlog
|
|
|
|
|
+ to be NONE, not the previous dead revision. */
|
|
|
|
|
+ li->rev_old = status == T_ADDED ? NULL : xstrdup (vers->vn_rcs);
|
|
|
|
|
+#else
|
|
|
|
|
li->rev_old = xstrdup (vers->vn_rcs);
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ li->date = xstrdup (vers->ts_user);
|
|
|
|
|
+#endif
|
|
|
|
|
li->rev_new = NULL;
|
|
|
|
|
p->data = (char *) li;
|
|
|
|
|
(void) addnode (ulist, p);
|
|
|
|
|
@@ -1230,7 +1246,11 @@
|
|
|
|
|
if (use_editor)
|
|
|
|
|
do_editor (finfo->update_dir, &saved_message,
|
|
|
|
|
finfo->repository, ulist);
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ do_verify (&saved_message, finfo->repository);
|
|
|
|
|
+#else
|
|
|
|
|
do_verify (saved_message, finfo->repository);
|
|
|
|
|
+#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = findnode (cilist, finfo->file);
|
|
|
|
|
@@ -1552,7 +1572,11 @@
|
|
|
|
|
got_message = 1;
|
|
|
|
|
if (use_editor)
|
|
|
|
|
do_editor (update_dir, &saved_message, real_repos, ulist);
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ do_verify (&saved_message, real_repos);
|
|
|
|
|
+#else
|
|
|
|
|
do_verify (saved_message, real_repos);
|
|
|
|
|
+#endif
|
|
|
|
|
free (real_repos);
|
|
|
|
|
return (R_PROCESS);
|
|
|
|
|
}
|
|
|
|
|
@@ -2296,6 +2320,10 @@
|
|
|
|
|
free (li->rev_old);
|
|
|
|
|
if (li->rev_new)
|
|
|
|
|
free (li->rev_new);
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ if (li->date)
|
|
|
|
|
+ free (li->date);
|
|
|
|
|
+#endif
|
|
|
|
|
free (li);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Index: src/create_adm.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/create_adm.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 create_adm.c
|
|
|
|
|
--- src/create_adm.c 19 Apr 2001 19:45:32 -0000 1.1.1.4
|
|
|
|
|
+++ src/create_adm.c 16 Feb 2002 14:00:14 -0000
|
|
|
|
|
@@ -21,6 +21,41 @@
|
|
|
|
|
or after which CVS might do something non-useful. If WARN is zero, then
|
|
|
|
|
don't print warnings; all errors are fatal then. */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+static int local_template_cb(char *repository, char *template)
|
|
|
|
|
+{
|
|
|
|
|
+ FILE *fpIN, *fpOUT;
|
|
|
|
|
+ char buf[1024];
|
|
|
|
|
+ size_t n;
|
|
|
|
|
+
|
|
|
|
|
+ if ((fpOUT = CVS_FOPEN(CVSADM_TEMPLATE, "w+")) == NULL)
|
|
|
|
|
+ error(1, errno, "cannot open %s for writing", CVSADM_TEMPLATE);
|
|
|
|
|
+ if ((fpIN = CVS_FOPEN(template, "r")) == NULL)
|
|
|
|
|
+ error(1, errno, "cannot open %s for reading", template);
|
|
|
|
|
+ while (!feof(fpIN)) {
|
|
|
|
|
+ n = fread(buf, 1, sizeof buf, fpIN);
|
|
|
|
|
+ if (n == 0) {
|
|
|
|
|
+ if (ferror(fpIN))
|
|
|
|
|
+ error(0, errno, "cannot read template file %s", template);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ fwrite(buf, 1, n, fpOUT);
|
|
|
|
|
+ }
|
|
|
|
|
+ fclose(fpIN);
|
|
|
|
|
+ fclose(fpOUT);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void local_template(char *update_dir, char *repository)
|
|
|
|
|
+{
|
|
|
|
|
+ cvsroot_type *e;
|
|
|
|
|
+
|
|
|
|
|
+ if ((e = cvsroot_lookup(NULL, NULL, current_parsed_root->original)) != NULL)
|
|
|
|
|
+ Parse_Info(CVSROOTADM_RCSINFO, repository, local_template_cb, 1);
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
int
|
|
|
|
|
Create_Admin (dir, update_dir, repository, tag, date, nonbranch, warn,
|
|
|
|
|
dotemplate)
|
|
|
|
|
@@ -179,6 +214,20 @@
|
|
|
|
|
fprintf (stderr, "%c<- Create_Admin\n",
|
|
|
|
|
(server_active) ? 'S' : ' ');
|
|
|
|
|
}
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ /* Under our "cvs root" feature, checkouts are performed
|
|
|
|
|
+ locally (from the repository copy and without C/S), but commits
|
|
|
|
|
+ are performed remotely (to the master repository with C/S).
|
|
|
|
|
+ Unfortunately, CVS "optimizes" processing and doesn't provide
|
|
|
|
|
+ CVS/Template files on non-C/S checkouts. This would mean that
|
|
|
|
|
+ if "cvs root" feature is used, the rcsinfo-configured templates
|
|
|
|
|
+ are never used. So, if and only if we do a non-C/S checkout (or
|
|
|
|
|
+ similar operation which creates CVS/Template) _and_ the current
|
|
|
|
|
+ CVSROOT is known to be a repository copy, we force the creation
|
|
|
|
|
+ of CVS/Template. */
|
|
|
|
|
+ if (!server_active && !(current_parsed_root->isremote) && dotemplate)
|
|
|
|
|
+ local_template(update_dir, repository);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
free (reposcopy);
|
|
|
|
|
Index: src/cvs.h
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/cvs.h,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 cvs.h
|
|
|
|
|
--- src/cvs.h 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/cvs.h 16 Feb 2002 12:36:21 -0000
|
|
|
|
|
@@ -187,6 +187,33 @@
|
|
|
|
|
#define CVSROOTADM_WRITERS "writers"
|
|
|
|
|
#define CVSROOTADM_PASSWD "passwd"
|
|
|
|
|
#define CVSROOTADM_CONFIG "config"
|
|
|
|
|
+#ifdef RSE_PATCH_ADMININFO
|
|
|
|
|
+#define CVSROOTADM_ADMININFO "admininfo"
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_IMPORTINFO
|
|
|
|
|
+#define CVSROOTADM_IMPORTINFO "importinfo"
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_ALTADMINFILES
|
|
|
|
|
+#define CVSROOTADM_MODULES_ALT "conf_modules"
|
|
|
|
|
+#define CVSROOTADM_LOGINFO_ALT "hook_logwrite"
|
|
|
|
|
+#define CVSROOTADM_RCSINFO_ALT "hook_logtempl"
|
|
|
|
|
+#define CVSROOTADM_COMMITINFO_ALT "hook_commit"
|
|
|
|
|
+#define CVSROOTADM_TAGINFO_ALT "hook_tag"
|
|
|
|
|
+#define CVSROOTADM_EDITINFO_ALT "hook_logedit"
|
|
|
|
|
+#define CVSROOTADM_VERIFYMSG_ALT "hook_logverify"
|
|
|
|
|
+#define CVSROOTADM_HISTORY_ALT "data_history"
|
|
|
|
|
+#define CVSROOTADM_VALTAGS_ALT "data_valtags"
|
|
|
|
|
+#define CVSROOTADM_IGNORE_ALT "conf_ignore"
|
|
|
|
|
+#define CVSROOTADM_CHECKOUTLIST_ALT "conf_checkout"
|
|
|
|
|
+#define CVSROOTADM_WRAPPER_ALT "hook_wrapper"
|
|
|
|
|
+#define CVSROOTADM_NOTIFY_ALT "hook_notify"
|
|
|
|
|
+#define CVSROOTADM_USERS_ALT "conf_users"
|
|
|
|
|
+#define CVSROOTADM_READERS_ALT "conf_readers"
|
|
|
|
|
+#define CVSROOTADM_WRITERS_ALT "conf_writers"
|
|
|
|
|
+#define CVSROOTADM_PASSWD_ALT "conf_passwd"
|
|
|
|
|
+#define CVSROOTADM_CONFIG_ALT "conf_global"
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
#define CVSNULLREPOS "Emptydir" /* an empty directory */
|
|
|
|
|
|
|
|
|
|
@@ -273,6 +300,10 @@
|
|
|
|
|
#define CVSUMASK_ENV "CVSUMASK" /* Effective umask for repository */
|
|
|
|
|
/* #define CVSUMASK_DFLT Set by options.h */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+#define CVSNOLOCK_ENV "CVSNOLOCK" /* do not create lock files */
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/*
|
|
|
|
|
* If the beginning of the Repository matches the following string, strip it
|
|
|
|
|
* so that the output to the logfile does not contain a full pathname.
|
|
|
|
|
@@ -363,6 +394,9 @@
|
|
|
|
|
extern int use_editor;
|
|
|
|
|
extern int cvswrite;
|
|
|
|
|
extern mode_t cvsumask;
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+extern char *RCS_citag;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* Access method specified in CVSroot. */
|
|
|
|
|
typedef enum {
|
|
|
|
|
@@ -400,6 +434,9 @@
|
|
|
|
|
|
|
|
|
|
extern int trace; /* Show all commands */
|
|
|
|
|
extern int noexec; /* Don't modify disk anywhere */
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+extern int nolock; /* Don't create locks */
|
|
|
|
|
+#endif
|
|
|
|
|
extern int logoff; /* Don't write history entry */
|
|
|
|
|
|
|
|
|
|
extern int top_level_admin;
|
|
|
|
|
@@ -467,6 +504,27 @@
|
|
|
|
|
void root_allow_free PROTO ((void));
|
|
|
|
|
int root_allow_ok PROTO ((char *));
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+void root_map_add PROTO ((char *, char *));
|
|
|
|
|
+void root_map_free PROTO ((void));
|
|
|
|
|
+int root_map_it PROTO ((char *, char **, int));
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+typedef struct {
|
|
|
|
|
+ char *nickname;
|
|
|
|
|
+ char *masterpath;
|
|
|
|
|
+ char *slavepath;
|
|
|
|
|
+ char *syncprog;
|
|
|
|
|
+} cvsroot_type;
|
|
|
|
|
+char *cvsroot_filename(void);
|
|
|
|
|
+void cvsroot_free(cvsroot_type *);
|
|
|
|
|
+cvsroot_type *cvsroot_entry_read(FILE *);
|
|
|
|
|
+void cvsroot_entry_write(FILE *, cvsroot_type *);
|
|
|
|
|
+cvsroot_type *cvsroot_lookup(char *, char *, char *);
|
|
|
|
|
+void cvsroot_synchronize(cvsroot_type *, int);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
char *gca PROTO((const char *rev1, const char *rev2));
|
|
|
|
|
extern void check_numeric PROTO ((const char *, int, char **));
|
|
|
|
|
char *getcaller PROTO((void));
|
|
|
|
|
@@ -570,6 +628,10 @@
|
|
|
|
|
extern void expand_wild PROTO ((int argc, char **argv,
|
|
|
|
|
int *pargc, char ***pargv));
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_HANDLE
|
|
|
|
|
+int handle2dates(char *, time_t *, time_t *);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
#ifdef SERVER_SUPPORT
|
|
|
|
|
extern int cvs_casecmp PROTO ((char *, char *));
|
|
|
|
|
extern int fopen_case PROTO ((char *, char *, FILE **, char **));
|
|
|
|
|
@@ -589,7 +651,11 @@
|
|
|
|
|
void do_editor PROTO((char *dir, char **messagep,
|
|
|
|
|
char *repository, List * changes));
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+void do_verify PROTO((char **messagep, char *repository));
|
|
|
|
|
+#else
|
|
|
|
|
void do_verify PROTO((char *message, char *repository));
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
typedef int (*CALLBACKPROC) PROTO((int argc, char *argv[], char *where,
|
|
|
|
|
char *mwhere, char *mfile, int shorten, int local_specified,
|
|
|
|
|
@@ -812,6 +878,9 @@
|
|
|
|
|
NULL for add or import */
|
|
|
|
|
char *rev_new; /* rev number after a commit/modify,
|
|
|
|
|
add, or import, NULL for remove */
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ char *date;
|
|
|
|
|
+#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Wrappers. */
|
|
|
|
|
@@ -851,6 +920,13 @@
|
|
|
|
|
int unedit PROTO ((int argc, char **argv));
|
|
|
|
|
int editors PROTO ((int argc, char **argv));
|
|
|
|
|
int watchers PROTO ((int argc, char **argv));
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+int root PROTO ((int argc, char **argv));
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_PSERVERD
|
|
|
|
|
+int pserverd PROTO ((int argc, char **argv));
|
|
|
|
|
+int pserver_daemon PROTO ((int argc, char **argv));
|
|
|
|
|
+#endif
|
|
|
|
|
extern int annotate PROTO ((int argc, char **argv));
|
|
|
|
|
extern int add PROTO ((int argc, char **argv));
|
|
|
|
|
extern int admin PROTO ((int argc, char **argv));
|
|
|
|
|
@@ -871,6 +947,9 @@
|
|
|
|
|
extern int cvsstatus PROTO((int argc, char **argv));
|
|
|
|
|
extern int cvstag PROTO((int argc, char **argv));
|
|
|
|
|
extern int version PROTO((int argc, char **argv));
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+extern int cvslist PROTO((int argc, char **argv));
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
extern unsigned long int lookup_command_attribute PROTO((char *));
|
|
|
|
|
|
|
|
|
|
Index: src/cvsrc.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/cvsrc.c,v
|
|
|
|
|
retrieving revision 1.1.1.2
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.2 cvsrc.c
|
|
|
|
|
--- src/cvsrc.c 23 Dec 1998 15:15:00 -0000 1.1.1.2
|
|
|
|
|
+++ src/cvsrc.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -12,6 +12,203 @@
|
|
|
|
|
#include "cvs.h"
|
|
|
|
|
#include "getline.h"
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSRC
|
|
|
|
|
+
|
|
|
|
|
+#include <ctype.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+
|
|
|
|
|
+static char *strq_start = NULL;
|
|
|
|
|
+
|
|
|
|
|
+static char *
|
|
|
|
|
+strqtok_cchar(
|
|
|
|
|
+ register char *s,
|
|
|
|
|
+ register char *c,
|
|
|
|
|
+ int *backslashed)
|
|
|
|
|
+{
|
|
|
|
|
+ register char ch;
|
|
|
|
|
+
|
|
|
|
|
+ if ((*backslashed = (*s == '\\'))) {
|
|
|
|
|
+ switch (*++s) {
|
|
|
|
|
+ case 'a':
|
|
|
|
|
+ *c = '\a';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'b':
|
|
|
|
|
+ *c = '\b';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'f':
|
|
|
|
|
+ *c = '\f';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'n':
|
|
|
|
|
+ *c = '\n';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'r':
|
|
|
|
|
+ *c = '\r';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 't':
|
|
|
|
|
+ *c = '\t';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'v':
|
|
|
|
|
+ *c = '\v';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '\\':
|
|
|
|
|
+ *c = '\\';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '^':
|
|
|
|
|
+ *c = '^';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '\'':
|
|
|
|
|
+ *c = '\'';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '"':
|
|
|
|
|
+ *c = '"';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '?':
|
|
|
|
|
+ *c = '?';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '0':
|
|
|
|
|
+ case '1':
|
|
|
|
|
+ case '2':
|
|
|
|
|
+ case '3':
|
|
|
|
|
+ case '4':
|
|
|
|
|
+ case '5':
|
|
|
|
|
+ case '6':
|
|
|
|
|
+ case '7':
|
|
|
|
|
+ ch = 0;
|
|
|
|
|
+ if (isdigit(*s) && *s != '8' && *s != '9') {
|
|
|
|
|
+ ch = *s++ - '0';
|
|
|
|
|
+ if (isdigit(*s) && *s != '8' && *s != '9') {
|
|
|
|
|
+ ch <<= 3;
|
|
|
|
|
+ ch |= *s++ - '0';
|
|
|
|
|
+ if (isdigit(*s) && *s != '8' && *s != '9') {
|
|
|
|
|
+ ch <<= 3;
|
|
|
|
|
+ ch |= *s++ - '0';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ s--;
|
|
|
|
|
+ *c = ch;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'x':
|
|
|
|
|
+ s++;
|
|
|
|
|
+ for (ch = 0; isxdigit(*s); s++) {
|
|
|
|
|
+ ch <<= 4;
|
|
|
|
|
+ ch |= isdigit(*s) ? *s - '0' :
|
|
|
|
|
+ islower(*s) ? *s + 10 - 'a' : *s + 10 - 'A';
|
|
|
|
|
+ }
|
|
|
|
|
+ s--;
|
|
|
|
|
+ *c = ch;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ *c = *s;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else
|
|
|
|
|
+ *c = *s;
|
|
|
|
|
+ return (*s) ? s+1 : NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static char *
|
|
|
|
|
+strqtok(
|
|
|
|
|
+ char *s, /* String to tokenize. NULL to continue same str */
|
|
|
|
|
+ char *delim, /* Token delimiters. Can be changed w/ each call. */
|
|
|
|
|
+ char *quotemarks, /* Quotation marks. Can be changed w/ each call. */
|
|
|
|
|
+ char *commentchars, /* Comment characters. Can be changed w/ each call. */
|
|
|
|
|
+ unsigned int flags) /* flags&01 -> strip quotes;
|
|
|
|
|
+ * flags&02 -> enable backslash escapes;
|
|
|
|
|
+ * flags&04 -> skip all delims before return;
|
|
|
|
|
+ */
|
|
|
|
|
+{
|
|
|
|
|
+ register char *p, *q;
|
|
|
|
|
+ char c;
|
|
|
|
|
+ char leftquote = 0;
|
|
|
|
|
+ char *token;
|
|
|
|
|
+ int backslashed, inquote, intok;
|
|
|
|
|
+
|
|
|
|
|
+ int stripquote = flags & 01; /* strip quotemarks from tokens */
|
|
|
|
|
+ int backslash = flags & 02; /* backslash sequences */
|
|
|
|
|
+ int skipdelim = flags & 04; /* skip seq of delims at end of token */
|
|
|
|
|
+
|
|
|
|
|
+ /* New string? */
|
|
|
|
|
+ if (s)
|
|
|
|
|
+ strq_start = s;
|
|
|
|
|
+ if (!strq_start)
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+
|
|
|
|
|
+ /* Skip leading delimiters */
|
|
|
|
|
+ for (p=strq_start; *p && strchr(delim, *p); p++)
|
|
|
|
|
+ ;
|
|
|
|
|
+ if (!(*p) || strchr(commentchars, *p))
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+
|
|
|
|
|
+ /* Set `token' to point to returned string.
|
|
|
|
|
+ * Use p and q to walk through the user's string:
|
|
|
|
|
+ * p will follow input characters;
|
|
|
|
|
+ * q will overwrite w/ outputted characters, minus possibly-stripped
|
|
|
|
|
+ * quotes and including nulls after each token.
|
|
|
|
|
+ */
|
|
|
|
|
+ token = q = p;
|
|
|
|
|
+ inquote = 0;
|
|
|
|
|
+ intok = 1;
|
|
|
|
|
+ if (backslash) {
|
|
|
|
|
+ while (intok && (p = strqtok_cchar(p, &c, &backslashed))) {
|
|
|
|
|
+ if (backslashed) {
|
|
|
|
|
+ *q++ = c; /* treat as plain character */
|
|
|
|
|
+ } else if (!inquote && *delim && strchr(delim, c)) {
|
|
|
|
|
+ *q = '\0'; /* Reached end of token */
|
|
|
|
|
+ intok = 0;
|
|
|
|
|
+ } else if (!inquote && *commentchars && strchr(commentchars, c)) {
|
|
|
|
|
+ *q = '\0'; /* Reached end of token */
|
|
|
|
|
+ *p = '\0'; /* make it act like end of string */
|
|
|
|
|
+ intok = 0;
|
|
|
|
|
+ } else if (!inquote && *quotemarks && strchr(quotemarks, c)) {
|
|
|
|
|
+ inquote = 1; /* Beginning a quoted segment */
|
|
|
|
|
+ leftquote = c; /* Save quote char for matching with */
|
|
|
|
|
+ if (!stripquote) *q++ = c;
|
|
|
|
|
+ } else if (inquote && leftquote == c) {
|
|
|
|
|
+ inquote = 0; /* Ending a quoted segment */
|
|
|
|
|
+ if (!stripquote) *q++ = c;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ *q++ = c; /* Ordinary character */
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ strq_start = p; /* Where to start next search */
|
|
|
|
|
+ *q = '\0';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ while (intok && *p) {
|
|
|
|
|
+ if (!inquote && *delim && strchr(delim, *p)) {
|
|
|
|
|
+ *q = '\0'; /* Reached end of token */
|
|
|
|
|
+ p++; /* advance p for next token */
|
|
|
|
|
+ intok = 0;
|
|
|
|
|
+ } else if (!inquote && *commentchars && strchr(commentchars, *p)) {
|
|
|
|
|
+ *q = '\0'; /* Reached end of token */
|
|
|
|
|
+ *p = '\0'; /* make it act like end of string */
|
|
|
|
|
+ intok = 0;
|
|
|
|
|
+ } else if (!inquote && *quotemarks && strchr(quotemarks, *p)) {
|
|
|
|
|
+ inquote = 1; /* Beginning a quoted segment */
|
|
|
|
|
+ leftquote = *p++; /* Save quote char for matching with */
|
|
|
|
|
+ if (!stripquote) *q++ = leftquote;
|
|
|
|
|
+ } else if (inquote && leftquote == *p) {
|
|
|
|
|
+ inquote = 0; /* Ending a quoted segment */
|
|
|
|
|
+ p++;
|
|
|
|
|
+ if (!stripquote) *q++ = leftquote;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ *q++ = *p++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ strq_start = p; /* Where to start next search */
|
|
|
|
|
+ *q = '\0';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (skipdelim && strq_start) {
|
|
|
|
|
+ /* Skip trailing delimiters */
|
|
|
|
|
+ while (*strq_start && strchr(delim, *strq_start))
|
|
|
|
|
+ strq_start++;
|
|
|
|
|
+ }
|
|
|
|
|
+ return token;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* this file is to be found in the user's home directory */
|
|
|
|
|
|
|
|
|
|
#ifndef CVSRC_FILENAME
|
|
|
|
|
@@ -23,9 +220,68 @@
|
|
|
|
|
|
|
|
|
|
extern char *strtok ();
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSRC
|
|
|
|
|
+static void read_cvsrc_parentdirs ();
|
|
|
|
|
+static void read_cvsrc_file ();
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* Read cvsrc, processing options matching CMDNAME ("cvs" for global
|
|
|
|
|
options, and update *ARGC and *ARGV accordingly. */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSRC
|
|
|
|
|
+void
|
|
|
|
|
+read_cvsrc (argc, argv, cmdname)
|
|
|
|
|
+ int *argc;
|
|
|
|
|
+ char ***argv;
|
|
|
|
|
+ char *cmdname;
|
|
|
|
|
+{
|
|
|
|
|
+ /* try to read .cvsrc files from parent directories */
|
|
|
|
|
+ read_cvsrc_parentdirs(argc, argv, cmdname);
|
|
|
|
|
+
|
|
|
|
|
+ /* try to read .cvsrc file from home directory */
|
|
|
|
|
+ read_cvsrc_file(argc, argv, cmdname, get_homedir());
|
|
|
|
|
+
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* read .cvsrc files from all parent directories (including the current dir) */
|
|
|
|
|
+static void
|
|
|
|
|
+read_cvsrc_parentdirs (argc, argv, cmdname)
|
|
|
|
|
+ int *argc;
|
|
|
|
|
+ char ***argv;
|
|
|
|
|
+ char *cmdname;
|
|
|
|
|
+{
|
|
|
|
|
+ char cwd[PATH_MAX];
|
|
|
|
|
+ char *cp;
|
|
|
|
|
+ int l;
|
|
|
|
|
+
|
|
|
|
|
+ if (getcwd(cwd, sizeof(cwd)) == NULL)
|
|
|
|
|
+ return;
|
|
|
|
|
+ if ((l = strlen(cwd)) <= 0)
|
|
|
|
|
+ return;
|
|
|
|
|
+ if (cwd[l-1] != '/') {
|
|
|
|
|
+ cwd[l++] = '/';
|
|
|
|
|
+ cwd[l++] = '\0';
|
|
|
|
|
+ }
|
|
|
|
|
+ while (cwd[0] != '\0') {
|
|
|
|
|
+ cwd[strlen(cwd)-1] = '\0';
|
|
|
|
|
+ read_cvsrc_file(argc, argv, cmdname, cwd);
|
|
|
|
|
+ if ((cp = strrchr(cwd, '/')) == NULL)
|
|
|
|
|
+ break;
|
|
|
|
|
+ *(cp+1) = '\0';
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* read .cvsrc file from a particular directory */
|
|
|
|
|
+static void
|
|
|
|
|
+read_cvsrc_file (argc, argv, cmdname, homedir)
|
|
|
|
|
+ int *argc;
|
|
|
|
|
+ char ***argv;
|
|
|
|
|
+ char *cmdname;
|
|
|
|
|
+ char *homedir;
|
|
|
|
|
+{
|
|
|
|
|
+#else
|
|
|
|
|
void
|
|
|
|
|
read_cvsrc (argc, argv, cmdname)
|
|
|
|
|
int *argc;
|
|
|
|
|
@@ -33,6 +289,7 @@
|
|
|
|
|
char *cmdname;
|
|
|
|
|
{
|
|
|
|
|
char *homedir;
|
|
|
|
|
+#endif
|
|
|
|
|
char *homeinit;
|
|
|
|
|
FILE *cvsrcfile;
|
|
|
|
|
|
|
|
|
|
@@ -64,7 +321,9 @@
|
|
|
|
|
|
|
|
|
|
/* determine filename for ~/.cvsrc */
|
|
|
|
|
|
|
|
|
|
+#ifndef RSE_PATCH_CVSRC
|
|
|
|
|
homedir = get_homedir ();
|
|
|
|
|
+#endif
|
|
|
|
|
/* If we can't find a home directory, ignore ~/.cvsrc. This may
|
|
|
|
|
make tracking down problems a bit of a pain, but on the other
|
|
|
|
|
hand it might be obnoxious to complain when CVS will function
|
|
|
|
|
@@ -123,9 +382,15 @@
|
|
|
|
|
if (found)
|
|
|
|
|
{
|
|
|
|
|
/* skip over command in the options line */
|
|
|
|
|
+#ifdef RSE_PATCH_CVSRC
|
|
|
|
|
+ for (optstart = strqtok (line + command_len, "\t \n", "\"'", "", 7);
|
|
|
|
|
+ optstart;
|
|
|
|
|
+ optstart = strqtok (NULL, "\t \n", "\"'", "", 7))
|
|
|
|
|
+#else
|
|
|
|
|
for (optstart = strtok (line + command_len, "\t \n");
|
|
|
|
|
optstart;
|
|
|
|
|
optstart = strtok (NULL, "\t \n"))
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
new_argv [new_argc++] = xstrdup (optstart);
|
|
|
|
|
|
|
|
|
|
Index: src/diff.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/diff.c,v
|
|
|
|
|
retrieving revision 1.1.1.3
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.3 diff.c
|
|
|
|
|
--- src/diff.c 24 Apr 2001 18:14:53 -0000 1.1.1.3
|
|
|
|
|
+++ src/diff.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -77,7 +77,11 @@
|
|
|
|
|
"\t-r rev2\tDiff rev1/date1 against rev2.\n",
|
|
|
|
|
"\t--ifdef=arg\tOutput diffs in ifdef format.\n",
|
|
|
|
|
"(consult the documentation for your diff program for rcsdiff-options.\n",
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS
|
|
|
|
|
+ "The most popular is -c for context diffs and -u for unified diffs).\n",
|
|
|
|
|
+#else
|
|
|
|
|
"The most popular is -c for context diffs but there are many more).\n",
|
|
|
|
|
+#endif
|
|
|
|
|
"(Specify the --help global option for a list of other help options)\n",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
@@ -224,13 +228,21 @@
|
|
|
|
|
|
|
|
|
|
optind = 0;
|
|
|
|
|
while ((c = getopt_long (argc, argv,
|
|
|
|
|
+#if defined(RSE_PATCH_HANDLE)
|
|
|
|
|
+ "+abcdefh:ilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:",
|
|
|
|
|
+#else
|
|
|
|
|
"+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:",
|
|
|
|
|
+#endif
|
|
|
|
|
longopts, &option_index)) != -1)
|
|
|
|
|
{
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
|
|
|
+#if defined(RSE_PATCH_HANDLE)
|
|
|
|
|
+ case 'i': case 'n': case 'p': case 's': case 't':
|
|
|
|
|
+#else
|
|
|
|
|
case 'h': case 'i': case 'n': case 'p': case 's': case 't':
|
|
|
|
|
+#endif
|
|
|
|
|
case 'u': case 'w': case 'y':
|
|
|
|
|
case '0': case '1': case '2': case '3': case '4': case '5':
|
|
|
|
|
case '6': case '7': case '8': case '9':
|
|
|
|
|
@@ -302,6 +314,17 @@
|
|
|
|
|
else
|
|
|
|
|
diff_date1 = Make_Date (optarg);
|
|
|
|
|
break;
|
|
|
|
|
+#ifdef RSE_PATCH_HANDLE
|
|
|
|
|
+ case 'h': {
|
|
|
|
|
+ time_t t1, t2;
|
|
|
|
|
+ if (!handle2dates(optarg, &t1, &t2))
|
|
|
|
|
+ error (1, 0, "invalid handle string");
|
|
|
|
|
+ t1 -= 1; /* subtract one second to have a real difference */
|
|
|
|
|
+ diff_date1 = date_from_time_t(t1);
|
|
|
|
|
+ diff_date2 = date_from_time_t(t2);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
case 'N':
|
|
|
|
|
empty_files = 1;
|
|
|
|
|
break;
|
|
|
|
|
@@ -436,8 +459,16 @@
|
|
|
|
|
char *head =
|
|
|
|
|
(vers->vn_rcs == NULL
|
|
|
|
|
? NULL
|
|
|
|
|
+#ifdef RSE_PATCH_DIFFHEAD
|
|
|
|
|
+ : RCS_head (vers->srcfile));
|
|
|
|
|
+#else
|
|
|
|
|
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_DEADAWARE
|
|
|
|
|
+ exists = (head != NULL && !RCS_isdead(vers->srcfile, head));
|
|
|
|
|
+#else
|
|
|
|
|
exists = head != NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
if (head != NULL)
|
|
|
|
|
free (head);
|
|
|
|
|
}
|
|
|
|
|
@@ -447,7 +478,12 @@
|
|
|
|
|
|
|
|
|
|
xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1,
|
|
|
|
|
1, 0);
|
|
|
|
|
+#ifdef RSE_PATCH_DEADAWARE
|
|
|
|
|
+ exists = (xvers->vn_rcs != NULL &&
|
|
|
|
|
+ !RCS_isdead(xvers->srcfile, xvers->vn_rcs));
|
|
|
|
|
+#else
|
|
|
|
|
exists = xvers->vn_rcs != NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
freevers_ts (&xvers);
|
|
|
|
|
}
|
|
|
|
|
if (exists)
|
|
|
|
|
@@ -840,7 +876,11 @@
|
|
|
|
|
if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
|
|
|
|
|
use_rev1 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
|
|
|
|
|
? NULL
|
|
|
|
|
+#ifdef RSE_PATCH_DIFFHEAD
|
|
|
|
|
+ : RCS_head (vers->srcfile));
|
|
|
|
|
+#else
|
|
|
|
|
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
|
|
|
|
|
+#endif
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0);
|
|
|
|
|
@@ -855,7 +895,11 @@
|
|
|
|
|
if (diff_rev2 && strcmp (diff_rev2, TAG_HEAD) == 0)
|
|
|
|
|
use_rev2 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
|
|
|
|
|
? NULL
|
|
|
|
|
+#ifdef RSE_PATCH_DIFFHEAD
|
|
|
|
|
+ : RCS_head (vers->srcfile));
|
|
|
|
|
+#else
|
|
|
|
|
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
|
|
|
|
|
+#endif
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
xvers = Version_TS (finfo, NULL, diff_rev2, diff_date2, 1, 0);
|
|
|
|
|
Index: src/hash.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/hash.c,v
|
|
|
|
|
retrieving revision 1.1.1.3
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.3 hash.c
|
|
|
|
|
--- src/hash.c 19 Sep 2000 00:06:35 -0000 1.1.1.3
|
|
|
|
|
+++ src/hash.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -25,17 +25,25 @@
|
|
|
|
|
const char *key;
|
|
|
|
|
{
|
|
|
|
|
unsigned int h = 0;
|
|
|
|
|
+#ifndef RSE_PATCH_HASHFUNC
|
|
|
|
|
unsigned int g;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
assert(key != NULL);
|
|
|
|
|
|
|
|
|
|
while (*key != 0)
|
|
|
|
|
{
|
|
|
|
|
+#ifdef RSE_PATCH_HASHFUNC
|
|
|
|
|
+ /* D.J. Bernstein's popular times 33 function
|
|
|
|
|
+ (fast and distributes very well) */
|
|
|
|
|
+ h = ((h << 5) + h) + FOLD_FN_CHAR(*key++);
|
|
|
|
|
+#else
|
|
|
|
|
unsigned int c = *key++;
|
|
|
|
|
/* The FOLD_FN_CHAR is so that findnode_fn works. */
|
|
|
|
|
h = (h << 4) + FOLD_FN_CHAR (c);
|
|
|
|
|
if ((g = h & 0xf0000000) != 0)
|
|
|
|
|
h = (h ^ (g >> 24)) ^ g;
|
|
|
|
|
+#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (h % HASHSIZE);
|
|
|
|
|
Index: src/history.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/history.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 history.c
|
|
|
|
|
--- src/history.c 19 Apr 2001 19:45:32 -0000 1.1.1.4
|
|
|
|
|
+++ src/history.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -235,6 +235,9 @@
|
|
|
|
|
static char *tz_name = "+0000";
|
|
|
|
|
|
|
|
|
|
char *logHistory = ALL_REC_TYPES;
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+char *history_file = NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* -r, -t, or -b options, malloc'd. These are "" if the option in
|
|
|
|
|
question is not specified or is overridden by another option. The
|
|
|
|
|
@@ -668,6 +671,10 @@
|
|
|
|
|
|
|
|
|
|
if (histfile)
|
|
|
|
|
fname = xstrdup (histfile);
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+ else if (history_file)
|
|
|
|
|
+ fname = xstrdup (history_file);
|
|
|
|
|
+#endif
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fname = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
|
|
|
|
|
@@ -716,10 +723,18 @@
|
|
|
|
|
return;
|
|
|
|
|
if ( strchr(logHistory, type) == NULL )
|
|
|
|
|
return;
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+ if (history_file != NULL)
|
|
|
|
|
+ fname = xstrdup (history_file);
|
|
|
|
|
+ else {
|
|
|
|
|
+#endif
|
|
|
|
|
fname = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
|
|
|
|
|
+ sizeof (CVSROOTADM_HISTORY) + 3);
|
|
|
|
|
(void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
|
|
|
|
|
CVSROOTADM, CVSROOTADM_HISTORY);
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* turn off history logging if the history file does not exist */
|
|
|
|
|
if (!isfile (fname))
|
|
|
|
|
@@ -731,7 +746,11 @@
|
|
|
|
|
if (trace)
|
|
|
|
|
fprintf (stderr, "%s-> fopen(%s,a)\n",
|
|
|
|
|
CLIENT_SERVER_STR, fname);
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (nolock)
|
|
|
|
|
+#else
|
|
|
|
|
if (noexec)
|
|
|
|
|
+#endif
|
|
|
|
|
goto out;
|
|
|
|
|
fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666);
|
|
|
|
|
if (fd < 0)
|
|
|
|
|
Index: src/import.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/import.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 import.c
|
|
|
|
|
--- src/import.c 19 Apr 2001 19:45:32 -0000 1.1.1.4
|
|
|
|
|
+++ src/import.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -57,6 +57,140 @@
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_IMPORTINFO
|
|
|
|
|
+
|
|
|
|
|
+static char *importinfo_vtag;
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+importinfo_descend(thisdir)
|
|
|
|
|
+ char *thisdir;
|
|
|
|
|
+{
|
|
|
|
|
+ DIR *dirp;
|
|
|
|
|
+ struct dirent *dp;
|
|
|
|
|
+ int err = 0;
|
|
|
|
|
+ List *dirlist = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ if ((dirp = CVS_OPENDIR(thisdir)) == NULL) {
|
|
|
|
|
+ error(0, errno, "cannot open directory");
|
|
|
|
|
+ err++;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ errno = 0;
|
|
|
|
|
+ while ((dp = readdir(dirp)) != NULL) {
|
|
|
|
|
+ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
|
|
|
|
|
+ goto one_more_time_boys;
|
|
|
|
|
+ if (strcmp(dp->d_name, CVSADM) == 0)
|
|
|
|
|
+ goto one_more_time_boys;
|
|
|
|
|
+ if (ign_name(dp->d_name))
|
|
|
|
|
+ goto one_more_time_boys;
|
|
|
|
|
+ if (
|
|
|
|
|
+#ifdef DT_DIR
|
|
|
|
|
+ (dp->d_type == DT_DIR || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
|
|
|
|
|
+#else
|
|
|
|
|
+ isdir (dp->d_name)
|
|
|
|
|
+#endif
|
|
|
|
|
+ && !wrap_name_has(dp->d_name, WRAP_TOCVS)
|
|
|
|
|
+ ) {
|
|
|
|
|
+ Node *n;
|
|
|
|
|
+ if (dirlist == NULL)
|
|
|
|
|
+ dirlist = getlist();
|
|
|
|
|
+ n = getnode();
|
|
|
|
|
+ n->key = xstrdup(dp->d_name);
|
|
|
|
|
+ addnode(dirlist, n);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (
|
|
|
|
|
+#ifdef DT_DIR
|
|
|
|
|
+ dp->d_type == DT_LNK || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
|
|
|
|
|
+#else
|
|
|
|
|
+ islink (dp->d_name)
|
|
|
|
|
+#endif
|
|
|
|
|
+ ) {
|
|
|
|
|
+ err++;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ if (strcmp(thisdir, ".") == 0) {
|
|
|
|
|
+ run_arg(dp->d_name);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ char *p;
|
|
|
|
|
+ p = xmalloc(strlen(thisdir)+1+strlen(dp->d_name)+1);
|
|
|
|
|
+ (void)sprintf(p, "%s/%s", thisdir, dp->d_name);
|
|
|
|
|
+ run_arg(p);
|
|
|
|
|
+ free(p);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ one_more_time_boys:
|
|
|
|
|
+ errno = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (errno != 0) {
|
|
|
|
|
+ error(0, errno, "cannot read directory");
|
|
|
|
|
+ err++;
|
|
|
|
|
+ }
|
|
|
|
|
+ (void)closedir(dirp);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dirlist != NULL) {
|
|
|
|
|
+ Node *head, *p;
|
|
|
|
|
+ head = dirlist->list;
|
|
|
|
|
+ for (p = head->next; p != head; p = p->next) {
|
|
|
|
|
+ if (strcmp(thisdir, ".") == 0) {
|
|
|
|
|
+ err += importinfo_descend(p->key);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ char *nextdir;
|
|
|
|
|
+ nextdir = xmalloc(strlen(thisdir)+1+strlen(p->key)+1);
|
|
|
|
|
+ (void)sprintf(nextdir, "%s/%s", thisdir, p->key);
|
|
|
|
|
+ err += importinfo_descend(nextdir);
|
|
|
|
|
+ free(nextdir);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ dellist(&dirlist);
|
|
|
|
|
+ }
|
|
|
|
|
+ return err;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* importinfo configuration entry callback */
|
|
|
|
|
+static int
|
|
|
|
|
+importinfo_runproc(repository, filter)
|
|
|
|
|
+ char *repository;
|
|
|
|
|
+ char *filter;
|
|
|
|
|
+{
|
|
|
|
|
+ char *s, *cp;
|
|
|
|
|
+ int rv;
|
|
|
|
|
+
|
|
|
|
|
+ /* if possible, do an own check to make sure that filter really exists */
|
|
|
|
|
+ if (filter[0] == '/') {
|
|
|
|
|
+ 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-admin filter '%s'", s);
|
|
|
|
|
+ free(s);
|
|
|
|
|
+ return (1);
|
|
|
|
|
+ }
|
|
|
|
|
+ free(s);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* construct the filter command */
|
|
|
|
|
+ run_setup(filter);
|
|
|
|
|
+ run_arg(importinfo_vtag);
|
|
|
|
|
+ run_arg(repository);
|
|
|
|
|
+ ign_add_file(CVSDOTIGNORE, 1);
|
|
|
|
|
+ wrap_add_file(CVSDOTWRAPPER, 1);
|
|
|
|
|
+ rv = importinfo_descend(".");
|
|
|
|
|
+ if (rv > 0)
|
|
|
|
|
+ return rv;
|
|
|
|
|
+
|
|
|
|
|
+ /* execute the filter command */
|
|
|
|
|
+ rv = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
|
|
|
|
+
|
|
|
|
|
+ return rv;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
int
|
|
|
|
|
import (argc, argv)
|
|
|
|
|
int argc;
|
|
|
|
|
@@ -221,7 +355,11 @@
|
|
|
|
|
do_editor ((char *) NULL, &message, repository,
|
|
|
|
|
(List *) NULL);
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ do_verify (&message, repository);
|
|
|
|
|
+#else
|
|
|
|
|
do_verify (message, repository);
|
|
|
|
|
+#endif
|
|
|
|
|
msglen = message == NULL ? 0 : strlen (message);
|
|
|
|
|
if (msglen == 0 || message[msglen - 1] != '\n')
|
|
|
|
|
{
|
|
|
|
|
@@ -283,6 +421,12 @@
|
|
|
|
|
error (1, 0, "attempt to import the repository");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_IMPORTINFO
|
|
|
|
|
+ importinfo_vtag = argv[1];
|
|
|
|
|
+ if (Parse_Info(CVSROOTADM_IMPORTINFO, argv[0], importinfo_runproc, 1) > 0)
|
|
|
|
|
+ error(1, 0, "Pre-import check failed");
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/*
|
|
|
|
|
* Make all newly created directories writable. Should really use a more
|
|
|
|
|
* sophisticated security mechanism here.
|
|
|
|
|
@@ -323,7 +467,11 @@
|
|
|
|
|
"Use the following command to help the merge:");
|
|
|
|
|
cvs_output_tagged ("newline", NULL);
|
|
|
|
|
cvs_output_tagged ("newline", NULL);
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS
|
|
|
|
|
+ cvs_output_tagged ("text", " ");
|
|
|
|
|
+#else
|
|
|
|
|
cvs_output_tagged ("text", "\t");
|
|
|
|
|
+#endif
|
|
|
|
|
cvs_output_tagged ("text", program_name);
|
|
|
|
|
if (CVSroot_cmdline != NULL)
|
|
|
|
|
{
|
|
|
|
|
@@ -353,7 +501,11 @@
|
|
|
|
|
conflicts);
|
|
|
|
|
(void) fprintf (logfp,
|
|
|
|
|
"Use the following command to help the merge:\n\n");
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS
|
|
|
|
|
+ (void) fprintf (logfp, " %s checkout ", program_name);
|
|
|
|
|
+#else
|
|
|
|
|
(void) fprintf (logfp, "\t%s checkout ", program_name);
|
|
|
|
|
+#endif
|
|
|
|
|
(void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
|
|
|
|
|
argv[1], argv[1], argv[0]);
|
|
|
|
|
}
|
|
|
|
|
@@ -376,6 +528,9 @@
|
|
|
|
|
li->type = T_TITLE;
|
|
|
|
|
li->tag = xstrdup (vbranch);
|
|
|
|
|
li->rev_old = li->rev_new = NULL;
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ li->date = NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
p->data = (char *) li;
|
|
|
|
|
(void) addnode (ulist, p);
|
|
|
|
|
Update_Logfile (repository, message, logfp, ulist);
|
|
|
|
|
@@ -663,7 +818,11 @@
|
|
|
|
|
*/
|
|
|
|
|
if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
|
|
|
|
|
retval = 1;
|
|
|
|
|
+#ifdef RSE_PATCH_IMPORTTOUCH
|
|
|
|
|
+ add_log ('T', vfile);
|
|
|
|
|
+#else
|
|
|
|
|
add_log ('U', vfile);
|
|
|
|
|
+#endif
|
|
|
|
|
freevers_ts (&vers);
|
|
|
|
|
return (retval);
|
|
|
|
|
}
|
|
|
|
|
Index: src/list.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: src/list.c
|
|
|
|
|
diff -N src/list.c
|
|
|
|
|
--- /dev/null 1 Jan 1970 00:00:00 -0000
|
|
|
|
|
+++ src/list.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -0,0 +1,282 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * Copyright (c) 1998, Dan Rich <drich@employees.com>
|
|
|
|
|
+ *
|
|
|
|
|
+ * 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.
|
|
|
|
|
+ *
|
|
|
|
|
+ * List Directory
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+
|
|
|
|
|
+#include <time.h>
|
|
|
|
|
+#include <pwd.h>
|
|
|
|
|
+#include <grp.h>
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
|
|
+#include "cvs.h"
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+static int cvslist_fileproc PROTO((void *callerdat, struct file_info * finfo));
|
|
|
|
|
+static Dtype cvslist_dirproc PROTO((void *callerdat, char *dir, char *repos, char *update_dir, List * entries));
|
|
|
|
|
+static int cvslist_output_dir PROTO((Node * node, void *closure));
|
|
|
|
|
+static int cvslist_output_file PROTO((char *name));
|
|
|
|
|
+static int cvslist_tag_proc PROTO((Node * p, void *closure));
|
|
|
|
|
+
|
|
|
|
|
+static char *numtag;
|
|
|
|
|
+static char *date = NULL;
|
|
|
|
|
+static int force_tag_match = 1;
|
|
|
|
|
+static int local = 0;
|
|
|
|
|
+static int verbose = 0;
|
|
|
|
|
+static int list_attic = 0;
|
|
|
|
|
+static RCSNode *xrcsnode;
|
|
|
|
|
+
|
|
|
|
|
+static const char *const status_usage[] = {
|
|
|
|
|
+ "Usage: %s %s [-alRv] [-r tag|-D date] modules\n",
|
|
|
|
|
+ "\t-a\tInclude attic files\n",
|
|
|
|
|
+ "\t-v\tVerbose format; includes additional information for the file\n",
|
|
|
|
|
+ "\t-l\tProcess this directory only (not recursive).\n",
|
|
|
|
|
+ "\t-R\tProcess directories recursively.\n",
|
|
|
|
|
+ "\t-r rev\tExisting revision/tag.\n",
|
|
|
|
|
+ "\t-D\tExisting date.\n",
|
|
|
|
|
+ "(Specify the --help global option for a list of other help options)\n",
|
|
|
|
|
+ NULL
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+int cvslist(int argc, char **argv)
|
|
|
|
|
+{
|
|
|
|
|
+ int c;
|
|
|
|
|
+ int i;
|
|
|
|
|
+ int which;
|
|
|
|
|
+ int retval;
|
|
|
|
|
+
|
|
|
|
|
+ if (argc == -1)
|
|
|
|
|
+ usage(status_usage);
|
|
|
|
|
+ optind = 0;
|
|
|
|
|
+ while ((c = getopt(argc, argv, "+alRr:v")) != -1) {
|
|
|
|
|
+ switch (c) {
|
|
|
|
|
+ case 'a':
|
|
|
|
|
+ list_attic = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'D':
|
|
|
|
|
+ if (date)
|
|
|
|
|
+ free(date);
|
|
|
|
|
+ date = Make_Date(optarg);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'l':
|
|
|
|
|
+ local = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'R':
|
|
|
|
|
+ local = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'r':
|
|
|
|
|
+ numtag = optarg;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'v':
|
|
|
|
|
+ verbose = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '?':
|
|
|
|
|
+ default:
|
|
|
|
|
+ usage(status_usage);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ argc -= optind;
|
|
|
|
|
+ argv += optind;
|
|
|
|
|
+
|
|
|
|
|
+ if (date && numtag)
|
|
|
|
|
+ error(1, 0, "-r and -D options are mutually exclusive");
|
|
|
|
|
+
|
|
|
|
|
+ wrap_setup();
|
|
|
|
|
+#ifdef CLIENT_SUPPORT
|
|
|
|
|
+ if (current_parsed_root->isremote) {
|
|
|
|
|
+ start_server();
|
|
|
|
|
+ ign_setup();
|
|
|
|
|
+ if (list_attic)
|
|
|
|
|
+ send_arg("-a");
|
|
|
|
|
+ if (local)
|
|
|
|
|
+ send_arg("-l");
|
|
|
|
|
+ if (verbose)
|
|
|
|
|
+ send_arg("-v");
|
|
|
|
|
+ if (numtag)
|
|
|
|
|
+ option_with_arg("-r", numtag);
|
|
|
|
|
+ if (date)
|
|
|
|
|
+ client_senddate(date);
|
|
|
|
|
+#if 0
|
|
|
|
|
+ if (supported_request("expand-modules")) {
|
|
|
|
|
+ /* This is done here because we need to read responses from the
|
|
|
|
|
+ server before we send the command checkout or export files. */
|
|
|
|
|
+ client_expand_modules(argc, argv, local);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+ /* Send any remaining arguments -- probably dir/file names */
|
|
|
|
|
+ for (i = 0; i < argc; ++i)
|
|
|
|
|
+ send_arg(argv[i]);
|
|
|
|
|
+ send_to_server("list\012", 0); /* Send the command */
|
|
|
|
|
+ return get_responses_and_close();
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef SERVER_SUPPORT
|
|
|
|
|
+ /* If we're the server, make sure we're starting at the root */
|
|
|
|
|
+ if (server_active)
|
|
|
|
|
+ CVS_CHDIR(current_parsed_root->directory);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
|
|
+ if (numtag != NULL)
|
|
|
|
|
+ tag_check_valid(numtag, argc, argv, local, 0, "");
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ which = W_REPOS;
|
|
|
|
|
+ if (list_attic)
|
|
|
|
|
+ which |= W_ATTIC;
|
|
|
|
|
+
|
|
|
|
|
+ /* start the recursion processor */
|
|
|
|
|
+ cvs_output_tagged("+list", NULL);
|
|
|
|
|
+ retval = start_recursion(cvslist_fileproc, (FILESDONEPROC)NULL,
|
|
|
|
|
+ cvslist_dirproc, (DIRLEAVEPROC)NULL, NULL,
|
|
|
|
|
+ argc, argv, local, which, 0, 1, (char *)NULL, 1);
|
|
|
|
|
+ cvs_output_tagged("-list", NULL);
|
|
|
|
|
+
|
|
|
|
|
+ return retval;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Display file info
|
|
|
|
|
+ */
|
|
|
|
|
+/* ARGSUSED */
|
|
|
|
|
+static int cvslist_fileproc(callerdat, finfo)
|
|
|
|
|
+ void *callerdat;
|
|
|
|
|
+ struct file_info *finfo;
|
|
|
|
|
+{
|
|
|
|
|
+ char *buf;
|
|
|
|
|
+ Vers_TS *vers;
|
|
|
|
|
+
|
|
|
|
|
+ /* If a particular revision was specified, only show that one */
|
|
|
|
|
+ if (numtag != NULL || date != NULL) {
|
|
|
|
|
+ vers = Version_TS(finfo, NULL, NULL, NULL, 0, 0);
|
|
|
|
|
+ if (RCS_getversion(vers->srcfile, numtag, date, force_tag_match, NULL) == NULL)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cvslist_output_file(finfo->fullname);
|
|
|
|
|
+
|
|
|
|
|
+ if (verbose) {
|
|
|
|
|
+ vers = Version_TS(finfo, NULL, NULL, NULL, 0, 0);
|
|
|
|
|
+ if (vers->srcfile) {
|
|
|
|
|
+ List *symbols = RCS_symbols(vers->srcfile);
|
|
|
|
|
+
|
|
|
|
|
+ cvs_output_tagged("+info", NULL);
|
|
|
|
|
+ if (vers->vn_rcs == NULL)
|
|
|
|
|
+ cvs_output_tagged("finfo",
|
|
|
|
|
+ " Repository revision:\tNo revision control file");
|
|
|
|
|
+ else {
|
|
|
|
|
+ buf = (char *)malloc(24 + strlen(vers->vn_rcs) + 1 +
|
|
|
|
|
+ strlen(vers->srcfile->path) + 1);
|
|
|
|
|
+ sprintf(buf, " Repository revision:\t%s\t%s",
|
|
|
|
|
+ vers->vn_rcs, vers->srcfile->path);
|
|
|
|
|
+ cvs_output_tagged("finfo", buf);
|
|
|
|
|
+ }
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ cvs_output_tagged("finfo", " Existing Tags:");
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ if (symbols) {
|
|
|
|
|
+ xrcsnode = finfo->rcs;
|
|
|
|
|
+ (void)walklist(symbols, cvslist_tag_proc, NULL);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ cvs_output_tagged("finfo", "\tNo Tags Exist");
|
|
|
|
|
+
|
|
|
|
|
+ cvs_output_tagged("-info", NULL);
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Display directory info
|
|
|
|
|
+ */
|
|
|
|
|
+/* ARGSUSED */
|
|
|
|
|
+static Dtype cvslist_dirproc(callerdat, dir, repos, update_dir, entries)
|
|
|
|
|
+ void *callerdat;
|
|
|
|
|
+ char *dir;
|
|
|
|
|
+ char *repos;
|
|
|
|
|
+ char *update_dir;
|
|
|
|
|
+ List *entries;
|
|
|
|
|
+{
|
|
|
|
|
+ char *buf;
|
|
|
|
|
+ List *dirs;
|
|
|
|
|
+
|
|
|
|
|
+ buf = (char *)malloc(strlen(update_dir) + 2);
|
|
|
|
|
+ sprintf(buf, "%s", update_dir);
|
|
|
|
|
+ cvs_output_tagged("fname", buf);
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ free(buf);
|
|
|
|
|
+
|
|
|
|
|
+ if (local) { /* We need to output the current dirs */
|
|
|
|
|
+ dirs = Find_Directories(update_dir, W_REPOS, NULL);
|
|
|
|
|
+ walklist(dirs, cvslist_output_dir, update_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+ return R_PROCESS;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int cvslist_output_dir(node, closure)
|
|
|
|
|
+ Node *node;
|
|
|
|
|
+ void *closure;
|
|
|
|
|
+{
|
|
|
|
|
+ char *buf;
|
|
|
|
|
+
|
|
|
|
|
+ buf = (char *)malloc(strlen((char *)closure) + strlen(node->key) + 3);
|
|
|
|
|
+ sprintf(buf, "%s/%s/", (char *)closure, node->key);
|
|
|
|
|
+ cvs_output_tagged("fname", buf);
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ free(buf);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int cvslist_output_file(name)
|
|
|
|
|
+ char *name;
|
|
|
|
|
+{
|
|
|
|
|
+ char *buf;
|
|
|
|
|
+ char *nlptr;
|
|
|
|
|
+
|
|
|
|
|
+ buf = (char *)malloc(strlen(name) + 1);
|
|
|
|
|
+ strncpy(buf, name, strlen(name));
|
|
|
|
|
+ *(buf+strlen(name)) = '\0';
|
|
|
|
|
+
|
|
|
|
|
+ /* cvs_output_tagged doesn't like \n */
|
|
|
|
|
+ if ((nlptr = strchr(buf, '\n')) != NULL)
|
|
|
|
|
+ nlptr = '\0';
|
|
|
|
|
+ cvs_output_tagged("fname", buf);
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ free(buf);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int cvslist_tag_proc(p, closure)
|
|
|
|
|
+ Node *p;
|
|
|
|
|
+ void *closure;
|
|
|
|
|
+{
|
|
|
|
|
+ char *branch = NULL;
|
|
|
|
|
+ char *buf;
|
|
|
|
|
+
|
|
|
|
|
+ if (RCS_nodeisbranch(xrcsnode, p->key))
|
|
|
|
|
+ branch = RCS_whatbranch(xrcsnode, p->key);
|
|
|
|
|
+
|
|
|
|
|
+ buf = xmalloc(80 + strlen(p->key)
|
|
|
|
|
+ + (branch ? strlen(branch) : strlen(p->data)));
|
|
|
|
|
+ sprintf(buf, "\t%-25s\t(%s: %s)", p->key,
|
|
|
|
|
+ branch ? "branch" : "revision", branch ? branch : p->data);
|
|
|
|
|
+ cvs_output_tagged("finfo", buf);
|
|
|
|
|
+ cvs_output_tagged("newline", NULL);
|
|
|
|
|
+ free(buf);
|
|
|
|
|
+
|
|
|
|
|
+ if (branch)
|
|
|
|
|
+ free(branch);
|
|
|
|
|
+
|
|
|
|
|
+ return (0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif /* RSE_PATCH_RLIST */
|
|
|
|
|
+
|
|
|
|
|
Index: src/lock.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/lock.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 lock.c
|
|
|
|
|
--- src/lock.c 19 Apr 2001 19:45:32 -0000 1.1.1.4
|
|
|
|
|
+++ src/lock.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -396,7 +396,11 @@
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (nolock)
|
|
|
|
|
+#else
|
|
|
|
|
if (noexec)
|
|
|
|
|
+#endif
|
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
|
|
/* we only do one directory at a time for read locks! */
|
|
|
|
|
@@ -468,7 +472,11 @@
|
|
|
|
|
{
|
|
|
|
|
char *wait_repos;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (nolock)
|
|
|
|
|
+#else
|
|
|
|
|
if (noexec)
|
|
|
|
|
+#endif
|
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
|
|
/* We only know how to do one list at a time */
|
|
|
|
|
Index: src/logmsg.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/logmsg.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 logmsg.c
|
|
|
|
|
--- src/logmsg.c 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/logmsg.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -387,14 +387,26 @@
|
|
|
|
|
independant of the running of an editor for getting a message.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+do_verify (messagep, repository)
|
|
|
|
|
+ char **messagep;
|
|
|
|
|
+#else
|
|
|
|
|
do_verify (message, repository)
|
|
|
|
|
char *message;
|
|
|
|
|
+#endif
|
|
|
|
|
char *repository;
|
|
|
|
|
{
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char *fname;
|
|
|
|
|
int retcode = 0;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ char *line;
|
|
|
|
|
+ int line_length;
|
|
|
|
|
+ size_t line_chars_allocated;
|
|
|
|
|
+ char *p;
|
|
|
|
|
+ struct stat stbuf;
|
|
|
|
|
+#endif
|
|
|
|
|
#ifdef CLIENT_SUPPORT
|
|
|
|
|
if (current_parsed_root->isremote)
|
|
|
|
|
/* The verification will happen on the server. */
|
|
|
|
|
@@ -408,7 +420,11 @@
|
|
|
|
|
|
|
|
|
|
/* If there's no message, then we have nothing to verify. Can this
|
|
|
|
|
case happen? And if so why would we print a message? */
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ if (*messagep == NULL)
|
|
|
|
|
+#else
|
|
|
|
|
if (message == NULL)
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
cvs_output ("No message to verify\n", 0);
|
|
|
|
|
return;
|
|
|
|
|
@@ -421,9 +437,15 @@
|
|
|
|
|
error (1, errno, "cannot create temporary file %s", fname);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ fprintf (fp, "%s", *messagep);
|
|
|
|
|
+ if ((*messagep)[0] == '\0' ||
|
|
|
|
|
+ (*messagep)[strlen (*messagep) - 1] != '\n')
|
|
|
|
|
+#else
|
|
|
|
|
fprintf (fp, "%s", message);
|
|
|
|
|
if ((message)[0] == '\0' ||
|
|
|
|
|
(message)[strlen (message) - 1] != '\n')
|
|
|
|
|
+#endif
|
|
|
|
|
(void) fprintf (fp, "%s", "\n");
|
|
|
|
|
if (fclose (fp) == EOF)
|
|
|
|
|
error (1, errno, "%s", fname);
|
|
|
|
|
@@ -453,6 +475,41 @@
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_VERIFY
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Put the entire message back into the *messagep variable
|
|
|
|
|
+ */
|
|
|
|
|
+ if ((fp = open_file (fname, "r")) == NULL) {
|
|
|
|
|
+ error(1, errno, "cannot open temporary file %s", fname);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (*messagep)
|
|
|
|
|
+ free (*messagep);
|
|
|
|
|
+ if (CVS_STAT(fname, &stbuf) != 0)
|
|
|
|
|
+ error(1, errno, "cannot find size of temp file %s", fname);
|
|
|
|
|
+ *messagep = (char *)xmalloc(stbuf.st_size + 1);
|
|
|
|
|
+ *messagep[0] = '\0';
|
|
|
|
|
+ line = NULL;
|
|
|
|
|
+ line_chars_allocated = 0;
|
|
|
|
|
+ if (stbuf.st_size > 0) {
|
|
|
|
|
+ p = *messagep;
|
|
|
|
|
+ while (1) {
|
|
|
|
|
+ line_length = getline (&line, &line_chars_allocated, fp);
|
|
|
|
|
+ if (line_length == -1) {
|
|
|
|
|
+ if (ferror (fp))
|
|
|
|
|
+ error (0, errno, "warning: cannot read %s", fname);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ (void) strcpy (p, line);
|
|
|
|
|
+ p += line_length;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (fclose (fp) < 0)
|
|
|
|
|
+ error (0, errno, "warning: cannot close %s", fname);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* Delete the temp file */
|
|
|
|
|
|
|
|
|
|
if (unlink_file (fname) < 0)
|
|
|
|
|
@@ -582,6 +639,42 @@
|
|
|
|
|
{
|
|
|
|
|
switch (*c)
|
|
|
|
|
{
|
|
|
|
|
+#ifdef RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+ case 'o': {
|
|
|
|
|
+ char T[2];
|
|
|
|
|
+ str_list = xrealloc (str_list, (strlen (str_list) + 1 + 1));
|
|
|
|
|
+ switch (li->type) {
|
|
|
|
|
+ case T_ADDED: T[0] = 'A'; break;
|
|
|
|
|
+ case T_MODIFIED: T[0] = 'M'; break;
|
|
|
|
|
+ case T_REMOVED: T[0] = 'R'; break;
|
|
|
|
|
+ default: T[0] = '?'; break;
|
|
|
|
|
+ }
|
|
|
|
|
+ T[1] = '\0';
|
|
|
|
|
+ (void) strcat (str_list, T);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ case 't':
|
|
|
|
|
+ str_list =
|
|
|
|
|
+ xrealloc (str_list,
|
|
|
|
|
+ (strlen (str_list)
|
|
|
|
|
+ + (li->tag ? strlen (li->tag) : 0)
|
|
|
|
|
+ + 10)
|
|
|
|
|
+ );
|
|
|
|
|
+ (void) strcat (str_list, (li->tag ? li->tag : ""));
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'd': {
|
|
|
|
|
+ time_t t;
|
|
|
|
|
+ if (li->date != NULL) {
|
|
|
|
|
+ t = get_date(li->date, NULL);
|
|
|
|
|
+ if (t != ((time_t)-1)) {
|
|
|
|
|
+ t += 1; /* re-adjust because of fudge */
|
|
|
|
|
+ str_list = xrealloc (str_list, (strlen(str_list)+20));
|
|
|
|
|
+ sprintf(str_list+strlen(str_list), "%ld", (long)t);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
case 's':
|
|
|
|
|
str_list =
|
|
|
|
|
xrealloc (str_list,
|
|
|
|
|
Index: src/main.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/main.c,v
|
|
|
|
|
retrieving revision 1.1.1.5
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.5 main.c
|
|
|
|
|
--- src/main.c 27 Apr 2001 19:57:23 -0000 1.1.1.5
|
|
|
|
|
+++ src/main.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -41,6 +41,9 @@
|
|
|
|
|
int quiet = 0;
|
|
|
|
|
int trace = 0;
|
|
|
|
|
int noexec = 0;
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+int nolock = 0;
|
|
|
|
|
+#endif
|
|
|
|
|
int logoff = 0;
|
|
|
|
|
|
|
|
|
|
/* Set if we should be writing CVSADM directories at top level. At
|
|
|
|
|
@@ -50,6 +53,15 @@
|
|
|
|
|
|
|
|
|
|
mode_t cvsumask = UMASK_DFLT;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+char *RCS_citag = NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+char *cvs_prolog = NULL;
|
|
|
|
|
+char *cvs_epilog = NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
char *CurDir;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -124,11 +136,17 @@
|
|
|
|
|
{ "login", "logon", "lgn", login, 0 },
|
|
|
|
|
{ "logout", NULL, NULL, logout, 0 },
|
|
|
|
|
#endif /* AUTH_CLIENT_SUPPORT */
|
|
|
|
|
+#ifdef RSE_PATCH_PSERVERD
|
|
|
|
|
+ { "pserverd", NULL, NULL, pserverd },
|
|
|
|
|
+#endif
|
|
|
|
|
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
|
|
|
|
|
{ "pserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
|
|
|
|
|
#endif
|
|
|
|
|
{ "rannotate","rann", "ra", annotate, 0 },
|
|
|
|
|
{ "rdiff", "patch", "pa", patch, 0 },
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+ { "rlist", "rls", NULL, cvslist, 0 },
|
|
|
|
|
+#endif
|
|
|
|
|
{ "release", "re", "rel", release, 0 },
|
|
|
|
|
{ "remove", "rm", "delete", cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
|
|
|
|
|
{ "rlog", "rl", NULL, cvslog, 0 },
|
|
|
|
|
@@ -143,9 +161,53 @@
|
|
|
|
|
{ "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 },
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ { "root", "ro", "repo", root, CVS_CMD_IGNORE_ADMROOT },
|
|
|
|
|
+#endif
|
|
|
|
|
{ NULL, NULL, NULL, NULL, 0 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+
|
|
|
|
|
+/* the table of custom commands */
|
|
|
|
|
+#define CUSTOMCMD_MAX 20
|
|
|
|
|
+static int customcmd_num = 0;
|
|
|
|
|
+struct customcmd {
|
|
|
|
|
+ char *name;
|
|
|
|
|
+ char *command;
|
|
|
|
|
+};
|
|
|
|
|
+static struct customcmd customcmd_tab[CUSTOMCMD_MAX];
|
|
|
|
|
+
|
|
|
|
|
+/* the internal handler function for custom commands */
|
|
|
|
|
+static int
|
|
|
|
|
+customcmd_run(argc, argv)
|
|
|
|
|
+ int argc;
|
|
|
|
|
+ char **argv;
|
|
|
|
|
+{
|
|
|
|
|
+ int i;
|
|
|
|
|
+ char *cmd;
|
|
|
|
|
+
|
|
|
|
|
+ /* support for `cvs -H <cmd>' */
|
|
|
|
|
+ if (argc == -1) {
|
|
|
|
|
+ (void)fprintf(stderr, "Usage: %s %s [command arguments]\n",
|
|
|
|
|
+ program_name, command_name);
|
|
|
|
|
+ error_exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* execute the command */
|
|
|
|
|
+ cmd = expand_path(argv[0], command_name, 0);
|
|
|
|
|
+ run_setup(cmd);
|
|
|
|
|
+ for (i = 1; i < argc; i++)
|
|
|
|
|
+ run_arg(argv[i]);
|
|
|
|
|
+ if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
|
|
|
|
|
+ error(1, 0, "program `%s' of custom command `%s' returned non-zero",
|
|
|
|
|
+ cmd, command_name);
|
|
|
|
|
+ free(cmd);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
static const char *const usg[] =
|
|
|
|
|
{
|
|
|
|
|
/* CVS usage messages never have followed the GNU convention of
|
|
|
|
|
@@ -186,9 +248,13 @@
|
|
|
|
|
paragraph in ../cvs.spec without assuming the reader knows what
|
|
|
|
|
version control means. */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_COSMETICS
|
|
|
|
|
+ "For CVS updates and additional information, see http://www.cvshome.org/\n",
|
|
|
|
|
+#else
|
|
|
|
|
"For CVS updates and additional information, see\n",
|
|
|
|
|
" the CVS home page at http://www.cvshome.org/ or\n",
|
|
|
|
|
" Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n",
|
|
|
|
|
+#endif
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -215,11 +281,17 @@
|
|
|
|
|
" login Prompt for password for authenticating server\n",
|
|
|
|
|
" logout Removes entry in .cvspass for remote repository\n",
|
|
|
|
|
#endif /* AUTH_CLIENT_SUPPORT */
|
|
|
|
|
+#ifdef RSE_PATCH_PSERVERD
|
|
|
|
|
+ " pserverd Password server daemon\n",
|
|
|
|
|
+#endif
|
|
|
|
|
#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",
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+ " rlist List repository directories.\n",
|
|
|
|
|
+#endif
|
|
|
|
|
" 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",
|
|
|
|
|
@@ -234,6 +306,9 @@
|
|
|
|
|
" version Show current CVS version(s)\n",
|
|
|
|
|
" watch Set watches\n",
|
|
|
|
|
" watchers See who is watching a file\n",
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ " root Maintain repository root locations\n",
|
|
|
|
|
+#endif
|
|
|
|
|
"(Specify the --help option for a list of other help options)\n",
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
@@ -249,6 +324,9 @@
|
|
|
|
|
" -w Make checked-out files read-write (default).\n",
|
|
|
|
|
" -l Turn history logging off.\n",
|
|
|
|
|
" -n Do not execute anything that will change the disk.\n",
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ " -u Do not create lock files (implies -l).\n",
|
|
|
|
|
+#endif
|
|
|
|
|
" -t Show trace of program execution -- try with -n.\n",
|
|
|
|
|
" -v CVS version and copyright.\n",
|
|
|
|
|
" -T tmpdir Use 'tmpdir' for temporary files.\n",
|
|
|
|
|
@@ -262,6 +340,10 @@
|
|
|
|
|
#endif
|
|
|
|
|
" -a Authenticate all net traffic.\n",
|
|
|
|
|
#endif
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+ " -P program Run prolog program before processing.\n",
|
|
|
|
|
+ " -E program Run epilog program after processing.\n",
|
|
|
|
|
+#endif
|
|
|
|
|
" -s VAR=VAL Set CVS user variable.\n",
|
|
|
|
|
"(Specify the --help option for a list of other help options)\n",
|
|
|
|
|
NULL
|
|
|
|
|
@@ -332,6 +414,20 @@
|
|
|
|
|
if (strcmp (cmd_name, cm->fullname) == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+ {
|
|
|
|
|
+ int i;
|
|
|
|
|
+ unsigned long int ret = 0;
|
|
|
|
|
+ for (i = 0; i < customcmd_num; i++) {
|
|
|
|
|
+ if (strcmp(customcmd_tab[i].name, cmd_name) == 0) {
|
|
|
|
|
+ ret |= CVS_CMD_IGNORE_ADMROOT;
|
|
|
|
|
+ ret &= ~(CVS_CMD_USES_WORK_DIR);
|
|
|
|
|
+ ret &= ~(CVS_CMD_MODIFIES_REPOSITORY);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
return cm->attr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -401,11 +497,34 @@
|
|
|
|
|
int free_CVSroot = 0;
|
|
|
|
|
int free_Editor = 0;
|
|
|
|
|
int free_Tmpdir = 0;
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ cvsroot_type *cvsroot_sync = NULL;
|
|
|
|
|
+ int cvsroot_cmdline_isreal = 0;
|
|
|
|
|
+#endif
|
|
|
|
|
+#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ int standalone_command = 0;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
int help = 0; /* Has the user asked for help? This
|
|
|
|
|
lets us support the `cvs -H cmd'
|
|
|
|
|
convention to give help for cmd. */
|
|
|
|
|
+#if defined(RSE_PATCH_NOLOCK) ||\
|
|
|
|
|
+ defined(RSE_PATCH_PROLOGEPILOG) ||\
|
|
|
|
|
+ defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa"
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ "u"
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+ "P:E:"
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+ "C:"
|
|
|
|
|
+#endif
|
|
|
|
|
+ ;
|
|
|
|
|
+#else
|
|
|
|
|
static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa";
|
|
|
|
|
+#endif
|
|
|
|
|
static struct option long_options[] =
|
|
|
|
|
{
|
|
|
|
|
{"help", 0, NULL, 'H'},
|
|
|
|
|
@@ -414,6 +533,9 @@
|
|
|
|
|
{"help-synonyms", 0, NULL, 2},
|
|
|
|
|
{"help-options", 0, NULL, 4},
|
|
|
|
|
{"allow-root", required_argument, NULL, 3},
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ {"map-root", required_argument, NULL, 5},
|
|
|
|
|
+#endif
|
|
|
|
|
{0, 0, 0, 0}
|
|
|
|
|
};
|
|
|
|
|
/* `getopt_long' stores the option index here, but right now we
|
|
|
|
|
@@ -468,6 +590,16 @@
|
|
|
|
|
}
|
|
|
|
|
if (getenv (CVSREAD_ENV) != NULL)
|
|
|
|
|
cvswrite = 0;
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (getenv (CVSNOLOCK_ENV)) {
|
|
|
|
|
+ nolock = 1;
|
|
|
|
|
+ logoff = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+ cvs_prolog = getenv("CVSPROLOG");
|
|
|
|
|
+ cvs_epilog = getenv("CVSEPILOG");
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* Set this to 0 to force getopt initialization. getopt() sets
|
|
|
|
|
this to 1 internally. */
|
|
|
|
|
@@ -487,12 +619,63 @@
|
|
|
|
|
use_cvsrc = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_GLOBALOPTION
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Perform a pre-lookup of the command name in order to scan cvsrc
|
|
|
|
|
+ * file also for command dependent global options. For instance a
|
|
|
|
|
+ * "-d" option only for "commit" commands (useful if one uses a
|
|
|
|
|
+ * local repository copy for all cvs commands, but commits have to
|
|
|
|
|
+ * go directly to the master repository).
|
|
|
|
|
+ */
|
|
|
|
|
+ if (use_cvsrc) {
|
|
|
|
|
+ command_name = argv[optind];
|
|
|
|
|
+ if (command_name != NULL && command_name[0] != '\0') {
|
|
|
|
|
+ for (cm = cmds; cm->fullname != NULL; cm++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (cm->nick1 && !strcmp(command_name, cm->nick1))
|
|
|
|
|
+ break;
|
|
|
|
|
+ if (cm->nick2 && !strcmp(command_name, cm->nick2))
|
|
|
|
|
+ break;
|
|
|
|
|
+ if (!strcmp(command_name, cm->fullname))
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ command_name = cm->fullname;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/*
|
|
|
|
|
* Scan cvsrc file for global options.
|
|
|
|
|
*/
|
|
|
|
|
if (use_cvsrc)
|
|
|
|
|
read_cvsrc (&argc, &argv, "cvs");
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_GLOBALOPTION
|
|
|
|
|
+ if (use_cvsrc) {
|
|
|
|
|
+ if (command_name != NULL && command_name[0] != '\0') {
|
|
|
|
|
+ char *cmd;
|
|
|
|
|
+#ifdef RSE_PATCH_GLOBALOPTION_PARTLY
|
|
|
|
|
+ if ( strcmp(command_name, "commit") == 0
|
|
|
|
|
+ || strcmp(command_name, "tag") == 0
|
|
|
|
|
+ || strcmp(command_name, "rtag") == 0
|
|
|
|
|
+ || strcmp(command_name, "history") == 0
|
|
|
|
|
+ || strcmp(command_name, "admin") == 0
|
|
|
|
|
+ || strcmp(command_name, "import") == 0
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+ || strcmp(command_name, "rlist") == 0
|
|
|
|
|
+#endif
|
|
|
|
|
+ || strcmp(command_name, "rdiff") == 0) {
|
|
|
|
|
+#endif
|
|
|
|
|
+ cmd = xmalloc(4 + strlen(command_name) + 1);
|
|
|
|
|
+ sprintf(cmd, "cvs/%s", command_name);
|
|
|
|
|
+ read_cvsrc (&argc, &argv, cmd);
|
|
|
|
|
+#ifdef RSE_PATCH_GLOBALOPTION_PARTLY
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
optind = 0;
|
|
|
|
|
opterr = 1;
|
|
|
|
|
|
|
|
|
|
@@ -518,6 +701,17 @@
|
|
|
|
|
/* --allow-root */
|
|
|
|
|
root_allow_add (optarg);
|
|
|
|
|
break;
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ case 5: {
|
|
|
|
|
+ /* --map-root */
|
|
|
|
|
+ char *cp;
|
|
|
|
|
+ if ((cp = strchr(optarg, ':')) == NULL)
|
|
|
|
|
+ error(1, 0, "invalid argument syntax for --map-root option");
|
|
|
|
|
+ *cp++ = '\0';
|
|
|
|
|
+ root_map_add(optarg, cp);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
case 'Q':
|
|
|
|
|
really_quiet = 1;
|
|
|
|
|
/* FALL THROUGH */
|
|
|
|
|
@@ -535,6 +729,10 @@
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
|
|
|
|
noexec = 1;
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ case 'u': /* Fall through */
|
|
|
|
|
+ nolock = 1;
|
|
|
|
|
+#endif
|
|
|
|
|
case 'l': /* Fall through */
|
|
|
|
|
logoff = 1;
|
|
|
|
|
break;
|
|
|
|
|
@@ -573,10 +771,34 @@
|
|
|
|
|
case 'd':
|
|
|
|
|
if (CVSroot_cmdline != NULL)
|
|
|
|
|
free (CVSroot_cmdline);
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ {
|
|
|
|
|
+ char *newarg;
|
|
|
|
|
+ if (root_map_it(optarg, &newarg, 0))
|
|
|
|
|
+ optarg = newarg;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ {
|
|
|
|
|
+ cvsroot_type *e;
|
|
|
|
|
+ if ((e = cvsroot_lookup(optarg, NULL, NULL)) != NULL) {
|
|
|
|
|
+ if (!quiet)
|
|
|
|
|
+ fprintf(stderr, "%s: using repository `%s'\n", program_name, e->masterpath);
|
|
|
|
|
+ CVSroot_cmdline = xstrdup(e->masterpath);
|
|
|
|
|
+ CVSroot = xstrdup(e->masterpath);
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ cvsroot_cmdline_isreal = 1;
|
|
|
|
|
+#endif
|
|
|
|
|
CVSroot_cmdline = xstrdup (optarg);
|
|
|
|
|
if (free_CVSroot)
|
|
|
|
|
free (CVSroot);
|
|
|
|
|
CVSroot = xstrdup (optarg);
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
free_CVSroot = 1;
|
|
|
|
|
cvs_update_env = 1; /* need to update environment */
|
|
|
|
|
break;
|
|
|
|
|
@@ -618,6 +840,28 @@
|
|
|
|
|
We will issue an error later if stream
|
|
|
|
|
authentication is not supported. */
|
|
|
|
|
break;
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+ case 'P':
|
|
|
|
|
+ cvs_prolog = xstrdup(optarg);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'E':
|
|
|
|
|
+ cvs_epilog = xstrdup(optarg);
|
|
|
|
|
+ break;
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+ case 'C': {
|
|
|
|
|
+ char *cp;
|
|
|
|
|
+ if (customcmd_num >= CUSTOMCMD_MAX)
|
|
|
|
|
+ error(1, 0, "maximum number of allowed -C options reached");
|
|
|
|
|
+ if ((cp = strchr(optarg, ':')) == NULL)
|
|
|
|
|
+ error(1, 0, "invalid argument to option -C (has to be \"name:cmd\")");
|
|
|
|
|
+ *cp++ = '\0';
|
|
|
|
|
+ customcmd_tab[customcmd_num].name = xstrdup(optarg);
|
|
|
|
|
+ customcmd_tab[customcmd_num].command = xstrdup(cp);
|
|
|
|
|
+ customcmd_num++;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
case '?':
|
|
|
|
|
default:
|
|
|
|
|
usage (usg);
|
|
|
|
|
@@ -629,6 +873,28 @@
|
|
|
|
|
if (argc < 1)
|
|
|
|
|
usage (usg);
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+ /* Look up the custom command. */
|
|
|
|
|
+ cm = NULL;
|
|
|
|
|
+ {
|
|
|
|
|
+ int i;
|
|
|
|
|
+ command_name = argv[0];
|
|
|
|
|
+ for (i = 0; i < customcmd_num; i++) {
|
|
|
|
|
+ if (strcmp(customcmd_tab[i].name, command_name) == 0) {
|
|
|
|
|
+ struct cmd *ccm;
|
|
|
|
|
+ ccm = (struct cmd *)xmalloc(sizeof(struct cmd));
|
|
|
|
|
+ ccm->nick1 = NULL;
|
|
|
|
|
+ ccm->nick2 = NULL;
|
|
|
|
|
+ ccm->func = customcmd_run;
|
|
|
|
|
+ ccm->fullname = customcmd_tab[i].name;
|
|
|
|
|
+ argv[0] = customcmd_tab[i].command;
|
|
|
|
|
+ cm = (const struct cmd *)ccm;
|
|
|
|
|
+ standalone_command = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (cm == NULL) {
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* Look up the command name. */
|
|
|
|
|
|
|
|
|
|
@@ -651,6 +917,10 @@
|
|
|
|
|
else
|
|
|
|
|
command_name = cm->fullname; /* Global pointer for later use */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
if (help)
|
|
|
|
|
{
|
|
|
|
|
argc = -1; /* some functions only check for this */
|
|
|
|
|
@@ -676,6 +946,71 @@
|
|
|
|
|
CVSUMASK_ENV, cp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSPID
|
|
|
|
|
+ /* provide the process id of the parent CVS process to
|
|
|
|
|
+ sub-processes (usually scripts called from *info files) in order
|
|
|
|
|
+ to let them have a unique session handle */
|
|
|
|
|
+ {
|
|
|
|
|
+ char pidbuf[64];
|
|
|
|
|
+ sprintf(pidbuf, "CVSPID=%lu", (unsigned long)getpid());
|
|
|
|
|
+ putenv(pidbuf);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_SETXID
|
|
|
|
|
+ if ( strcmp(command_name, "kserver") != 0
|
|
|
|
|
+ && strcmp(command_name, "pserver") != 0
|
|
|
|
|
+ && strcmp(command_name, "server") == 0) {
|
|
|
|
|
+ uid_t uid, euid;
|
|
|
|
|
+ gid_t gid, egid;
|
|
|
|
|
+ struct passwd *pw;
|
|
|
|
|
+ char *env;
|
|
|
|
|
+
|
|
|
|
|
+ /* adjust group id */
|
|
|
|
|
+ gid = getgid();
|
|
|
|
|
+ egid = getegid();
|
|
|
|
|
+ if (gid != egid)
|
|
|
|
|
+ setgid(egid); /* upgrade real to effective gid */
|
|
|
|
|
+ else
|
|
|
|
|
+ setegid(gid); /* downgrade effective to real gid */
|
|
|
|
|
+
|
|
|
|
|
+ /* adjust user id */
|
|
|
|
|
+ uid = getuid();
|
|
|
|
|
+ euid = geteuid();
|
|
|
|
|
+ if (uid != euid)
|
|
|
|
|
+ setuid(euid); /* upgrade real to effective uid */
|
|
|
|
|
+ else
|
|
|
|
|
+ seteuid(uid); /* downgrade effective to real uid */
|
|
|
|
|
+
|
|
|
|
|
+ /* still do not adjust umask */
|
|
|
|
|
+ umask(0);
|
|
|
|
|
+
|
|
|
|
|
+ /* remember real user (especially for getcaller()) */
|
|
|
|
|
+ pw = getpwuid(uid);
|
|
|
|
|
+#ifdef AUTH_SERVER_SUPPORT
|
|
|
|
|
+ CVS_Username = xstrdup(pw->pw_name);
|
|
|
|
|
+#if HAVE_PUTENV
|
|
|
|
|
+ env = xmalloc(sizeof("LOGNAME=")+strlen(CVS_Username));
|
|
|
|
|
+ (void)sprintf(env, "LOGNAME=%s", CVS_Username);
|
|
|
|
|
+ (void)putenv(env);
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if HAVE_PUTENV
|
|
|
|
|
+ /* remember running user */
|
|
|
|
|
+ pw = getpwuid(getuid());
|
|
|
|
|
+ env = xmalloc(sizeof("USER=")+strlen(pw->pw_name));
|
|
|
|
|
+ (void)sprintf(env, "USER=%s", pw->pw_name);
|
|
|
|
|
+ (void)putenv(env);
|
|
|
|
|
+#endif
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ /* delete effective user and group id */
|
|
|
|
|
+ seteuid(getuid());
|
|
|
|
|
+ setegid(getgid());
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
|
|
|
|
|
/* If we are invoked with a single argument "kserver", then we are
|
|
|
|
|
running as Kerberos server as root. Do the authentication as
|
|
|
|
|
@@ -690,6 +1025,21 @@
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_KERBEROS */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_PSERVERD
|
|
|
|
|
+ if (strcmp(command_name, "pserverd") == 0) {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * perform the socket listening. This returns multiple times,
|
|
|
|
|
+ * i.e., for each connection. But the parent never returns.
|
|
|
|
|
+ */
|
|
|
|
|
+ pserver_daemon(argc, argv);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * switch to regular "cvs server" operation.
|
|
|
|
|
+ */
|
|
|
|
|
+ argc = 0;
|
|
|
|
|
+ command_name = "server";
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
|
|
|
|
|
if (strcmp (command_name, "pserver") == 0)
|
|
|
|
|
@@ -714,6 +1064,11 @@
|
|
|
|
|
server_active = strcmp (command_name, "server") == 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ if (strcmp(command_name, "root") == 0)
|
|
|
|
|
+ standalone_command = 1;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* This is only used for writing into the history file. For
|
|
|
|
|
remote connections, it might be nice to have hostname
|
|
|
|
|
and/or remote path, on the other hand I'm not sure whether
|
|
|
|
|
@@ -784,8 +1139,12 @@
|
|
|
|
|
in server mode, since the client will send the repository
|
|
|
|
|
directory after the connection is made. */
|
|
|
|
|
|
|
|
|
|
+#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ if (!server_active && !standalone_command)
|
|
|
|
|
+#else
|
|
|
|
|
if (!server_active)
|
|
|
|
|
#endif
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
char *CVSADM_Root;
|
|
|
|
|
|
|
|
|
|
@@ -841,6 +1200,54 @@
|
|
|
|
|
error (1, 0,
|
|
|
|
|
"CVS/Root file (if any).");
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ if (CVSroot_cmdline == NULL || !cvsroot_cmdline_isreal) {
|
|
|
|
|
+ cvsroot_type *e;
|
|
|
|
|
+ if (lookup_command_attribute(command_name) & CVS_CMD_MODIFIES_REPOSITORY) {
|
|
|
|
|
+ if ((e = cvsroot_lookup(NULL, NULL, CVSroot)) != NULL) {
|
|
|
|
|
+ /* command modifies repository and we still operare on
|
|
|
|
|
+ the slave repository, so switch to the master repository,
|
|
|
|
|
+ because we can only perform modifications there. */
|
|
|
|
|
+ if (!quiet) {
|
|
|
|
|
+ fprintf(stderr, "%s: switching to MASTER location of repository `%s'\n", program_name, e->nickname);
|
|
|
|
|
+ fprintf(stderr, "%s: %s <-- %s\n", program_name, e->masterpath, e->slavepath);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (free_CVSroot)
|
|
|
|
|
+ free(CVSroot);
|
|
|
|
|
+ CVSroot = xstrdup(e->masterpath);
|
|
|
|
|
+ if (CVSroot_cmdline != NULL)
|
|
|
|
|
+ free(CVSroot_cmdline);
|
|
|
|
|
+ CVSroot_cmdline = xstrdup(e->masterpath);
|
|
|
|
|
+ cvsroot_sync = e;
|
|
|
|
|
+ free_CVSroot = 1;
|
|
|
|
|
+ cvs_update_env = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ if ((e = cvsroot_lookup(NULL, CVSroot, NULL)) != NULL) {
|
|
|
|
|
+ if (e->slavepath[0] != '\0') {
|
|
|
|
|
+ /* command does not modify repository and we still operare on
|
|
|
|
|
+ the master repository, so switch to the slave repository,
|
|
|
|
|
+ because it is faster by definition. */
|
|
|
|
|
+ if (!quiet) {
|
|
|
|
|
+ fprintf(stderr, "%s: switching to SLAVE location of repository `%s'\n", program_name, e->nickname);
|
|
|
|
|
+ fprintf(stderr, "%s: %s --> %s\n", program_name, e->masterpath, e->slavepath);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (free_CVSroot)
|
|
|
|
|
+ free(CVSroot);
|
|
|
|
|
+ CVSroot = xstrdup(e->slavepath);
|
|
|
|
|
+ if (CVSroot_cmdline != NULL)
|
|
|
|
|
+ free(CVSroot_cmdline);
|
|
|
|
|
+ CVSroot_cmdline = xstrdup(e->slavepath);
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ free_CVSroot = 1;
|
|
|
|
|
+ cvs_update_env = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif /* RSE_PATCH_CVSROOT */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Here begins the big loop over unique cvsroot values. We
|
|
|
|
|
@@ -873,6 +1280,9 @@
|
|
|
|
|
end of things. */
|
|
|
|
|
|
|
|
|
|
while (
|
|
|
|
|
+#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ standalone_command ||
|
|
|
|
|
+#endif
|
|
|
|
|
#ifdef SERVER_SUPPORT
|
|
|
|
|
server_active ||
|
|
|
|
|
#endif
|
|
|
|
|
@@ -884,8 +1294,12 @@
|
|
|
|
|
in server mode, since the client will send the repository
|
|
|
|
|
directory after the connection is made. */
|
|
|
|
|
|
|
|
|
|
+#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ if (!server_active && !standalone_command)
|
|
|
|
|
+#else
|
|
|
|
|
if (!server_active)
|
|
|
|
|
#endif
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
/* Now we're 100% sure that we have a valid CVSROOT
|
|
|
|
|
variable. Parse it to see if we're supposed to do
|
|
|
|
|
@@ -904,7 +1318,11 @@
|
|
|
|
|
* Check to see if the repository exists.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef CLIENT_SUPPORT
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (!current_parsed_root->isremote && !nolock)
|
|
|
|
|
+#else
|
|
|
|
|
if (!current_parsed_root->isremote)
|
|
|
|
|
+#endif
|
|
|
|
|
#endif /* CLIENT_SUPPORT */
|
|
|
|
|
{
|
|
|
|
|
char *path;
|
|
|
|
|
@@ -918,7 +1336,12 @@
|
|
|
|
|
{
|
|
|
|
|
save_errno = errno;
|
|
|
|
|
/* If this is "cvs init", the root need not exist yet. */
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ if (strcmp (command_name, "init") != 0 &&
|
|
|
|
|
+ strcmp (command_name, "root") != 0)
|
|
|
|
|
+#else
|
|
|
|
|
if (strcmp (command_name, "init") != 0)
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
error (1, save_errno, "%s", path);
|
|
|
|
|
}
|
|
|
|
|
@@ -954,6 +1377,9 @@
|
|
|
|
|
read_cvsrc and other such places or vice versa. That sort
|
|
|
|
|
of thing probably needs more thought. */
|
|
|
|
|
if (1
|
|
|
|
|
+#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ && !standalone_command
|
|
|
|
|
+#endif
|
|
|
|
|
#ifdef SERVER_SUPPORT
|
|
|
|
|
&& !server_active
|
|
|
|
|
#endif
|
|
|
|
|
@@ -984,7 +1410,49 @@
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+ if (cvs_prolog != NULL) {
|
|
|
|
|
+ char *cmd;
|
|
|
|
|
+ cmd = expand_path(cvs_prolog, "prolog", 0);
|
|
|
|
|
+ run_setup(cmd);
|
|
|
|
|
+ run_arg("prolog");
|
|
|
|
|
+ run_arg(command_name);
|
|
|
|
|
+ if (CurDir != NULL)
|
|
|
|
|
+ run_arg(CurDir);
|
|
|
|
|
+ else
|
|
|
|
|
+ run_arg("unknown-cwd");
|
|
|
|
|
+ if (current_parsed_root != NULL && current_parsed_root->directory != NULL)
|
|
|
|
|
+ run_arg(current_parsed_root->directory);
|
|
|
|
|
+ else
|
|
|
|
|
+ run_arg("unknown-cvsroot");
|
|
|
|
|
+ if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
|
|
|
|
|
+ error(1, 0, "prolog program `%s' returned non-zero", cmd);
|
|
|
|
|
+ free(cmd);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
err = (*(cm->func)) (argc, argv);
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+ if (cvs_epilog != NULL) {
|
|
|
|
|
+ char *cmd;
|
|
|
|
|
+ cmd = expand_path(cvs_epilog, "epilog", 0);
|
|
|
|
|
+ run_setup(cmd);
|
|
|
|
|
+ run_arg("epilog");
|
|
|
|
|
+ run_arg(command_name);
|
|
|
|
|
+ if (CurDir != NULL)
|
|
|
|
|
+ run_arg(CurDir);
|
|
|
|
|
+ else
|
|
|
|
|
+ run_arg("unknown-cwd");
|
|
|
|
|
+ if (current_parsed_root != NULL && current_parsed_root->directory != NULL)
|
|
|
|
|
+ run_arg(current_parsed_root->directory);
|
|
|
|
|
+ else
|
|
|
|
|
+ run_arg("unknown-cvsroot");
|
|
|
|
|
+ if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
|
|
|
|
|
+ error(1, 0, "epilog program `%s' returned non-zero", cmd);
|
|
|
|
|
+ free(cmd);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* Mark this root directory as done. When the server is
|
|
|
|
|
active, current_root will be NULL -- don't try and
|
|
|
|
|
@@ -1003,11 +1471,20 @@
|
|
|
|
|
dellist (&root_directories);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
|
|
|
|
|
+ if (standalone_command)
|
|
|
|
|
+ break;
|
|
|
|
|
+#endif
|
|
|
|
|
#ifdef SERVER_SUPPORT
|
|
|
|
|
if (server_active)
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
} /* end of loop for cvsroot values */
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+ if (cvsroot_sync != NULL)
|
|
|
|
|
+ cvsroot_synchronize(cvsroot_sync, 0);
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
} /* end of stuff that gets done if the user DOESN'T ask for help */
|
|
|
|
|
|
|
|
|
|
Index: src/mkmodules.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/mkmodules.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 mkmodules.c
|
|
|
|
|
--- src/mkmodules.c 19 Apr 2001 19:45:32 -0000 1.1.1.4
|
|
|
|
|
+++ src/mkmodules.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -186,6 +186,48 @@
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_ADMININFO
|
|
|
|
|
+static const char *const admininfo_contents[] = {
|
|
|
|
|
+ "# The \"admininfo\" file is used to control pre-admin checks.\n",
|
|
|
|
|
+ "# The filter on the right is invoked with the repository and a list \n",
|
|
|
|
|
+ "# of files to check. A non-zero exit of the filter program will \n",
|
|
|
|
|
+ "# cause the admin operation to be aborted.\n",
|
|
|
|
|
+ "#\n",
|
|
|
|
|
+ "# The first entry on a line is a regular expression which is tested\n",
|
|
|
|
|
+ "# against the directory that the change is being committed to, relative\n",
|
|
|
|
|
+ "# to the $CVSROOT. For the first match that is found, then the remainder\n",
|
|
|
|
|
+ "# of the line is the name of the filter to run.\n",
|
|
|
|
|
+ "#\n",
|
|
|
|
|
+ "# If the repository name does not match any of the regular expressions in this\n",
|
|
|
|
|
+ "# file, the \"DEFAULT\" line is used, if it is specified.\n",
|
|
|
|
|
+ "#\n",
|
|
|
|
|
+ "# If the name \"ALL\" appears as a regular expression it is always used\n",
|
|
|
|
|
+ "# in addition to the first matching regex or \"DEFAULT\".\n",
|
|
|
|
|
+ NULL
|
|
|
|
|
+};
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_IMPORTINFO
|
|
|
|
|
+static const char *const importinfo_contents[] = {
|
|
|
|
|
+ "# The \"importinfo\" file is used to control pre-import checks.\n",
|
|
|
|
|
+ "# The filter on the right is invoked with the repository to check.\n",
|
|
|
|
|
+ "# A non-zero exit of the filter program will cause the import\n",
|
|
|
|
|
+ "# operation to be aborted.\n",
|
|
|
|
|
+ "#\n",
|
|
|
|
|
+ "# The first entry on a line is a regular expression which is tested\n",
|
|
|
|
|
+ "# against the directory that the change is being committed to, relative\n",
|
|
|
|
|
+ "# to the $CVSROOT. For the first match that is found, then the remainder\n",
|
|
|
|
|
+ "# of the line is the name of the filter to run.\n",
|
|
|
|
|
+ "#\n",
|
|
|
|
|
+ "# If the repository name does not match any of the regular expressions in this\n",
|
|
|
|
|
+ "# file, the \"DEFAULT\" line is used, if it is specified.\n",
|
|
|
|
|
+ "#\n",
|
|
|
|
|
+ "# If the name \"ALL\" appears as a regular expression it is always used\n",
|
|
|
|
|
+ "# in addition to the first matching regex or \"DEFAULT\".\n",
|
|
|
|
|
+ NULL
|
|
|
|
|
+};
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
static const char *const checkoutlist_contents[] = {
|
|
|
|
|
"# The \"checkoutlist\" file is used to support additional version controlled\n",
|
|
|
|
|
"# administrative files in $CVSROOT/CVSROOT, such as template files.\n",
|
|
|
|
|
@@ -297,6 +339,26 @@
|
|
|
|
|
"# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the\n",
|
|
|
|
|
"# history file, or a subset as needed (ie `TMAR' logs all write operations)\n",
|
|
|
|
|
"#LogHistory=TOFEWGCMAR\n",
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# Set `HistoryFile' to the path name (relative to CVSROOT) of the history file\n",
|
|
|
|
|
+ "# if you do not want to store it not under CVSROOT/history\n",
|
|
|
|
|
+ "#HistoryFile=CVSROOT/history\n",
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# Set `LocalIdName' to the name of a local tag to use in addition to Id\n",
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID_NAME
|
|
|
|
|
+ "#LocalIdName=" RSE_PATCH_LOCALID_NAME "\n",
|
|
|
|
|
+#else
|
|
|
|
|
+ "#LocalIdName=LocalId\n",
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_CONFIGUMASK
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# Set `UMask' to the octal value of the umask.\n",
|
|
|
|
|
+ "#UMask=002\n",
|
|
|
|
|
+#endif
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -319,6 +381,16 @@
|
|
|
|
|
{CVSROOTADM_TAGINFO,
|
|
|
|
|
"a %s file can be used to configure 'cvs tag' checking",
|
|
|
|
|
taginfo_contents},
|
|
|
|
|
+#ifdef RSE_PATCH_ADMININFO
|
|
|
|
|
+ {CVSROOTADM_ADMININFO,
|
|
|
|
|
+ "a %s file can be used to configure 'cvs admin' checking",
|
|
|
|
|
+ admininfo_contents},
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_IMPORTINFO
|
|
|
|
|
+ {CVSROOTADM_IMPORTINFO,
|
|
|
|
|
+ "a %s file can be used to configure 'cvs import' checking",
|
|
|
|
|
+ importinfo_contents},
|
|
|
|
|
+#endif
|
|
|
|
|
{CVSROOTADM_IGNORE,
|
|
|
|
|
"a %s file can be used to specify files to ignore",
|
|
|
|
|
NULL},
|
|
|
|
|
Index: src/options.h.in
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/options.h.in,v
|
|
|
|
|
retrieving revision 1.1.1.2
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.2 options.h.in
|
|
|
|
|
--- src/options.h.in 27 Jan 1999 22:58:14 -0000 1.1.1.2
|
|
|
|
|
+++ src/options.h.in 16 Feb 2002 12:36:46 -0000
|
|
|
|
|
@@ -198,3 +198,48 @@
|
|
|
|
|
#ifndef STDC_HEADERS
|
|
|
|
|
extern void exit ();
|
|
|
|
|
#endif
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Support for compiling in various RSE extension
|
|
|
|
|
+ */
|
|
|
|
|
+#ifdef RSE_PATCHES
|
|
|
|
|
+#define RSE_PATCH_CVSRC
|
|
|
|
|
+#define RSE_PATCH_CVSROOT
|
|
|
|
|
+#define RSE_PATCH_GLOBALOPTION
|
|
|
|
|
+#define RSE_PATCH_GLOBALOPTION_PARTLY
|
|
|
|
|
+#define RSE_PATCH_CUSTOMCMD
|
|
|
|
|
+#define RSE_PATCH_PROLOGEPILOG
|
|
|
|
|
+#define RSE_PATCH_VERIFY
|
|
|
|
|
+#define RSE_PATCH_LOCALID
|
|
|
|
|
+#define RSE_PATCH_CVSHEADER
|
|
|
|
|
+#define RSE_PATCH_NOLOCK
|
|
|
|
|
+#define RSE_PATCH_EXTRAPERCENT
|
|
|
|
|
+#define RSE_PATCH_READDNEW
|
|
|
|
|
+#define RSE_PATCH_CONFIGUMASK
|
|
|
|
|
+#define RSE_PATCH_FASTERUPDATE
|
|
|
|
|
+#define RSE_PATCH_DEADAWARE
|
|
|
|
|
+#define RSE_PATCH_LOGNAME
|
|
|
|
|
+#define RSE_PATCH_HISTORYFILE
|
|
|
|
|
+#define RSE_PATCH_IMPORTINFO
|
|
|
|
|
+#define RSE_PATCH_ADMININFO
|
|
|
|
|
+#define RSE_PATCH_HANDLE
|
|
|
|
|
+#define RSE_PATCH_IMPORTTOUCH
|
|
|
|
|
+#define RSE_PATCH_RELLOCKDIR
|
|
|
|
|
+#define RSE_PATCH_CVSUSER
|
|
|
|
|
+#define RSE_PATCH_SETXID
|
|
|
|
|
+#define RSE_PATCH_PSERVERD
|
|
|
|
|
+#define RSE_PATCH_MAPROOT
|
|
|
|
|
+#define RSE_PATCH_RLIST
|
|
|
|
|
+#define RSE_PATCH_COSMETICS
|
|
|
|
|
+#define RSE_PATCH_HASHFUNC
|
|
|
|
|
+#define RSE_PATCH_ADDFILEATTR
|
|
|
|
|
+#define RSE_PATCH_WILDPASSWD
|
|
|
|
|
+#define RSE_PATCH_CVSPID
|
|
|
|
|
+#define RSE_PATCH_BUGFIX
|
|
|
|
|
+/* problematic changes, because they break "make check" */
|
|
|
|
|
+#undef RSE_PATCH_COSMETICS_HARD
|
|
|
|
|
+#undef RSE_PATCH_MERGENOKEYWORD
|
|
|
|
|
+#undef RSE_PATCH_DIFFHEAD
|
|
|
|
|
+#undef RSE_PATCH_SMARTCONFIG
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
Index: src/parseinfo.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/parseinfo.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 parseinfo.c
|
|
|
|
|
--- src/parseinfo.c 19 Apr 2001 19:45:32 -0000 1.1.1.4
|
|
|
|
|
+++ src/parseinfo.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -11,6 +11,9 @@
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
extern char *logHistory;
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+extern char *history_file;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
|
|
|
|
|
@@ -371,7 +374,24 @@
|
|
|
|
|
{
|
|
|
|
|
if (lock_dir != NULL)
|
|
|
|
|
free (lock_dir);
|
|
|
|
|
+#ifdef RSE_PATCH_RELLOCKDIR
|
|
|
|
|
+ if (p[0] == '/') {
|
|
|
|
|
+#endif
|
|
|
|
|
lock_dir = xstrdup (p);
|
|
|
|
|
+#ifdef RSE_PATCH_RELLOCKDIR
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ char *s;
|
|
|
|
|
+
|
|
|
|
|
+ lock_dir = xmalloc (strlen (p)
|
|
|
|
|
+ + strlen (current_parsed_root->directory)
|
|
|
|
|
+ + 2);
|
|
|
|
|
+ strcpy (lock_dir, current_parsed_root->directory);
|
|
|
|
|
+ s = lock_dir + strlen (lock_dir);
|
|
|
|
|
+ *s++ = '/';
|
|
|
|
|
+ strcpy (s, p);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
/* Could try some validity checking, like whether we can
|
|
|
|
|
opendir it or something, but I don't see any particular
|
|
|
|
|
reason to do that now rather than waiting until lock.c. */
|
|
|
|
|
@@ -384,6 +404,28 @@
|
|
|
|
|
strcpy (logHistory, p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_HISTORYFILE
|
|
|
|
|
+ else if (strcmp (line, "HistoryFile") == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (history_file != NULL)
|
|
|
|
|
+ free (history_file);
|
|
|
|
|
+ history_file = xstrdup (p);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+ else if (strcmp (line, "LocalIdName") == 0) {
|
|
|
|
|
+ RCS_citag = strdup(p);
|
|
|
|
|
+ if (RCS_citag == NULL) {
|
|
|
|
|
+ error (0, 0, "%s: no memory for local tag '%s'", infopath, p);
|
|
|
|
|
+ goto error_return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef RSE_PATCH_CONFIGUMASK
|
|
|
|
|
+ else if (strcmp (line, "UMask") == 0) {
|
|
|
|
|
+ cvsumask = (mode_t)(strtol(p, NULL, 8) & 0777);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We may be dealing with a keyword which was added in a
|
|
|
|
|
@@ -397,9 +439,11 @@
|
|
|
|
|
adding new keywords to your CVSROOT/config file is not
|
|
|
|
|
particularly recommended unless you are planning on using
|
|
|
|
|
the new features. */
|
|
|
|
|
+#ifndef RSE_PATCH_SMARTCONFIG
|
|
|
|
|
error (0, 0, "%s: unrecognized keyword '%s'",
|
|
|
|
|
infopath, line);
|
|
|
|
|
goto error_return;
|
|
|
|
|
+#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ferror (fp_info))
|
|
|
|
|
Index: src/rcs.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/rcs.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 rcs.c
|
|
|
|
|
--- src/rcs.c 24 Apr 2001 18:14:53 -0000 1.1.1.4
|
|
|
|
|
+++ src/rcs.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -114,6 +114,10 @@
|
|
|
|
|
static void rcs_internal_unlockfile PROTO ((FILE *, char *));
|
|
|
|
|
static char *rcs_lockfilename PROTO ((char *));
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+static char *getfullCVSname PROTO((char *, char **));
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* The RCS file reading functions are called a lot, and they do some
|
|
|
|
|
string comparisons. This macro speeds things up a bit by skipping
|
|
|
|
|
the function call when the first characters are different. It
|
|
|
|
|
@@ -3342,10 +3346,17 @@
|
|
|
|
|
size_t len;
|
|
|
|
|
};
|
|
|
|
|
#define KEYWORD_INIT(s) (s), sizeof (s) - 1
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+static struct rcs_keyword keywords[] =
|
|
|
|
|
+#else
|
|
|
|
|
static const struct rcs_keyword keywords[] =
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
{ KEYWORD_INIT ("Author") },
|
|
|
|
|
{ KEYWORD_INIT ("Date") },
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+ { KEYWORD_INIT ("CVSHeader") },
|
|
|
|
|
+#endif
|
|
|
|
|
{ KEYWORD_INIT ("Header") },
|
|
|
|
|
{ KEYWORD_INIT ("Id") },
|
|
|
|
|
{ KEYWORD_INIT ("Locker") },
|
|
|
|
|
@@ -3355,12 +3366,22 @@
|
|
|
|
|
{ KEYWORD_INIT ("Revision") },
|
|
|
|
|
{ KEYWORD_INIT ("Source") },
|
|
|
|
|
{ KEYWORD_INIT ("State") },
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID_NAME
|
|
|
|
|
+ { KEYWORD_INIT (RSE_PATCH_LOCALID_NAME) },
|
|
|
|
|
+#else
|
|
|
|
|
+ { KEYWORD_INIT ("LocalId") },
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
{ NULL, 0 }
|
|
|
|
|
};
|
|
|
|
|
enum keyword
|
|
|
|
|
{
|
|
|
|
|
KEYWORD_AUTHOR = 0,
|
|
|
|
|
KEYWORD_DATE,
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+ KEYWORD_CVSHEADER,
|
|
|
|
|
+#endif
|
|
|
|
|
KEYWORD_HEADER,
|
|
|
|
|
KEYWORD_ID,
|
|
|
|
|
KEYWORD_LOCKER,
|
|
|
|
|
@@ -3369,7 +3390,12 @@
|
|
|
|
|
KEYWORD_RCSFILE,
|
|
|
|
|
KEYWORD_REVISION,
|
|
|
|
|
KEYWORD_SOURCE,
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+ KEYWORD_STATE,
|
|
|
|
|
+ KEYWORD_LOCALID
|
|
|
|
|
+#else
|
|
|
|
|
KEYWORD_STATE
|
|
|
|
|
+#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Convert an RCS date string into a readable string. This is like
|
|
|
|
|
@@ -3506,6 +3532,13 @@
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+ if (RCS_citag != NULL && keywords[KEYWORD_LOCALID].string == NULL) {
|
|
|
|
|
+ keywords[KEYWORD_LOCALID].string = RCS_citag;
|
|
|
|
|
+ keywords[KEYWORD_LOCALID].len = strlen(RCS_citag);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* If we are using -kkvl, dig out the locker information if any. */
|
|
|
|
|
locker = NULL;
|
|
|
|
|
if (expand == KFLAG_KVL)
|
|
|
|
|
@@ -3595,15 +3628,28 @@
|
|
|
|
|
free_value = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+ case KEYWORD_CVSHEADER:
|
|
|
|
|
+#endif
|
|
|
|
|
case KEYWORD_HEADER:
|
|
|
|
|
case KEYWORD_ID:
|
|
|
|
|
+#ifdef RSE_PATCH_LOCALID
|
|
|
|
|
+ case KEYWORD_LOCALID:
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
char *path;
|
|
|
|
|
int free_path;
|
|
|
|
|
char *date;
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+ char *old_path = NULL;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
if (kw == KEYWORD_HEADER)
|
|
|
|
|
path = rcs->path;
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+ else if (kw == KEYWORD_CVSHEADER)
|
|
|
|
|
+ path = getfullCVSname(rcs->path, &old_path);
|
|
|
|
|
+#endif
|
|
|
|
|
else
|
|
|
|
|
path = last_component (rcs->path);
|
|
|
|
|
path = escape_keyword_value (path, &free_path);
|
|
|
|
|
@@ -3623,6 +3669,10 @@
|
|
|
|
|
locker != NULL ? locker : "");
|
|
|
|
|
if (free_path)
|
|
|
|
|
free (path);
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+ if (old_path)
|
|
|
|
|
+ free (old_path);
|
|
|
|
|
+#endif
|
|
|
|
|
free (date);
|
|
|
|
|
free_value = 1;
|
|
|
|
|
}
|
|
|
|
|
@@ -8419,3 +8469,38 @@
|
|
|
|
|
}
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_CVSHEADER
|
|
|
|
|
+static char *
|
|
|
|
|
+getfullCVSname(CVSname, pathstore)
|
|
|
|
|
+ char *CVSname, **pathstore;
|
|
|
|
|
+{
|
|
|
|
|
+ int rootlen;
|
|
|
|
|
+ char *c;
|
|
|
|
|
+ int alen;
|
|
|
|
|
+
|
|
|
|
|
+ if (current_parsed_root->directory != NULL) {
|
|
|
|
|
+ alen = sizeof("/" CVSATTIC) - 1;
|
|
|
|
|
+ *pathstore = xstrdup(CVSname);
|
|
|
|
|
+ if ((c = strrchr(*pathstore, '/')) != NULL) {
|
|
|
|
|
+ if (c - *pathstore >= alen) {
|
|
|
|
|
+ if (!strncmp(c - alen, "/" CVSATTIC, alen)) {
|
|
|
|
|
+ while (*c != '\0') {
|
|
|
|
|
+ *(c - alen) = *c;
|
|
|
|
|
+ c++;
|
|
|
|
|
+ }
|
|
|
|
|
+ *(c - alen) = '\0';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ rootlen = strlen(current_parsed_root->directory);
|
|
|
|
|
+ if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) &&
|
|
|
|
|
+ (*pathstore)[rootlen] == '/')
|
|
|
|
|
+ CVSname = (*pathstore + rootlen + 1);
|
|
|
|
|
+ else
|
|
|
|
|
+ CVSname = (*pathstore);
|
|
|
|
|
+ }
|
|
|
|
|
+ return CVSname;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
Index: src/recurse.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/recurse.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 recurse.c
|
|
|
|
|
--- src/recurse.c 19 Apr 2001 19:45:33 -0000 1.1.1.4
|
|
|
|
|
+++ src/recurse.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -508,7 +508,11 @@
|
|
|
|
|
if (frame->flags == R_SKIP_ALL)
|
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ should_readlock = nolock ? 0 : frame->readlock;
|
|
|
|
|
+#else
|
|
|
|
|
should_readlock = noexec ? 0 : frame->readlock;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/* The fact that locks are not active here is what makes us fail to have
|
|
|
|
|
the
|
|
|
|
|
@@ -550,7 +554,11 @@
|
|
|
|
|
*/
|
|
|
|
|
if (server_active
|
|
|
|
|
/* If there are writelocks around, we cannot pause here. */
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ && (should_readlock || nolock))
|
|
|
|
|
+#else
|
|
|
|
|
&& (should_readlock || noexec))
|
|
|
|
|
+#endif
|
|
|
|
|
server_pause_check();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
Index: src/repos.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/repos.c,v
|
|
|
|
|
retrieving revision 1.1.1.3
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.3 repos.c
|
|
|
|
|
--- src/repos.c 19 Apr 2001 19:45:33 -0000 1.1.1.3
|
|
|
|
|
+++ src/repos.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -204,3 +204,11 @@
|
|
|
|
|
repository[len - 2] = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+/* Shameless hack: in order to avoid having to patch the brain-dead
|
|
|
|
|
+ Automake-based CVS build environment (src/Makefile.am) we add the
|
|
|
|
|
+ "cvs rlist" code to an arbitrarily chosen source file. */
|
|
|
|
|
+#include "list.c"
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
Index: src/root.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/root.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 root.c
|
|
|
|
|
--- src/root.c 19 Apr 2001 19:45:33 -0000 1.1.1.4
|
|
|
|
|
+++ src/root.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -122,6 +122,9 @@
|
|
|
|
|
/* allocate space to return and fill it in */
|
|
|
|
|
strip_trailing_slashes (root);
|
|
|
|
|
ret = xstrdup (root);
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ root_map_it(ret, &ret, 0);
|
|
|
|
|
+#endif
|
|
|
|
|
out:
|
|
|
|
|
free (cvsadm);
|
|
|
|
|
free (tmp);
|
|
|
|
|
@@ -267,6 +270,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+
|
|
|
|
|
+typedef struct root_map_st {
|
|
|
|
|
+ char *old;
|
|
|
|
|
+ char *new;
|
|
|
|
|
+} root_map_t;
|
|
|
|
|
+
|
|
|
|
|
+#define ROOT_MAP_MAX 10
|
|
|
|
|
+static int root_map_max = 0;
|
|
|
|
|
+static root_map_t root_map_vec[ROOT_MAP_MAX];
|
|
|
|
|
+
|
|
|
|
|
+void root_map_add(char *old, char *new)
|
|
|
|
|
+{
|
|
|
|
|
+ if (root_map_max >= ROOT_MAP_MAX)
|
|
|
|
|
+ return;
|
|
|
|
|
+ root_map_vec[root_map_max].old = xstrdup(old);
|
|
|
|
|
+ root_map_vec[root_map_max].new = xstrdup(new);
|
|
|
|
|
+ root_map_max++;
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void root_map_free(void)
|
|
|
|
|
+{
|
|
|
|
|
+ while (root_map_max > 0) {
|
|
|
|
|
+ free(root_map_vec[root_map_max].old);
|
|
|
|
|
+ free(root_map_vec[root_map_max].new);
|
|
|
|
|
+ root_map_max--;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int root_map_it(char *old, char **new, int prefixonly)
|
|
|
|
|
+{
|
|
|
|
|
+ int rv;
|
|
|
|
|
+ int i;
|
|
|
|
|
+ int n;
|
|
|
|
|
+
|
|
|
|
|
+ if (old == NULL)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ rv = 0;
|
|
|
|
|
+ for (i = 0; i < root_map_max; i++) {
|
|
|
|
|
+ n = strlen(root_map_vec[i].old);
|
|
|
|
|
+ if (!prefixonly && strcmp(old, root_map_vec[i].old) == 0) {
|
|
|
|
|
+ if (new == NULL) {
|
|
|
|
|
+ /* we assume old is buffer and override it */
|
|
|
|
|
+ strcpy(old, root_map_vec[i].new);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ if (old == *new)
|
|
|
|
|
+ /* old and new is same pointer we free before */
|
|
|
|
|
+ free(old);
|
|
|
|
|
+ /* provide new allocated buffer */
|
|
|
|
|
+ *new = xmalloc(strlen(root_map_vec[i].new)+1);
|
|
|
|
|
+ strcpy(*new, root_map_vec[i].new);
|
|
|
|
|
+ }
|
|
|
|
|
+ rv = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (prefixonly && strncmp(old, root_map_vec[i].old, n) == 0) {
|
|
|
|
|
+ if (new == NULL) {
|
|
|
|
|
+ /* we assume old is buffer and override it */
|
|
|
|
|
+ sprintf(old, "%s%s", root_map_vec[i].new, old+n);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ char *oldnew = *new;
|
|
|
|
|
+ /* provide new allocated buffer */
|
|
|
|
|
+ *new = xmalloc(strlen(root_map_vec[i].new)+strlen(old+n)+1);
|
|
|
|
|
+ sprintf(*new, "%s%s", root_map_vec[i].new, old+n);
|
|
|
|
|
+ if (old == oldnew)
|
|
|
|
|
+ /* old and new is same pointer we free before */
|
|
|
|
|
+ free(old);
|
|
|
|
|
+ }
|
|
|
|
|
+ rv = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return rv;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif /* RSE_PATCH_MAPROOT */
|
|
|
|
|
+
|
|
|
|
|
/* 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. */
|
|
|
|
|
@@ -804,3 +888,472 @@
|
|
|
|
|
/* NOTREACHED */
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_CVSROOT
|
|
|
|
|
+
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+
|
|
|
|
|
+#ifndef CVS_ROOT_FILE
|
|
|
|
|
+#define CVS_ROOT_FILE ".cvsroot"
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+char *
|
|
|
|
|
+cvsroot_filename(
|
|
|
|
|
+ void)
|
|
|
|
|
+{
|
|
|
|
|
+ char *homedir;
|
|
|
|
|
+ char *rootfile;
|
|
|
|
|
+
|
|
|
|
|
+ /* Environment should override file. */
|
|
|
|
|
+ if ((rootfile = getenv("CVS_ROOTFILE")) != NULL)
|
|
|
|
|
+ return xstrdup(rootfile);
|
|
|
|
|
+
|
|
|
|
|
+ /* Construct absolute pathname to user's password file. */
|
|
|
|
|
+ if ((homedir = get_homedir()) == NULL) {
|
|
|
|
|
+ error(1, 0, "could not find out home directory");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ rootfile = (char *)xmalloc(strlen(homedir)+strlen(CVS_ROOT_FILE)+3);
|
|
|
|
|
+ strcpy(rootfile, homedir);
|
|
|
|
|
+ strcat(rootfile, "/");
|
|
|
|
|
+ strcat(rootfile, CVS_ROOT_FILE);
|
|
|
|
|
+ return rootfile;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void cvsroot_free(
|
|
|
|
|
+ cvsroot_type *e)
|
|
|
|
|
+{
|
|
|
|
|
+ if (e != NULL) {
|
|
|
|
|
+ if (e->nickname != NULL)
|
|
|
|
|
+ free(e->nickname);
|
|
|
|
|
+ if (e->masterpath != NULL)
|
|
|
|
|
+ free(e->masterpath);
|
|
|
|
|
+ if (e->slavepath != NULL)
|
|
|
|
|
+ free(e->slavepath);
|
|
|
|
|
+ if (e->syncprog != NULL)
|
|
|
|
|
+ free(e->syncprog);
|
|
|
|
|
+ free(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+cvsroot_type *
|
|
|
|
|
+cvsroot_entry_read(
|
|
|
|
|
+ FILE *fp)
|
|
|
|
|
+{
|
|
|
|
|
+ cvsroot_type *e;
|
|
|
|
|
+ char *nickname;
|
|
|
|
|
+ char *masterpath;
|
|
|
|
|
+ char *slavepath;
|
|
|
|
|
+ char *syncprog;
|
|
|
|
|
+ char *line;
|
|
|
|
|
+ int line_length;
|
|
|
|
|
+ size_t line_chars_allocated;
|
|
|
|
|
+ size_t n;
|
|
|
|
|
+
|
|
|
|
|
+ e = NULL;
|
|
|
|
|
+ line = NULL;
|
|
|
|
|
+ line_chars_allocated = 0;
|
|
|
|
|
+ while ((line_length = getline(&line, &line_chars_allocated, fp)) >= 0) {
|
|
|
|
|
+ /* parse line */
|
|
|
|
|
+ line += strspn(line, " \t\n");
|
|
|
|
|
+ if (line[0] == '#')
|
|
|
|
|
+ continue;
|
|
|
|
|
+ nickname = line;
|
|
|
|
|
+ if ((n = strcspn(line, " \t\n")) == 0)
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ line += n;
|
|
|
|
|
+ *line++ = '\0';
|
|
|
|
|
+ line += strspn(line, " \t");
|
|
|
|
|
+ masterpath = line;
|
|
|
|
|
+ if ((n = strcspn(line, " \t\n")) == 0)
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ line += n;
|
|
|
|
|
+ *line++ = '\0';
|
|
|
|
|
+ line += strspn(line, " \t\n");
|
|
|
|
|
+ slavepath = "";
|
|
|
|
|
+ syncprog = "";
|
|
|
|
|
+ if (line[0] != '\0') {
|
|
|
|
|
+ slavepath = line;
|
|
|
|
|
+ n = strcspn(line, " \t\n");
|
|
|
|
|
+ line += n;
|
|
|
|
|
+ *line++ = '\0';
|
|
|
|
|
+ if (line[0] != '\0') {
|
|
|
|
|
+ syncprog = line;
|
|
|
|
|
+ n = strcspn(line, " \t\n");
|
|
|
|
|
+ line += n;
|
|
|
|
|
+ *line++ = '\0';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ e = (cvsroot_type *)xmalloc(sizeof(cvsroot_type));
|
|
|
|
|
+ e->nickname = xstrdup(nickname);
|
|
|
|
|
+ e->masterpath = xstrdup(masterpath);
|
|
|
|
|
+ e->slavepath = xstrdup(slavepath);
|
|
|
|
|
+ e->syncprog = xstrdup(syncprog);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return e;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void
|
|
|
|
|
+cvsroot_entry_write(
|
|
|
|
|
+ FILE *fp,
|
|
|
|
|
+ cvsroot_type *e)
|
|
|
|
|
+{
|
|
|
|
|
+ if (fp != NULL && e != NULL) {
|
|
|
|
|
+ fprintf(fp, "%s %s",
|
|
|
|
|
+ e->nickname, e->masterpath);
|
|
|
|
|
+ if (e->slavepath[0] != '\0')
|
|
|
|
|
+ fprintf(fp, " %s", e->slavepath);
|
|
|
|
|
+ if (e->syncprog[0] != '\0')
|
|
|
|
|
+ fprintf(fp, " %s", e->syncprog);
|
|
|
|
|
+ fprintf(fp, "\n");
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+cvsroot_type *
|
|
|
|
|
+cvsroot_lookup(
|
|
|
|
|
+ char *by_nickname,
|
|
|
|
|
+ char *by_masterpath,
|
|
|
|
|
+ char *by_slavepath)
|
|
|
|
|
+{
|
|
|
|
|
+ char *rootfile;
|
|
|
|
|
+ cvsroot_type *e = NULL;
|
|
|
|
|
+ FILE *fp;
|
|
|
|
|
+
|
|
|
|
|
+ if ((rootfile = cvsroot_filename()) == NULL)
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ if ((fp = fopen(rootfile, "r")) == NULL) {
|
|
|
|
|
+ free(rootfile);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ while ((e = cvsroot_entry_read(fp)) != NULL) {
|
|
|
|
|
+ if ( (by_nickname != NULL && strcmp(e->nickname, by_nickname) == 0)
|
|
|
|
|
+ || (by_masterpath != NULL && strcmp(e->masterpath, by_masterpath) == 0)
|
|
|
|
|
+ || (by_slavepath != NULL && strcmp(e->slavepath, by_slavepath) == 0))
|
|
|
|
|
+ break;
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ free(rootfile);
|
|
|
|
|
+ return e;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void
|
|
|
|
|
+cvsroot_synchronize(
|
|
|
|
|
+ cvsroot_type *e,
|
|
|
|
|
+ int force)
|
|
|
|
|
+{
|
|
|
|
|
+ char *cmd;
|
|
|
|
|
+ char *arg;
|
|
|
|
|
+ char *rsh;
|
|
|
|
|
+ int smart;
|
|
|
|
|
+ char *syncprog;
|
|
|
|
|
+
|
|
|
|
|
+ smart = 0;
|
|
|
|
|
+ syncprog = e->syncprog;
|
|
|
|
|
+ if (syncprog[0] == '-') {
|
|
|
|
|
+ smart++;
|
|
|
|
|
+ syncprog++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (smart && !force) {
|
|
|
|
|
+ if (!really_quiet) {
|
|
|
|
|
+ if (strcasecmp(syncprog, "manual") == 0) {
|
|
|
|
|
+ fprintf(stderr, "%s: synchronize SLAVE with MASTER of repository `%s', please!\n", program_name, e->nickname);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ fprintf(stderr, "%s: synchronize SLAVE with MASTER of repository `%s'\n", program_name, e->nickname);
|
|
|
|
|
+ fprintf(stderr, "%s: by running the command `%s root -s %s', please.\n", program_name, program_name, e->nickname);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (strcasecmp(syncprog, "manual") == 0) {
|
|
|
|
|
+ if (!really_quiet) {
|
|
|
|
|
+ fprintf(stderr, "%s: synchronizing SLAVE with MASTER of repository `%s'\n", program_name, e->nickname);
|
|
|
|
|
+ fprintf(stderr, "%s: has to be performed manually by you!\n", program_name);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (strcasecmp(syncprog, "rsync") == 0 ||
|
|
|
|
|
+ strncasecmp(syncprog, "rsync:", 6) == 0) {
|
|
|
|
|
+ if (!really_quiet) {
|
|
|
|
|
+ fprintf(stderr, "%s: synchronizing SLAVE with MASTER of repository `%s':\n", program_name, e->nickname);
|
|
|
|
|
+ fprintf(stderr, "%s: %s --> %s (rsync)\n", program_name, e->masterpath, e->slavepath);
|
|
|
|
|
+ }
|
|
|
|
|
+ run_setup("rsync");
|
|
|
|
|
+ if (!quiet)
|
|
|
|
|
+ run_arg("-v");
|
|
|
|
|
+ if ((rsh = getenv("CVS_RSH")) != NULL) {
|
|
|
|
|
+ arg = xmalloc(strlen(rsh)+7);
|
|
|
|
|
+ strcpy(arg, "--rsh=");
|
|
|
|
|
+ strcat(arg, rsh);
|
|
|
|
|
+ run_arg(arg);
|
|
|
|
|
+ free(arg);
|
|
|
|
|
+ }
|
|
|
|
|
+ run_arg("-rlpt");
|
|
|
|
|
+ run_arg("--delete");
|
|
|
|
|
+ if (strncasecmp(syncprog, "rsync:", 6) == 0) {
|
|
|
|
|
+ char *list = xstrdup(syncprog+6);
|
|
|
|
|
+ for (arg = strtok(list, ","); arg != NULL; arg = strtok(NULL, ",")) {
|
|
|
|
|
+ if (arg[0] == '!') {
|
|
|
|
|
+ run_arg("--exclude");
|
|
|
|
|
+ run_arg(arg+1);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ run_arg("--include");
|
|
|
|
|
+ run_arg(arg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ free(list);
|
|
|
|
|
+ }
|
|
|
|
|
+ arg = xmalloc(strlen(e->masterpath)+2);
|
|
|
|
|
+ strcpy(arg, e->masterpath);
|
|
|
|
|
+ strcat(arg, "/");
|
|
|
|
|
+ run_arg(arg);
|
|
|
|
|
+ free(arg);
|
|
|
|
|
+ arg = xmalloc(strlen(e->slavepath)+2);
|
|
|
|
|
+ strcpy(arg, e->slavepath);
|
|
|
|
|
+ strcat(arg, "/");
|
|
|
|
|
+ run_arg(arg);
|
|
|
|
|
+ free(arg);
|
|
|
|
|
+ if (trace) {
|
|
|
|
|
+ cvs_output(program_name, 0);
|
|
|
|
|
+ cvs_output(" ", 1);
|
|
|
|
|
+ cvs_output(command_name, 0);
|
|
|
|
|
+ cvs_output(": Executing ", 0);
|
|
|
|
|
+ run_print(stdout);
|
|
|
|
|
+ cvs_output("\n", 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
|
|
|
|
|
+ error(1, 0, "synchronization program `rsync' returned non-zero");
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ if (!really_quiet) {
|
|
|
|
|
+ fprintf(stderr, "%s: synchronizing SLAVE with MASTER of repository `%s':\n", program_name, e->nickname);
|
|
|
|
|
+ fprintf(stderr, "%s: %s --> %s (%s)\n", program_name, e->masterpath, e->slavepath, e->syncprog);
|
|
|
|
|
+ }
|
|
|
|
|
+ cmd = expand_path(syncprog, "sync", 0);
|
|
|
|
|
+ run_setup(cmd);
|
|
|
|
|
+ run_arg(e->nickname);
|
|
|
|
|
+ run_arg(e->masterpath);
|
|
|
|
|
+ run_arg(e->slavepath);
|
|
|
|
|
+ if (trace) {
|
|
|
|
|
+ cvs_output(program_name, 0);
|
|
|
|
|
+ cvs_output(" ", 1);
|
|
|
|
|
+ cvs_output(command_name, 0);
|
|
|
|
|
+ cvs_output(": Executing ", 0);
|
|
|
|
|
+ run_print(stdout);
|
|
|
|
|
+ cvs_output("\n", 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
|
|
|
|
|
+ error(1, 0, "synchronization program `%s' returned non-zero", cmd);
|
|
|
|
|
+ free(cmd);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static const char *const root_usage[] = {
|
|
|
|
|
+ "Usage: %s %s [-v] -e|-E|-l|s [arg ...]\n",
|
|
|
|
|
+ "Options:\n",
|
|
|
|
|
+ " -v Verbose mode.\n",
|
|
|
|
|
+ " -e Edit entry from ~/.cvsroot in batch mode.\n",
|
|
|
|
|
+ " -E Edit entry from ~/.cvsroot in visual mode.\n",
|
|
|
|
|
+ " -l List entries from ~/.cvsroot.\n",
|
|
|
|
|
+ " -s Synchronize entries from ~/.cvsroot.\n",
|
|
|
|
|
+ "Synopsis:\n",
|
|
|
|
|
+ " Add/Modify an entry:\n",
|
|
|
|
|
+ " cvs root -e nickname masterpath [slavepath [syncprog]]\n",
|
|
|
|
|
+ " Delete an entry:\n",
|
|
|
|
|
+ " cvs root -e nickname\n",
|
|
|
|
|
+ " List all or some particular entries:\n",
|
|
|
|
|
+ " cvs [-Q] [-q] root [-v] -l [nickname ...]\n",
|
|
|
|
|
+ " Synchronize all or some particular entries:\n",
|
|
|
|
|
+ " cvs [-Q] [-q] root -s [nickname ...]\n",
|
|
|
|
|
+ "(Specify the --help global option for a list of other help options)\n",
|
|
|
|
|
+ NULL
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+root(
|
|
|
|
|
+ int argc,
|
|
|
|
|
+ char **argv)
|
|
|
|
|
+{
|
|
|
|
|
+ enum {
|
|
|
|
|
+ ROOT_MODE_UNKNOWN,
|
|
|
|
|
+ ROOT_MODE_EDIT_CMDLINE,
|
|
|
|
|
+ ROOT_MODE_EDIT_VISUAL,
|
|
|
|
|
+ ROOT_MODE_LIST,
|
|
|
|
|
+ ROOT_MODE_SYNC
|
|
|
|
|
+ };
|
|
|
|
|
+ int mode = ROOT_MODE_UNKNOWN;
|
|
|
|
|
+ char *rootfile;
|
|
|
|
|
+ char *rootfilebak = NULL;
|
|
|
|
|
+ FILE *fp;
|
|
|
|
|
+ FILE *fpbak = NULL;
|
|
|
|
|
+ int option;
|
|
|
|
|
+ cvsroot_type *e;
|
|
|
|
|
+ cvsroot_type E;
|
|
|
|
|
+ int doit;
|
|
|
|
|
+ int i;
|
|
|
|
|
+ int rc;
|
|
|
|
|
+ int verbose = 0;
|
|
|
|
|
+ int found = 0;
|
|
|
|
|
+ int oldexists;
|
|
|
|
|
+
|
|
|
|
|
+ if (argc == -1)
|
|
|
|
|
+ usage(root_usage);
|
|
|
|
|
+ optind = 0;
|
|
|
|
|
+ while ((option = getopt(argc, argv, "veEsl")) != EOF) {
|
|
|
|
|
+ switch ((char)option) {
|
|
|
|
|
+ case 'v':
|
|
|
|
|
+ verbose = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'e':
|
|
|
|
|
+ mode = ROOT_MODE_EDIT_CMDLINE;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'E':
|
|
|
|
|
+ mode = ROOT_MODE_EDIT_VISUAL;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'l':
|
|
|
|
|
+ mode = ROOT_MODE_LIST;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 's':
|
|
|
|
|
+ mode = ROOT_MODE_SYNC;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '?':
|
|
|
|
|
+ default:
|
|
|
|
|
+ usage(root_usage);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ argc -= optind;
|
|
|
|
|
+ argv += optind;
|
|
|
|
|
+ if (mode == ROOT_MODE_UNKNOWN)
|
|
|
|
|
+ error(1, 0, "exactly one of the -e, -E, -l or -s options have to given");
|
|
|
|
|
+
|
|
|
|
|
+ if (mode == ROOT_MODE_EDIT_CMDLINE) {
|
|
|
|
|
+ if (argc < 1 || argc > 4)
|
|
|
|
|
+ error(1, 0, "option -e requires 1-4 arguments");
|
|
|
|
|
+ E.nickname = argv[0];
|
|
|
|
|
+ if (argc >= 2)
|
|
|
|
|
+ E.masterpath = argv[1];
|
|
|
|
|
+ else
|
|
|
|
|
+ E.masterpath = "";
|
|
|
|
|
+ if (argc >= 3)
|
|
|
|
|
+ E.slavepath = argv[2];
|
|
|
|
|
+ else
|
|
|
|
|
+ E.slavepath = "";
|
|
|
|
|
+ if (argc == 4)
|
|
|
|
|
+ E.syncprog = argv[3];
|
|
|
|
|
+ else
|
|
|
|
|
+ E.syncprog = "";
|
|
|
|
|
+ if ((rootfile = cvsroot_filename()) == NULL)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ oldexists = 0;
|
|
|
|
|
+ if (isfile(rootfile)) {
|
|
|
|
|
+ oldexists = 1;
|
|
|
|
|
+ rootfilebak = xmalloc(strlen(rootfile)+5);
|
|
|
|
|
+ strcpy(rootfilebak, rootfile);
|
|
|
|
|
+ strcat(rootfilebak, ".bak");
|
|
|
|
|
+ rename(rootfile, rootfilebak);
|
|
|
|
|
+ if ((fpbak = fopen(rootfilebak, "r")) == NULL) {
|
|
|
|
|
+ free(rootfile);
|
|
|
|
|
+ free(rootfilebak);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((fp = fopen(rootfile, "w")) == NULL) {
|
|
|
|
|
+ fclose(fpbak);
|
|
|
|
|
+ free(rootfile);
|
|
|
|
|
+ free(rootfilebak);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (oldexists) {
|
|
|
|
|
+ found = 0;
|
|
|
|
|
+ while ((e = cvsroot_entry_read(fpbak)) != NULL) {
|
|
|
|
|
+ if (strcmp(e->nickname, E.nickname) == 0) {
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ found = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ cvsroot_entry_write(fp, e);
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (argc > 1)
|
|
|
|
|
+ cvsroot_entry_write(fp, &E);
|
|
|
|
|
+ if (oldexists) {
|
|
|
|
|
+ if (found) {
|
|
|
|
|
+ while ((e = cvsroot_entry_read(fpbak)) != NULL) {
|
|
|
|
|
+ cvsroot_entry_write(fp, e);
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ fclose(fpbak);
|
|
|
|
|
+ }
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (mode == ROOT_MODE_EDIT_VISUAL) {
|
|
|
|
|
+ if (argc != 0)
|
|
|
|
|
+ error(1, 0, "option -E requires no arguments");
|
|
|
|
|
+ if ((rootfile = cvsroot_filename()) == NULL)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ run_setup(Editor);
|
|
|
|
|
+ run_arg(rootfile);
|
|
|
|
|
+ if ((rc = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_SIGIGNORE)) != 0)
|
|
|
|
|
+ error (1, rc == -1 ? errno : 0, "warning: editor session failed");
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (mode == ROOT_MODE_LIST || mode == ROOT_MODE_SYNC) {
|
|
|
|
|
+ if ((rootfile = cvsroot_filename()) == NULL)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ if ((fp = fopen(rootfile, "r")) == NULL) {
|
|
|
|
|
+ free(rootfile);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ while ((e = cvsroot_entry_read(fp)) != NULL) {
|
|
|
|
|
+ doit = 0;
|
|
|
|
|
+ if (argc == 0)
|
|
|
|
|
+ doit = 1;
|
|
|
|
|
+ else {
|
|
|
|
|
+ for (i = 0; i < argc; i++) {
|
|
|
|
|
+ if (strcmp(argv[i], e->nickname) == 0) {
|
|
|
|
|
+ doit = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (doit) {
|
|
|
|
|
+ if (mode == ROOT_MODE_LIST) {
|
|
|
|
|
+ if (verbose)
|
|
|
|
|
+ fprintf(stdout, "Repository `%s':\n"
|
|
|
|
|
+ " Master Path: %s\n"
|
|
|
|
|
+ " Slave Path: %s\n"
|
|
|
|
|
+ " Synchronize: %s\n",
|
|
|
|
|
+ e->nickname, e->masterpath,
|
|
|
|
|
+ e->slavepath, e->syncprog);
|
|
|
|
|
+ else
|
|
|
|
|
+ fprintf(stdout, "%s %s %s %s\n",
|
|
|
|
|
+ e->nickname, e->masterpath,
|
|
|
|
|
+ e->slavepath, e->syncprog);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (mode == ROOT_MODE_SYNC) {
|
|
|
|
|
+ if (e->slavepath[0] == '\0' || e->syncprog[0] == '\0') {
|
|
|
|
|
+ if (argc > 0)
|
|
|
|
|
+ error(1, 0, "repository `%s' has no slave path or sync program defined", e->nickname);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ cvsroot_synchronize(e, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ cvsroot_free(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ free(rootfile);
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#endif /* RSE_PATCH_CVSROOT */
|
|
|
|
|
+
|
|
|
|
|
Index: src/sanity.sh
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/sanity.sh,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 sanity.sh
|
|
|
|
|
--- src/sanity.sh 25 Apr 2001 22:30:56 -0000 1.1.1.4
|
|
|
|
|
+++ src/sanity.sh 16 Feb 2002 12:36:35 -0000
|
|
|
|
|
@@ -104,6 +104,7 @@
|
|
|
|
|
# "debugger"
|
|
|
|
|
#set -x
|
|
|
|
|
|
|
|
|
|
+echo '[THIS PROCEDURE TAKES APPROX. 25min ON A PII/400MHz, SO BE PATIENT!]'
|
|
|
|
|
echo 'This test should produce no other output than this line, and a final "OK".'
|
|
|
|
|
|
|
|
|
|
# Regexp to match what CVS will call itself in output that it prints.
|
|
|
|
|
@@ -8517,11 +8518,13 @@
|
|
|
|
|
############################################################
|
|
|
|
|
# Check out the whole repository
|
|
|
|
|
mkdir 1; cd 1
|
|
|
|
|
- dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/checkoutlist
|
|
|
|
|
+ dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/admininfo
|
|
|
|
|
+U CVSROOT/checkoutlist
|
|
|
|
|
U CVSROOT/commitinfo
|
|
|
|
|
U CVSROOT/config
|
|
|
|
|
U CVSROOT/cvswrappers
|
|
|
|
|
U CVSROOT/editinfo
|
|
|
|
|
+U CVSROOT/importinfo
|
|
|
|
|
U CVSROOT/loginfo
|
|
|
|
|
U CVSROOT/modules
|
|
|
|
|
U CVSROOT/notify
|
|
|
|
|
@@ -8541,11 +8544,13 @@
|
|
|
|
|
############################################################
|
|
|
|
|
# Check out CVSROOT
|
|
|
|
|
mkdir 1; cd 1
|
|
|
|
|
- dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
|
|
|
|
|
+ dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/admininfo
|
|
|
|
|
+U CVSROOT/checkoutlist
|
|
|
|
|
U CVSROOT/commitinfo
|
|
|
|
|
U CVSROOT/config
|
|
|
|
|
U CVSROOT/cvswrappers
|
|
|
|
|
U CVSROOT/editinfo
|
|
|
|
|
+U CVSROOT/importinfo
|
|
|
|
|
U CVSROOT/loginfo
|
|
|
|
|
U CVSROOT/modules
|
|
|
|
|
U CVSROOT/notify
|
|
|
|
|
@@ -8568,11 +8573,13 @@
|
|
|
|
|
mkdir 1; cd 1
|
|
|
|
|
dotest modules-3 "${testcvs} -q co somedir" ''
|
|
|
|
|
cd somedir
|
|
|
|
|
- dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
|
|
|
|
|
+ dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/admininfo
|
|
|
|
|
+U CVSROOT/checkoutlist
|
|
|
|
|
U CVSROOT/commitinfo
|
|
|
|
|
U CVSROOT/config
|
|
|
|
|
U CVSROOT/cvswrappers
|
|
|
|
|
U CVSROOT/editinfo
|
|
|
|
|
+U CVSROOT/importinfo
|
|
|
|
|
U CVSROOT/loginfo
|
|
|
|
|
U CVSROOT/modules
|
|
|
|
|
U CVSROOT/notify
|
|
|
|
|
@@ -18230,7 +18237,7 @@
|
|
|
|
|
add a line on trunk after trunktag"
|
|
|
|
|
# But diff thinks that HEAD is "br1". Case (b) from cvs.texinfo.
|
|
|
|
|
# Probably people are relying on it.
|
|
|
|
|
- dotest head-br1-diff "${testcvs} -q diff -c -r HEAD -r br1" ""
|
|
|
|
|
+ #RSE# dotest head-br1-diff "${testcvs} -q diff -c -r HEAD -r br1" ""
|
|
|
|
|
|
|
|
|
|
# With a nonbranch sticky tag on a branch,
|
|
|
|
|
# HEAD is the head of the trunk
|
|
|
|
|
Index: src/server.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/server.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 server.c
|
|
|
|
|
--- src/server.c 19 Apr 2001 19:34:04 -0000 1.1.1.4
|
|
|
|
|
+++ src/server.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -117,6 +117,13 @@
|
|
|
|
|
|
|
|
|
|
# endif /* AUTH_SERVER_SUPPORT */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_PSERVERD
|
|
|
|
|
+#include <sys/ioctl.h>
|
|
|
|
|
+#include <netinet/in.h>
|
|
|
|
|
+#include <arpa/inet.h>
|
|
|
|
|
+#include <netdb.h>
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
/* While processing requests, this buffer accumulates data to be sent to
|
|
|
|
|
the client, and then once we are in do_cvs_command, we use it
|
|
|
|
|
@@ -734,6 +741,13 @@
|
|
|
|
|
|
|
|
|
|
if (error_pending()) return;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ {
|
|
|
|
|
+ char *argnew;
|
|
|
|
|
+ if (root_map_it(arg, &argnew, 0))
|
|
|
|
|
+ arg = argnew;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
if (!isabsolute (arg))
|
|
|
|
|
{
|
|
|
|
|
if (alloc_pending (80 + strlen (arg)))
|
|
|
|
|
@@ -1155,6 +1169,9 @@
|
|
|
|
|
char *repos;
|
|
|
|
|
|
|
|
|
|
status = buf_read_line (buf_from_net, &repos, (int *) NULL);
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ root_map_it(repos, &repos, 1);
|
|
|
|
|
+#endif
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
if (!outside_root (repos))
|
|
|
|
|
@@ -2181,6 +2198,11 @@
|
|
|
|
|
case 'n':
|
|
|
|
|
noexec = 1;
|
|
|
|
|
break;
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ case 'u':
|
|
|
|
|
+ nolock = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+#endif
|
|
|
|
|
case 'q':
|
|
|
|
|
quiet = 1;
|
|
|
|
|
break;
|
|
|
|
|
@@ -3916,6 +3938,17 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See server.h for description. */
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+static void serve_list PROTO ((char *));
|
|
|
|
|
+static void
|
|
|
|
|
+serve_list (arg)
|
|
|
|
|
+ char *arg;
|
|
|
|
|
+{
|
|
|
|
|
+ if (print_pending_error())
|
|
|
|
|
+ return;
|
|
|
|
|
+ do_cvs_command("rlist", cvslist);
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
server_modtime (finfo, vers_ts)
|
|
|
|
|
@@ -4770,6 +4803,9 @@
|
|
|
|
|
REQ_LINE("expand-modules", serve_expand_modules, 0),
|
|
|
|
|
REQ_LINE("ci", serve_ci, RQ_ESSENTIAL),
|
|
|
|
|
REQ_LINE("co", serve_co, RQ_ESSENTIAL),
|
|
|
|
|
+#ifdef RSE_PATCH_RLIST
|
|
|
|
|
+ REQ_LINE("rlist", serve_list, 0),
|
|
|
|
|
+#endif
|
|
|
|
|
REQ_LINE("update", serve_update, RQ_ESSENTIAL),
|
|
|
|
|
REQ_LINE("diff", serve_diff, 0),
|
|
|
|
|
REQ_LINE("log", serve_log, 0),
|
|
|
|
|
@@ -5351,8 +5387,13 @@
|
|
|
|
|
{
|
|
|
|
|
char *env, *cvs_user;
|
|
|
|
|
|
|
|
|
|
+#if defined(RSE_PATCH_LOGNAME) && defined(AUTH_SERVER_SUPPORT)
|
|
|
|
|
+ env = xmalloc (sizeof "LOGNAME=" + strlen (CVS_Username));
|
|
|
|
|
+ (void) sprintf (env, "LOGNAME=%s", CVS_Username);
|
|
|
|
|
+#else
|
|
|
|
|
env = xmalloc (sizeof "LOGNAME=" + strlen (username));
|
|
|
|
|
(void) sprintf (env, "LOGNAME=%s", username);
|
|
|
|
|
+#endif
|
|
|
|
|
(void) putenv (env);
|
|
|
|
|
|
|
|
|
|
env = xmalloc (sizeof "USER=" + strlen (username));
|
|
|
|
|
@@ -5430,6 +5471,13 @@
|
|
|
|
|
found_it = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ if (strncmp(linebuf, "*:", 2) == 0) {
|
|
|
|
|
+ found_it = 1;
|
|
|
|
|
+ namelen = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
}
|
|
|
|
|
if (ferror (fp))
|
|
|
|
|
error (0, errno, "cannot read %s", filename);
|
|
|
|
|
@@ -5473,10 +5521,14 @@
|
|
|
|
|
/* Okay, after this conditional chain, found_password and
|
|
|
|
|
host_user_tmp will have useful values: */
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ if (non_cvsuser_portion[strspn(non_cvsuser_portion, " \t")] == '\0')
|
|
|
|
|
+#else
|
|
|
|
|
if ((non_cvsuser_portion == NULL)
|
|
|
|
|
|| (strlen (non_cvsuser_portion) == 0)
|
|
|
|
|
|| ((strspn (non_cvsuser_portion, " \t"))
|
|
|
|
|
== strlen (non_cvsuser_portion)))
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
found_password = NULL;
|
|
|
|
|
host_user_tmp = NULL;
|
|
|
|
|
@@ -5507,6 +5559,14 @@
|
|
|
|
|
*host_user_ptr = xstrdup (host_user_tmp);
|
|
|
|
|
retval = 1;
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ else if (strcmp(found_password, "*") == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ /* Give host_user_ptr permanent storage. */
|
|
|
|
|
+ *host_user_ptr = xstrdup(host_user_tmp);
|
|
|
|
|
+ retval = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*host_user_ptr = NULL;
|
|
|
|
|
@@ -5552,7 +5612,11 @@
|
|
|
|
|
/* host_user already set by reference, so just return. */
|
|
|
|
|
goto handle_return;
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ else if (rc == -1 || system_auth)
|
|
|
|
|
+#else
|
|
|
|
|
else if (rc == 0 && system_auth)
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
/* No cvs password found, so try /etc/passwd. */
|
|
|
|
|
|
|
|
|
|
@@ -5594,15 +5658,30 @@
|
|
|
|
|
if (*found_passwd)
|
|
|
|
|
{
|
|
|
|
|
/* user exists and has a password */
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ if (strcmp (found_passwd, crypt (password, found_passwd)) != 0) {
|
|
|
|
|
+ if (host_user != NULL) {
|
|
|
|
|
+ free (host_user);
|
|
|
|
|
+ host_user = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (host_user == NULL) {
|
|
|
|
|
+ host_user = xstrdup (username);
|
|
|
|
|
+ }
|
|
|
|
|
+#else
|
|
|
|
|
host_user = ((! strcmp (found_passwd,
|
|
|
|
|
crypt (password, found_passwd)))
|
|
|
|
|
? xstrdup (username) : NULL);
|
|
|
|
|
+#endif
|
|
|
|
|
goto handle_return;
|
|
|
|
|
}
|
|
|
|
|
else if (password && *password)
|
|
|
|
|
{
|
|
|
|
|
/* user exists and has no system password, but we got
|
|
|
|
|
one as parameter */
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ if (host_user == NULL)
|
|
|
|
|
+#endif
|
|
|
|
|
host_user = xstrdup (username);
|
|
|
|
|
goto handle_return;
|
|
|
|
|
}
|
|
|
|
|
@@ -5613,7 +5692,11 @@
|
|
|
|
|
goto handle_return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_WILDPASSWD
|
|
|
|
|
+ else
|
|
|
|
|
+#else
|
|
|
|
|
else if (rc == 0)
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
/* Note that the message _does_ distinguish between the case in
|
|
|
|
|
which we check for a system password and the case in which
|
|
|
|
|
@@ -5634,6 +5717,7 @@
|
|
|
|
|
#endif
|
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
+#ifndef RSE_PATCH_WILDPASSWD
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Something strange happened. We don't know what it was, but
|
|
|
|
|
@@ -5641,6 +5725,7 @@
|
|
|
|
|
host_user = NULL;
|
|
|
|
|
goto handle_return;
|
|
|
|
|
}
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
handle_return:
|
|
|
|
|
if (host_user)
|
|
|
|
|
@@ -5778,6 +5863,10 @@
|
|
|
|
|
strip_trailing_newlines (username);
|
|
|
|
|
strip_trailing_newlines (password);
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ root_map_it(repository, &repository, 0);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* ... and make sure the protocol ends on the right foot. */
|
|
|
|
|
/* See above comment about error handling. */
|
|
|
|
|
getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX);
|
|
|
|
|
@@ -6611,3 +6700,520 @@
|
|
|
|
|
cvs_output (text, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_PSERVERD
|
|
|
|
|
+
|
|
|
|
|
+/* ========================================================================= */
|
|
|
|
|
+
|
|
|
|
|
+#if !defined(SIGCHLD) && defined(SIGCLD)
|
|
|
|
|
+#define SIGCHLD SIGCLD
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+static void pserver_handshake(void);
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Main procedure stub. This is called in two contexts: first under "cvs
|
|
|
|
|
+ * -H pserverd" where we just display the usage; second inside the CVS
|
|
|
|
|
+ * main loop where we have to act as the regular "cvs server".
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+static const char *const pserverd_usage[] = {
|
|
|
|
|
+ "Usage: %s %s [-v] [-d] [-l addr[:port]] [-p pidfile] [-A user] [-R user:repos:chroot]\n",
|
|
|
|
|
+ "\t-v\tVerbose mode.\n",
|
|
|
|
|
+ "\t-d\tDetach into background and run as a daemon.\n",
|
|
|
|
|
+ "\t-l\tListen to a particular address/port.\n",
|
|
|
|
|
+ "\t-p\tWrite the daemon's PID to a file.\n",
|
|
|
|
|
+ "\t-A\tForce global -l -n -u options for a particular user.\n",
|
|
|
|
|
+ "\t-R\tPerform a chroot(2) for a user/repository pair.\n",
|
|
|
|
|
+ "(Specify the --help global option for a list of other help options)\n",
|
|
|
|
|
+ NULL
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+pserverd(
|
|
|
|
|
+ int argc,
|
|
|
|
|
+ char **argv)
|
|
|
|
|
+{
|
|
|
|
|
+ if (argc == -1)
|
|
|
|
|
+ usage(pserverd_usage);
|
|
|
|
|
+ return server(argc, argv);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * The pserver daemon. This listens on a particular TCP/IP socket for
|
|
|
|
|
+ * connections. If one occurs, it forks and returns to the caller inside
|
|
|
|
|
+ * the child process. The parent process runs forever.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+static struct {
|
|
|
|
|
+ char *user;
|
|
|
|
|
+ char *repos;
|
|
|
|
|
+ char *chroot;
|
|
|
|
|
+} pserver_chroot;
|
|
|
|
|
+
|
|
|
|
|
+static char *pserverd_anonymous_user = NULL;
|
|
|
|
|
+static int pserverd_verbose = 0;
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+tcp_setinaddr(
|
|
|
|
|
+ struct sockaddr_in *addr,
|
|
|
|
|
+ const char *host,
|
|
|
|
|
+ const char *service,
|
|
|
|
|
+ const char *protocol)
|
|
|
|
|
+{
|
|
|
|
|
+ struct hostent *hp;
|
|
|
|
|
+ char *end;
|
|
|
|
|
+ long portno;
|
|
|
|
|
+ struct servent *serv;
|
|
|
|
|
+
|
|
|
|
|
+ memset(addr, 0, sizeof *addr);
|
|
|
|
|
+ addr->sin_family = AF_INET;
|
|
|
|
|
+
|
|
|
|
|
+ /* set host part of address */
|
|
|
|
|
+ if (host == NULL)
|
|
|
|
|
+ addr->sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
+ else {
|
|
|
|
|
+ addr->sin_addr.s_addr = inet_addr(host);
|
|
|
|
|
+ if (addr->sin_addr.s_addr == (unsigned long) -1) {
|
|
|
|
|
+ if ((hp = gethostbyname(host)) == NULL)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
|
|
|
|
|
+ addr->sin_family = hp->h_addrtype;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* set port part of address */
|
|
|
|
|
+ if (service == NULL)
|
|
|
|
|
+ addr->sin_port = htons(0);
|
|
|
|
|
+ else {
|
|
|
|
|
+ portno = strtol(service, &end, 10);
|
|
|
|
|
+ if (portno > 0 && portno <= 65535 && end != service && *end == '\0')
|
|
|
|
|
+ addr->sin_port = htons(portno);
|
|
|
|
|
+ else {
|
|
|
|
|
+ if ((serv = getservbyname(service, protocol)) == NULL)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ addr->sin_port = serv->s_port;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+tcp_listen(
|
|
|
|
|
+ const char *host,
|
|
|
|
|
+ const char *port)
|
|
|
|
|
+{
|
|
|
|
|
+ int s;
|
|
|
|
|
+ struct protoent *proto;
|
|
|
|
|
+ struct sockaddr_in server;
|
|
|
|
|
+ int yes = 1;
|
|
|
|
|
+
|
|
|
|
|
+ if (tcp_setinaddr(&server, host, port, "tcp") < 0)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ if ((proto = getprotobyname("tcp")) == NULL)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ if ((s = socket(PF_INET, SOCK_STREAM, proto->p_proto)) < 0)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
|
|
|
|
|
+ if (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
|
|
|
|
|
+ close(s);
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (listen(s, 256) < 0) {
|
|
|
|
|
+ close(s);
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return s;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+proc_daemon(
|
|
|
|
|
+ int nochdir,
|
|
|
|
|
+ int noclose)
|
|
|
|
|
+{
|
|
|
|
|
+ int fd;
|
|
|
|
|
+ int rc;
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Ignore tty related signals
|
|
|
|
|
+ */
|
|
|
|
|
+#ifdef SIGTTOU
|
|
|
|
|
+ signal(SIGTTOU, SIG_IGN);
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef SIGTTIN
|
|
|
|
|
+ signal(SIGTTIN, SIG_IGN);
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef SIGTSTP
|
|
|
|
|
+ signal(SIGTSTP, SIG_IGN);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * fork so the parent can exit, this returns control to the command line
|
|
|
|
|
+ * or shell invoking your program. This step is required so that the new
|
|
|
|
|
+ * process is guaranteed not to be a process group leader (The next step,
|
|
|
|
|
+ * setsid, would fail if you're a process group leader).
|
|
|
|
|
+ */
|
|
|
|
|
+ rc = fork();
|
|
|
|
|
+ switch (rc) {
|
|
|
|
|
+ case -1: return -1;
|
|
|
|
|
+ case 0: break;
|
|
|
|
|
+ default: _exit(0); /* exit original process */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * setsid to become a process group and session group leader. Since a
|
|
|
|
|
+ * controlling terminal is associated with a session, and this new session
|
|
|
|
|
+ * has not yet acquired a controlling terminal our process now has no
|
|
|
|
|
+ * controlling terminal, which is a Good Thing for daemons.
|
|
|
|
|
+ */
|
|
|
|
|
+#ifdef HAVE_SETSID
|
|
|
|
|
+ if (setsid() == -1)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+#else
|
|
|
|
|
+ if (setpgid(0, getpid()) == -1)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+#ifndef _PATH_TTY
|
|
|
|
|
+#define _PATH_TTY "/dev/tty"
|
|
|
|
|
+#endif
|
|
|
|
|
+ if ((fd = open(_PATH_TTY, O_RDWR)) == -1)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ ioctl(fd, TIOCNOTTY, NULL);
|
|
|
|
|
+ close(fd);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * fork again so the parent, (the session group leader), can exit. This
|
|
|
|
|
+ * means that we, as a non-session group leader, can never regain a
|
|
|
|
|
+ * controlling terminal.
|
|
|
|
|
+ */
|
|
|
|
|
+ rc = fork();
|
|
|
|
|
+ switch (rc) {
|
|
|
|
|
+ case -1: return -1;
|
|
|
|
|
+ case 0: break;
|
|
|
|
|
+ default: _exit(0); /* exit original process */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * chdir("/") to ensure that our process doesn't keep any directory in
|
|
|
|
|
+ * use. Failure to do this could make it so that an administrator couldn't
|
|
|
|
|
+ * unmount a filesystem, because it was our current directory.
|
|
|
|
|
+ * [Equivalently, we could change to any directory containing files
|
|
|
|
|
+ * important to the daemon's operation.]
|
|
|
|
|
+ */
|
|
|
|
|
+ if (!nochdir)
|
|
|
|
|
+ chdir("/");
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * give us complete control over the permissions of anything we write. We
|
|
|
|
|
+ * don't know what umask we may have inherited. [This step is optional]
|
|
|
|
|
+ */
|
|
|
|
|
+ umask(0);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * close fds 0, 1, and 2. This releases the standard in, out, and error we
|
|
|
|
|
+ * inherited from our parent process. We have no way of knowing where
|
|
|
|
|
+ * these fds might have been redirected to.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
|
|
|
|
|
+ dup2(fd, STDIN_FILENO);
|
|
|
|
|
+ dup2(fd, STDOUT_FILENO);
|
|
|
|
|
+ dup2(fd, STDERR_FILENO);
|
|
|
|
|
+ if (fd > 2)
|
|
|
|
|
+ close(fd);
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
|
|
|
|
+pserver_daemon_reapchild(
|
|
|
|
|
+ int signo)
|
|
|
|
|
+{
|
|
|
|
|
+ pid_t child;
|
|
|
|
|
+ int status;
|
|
|
|
|
+ char buf[128];
|
|
|
|
|
+
|
|
|
|
|
+ while ((child = waitpid(-1, &status, WNOHANG)) > (pid_t)0) {
|
|
|
|
|
+ if (pserverd_verbose) {
|
|
|
|
|
+ sprintf(buf, "cvs pserverd[%ld]: child process (pid %ld): terminated.\n",
|
|
|
|
|
+ (long)getpid(), (long)child);
|
|
|
|
|
+ write(STDOUT_FILENO, buf, strlen(buf));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ signal(signo, &pserver_daemon_reapchild);
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+pserver_daemon(
|
|
|
|
|
+ int argc,
|
|
|
|
|
+ char **argv)
|
|
|
|
|
+{
|
|
|
|
|
+ int sd;
|
|
|
|
|
+ pid_t child;
|
|
|
|
|
+ int option;
|
|
|
|
|
+ char *host = NULL;
|
|
|
|
|
+ char *port = "2401";
|
|
|
|
|
+ char *listen = NULL;
|
|
|
|
|
+ struct sockaddr_in them;
|
|
|
|
|
+ int detach = 0;
|
|
|
|
|
+ char *pidfile = NULL;
|
|
|
|
|
+ FILE *fp;
|
|
|
|
|
+ char *cp;
|
|
|
|
|
+ int len;
|
|
|
|
|
+ int ns;
|
|
|
|
|
+
|
|
|
|
|
+ /* make sure we are running with root priviledges, because
|
|
|
|
|
+ we need it later for chroot, switch_to_user, etc. */
|
|
|
|
|
+ if (geteuid() != 0)
|
|
|
|
|
+ error(1, 0, "root priviledges required for pserver operation");
|
|
|
|
|
+
|
|
|
|
|
+ /* process "cvs pserverd" command options */
|
|
|
|
|
+ optind = 0;
|
|
|
|
|
+ while ((option = getopt(argc, argv, "vl:dp:A:R:")) != EOF) {
|
|
|
|
|
+ switch ((char) option) {
|
|
|
|
|
+ case 'v':
|
|
|
|
|
+ pserverd_verbose = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'l':
|
|
|
|
|
+ listen = xstrdup(optarg);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'd':
|
|
|
|
|
+ detach = 1;
|
|
|
|
|
+ pserverd_verbose = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'p':
|
|
|
|
|
+ pidfile = xstrdup(optarg);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'A':
|
|
|
|
|
+ pserverd_anonymous_user = xstrdup(optarg);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'R':
|
|
|
|
|
+ cp = xstrdup(optarg);
|
|
|
|
|
+ pserver_chroot.user = cp;
|
|
|
|
|
+ if ((cp = strchr(cp, ':')) == NULL)
|
|
|
|
|
+ error(1, 0, "invalid -R option argument");
|
|
|
|
|
+ *cp++ = '\0';
|
|
|
|
|
+ pserver_chroot.repos = cp;
|
|
|
|
|
+ if ((cp = strchr(cp, ':')) == NULL)
|
|
|
|
|
+ error(1, 0, "invalid -R option argument");
|
|
|
|
|
+ *cp++ = '\0';
|
|
|
|
|
+ pserver_chroot.chroot = cp;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case '?':
|
|
|
|
|
+ default:
|
|
|
|
|
+ usage(pserverd_usage);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ argc -= optind;
|
|
|
|
|
+ argv += optind;
|
|
|
|
|
+ if (argc < 0)
|
|
|
|
|
+ usage(pserverd_usage);
|
|
|
|
|
+
|
|
|
|
|
+ /* optionally go into the background as a real daemon */
|
|
|
|
|
+ if (detach)
|
|
|
|
|
+ proc_daemon(0, 0);
|
|
|
|
|
+
|
|
|
|
|
+ /* optionally write out the pid */
|
|
|
|
|
+ if (pidfile != NULL) {
|
|
|
|
|
+ if ((fp = fopen(pidfile, "w")) == NULL)
|
|
|
|
|
+ error(1, 0, "unable to write pid to file %s: %s",
|
|
|
|
|
+ pidfile, strerror(errno));
|
|
|
|
|
+ fprintf(fp, "%ld\n", (long)getpid());
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* listen on the TCP/IP socket */
|
|
|
|
|
+ if (listen != NULL) {
|
|
|
|
|
+ if ((port = strrchr(listen, ':')) != NULL)
|
|
|
|
|
+ *(port++) = '\0';
|
|
|
|
|
+ if (strcasecmp(listen, "*") == 0 || strcmp(listen, "0.0.0.0") == 0)
|
|
|
|
|
+ host = NULL;
|
|
|
|
|
+ else
|
|
|
|
|
+ host = listen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((sd = tcp_listen(host, port)) < 0)
|
|
|
|
|
+ error(1, 0, "unable to listen (%s:%s): %s",
|
|
|
|
|
+ host != NULL ? host : "*", port, strerror(errno));
|
|
|
|
|
+
|
|
|
|
|
+ /* make sure we reap the childs */
|
|
|
|
|
+ signal(SIGCHLD, &pserver_daemon_reapchild);
|
|
|
|
|
+
|
|
|
|
|
+ /* daemon loop */
|
|
|
|
|
+ for (;;) {
|
|
|
|
|
+ len = sizeof(them);
|
|
|
|
|
+ ns = accept(sd, (struct sockaddr *)&them, &len);
|
|
|
|
|
+ if (ns < 0) {
|
|
|
|
|
+ if (errno == EINTR)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ error(1, 0, "accept(2) failed: %s", strerror(errno));
|
|
|
|
|
+ }
|
|
|
|
|
+ switch (child = fork()) {
|
|
|
|
|
+ case -1:
|
|
|
|
|
+ error(1, 0, "unable to fork(2): %s", strerror(errno));
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ /* child */
|
|
|
|
|
+ close(sd);
|
|
|
|
|
+ signal(SIGCHLD, SIG_DFL);
|
|
|
|
|
+
|
|
|
|
|
+ /* connect stdin/stdout to socket */
|
|
|
|
|
+ dup2(ns, STDIN_FILENO);
|
|
|
|
|
+ dup2(ns, STDOUT_FILENO);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * perform "cvs pserver" authentication handshake.
|
|
|
|
|
+ */
|
|
|
|
|
+ pserver_handshake();
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * just return to caller, i.e., the main() procedure
|
|
|
|
|
+ * which in turn will dispatch into "cvs server" code
|
|
|
|
|
+ * for us...
|
|
|
|
|
+ */
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ /* parent */
|
|
|
|
|
+ if (pserverd_verbose)
|
|
|
|
|
+ fprintf(stderr, "cvs pserverd[%ld]: child process (pid %ld): started.\n",
|
|
|
|
|
+ (long)getpid(), (long)child);
|
|
|
|
|
+ close(ns);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ exit(0);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
|
|
|
|
+pserver_handshake(
|
|
|
|
|
+ void)
|
|
|
|
|
+{
|
|
|
|
|
+ char *tmp = NULL;
|
|
|
|
|
+ size_t tmp_allocated = 0;
|
|
|
|
|
+ char *repository = NULL;
|
|
|
|
|
+ size_t repository_allocated = 0;
|
|
|
|
|
+ char *username = NULL;
|
|
|
|
|
+ size_t username_allocated = 0;
|
|
|
|
|
+ char *password = NULL;
|
|
|
|
|
+ size_t password_allocated = 0;
|
|
|
|
|
+ char *host_user = NULL;
|
|
|
|
|
+ char *descrambled_password;
|
|
|
|
|
+ int verify_and_exit = 0;
|
|
|
|
|
+ char *chrootdir = NULL;
|
|
|
|
|
+ int on;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef SO_KEEPALIVE
|
|
|
|
|
+ /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
|
|
|
|
|
+ if the client dies while we are waiting for input. */
|
|
|
|
|
+ on = 1;
|
|
|
|
|
+ (void)setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
|
|
|
|
|
+ (char *)&on, sizeof(on));
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ /* Make sure the protocol starts off on the right foot... */
|
|
|
|
|
+ getline(&tmp, &tmp_allocated, stdin);
|
|
|
|
|
+
|
|
|
|
|
+ if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
|
|
|
|
|
+ verify_and_exit = 1;
|
|
|
|
|
+ else if (strcmp (tmp, "BEGIN AUTH REQUEST\n") == 0)
|
|
|
|
|
+ ;
|
|
|
|
|
+ else
|
|
|
|
|
+ error (1, 0, "bad auth protocol start: %s", tmp);
|
|
|
|
|
+
|
|
|
|
|
+ /* Get the three important pieces of information in order. */
|
|
|
|
|
+ getline(&repository, &repository_allocated, stdin);
|
|
|
|
|
+ getline(&username, &username_allocated, stdin);
|
|
|
|
|
+ getline(&password, &password_allocated, stdin);
|
|
|
|
|
+
|
|
|
|
|
+ /* Make them pure. */
|
|
|
|
|
+ strip_trailing_newlines(repository);
|
|
|
|
|
+ strip_trailing_newlines(username);
|
|
|
|
|
+ strip_trailing_newlines(password);
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_MAPROOT
|
|
|
|
|
+ root_map_it(repository, &repository, 0);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ /* ... and make sure the protocol ends on the right foot. */
|
|
|
|
|
+ getline(&tmp, &tmp_allocated, stdin);
|
|
|
|
|
+ if (strcmp (tmp, verify_and_exit ?
|
|
|
|
|
+ "END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n") != 0)
|
|
|
|
|
+ error (1, 0, "bad auth protocol end: %s", tmp);
|
|
|
|
|
+
|
|
|
|
|
+ if (!root_allow_ok(repository))
|
|
|
|
|
+ goto i_hate_you;
|
|
|
|
|
+ parse_config(repository);
|
|
|
|
|
+
|
|
|
|
|
+ /* We need the real cleartext before we hash it. */
|
|
|
|
|
+ descrambled_password = descramble(password);
|
|
|
|
|
+ host_user = check_password(username, descrambled_password, repository);
|
|
|
|
|
+ memset(descrambled_password, 0, strlen(descrambled_password));
|
|
|
|
|
+ free(descrambled_password);
|
|
|
|
|
+
|
|
|
|
|
+ if (host_user == NULL) {
|
|
|
|
|
+ i_hate_you:
|
|
|
|
|
+ printf("I HATE YOU\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if (pserverd_verbose)
|
|
|
|
|
+ fprintf(stderr, "cvs pserverd[%ld]: status=FAILED user=%s root=%s\n",
|
|
|
|
|
+ (long)getpid(), username, repository);
|
|
|
|
|
+ error_exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Don't go any farther if we're just responding to "cvs login". */
|
|
|
|
|
+ if (verify_and_exit) {
|
|
|
|
|
+ printf("I LOVE YOU\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if (pserverd_verbose)
|
|
|
|
|
+ fprintf(stderr, "cvs pserverd[%ld]: status=OK user=%s root=%s (huser=%s)\n",
|
|
|
|
|
+ (long)getpid(), username, repository, host_user);
|
|
|
|
|
+ exit(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Set Pserver_Repos so that we can check later that the same
|
|
|
|
|
+ repository is sent in later client/server protocol. */
|
|
|
|
|
+ Pserver_Repos = xmalloc(strlen(repository)+1);
|
|
|
|
|
+ strcpy(Pserver_Repos, repository);
|
|
|
|
|
+
|
|
|
|
|
+ /* Optionally perform a chroot */
|
|
|
|
|
+ if (pserver_chroot.user != NULL) {
|
|
|
|
|
+ if ( strcmp(username, pserver_chroot.user) == 0
|
|
|
|
|
+ && ( strcmp(repository, pserver_chroot.repos) == 0
|
|
|
|
|
+ || strcmp(pserver_chroot.repos, "*") == 0 )) {
|
|
|
|
|
+ chrootdir = pserver_chroot.chroot;
|
|
|
|
|
+ if (chdir(chrootdir) == -1)
|
|
|
|
|
+ error(1, 0, "failed to chdir(2) to %s: %s", chrootdir, strerror(errno));
|
|
|
|
|
+ if (chroot(chrootdir) == -1)
|
|
|
|
|
+ error(1, 0, "failed to chroot(2) to %s: %s", chrootdir, strerror(errno));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Additionally switch to read-only mode for anonymous user */
|
|
|
|
|
+ if (pserverd_anonymous_user != NULL) {
|
|
|
|
|
+ if (strcmp(username, pserverd_anonymous_user) == 0) {
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ nolock = 1;
|
|
|
|
|
+#endif
|
|
|
|
|
+ logoff = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Switch to run as this user. */
|
|
|
|
|
+ switch_to_user(host_user);
|
|
|
|
|
+ free(tmp);
|
|
|
|
|
+ free(repository);
|
|
|
|
|
+ free(username);
|
|
|
|
|
+ free(password);
|
|
|
|
|
+
|
|
|
|
|
+ printf("I LOVE YOU\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if (pserverd_verbose)
|
|
|
|
|
+ fprintf(stderr, "cvs pserverd[%ld]: status=OK user=%s root=%s (huser=%s hroot=%s)\n",
|
|
|
|
|
+ (long)getpid(), username, repository, host_user, chrootdir != NULL ? chrootdir : "/");
|
|
|
|
|
+ return;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif /* RSE_PATCH_PSERVERD */
|
|
|
|
|
+
|
|
|
|
|
Index: src/subr.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/subr.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 subr.c
|
|
|
|
|
--- src/subr.c 19 Apr 2001 19:34:04 -0000 1.1.1.4
|
|
|
|
|
+++ src/subr.c 16 Feb 2002 13:49:47 -0000
|
|
|
|
|
@@ -336,6 +336,22 @@
|
|
|
|
|
uid_t uid;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_CVSUSER
|
|
|
|
|
+#ifndef RSE_PATCH_CVSUSER_CALLER
|
|
|
|
|
+#define RSE_PATCH_CVSUSER_CALLER "cvs"
|
|
|
|
|
+#endif
|
|
|
|
|
+ uid = getuid();
|
|
|
|
|
+ if ((pw = (struct passwd *)getpwnam(RSE_PATCH_CVSUSER_CALLER)) != NULL) {
|
|
|
|
|
+ if (pw->pw_uid == uid) {
|
|
|
|
|
+ char *name;
|
|
|
|
|
+ if ((name = getenv("CVSUSER")) != NULL) {
|
|
|
|
|
+ cache = xstrdup(name);
|
|
|
|
|
+ return cache;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
/* If there is a CVS username, return it. */
|
|
|
|
|
#ifdef AUTH_SERVER_SUPPORT
|
|
|
|
|
if (CVS_Username != NULL)
|
|
|
|
|
@@ -797,6 +813,73 @@
|
|
|
|
|
|
|
|
|
|
return backup_name;
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef RSE_PATCH_HANDLE
|
|
|
|
|
+/* handle: 2000041317203601
|
|
|
|
|
+ date1: 2000/04/13 17:20:36
|
|
|
|
|
+ date2: 2000/04/13 17:20:37 */
|
|
|
|
|
+int handle2dates(char *handle, time_t *t1, time_t *t2)
|
|
|
|
|
+{
|
|
|
|
|
+ int Y,M,D,h,m,s,o;
|
|
|
|
|
+ char buf[17];
|
|
|
|
|
+ time_t t;
|
|
|
|
|
+ struct tm tm;
|
|
|
|
|
+ int rev = 0;
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ /* check for correct handle format */
|
|
|
|
|
+ if (handle == NULL)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ if (handle[0] == '!') {
|
|
|
|
|
+ handle++;
|
|
|
|
|
+ rev = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (strlen(handle) != 16)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ for (i = 0; i < 16; i++)
|
|
|
|
|
+ if (!isdigit(handle[i]))
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ /* parse out handle parts */
|
|
|
|
|
+ strcpy(buf, handle);
|
|
|
|
|
+ o = atoi(buf+14);
|
|
|
|
|
+ buf[14] = '\0';
|
|
|
|
|
+ s = atoi(buf+12);
|
|
|
|
|
+ buf[12] = '\0';
|
|
|
|
|
+ m = atoi(buf+10);
|
|
|
|
|
+ buf[10] = '\0';
|
|
|
|
|
+ h = atoi(buf+8);
|
|
|
|
|
+ buf[8] = '\0';
|
|
|
|
|
+ D = atoi(buf+6);
|
|
|
|
|
+ buf[6] = '\0';
|
|
|
|
|
+ M = atoi(buf+4);
|
|
|
|
|
+ buf[4] = '\0';
|
|
|
|
|
+ Y = atoi(buf);
|
|
|
|
|
+
|
|
|
|
|
+ /* assemble parts into a time value */
|
|
|
|
|
+ memset(&tm, 0, sizeof tm);
|
|
|
|
|
+ tm.tm_sec = s;
|
|
|
|
|
+ tm.tm_min = m;
|
|
|
|
|
+ tm.tm_hour = h;
|
|
|
|
|
+ tm.tm_mday = D;
|
|
|
|
|
+ tm.tm_mon = M - 1;
|
|
|
|
|
+ tm.tm_year = Y - 1900;
|
|
|
|
|
+ t = mktime(&tm);
|
|
|
|
|
+ if (t == -1)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ /* output the first and second time */
|
|
|
|
|
+ if (rev) {
|
|
|
|
|
+ *t2 = t;
|
|
|
|
|
+ *t1 = t + o;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ *t1 = t;
|
|
|
|
|
+ *t2 = t + o;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy a string into a buffer escaping any shell metacharacters. The
|
|
|
|
|
Index: src/tag.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/tag.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 tag.c
|
|
|
|
|
--- src/tag.c 24 Apr 2001 17:04:59 -0000 1.1.1.4
|
|
|
|
|
+++ src/tag.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -1229,7 +1229,11 @@
|
|
|
|
|
/* The tags is valid but not mentioned in val-tags. Add it. */
|
|
|
|
|
datum value;
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ if (noexec || nowrite || nolock)
|
|
|
|
|
+#else
|
|
|
|
|
if (noexec || nowrite)
|
|
|
|
|
+#endif
|
|
|
|
|
{
|
|
|
|
|
if (db != NULL)
|
|
|
|
|
dbm_close (db);
|
|
|
|
|
Index: src/update.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/update.c,v
|
|
|
|
|
retrieving revision 1.1.1.4
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.4 update.c
|
|
|
|
|
--- src/update.c 24 Apr 2001 17:04:59 -0000 1.1.1.4
|
|
|
|
|
+++ src/update.c 16 Feb 2002 12:36:09 -0000
|
|
|
|
|
@@ -203,7 +203,11 @@
|
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
pipeout = 1;
|
|
|
|
|
+#ifdef RSE_PATCH_NOLOCK
|
|
|
|
|
+ nolock = noexec = 1; /* so no locks will be created */
|
|
|
|
|
+#else
|
|
|
|
|
noexec = 1; /* so no locks will be created */
|
|
|
|
|
+#endif
|
|
|
|
|
break;
|
|
|
|
|
case 'j':
|
|
|
|
|
if (join_rev2)
|
|
|
|
|
@@ -1809,6 +1813,17 @@
|
|
|
|
|
patch can't handle that. */
|
|
|
|
|
fail = 1;
|
|
|
|
|
}
|
|
|
|
|
+#ifdef RSE_PATCH_FASTERUPDATE
|
|
|
|
|
+ else {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Don't send a diff if just sending the entire file
|
|
|
|
|
+ * would be smaller
|
|
|
|
|
+ */
|
|
|
|
|
+ fseek(e, 0L, SEEK_END);
|
|
|
|
|
+ if (file_info->st_size < ftell(e))
|
|
|
|
|
+ fail = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
fclose (e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -2563,8 +2578,16 @@
|
|
|
|
|
write_letter (finfo, 'C');
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
+#ifdef RSE_PATCH_MERGENOKEYWORD
|
|
|
|
|
+ {
|
|
|
|
|
+ if (*t_options == '\0')
|
|
|
|
|
+ t_options = "-kk"; /* to ignore keyword expansions */
|
|
|
|
|
+#endif
|
|
|
|
|
status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
|
|
|
|
|
t_options, rev1, rev2);
|
|
|
|
|
+#ifdef RSE_PATCH_MERGENOKEYWORD
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
if (status != 0 && status != 1)
|
|
|
|
|
{
|
|
|
|
|
Index: src/version.c
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/version.c,v
|
|
|
|
|
retrieving revision 1.1.1.5
|
|
|
|
|
diff -u -d -u -3 -r1.1.1.5 version.c
|
|
|
|
|
--- src/version.c 27 Apr 2001 20:02:28 -0000 1.1.1.5
|
|
|
|
|
+++ src/version.c 16 Feb 2002 12:38:04 -0000
|
|
|
|
|
@@ -12,7 +12,11 @@
|
|
|
|
|
|
|
|
|
|
#include "cvs.h"
|
|
|
|
|
|
|
|
|
|
+#ifdef RSE_PATCHES
|
|
|
|
|
+char *version_string = "Concurrent Versions System (CVS) 1.11.1p1 [RSE]";
|
|
|
|
|
+#else
|
|
|
|
|
char *version_string = "Concurrent Versions System (CVS) 1.11.1p1";
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
#ifdef CLIENT_SUPPORT
|
|
|
|
|
#ifdef SERVER_SUPPORT
|