diff options
Diffstat (limited to 'gnu/usr.bin/rcs/co')
-rw-r--r-- | gnu/usr.bin/rcs/co/Makefile | 8 | ||||
-rw-r--r-- | gnu/usr.bin/rcs/co/co.1 | 736 | ||||
-rw-r--r-- | gnu/usr.bin/rcs/co/co.c | 826 |
3 files changed, 0 insertions, 1570 deletions
diff --git a/gnu/usr.bin/rcs/co/Makefile b/gnu/usr.bin/rcs/co/Makefile deleted file mode 100644 index 0c73865..0000000 --- a/gnu/usr.bin/rcs/co/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -PROG= co -SRCS= co.c -CFLAGS+= -I${.CURDIR}/../lib -LDADD= ${LIBRCS} -DPADD= ${LIBRCS} - -.include "../../Makefile.inc" -.include <bsd.prog.mk> diff --git a/gnu/usr.bin/rcs/co/co.1 b/gnu/usr.bin/rcs/co/co.1 deleted file mode 100644 index 2aea3ad..0000000 --- a/gnu/usr.bin/rcs/co/co.1 +++ /dev/null @@ -1,736 +0,0 @@ -.de Id -.ds Rv \\$3 -.ds Dt \\$4 -.. -.Id $FreeBSD$ -.ds i \&\s-1ISO\s0 -.ds r \&\s-1RCS\s0 -.ds u \&\s-1UTC\s0 -.if n .ds - \%-- -.if t .ds - \(em -.TH CO 1 \*(Dt GNU -.SH NAME -co \- check out RCS revisions -.SH SYNOPSIS -.B co -.RI [ options ] " file " .\|.\|. -.SH DESCRIPTION -.B co -retrieves a revision from each \*r file and stores it into -the corresponding working file. -.PP -Pathnames matching an \*r suffix denote \*r files; -all others denote working files. -Names are paired as explained in -.BR ci (1). -.PP -Revisions of an \*r file can be checked out locked or unlocked. Locking a -revision prevents overlapping updates. A revision checked out for reading or -processing (e.g., compiling) need not be locked. A revision checked out -for editing and later checkin must normally be locked. Checkout with locking -fails if the revision to be checked out is currently locked by another user. -(A lock can be broken with -.BR rcs "(1).)\ \&" -Checkout with locking also requires the caller to be on the access list of -the \*r file, unless he is the owner of the -file or the superuser, or the access list is empty. -Checkout without locking is not subject to accesslist restrictions, and is -not affected by the presence of locks. -.PP -A revision is selected by options for revision or branch number, -checkin date/time, author, or state. -When the selection options -are applied in combination, -.B co -retrieves the latest revision -that satisfies all of them. -If none of the selection options -is specified, -.B co -retrieves the latest revision -on the default branch (normally the trunk, see the -.B \-b -option of -.BR rcs (1)). -A revision or branch number can be attached -to any of the options -.BR \-f , -.BR \-I , -.BR \-l , -.BR \-M , -.BR \-p , -.BR \-q , -.BR \-r , -or -.BR \-u . -The options -.B \-d -(date), -.B \-s -(state), and -.B \-w -(author) -retrieve from a single branch, the -.I selected -branch, -which is either specified by one of -.BR \-f , -\&.\|.\|., -.BR \-u , -or the default branch. -.PP -A -.B co -command applied to an \*r -file with no revisions creates a zero-length working file. -.B co -always performs keyword substitution (see below). -.SH OPTIONS -.TP -.BR \-r [\f2rev\fP] -retrieves the latest revision whose number is less than or equal to -.IR rev . -If -.I rev -indicates a branch rather than a revision, -the latest revision on that branch is retrieved. -If -.I rev -is omitted, the latest revision on the default branch -(see the -.B \-b -option of -.BR rcs (1)) -is retrieved. -If -.I rev -is -.BR $ , -.B co -determines the revision number from keyword values in the working file. -Otherwise, a revision is composed of one or more numeric or symbolic fields -separated by periods. -If -.I rev -begins with a period, -then the default branch (normally the trunk) is prepended to it. -If -.I rev -is a branch number followed by a period, -then the latest revision on that branch is used. -The numeric equivalent of a symbolic field -is specified with the -.B \-n -option of the commands -.BR ci (1) -and -.BR rcs (1). -.TP -.BR \-l [\f2rev\fP] -same as -.BR \-r , -except that it also locks the retrieved revision for -the caller. -.TP -.BR \-u [\f2rev\fP] -same as -.BR \-r , -except that it unlocks the retrieved revision if it was -locked by the caller. If -.I rev -is omitted, -.B \-u -retrieves the revision locked by the caller, if there is one; otherwise, -it retrieves the latest revision on the default branch. -.TP -.BR \-f [\f2rev\fP] -forces the overwriting of the working file; -useful in connection with -.BR \-q . -See also -.SM "FILE MODES" -below. -.TP -.B \-kkv -Generate keyword strings using the default form, e.g.\& -.B "$\&Revision: \*(Rv $" -for the -.B Revision -keyword. -A locker's name is inserted in the value of the -.BR Header , -.BR Id , -and -.B Locker -keyword strings -only as a file is being locked, -i.e. by -.B "ci\ \-l" -and -.BR "co\ \-l". -This is the default. -.TP -.B \-kkvl -Like -.BR \-kkv , -except that a locker's name is always inserted -if the given revision is currently locked. -.TP -.B \-kk -Generate only keyword names in keyword strings; omit their values. -See -.SM "KEYWORD SUBSTITUTION" -below. -For example, for the -.B Revision -keyword, generate the string -.B $\&Revision$ -instead of -.BR "$\&Revision: \*(Rv $" . -This option is useful to ignore differences due to keyword substitution -when comparing different revisions of a file. -Log messages are inserted after -.B $\&Log$ -keywords even if -.B \-kk -is specified, -since this tends to be more useful when merging changes. -.TP -.B \-ko -Generate the old keyword string, -present in the working file just before it was checked in. -For example, for the -.B Revision -keyword, generate the string -.B "$\&Revision: 1.1 $" -instead of -.B "$\&Revision: \*(Rv $" -if that is how the string appeared when the file was checked in. -This can be useful for file formats -that cannot tolerate any changes to substrings -that happen to take the form of keyword strings. -.TP -.B \-kb -Generate a binary image of the old keyword string. -This acts like -.BR \-ko , -except it performs all working file input and output in binary mode. -This makes little difference on Posix and Unix hosts, -but on DOS-like hosts one should use -.B "rcs\ \-i\ \-kb" -to initialize an \*r file intended to be used for binary files. -Also, on all hosts, -.BR rcsmerge (1) -normally refuses to merge files when -.B \-kb -is in effect. -.TP -.B \-kv -Generate only keyword values for keyword strings. -For example, for the -.B Revision -keyword, generate the string -.B \*(Rv -instead of -.BR "$\&Revision: \*(Rv $" . -This can help generate files in programming languages where it is hard to -strip keyword delimiters like -.B "$\&Revision:\ $" -from a string. -However, further keyword substitution cannot be performed once the -keyword names are removed, so this option should be used with care. -Because of this danger of losing keywords, -this option cannot be combined with -.BR \-l , -and the owner write permission of the working file is turned off; -to edit the file later, check it out again without -.BR \-kv . -.TP -.BR \-p [\f2rev\fP] -prints the retrieved revision on the standard output rather than storing it -in the working file. -This option is useful when -.B co -is part of a pipe. -.TP -.BR \-q [\f2rev\fP] -quiet mode; diagnostics are not printed. -.TP -.BR \-I [\f2rev\fP] -interactive mode; -the user is prompted and questioned -even if the standard input is not a terminal. -.TP -.BI \-d date -retrieves the latest revision on the selected branch whose checkin date/time is -less than or equal to -.IR date . -The date and time can be given in free format. -The time zone -.B LT -stands for local time; -other common time zone names are understood. -For example, the following -.IR date s -are equivalent -if local time is January 11, 1990, 8pm Pacific Standard Time, -eight hours west of Coordinated Universal Time (\*u): -.RS -.LP -.RS -.nf -.ta \w'\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP 'u -.ne 10 -\f38:00 pm lt\fP -\f34:00 AM, Jan. 12, 1990\fP default is \*u -\f31990-01-12 04:00:00+00\fP \*i 8601 (\*u) -\f31990-01-11 20:00:00\-08\fP \*i 8601 (local time) -\f31990/01/12 04:00:00\fP traditional \*r format -\f3Thu Jan 11 20:00:00 1990 LT\fP output of \f3ctime\fP(3) + \f3LT\fP -\f3Thu Jan 11 20:00:00 PST 1990\fP output of \f3date\fP(1) -\f3Fri Jan 12 04:00:00 GMT 1990\fP -\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP Internet RFC 822 -\f312-January-1990, 04:00 WET\fP -.ta 4n +4n +4n +4n -.fi -.RE -.LP -Most fields in the date and time can be defaulted. -The default time zone is normally \*u, but this can be overridden by the -.B \-z -option. -The other defaults are determined in the order year, month, day, -hour, minute, and second (most to least significant). At least one of these -fields must be provided. For omitted fields that are of higher significance -than the highest provided field, the time zone's current values are assumed. -For all other omitted fields, -the lowest possible values are assumed. -For example, without -.BR \-z , -the date -.B "20, 10:30" -defaults to -10:30:00 \*u of the 20th of the \*u time zone's current month and year. -The date/time must be quoted if it contains spaces. -.RE -.TP -.BR \-M [\f2rev\fP] -Set the modification time on the new working file -to be the date of the retrieved revision. -Use this option with care; it can confuse -.BR make (1). -.TP -.BI \-s state -retrieves the latest revision on the selected branch whose state is set to -.IR state . -.TP -.B \-T -Preserve the modification time on the \*r file -even if the \*r file changes because a lock is added or removed. -This option can suppress extensive recompilation caused by a -.BR make (1) -dependency of some other copy of the working file on the \*r file. -Use this option with care; it can suppress recompilation even when it is needed, -i.e. when the change of lock -would mean a change to keyword strings in the other working file. -.TP -.BR \-w [\f2login\fP] -retrieves the latest revision on the selected branch which was checked in -by the user with login name -.IR login . -If the argument -.I login -is -omitted, the caller's login is assumed. -.TP -.BI \-j joinlist -generates a new revision which is the join of the revisions on -.IR joinlist . -This option is largely obsoleted by -.BR rcsmerge (1) -but is retained for backwards compatibility. -.RS -.PP -The -.I joinlist -is a comma-separated list of pairs of the form -.IB rev2 : rev3, -where -.I rev2 -and -.I rev3 -are (symbolic or numeric) -revision numbers. -For the initial such pair, -.I rev1 -denotes the revision selected -by the above options -.BR \-f , -\&.\|.\|., -.BR \-w . -For all other pairs, -.I rev1 -denotes the revision generated by the previous pair. -(Thus, the output -of one join becomes the input to the next.) -.PP -For each pair, -.B co -joins revisions -.I rev1 -and -.I rev3 -with respect to -.IR rev2 . -This means that all changes that transform -.I rev2 -into -.I rev1 -are applied to a copy of -.IR rev3 . -This is particularly useful if -.I rev1 -and -.I rev3 -are the ends of two branches that have -.I rev2 -as a common ancestor. If -.IR rev1 < rev2 < rev3 -on the same branch, -joining generates a new revision which is like -.I rev3, -but with all changes that lead from -.I rev1 -to -.I rev2 -undone. -If changes from -.I rev2 -to -.I rev1 -overlap with changes from -.I rev2 -to -.I rev3, -.B co -reports overlaps as described in -.BR merge (1). -.PP -For the initial pair, -.I rev2 -can be omitted. The default is the common -ancestor. -If any of the arguments indicate branches, the latest revisions -on those branches are assumed. -The options -.B \-l -and -.B \-u -lock or unlock -.IR rev1 . -.RE -.TP -.BI \-V -Print \*r's version number. -.TP -.BI \-V n -Emulate \*r version -.I n, -where -.I n -can be -.BR 3 , -.BR 4 , -or -.BR 5 . -This can be useful when interchanging \*r files with others who are -running older versions of \*r. -To see which version of \*r your correspondents are running, have them invoke -.BR "rcs \-V" ; -this works with newer versions of \*r. -If it doesn't work, have them invoke -.B rlog -on an \*r file; -if none of the first few lines of output contain the string -.B branch: -it is version 3; -if the dates' years have just two digits, it is version 4; -otherwise, it is version 5. -An \*r file generated while emulating version 3 loses its default branch. -An \*r revision generated while emulating version 4 or earlier has -a time stamp that is off by up to 13 hours. -A revision extracted while emulating version 4 or earlier contains -abbreviated dates of the form -.IB yy / mm / dd -and can also contain different white space and line prefixes -in the substitution for -.BR $\&Log$ . -.TP -.BI \-x "suffixes" -Use -.I suffixes -to characterize \*r files. -See -.BR ci (1) -for details. -.TP -.BI \-z zone -specifies the date output format in keyword substitution, -and specifies the default time zone for -.I date -in the -.BI \-d date -option. -The -.I zone -should be empty, a numeric \*u offset, or the special string -.B LT -for local time. -The default is an empty -.IR zone , -which uses the traditional \*r format of \*u without any time zone indication -and with slashes separating the parts of the date; -otherwise, times are output in \*i 8601 format with time zone indication. -For example, if local time is January 11, 1990, 8pm Pacific Standard Time, -eight hours west of \*u, -then the time is output as follows: -.RS -.LP -.RS -.nf -.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u -.ne 4 -\f2option\fP \f2time output\fP -\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP -\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP -\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP -.ta 4n +4n +4n +4n -.fi -.RE -.LP -The -.B \-z -option does not affect dates stored in \*r files, -which are always \*u. -.RE -.SH "KEYWORD SUBSTITUTION" -Strings of the form -.BI $ keyword $ -and -.BI $ keyword : .\|.\|. $ -embedded in -the text are replaced -with strings of the form -.BI $ keyword : value $ -where -.I keyword -and -.I value -are pairs listed below. -Keywords can be embedded in literal strings -or comments to identify a revision. -.PP -Initially, the user enters strings of the form -.BI $ keyword $ . -On checkout, -.B co -replaces these strings with strings of the form -.BI $ keyword : value $ . -If a revision containing strings of the latter form -is checked back in, the value fields will be replaced during the next -checkout. -Thus, the keyword values are automatically updated on checkout. -This automatic substitution can be modified by the -.B \-k -options. -.PP -Keywords and their corresponding values: -.TP -.B $\&Author$ -The login name of the user who checked in the revision. -.TP -.B $\&Date$ -The date and time the revision was checked in. -With -.BI \-z zone -a numeric time zone offset is appended; otherwise, the date is \*u. -.TP -.B $\&Header$ -A standard header containing the full pathname of the \*r file, the -revision number, the date and time, the author, the state, -and the locker (if locked). -With -.BI \-z zone -a numeric time zone offset is appended to the date; otherwise, the date is \*u. -.TP -.B $\&Id$ -Same as -.BR $\&Header$ , -except that the \*r filename is without a path. -.TP -.B $\&Locker$ -The login name of the user who locked the revision (empty if not locked). -.TP -.B $\&Log$ -The log message supplied during checkin, preceded by a header -containing the \*r filename, the revision number, the author, and the date -and time. -With -.BI \-z zone -a numeric time zone offset is appended; otherwise, the date is \*u. -Existing log messages are -.I not -replaced. -Instead, the new log message is inserted after -.BR $\&Log: .\|.\|. $ . -This is useful for -accumulating a complete change log in a source file. -.RS -.LP -Each inserted line is prefixed by the string that prefixes the -.B $\&Log$ -line. For example, if the -.B $\&Log$ -line is -.RB \*(lq "//\ $\&Log: tan.cc\ $" \*(rq, -\*r prefixes each line of the log with -.RB \*(lq "//\ " \*(rq. -This is useful for languages with comments that go to the end of the line. -The convention for other languages is to use a -.RB \*(lq " \(** " \(rq -prefix inside a multiline comment. -For example, the initial log comment of a C program -conventionally is of the following form: -.RS -.LP -.nf -.ft 3 -.ne 3 -/\(** -.in +\w'/'u -\(** $\&Log$ -\(**/ -.in -.ft -.fi -.RE -.LP -For backwards compatibility with older versions of \*r, if the log prefix is -.B /\(** -or -.B (\(** -surrounded by optional white space, inserted log lines contain a space -instead of -.B / -or -.BR ( ; -however, this usage is obsolescent and should not be relied on. -.RE -.TP -.B $\&Name$ -The symbolic name used to check out the revision, if any. -For example, -.B "co\ \-rJoe" -generates -.BR "$\&Name:\ Joe\ $" . -Plain -.B co -generates just -.BR "$\&Name:\ \ $" . -.TP -.B $\&RCSfile$ -The name of the \*r file without a path. -.TP -.B $\&Revision$ -The revision number assigned to the revision. -.TP -.B $\&Source$ -The full pathname of the \*r file. -.TP -.B $\&State$ -The state assigned to the revision with the -.B \-s -option of -.BR rcs (1) -or -.BR ci (1). -.PP -The following characters in keyword values are represented by escape sequences -to keep keyword strings well-formed. -.LP -.RS -.nf -.ne 6 -.ta \w'newline 'u -\f2char escape sequence\fP -tab \f3\et\fP -newline \f3\en\fP -space \f3\e040 -$ \e044 -\e \e\e\fP -.fi -.RE -.SH "FILE MODES" -The working file inherits the read and execute permissions from the \*r -file. In addition, the owner write permission is turned on, unless -.B \-kv -is set or the file -is checked out unlocked and locking is set to strict (see -.BR rcs (1)). -.PP -If a file with the name of the working file exists already and has write -permission, -.B co -aborts the checkout, -asking beforehand if possible. -If the existing working file is -not writable or -.B \-f -is given, the working file is deleted without asking. -.SH FILES -.B co -accesses files much as -.BR ci (1) -does, except that it does not need to read the working file -unless a revision number of -.B $ -is specified. -.SH ENVIRONMENT -.TP -.B \s-1RCSINIT\s0 -options prepended to the argument list, separated by spaces. -See -.BR ci (1) -for details. -.SH DIAGNOSTICS -The \*r pathname, the working pathname, -and the revision number retrieved are -written to the diagnostic output. -The exit status is zero if and only if all operations were successful. -.SH IDENTIFICATION -Author: Walter F. Tichy. -.br -Manual Page Revision: \*(Rv; Release Date: \*(Dt. -.br -Copyright \(co 1982, 1988, 1989 Walter F. Tichy. -.br -Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert. -.SH "SEE ALSO" -rcsintro(1), ci(1), ctime(3), date(1), ident(1), make(1), -rcs(1), rcsclean(1), rcsdiff(1), rcsmerge(1), rlog(1), -rcsfile(5) -.br -Walter F. Tichy, -\*r\*-A System for Version Control, -.I "Software\*-Practice & Experience" -.BR 15 , -7 (July 1985), 637-654. -.SH LIMITS -Links to the \*r and working files are not preserved. -.PP -There is no way to selectively suppress the expansion of keywords, except -by writing them differently. In nroff and troff, this is done by embedding the -null-character -.B \e& -into the keyword. -.br diff --git a/gnu/usr.bin/rcs/co/co.c b/gnu/usr.bin/rcs/co/co.c deleted file mode 100644 index 51cb2b2..0000000 --- a/gnu/usr.bin/rcs/co/co.c +++ /dev/null @@ -1,826 +0,0 @@ -/* Check out working files from revisions of RCS files. */ - -/* Copyright 1982, 1988, 1989 Walter Tichy - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert - Distributed under license by the Free Software Foundation, Inc. - -This file is part of RCS. - -RCS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -RCS is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with RCS; see the file COPYING. -If not, write to the Free Software Foundation, -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -Report problems and direct all questions to: - - rcs-bugs@cs.purdue.edu - -*/ - -/* - * Revision 5.18 1995/06/16 06:19:24 eggert - * Update FSF address. - * - * Revision 5.17 1995/06/01 16:23:43 eggert - * (main, preparejoin): Pass argument instead of using `join' static variable. - * (main): Add -kb. - * - * Revision 5.16 1994/03/17 14:05:48 eggert - * Move buffer-flushes out of critical sections, since they aren't critical. - * Use ORCSerror to clean up after a fatal error. Remove lint. - * Specify subprocess input via file descriptor, not file name. - * - * Revision 5.15 1993/11/09 17:40:15 eggert - * -V now prints version on stdout and exits. Don't print usage twice. - * - * Revision 5.14 1993/11/03 17:42:27 eggert - * Add -z. Generate a value for the Name keyword. - * Don't arbitrarily limit the number of joins. - * Improve quality of diagnostics. - * - * Revision 5.13 1992/07/28 16:12:44 eggert - * Add -V. Check that working and RCS files are distinct. - * - * Revision 5.12 1992/02/17 23:02:08 eggert - * Add -T. - * - * Revision 5.11 1992/01/24 18:44:19 eggert - * Add support for bad_creat0. lint -> RCS_lint - * - * Revision 5.10 1992/01/06 02:42:34 eggert - * Update usage string. - * - * Revision 5.9 1991/10/07 17:32:46 eggert - * -k affects just working file, not RCS file. - * - * Revision 5.8 1991/08/19 03:13:55 eggert - * Warn before removing somebody else's file. - * Add -M. Fix co -j bugs. Tune. - * - * Revision 5.7 1991/04/21 11:58:15 eggert - * Ensure that working file is newer than RCS file after co -[lu]. - * Add -x, RCSINIT, MS-DOS support. - * - * Revision 5.6 1990/12/04 05:18:38 eggert - * Don't checkaccesslist() unless necessary. - * Use -I for prompts and -q for diagnostics. - * - * Revision 5.5 1990/11/01 05:03:26 eggert - * Fix -j. Add -I. - * - * Revision 5.4 1990/10/04 06:30:11 eggert - * Accumulate exit status across files. - * - * Revision 5.3 1990/09/11 02:41:09 eggert - * co -kv yields a readonly working file. - * - * Revision 5.2 1990/09/04 08:02:13 eggert - * Standardize yes-or-no procedure. - * - * Revision 5.0 1990/08/22 08:10:02 eggert - * Permit multiple locks by same user. Add setuid support. - * Remove compile-time limits; use malloc instead. - * Permit dates past 1999/12/31. Switch to GMT. - * Make lock and temp files faster and safer. - * Ansify and Posixate. Add -k, -V. Remove snooping. Tune. - * - * Revision 4.7 89/05/01 15:11:41 narten - * changed copyright header to reflect current distribution rules - * - * Revision 4.6 88/08/09 19:12:15 eggert - * Fix "co -d" core dump; rawdate wasn't always initialized. - * Use execv(), not system(); fix putchar('\0') and diagnose() botches; remove lint - * - * Revision 4.5 87/12/18 11:35:40 narten - * lint cleanups (from Guy Harris) - * - * Revision 4.4 87/10/18 10:20:53 narten - * Updating version numbers changes relative to 1.1, are actually - * relative to 4.2 - * - * Revision 1.3 87/09/24 13:58:30 narten - * Sources now pass through lint (if you ignore printf/sprintf/fprintf - * warnings) - * - * Revision 1.2 87/03/27 14:21:38 jenkins - * Port to suns - * - * Revision 4.2 83/12/05 13:39:48 wft - * made rewriteflag external. - * - * Revision 4.1 83/05/10 16:52:55 wft - * Added option -u and -f. - * Added handling of default branch. - * Replaced getpwuid() with getcaller(). - * Removed calls to stat(); now done by pairfilenames(). - * Changed and renamed rmoldfile() to rmworkfile(). - * Replaced catchints() calls with restoreints(), unlink()--link() with rename(); - * - * Revision 3.7 83/02/15 15:27:07 wft - * Added call to fastcopy() to copy remainder of RCS file. - * - * Revision 3.6 83/01/15 14:37:50 wft - * Added ignoring of interrupts while RCS file is renamed; this avoids - * deletion of RCS files during the unlink/link window. - * - * Revision 3.5 82/12/08 21:40:11 wft - * changed processing of -d to use DATEFORM; removed actual from - * call to preparejoin; re-fixed printing of done at the end. - * - * Revision 3.4 82/12/04 18:40:00 wft - * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE. - * Fixed printing of "done". - * - * Revision 3.3 82/11/28 22:23:11 wft - * Replaced getlogin() with getpwuid(), flcose() with ffclose(), - * %02d with %.2d, mode generation for working file with WORKMODE. - * Fixed nil printing. Fixed -j combined with -l and -p, and exit - * for non-existing revisions in preparejoin(). - * - * Revision 3.2 82/10/18 20:47:21 wft - * Mode of working file is now maintained even for co -l, but write permission - * is removed. - * The working file inherits its mode from the RCS file, plus write permission - * for the owner. The write permission is not given if locking is strict and - * co does not lock. - * An existing working file without write permission is deleted automatically. - * Otherwise, co asks (empty answer: abort co). - * Call to getfullRCSname() added, check for write error added, call - * for getlogin() fixed. - * - * Revision 3.1 82/10/13 16:01:30 wft - * fixed type of variables receiving from getc() (char -> int). - * removed unused variables. - */ - - - - -#include "rcsbase.h" - -static char *addjoin P((char*)); -static char const *getancestor P((char const*,char const*)); -static int buildjoin P((char const*)); -static int preparejoin P((char*)); -static int rmlock P((struct hshentry const*)); -static int rmworkfile P((void)); -static void cleanup P((void)); - -static char const quietarg[] = "-q"; - -static char const *expandarg, *suffixarg, *versionarg, *zonearg; -static char const **joinlist; /* revisions to be joined */ -static int joinlength; -static FILE *neworkptr; -static int exitstatus; -static int forceflag; -static int lastjoin; /* index of last element in joinlist */ -static int lockflag; /* -1 -> unlock, 0 -> do nothing, 1 -> lock */ -static int mtimeflag; -static struct hshentries *gendeltas; /* deltas to be generated */ -static struct hshentry *targetdelta; /* final delta to be generated */ -static struct stat workstat; - -mainProg(coId, "co", "$FreeBSD$") -{ - static char const cmdusage[] = - "\nco usage: co -{fIlMpqru}[rev] -ddate -jjoins -ksubst -sstate -T -w[who] -Vn -xsuff -zzone file ..."; - - char *a, *joinflag, **newargv; - char const *author, *date, *rev, *state; - char const *joinname, *newdate, *neworkname; - int changelock; /* 1 if a lock has been changed, -1 if error */ - int expmode, r, tostdout, workstatstat; - int Ttimeflag; - struct buf numericrev; /* expanded revision number */ - char finaldate[datesize]; -# if OPEN_O_BINARY - int stdout_mode = 0; -# endif - - setrid(); - author = date = rev = state = 0; - joinflag = 0; - bufautobegin(&numericrev); - expmode = -1; - suffixes = X_DEFAULT; - tostdout = false; - Ttimeflag = false; - - argc = getRCSINIT(argc, argv, &newargv); - argv = newargv; - while (a = *++argv, 0<--argc && *a++=='-') { - switch (*a++) { - - case 'r': - revno: - if (*a) { - if (rev) warn("redefinition of revision number"); - rev = a; - } - break; - - case 'f': - forceflag=true; - goto revno; - - case 'l': - if (lockflag < 0) { - warn("-u overridden by -l."); - } - lockflag = 1; - goto revno; - - case 'u': - if (0 < lockflag) { - warn("-l overridden by -u."); - } - lockflag = -1; - goto revno; - - case 'p': - tostdout = true; - goto revno; - - case 'I': - interactiveflag = true; - goto revno; - - case 'q': - quietflag=true; - goto revno; - - case 'd': - if (date) - redefined('d'); - str2date(a, finaldate); - date=finaldate; - break; - - case 'j': - if (*a) { - if (joinflag) redefined('j'); - joinflag = a; - } - break; - - case 'M': - mtimeflag = true; - goto revno; - - case 's': - if (*a) { - if (state) redefined('s'); - state = a; - } - break; - - case 'T': - if (*a) - goto unknown; - Ttimeflag = true; - break; - - case 'w': - if (author) redefined('w'); - if (*a) - author = a; - else - author = getcaller(); - break; - - case 'x': - suffixarg = *argv; - suffixes = a; - break; - - case 'V': - versionarg = *argv; - setRCSversion(versionarg); - break; - - case 'z': - zonearg = *argv; - zone_set(a); - break; - - case 'k': /* set keyword expand mode */ - expandarg = *argv; - if (0 <= expmode) redefined('k'); - if (0 <= (expmode = str2expmode(a))) - break; - /* fall into */ - default: - unknown: - error("unknown option: %s%s", *argv, cmdusage); - - }; - } /* end of option processing */ - - /* Now handle all pathnames. */ - if (nerror) cleanup(); - else if (argc < 1) faterror("no input file%s", cmdusage); - else for (; 0 < argc; cleanup(), ++argv, --argc) { - ffree(); - - if (pairnames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0) - continue; - - /* - * RCSname contains the name of the RCS file, and finptr - * points at it. workname contains the name of the working file. - * Also, RCSstat has been set. - */ - diagnose("%s --> %s\n", RCSname, tostdout?"standard output":workname); - - workstatstat = -1; - if (tostdout) { -# if OPEN_O_BINARY - int newmode = Expand==BINARY_EXPAND ? OPEN_O_BINARY : 0; - if (stdout_mode != newmode) { - stdout_mode = newmode; - oflush(); - VOID setmode(STDOUT_FILENO, newmode); - } -# endif - neworkname = 0; - neworkptr = workstdout = stdout; - } else { - workstatstat = stat(workname, &workstat); - if (workstatstat == 0 && same_file(RCSstat, workstat, 0)) { - rcserror("RCS file is the same as working file %s.", - workname - ); - continue; - } - neworkname = makedirtemp(1); - if (!(neworkptr = fopenSafer(neworkname, FOPEN_W_WORK))) { - if (errno == EACCES) - workerror("permission denied on parent directory"); - else - eerror(neworkname); - continue; - } - } - - gettree(); /* reads in the delta tree */ - - if (!Head) { - /* no revisions; create empty file */ - diagnose("no revisions present; generating empty revision 0.0\n"); - if (lockflag) - warn( - "no revisions, so nothing can be %slocked", - lockflag < 0 ? "un" : "" - ); - Ozclose(&fcopy); - if (workstatstat == 0) - if (!rmworkfile()) continue; - changelock = 0; - newdate = 0; - } else { - int locks = lockflag ? findlock(false, &targetdelta) : 0; - if (rev) { - /* expand symbolic revision number */ - if (!expandsym(rev, &numericrev)) - continue; - } else { - switch (locks) { - default: - continue; - case 0: - bufscpy(&numericrev, Dbranch?Dbranch:""); - break; - case 1: - bufscpy(&numericrev, targetdelta->num); - break; - } - } - /* get numbers of deltas to be generated */ - if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas))) - continue; - /* check reservations */ - changelock = - lockflag < 0 ? - rmlock(targetdelta) - : lockflag == 0 ? - 0 - : - addlock(targetdelta, true); - - if ( - changelock < 0 - || (changelock && !checkaccesslist()) - || dorewrite(lockflag, changelock) != 0 - ) - continue; - - if (0 <= expmode) - Expand = expmode; - if (0 < lockflag && Expand == VAL_EXPAND) { - rcserror("cannot combine -kv and -l"); - continue; - } - - if (joinflag && !preparejoin(joinflag)) - continue; - - diagnose("revision %s%s\n",targetdelta->num, - 0<lockflag ? " (locked)" : - lockflag<0 ? " (unlocked)" : ""); - - /* Prepare to remove old working file if necessary. */ - if (workstatstat == 0) - if (!rmworkfile()) continue; - - /* skip description */ - getdesc(false); /* don't echo*/ - - locker_expansion = 0 < lockflag; - targetdelta->name = namedrev(rev, targetdelta); - joinname = buildrevision( - gendeltas, targetdelta, - joinflag&&tostdout ? (FILE*)0 : neworkptr, - Expand < MIN_UNEXPAND - ); -# if !large_memory - if (fcopy == neworkptr) - fcopy = 0; /* Don't close it twice. */ -# endif - if_advise_access(changelock && gendeltas->first!=targetdelta, - finptr, MADV_SEQUENTIAL - ); - - if (donerewrite(changelock, - Ttimeflag ? RCSstat.st_mtime : (time_t)-1 - ) != 0) - continue; - - if (changelock) { - locks += lockflag; - if (1 < locks) - rcswarn("You now have %d locks.", locks); - } - - newdate = targetdelta->date; - if (joinflag) { - newdate = 0; - if (!joinname) { - aflush(neworkptr); - joinname = neworkname; - } - if (Expand == BINARY_EXPAND) - workerror("merging binary files"); - if (!buildjoin(joinname)) - continue; - } - } - if (!tostdout) { - mode_t m = WORKMODE(RCSstat.st_mode, - ! (Expand==VAL_EXPAND || (lockflag<=0 && StrictLocks)) - ); - time_t t = mtimeflag&&newdate ? date2time(newdate) : (time_t)-1; - aflush(neworkptr); - ignoreints(); - r = chnamemod(&neworkptr, neworkname, workname, 1, m, t); - keepdirtemp(neworkname); - restoreints(); - if (r != 0) { - eerror(workname); - error("see %s", neworkname); - continue; - } - diagnose("done\n"); - } - } - - tempunlink(); - Ofclose(workstdout); - exitmain(exitstatus); - -} /* end of main (co) */ - - static void -cleanup() -{ - if (nerror) exitstatus = EXIT_FAILURE; - Izclose(&finptr); - ORCSclose(); -# if !large_memory - if (fcopy!=workstdout) Ozclose(&fcopy); -# endif - if (neworkptr!=workstdout) Ozclose(&neworkptr); - dirtempunlink(); -} - -#if RCS_lint -# define exiterr coExit -#endif - void -exiterr() -{ - ORCSerror(); - dirtempunlink(); - tempunlink(); - _exit(EXIT_FAILURE); -} - - -/***************************************************************** - * The following routines are auxiliary routines - *****************************************************************/ - - static int -rmworkfile() -/* - * Prepare to remove workname, if it exists, and if - * it is read-only. - * Otherwise (file writable): - * if !quietmode asks the user whether to really delete it (default: fail); - * otherwise failure. - * Returns true if permission is gotten. - */ -{ - if (workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH) && !forceflag) { - /* File is writable */ - if (!yesorno(false, "writable %s exists%s; remove it? [ny](n): ", - workname, - myself(workstat.st_uid) ? "" : ", and you do not own it" - )) { - error(!quietflag && ttystdin() - ? "checkout aborted" - : "writable %s exists; checkout aborted", workname); - return false; - } - } - /* Actual unlink is done later by caller. */ - return true; -} - - - static int -rmlock(delta) - struct hshentry const *delta; -/* Function: removes the lock held by caller on delta. - * Returns -1 if someone else holds the lock, - * 0 if there is no lock on delta, - * and 1 if a lock was found and removed. - */ -{ register struct rcslock * next, * trail; - char const *num; - struct rcslock dummy; - int whomatch, nummatch; - - num=delta->num; - dummy.nextlock=next=Locks; - trail = &dummy; - while (next) { - whomatch = strcmp(getcaller(), next->login); - nummatch=strcmp(num,next->delta->num); - if ((whomatch==0) && (nummatch==0)) break; - /*found a lock on delta by caller*/ - if ((whomatch!=0)&&(nummatch==0)) { - rcserror("revision %s locked by %s; use co -r or rcs -u", - num, next->login - ); - return -1; - } - trail=next; - next=next->nextlock; - } - if (next) { - /*found one; delete it */ - trail->nextlock=next->nextlock; - Locks=dummy.nextlock; - next->delta->lockedby = 0; - return 1; /*success*/ - } else return 0; /*no lock on delta*/ -} - - - - -/***************************************************************** - * The rest of the routines are for handling joins - *****************************************************************/ - - - static char * -addjoin(joinrev) - char *joinrev; -/* Add joinrev's number to joinlist, yielding address of char past joinrev, - * or 0 if no such revision exists. - */ -{ - register char *j; - register struct hshentry *d; - char terminator; - struct buf numrev; - struct hshentries *joindeltas; - - j = joinrev; - for (;;) { - switch (*j++) { - default: - continue; - case 0: - case ' ': case '\t': case '\n': - case ':': case ',': case ';': - break; - } - break; - } - terminator = *--j; - *j = 0; - bufautobegin(&numrev); - d = 0; - if (expandsym(joinrev, &numrev)) - d = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&joindeltas); - bufautoend(&numrev); - *j = terminator; - if (d) { - joinlist[++lastjoin] = d->num; - return j; - } - return 0; -} - - static int -preparejoin(j) - register char *j; -/* Parse join list J and place pointers to the - * revision numbers into joinlist. - */ -{ - lastjoin= -1; - for (;;) { - while ((*j==' ')||(*j=='\t')||(*j==',')) j++; - if (*j=='\0') break; - if (lastjoin>=joinlength-2) { - joinlist = - (joinlength *= 2) == 0 - ? tnalloc(char const *, joinlength = 16) - : trealloc(char const *, joinlist, joinlength); - } - if (!(j = addjoin(j))) return false; - while ((*j==' ') || (*j=='\t')) j++; - if (*j == ':') { - j++; - while((*j==' ') || (*j=='\t')) j++; - if (*j!='\0') { - if (!(j = addjoin(j))) return false; - } else { - rcsfaterror("join pair incomplete"); - } - } else { - if (lastjoin==0) { /* first pair */ - /* common ancestor missing */ - joinlist[1]=joinlist[0]; - lastjoin=1; - /*derive common ancestor*/ - if (!(joinlist[0] = getancestor(targetdelta->num,joinlist[1]))) - return false; - } else { - rcsfaterror("join pair incomplete"); - } - } - } - if (lastjoin < 1) - rcsfaterror("empty join"); - return true; -} - - - - static char const * -getancestor(r1, r2) - char const *r1, *r2; -/* Yield the common ancestor of r1 and r2 if successful, 0 otherwise. - * Work reliably only if r1 and r2 are not branch numbers. - */ -{ - static struct buf t1, t2; - - int l1, l2, l3; - char const *r; - - l1 = countnumflds(r1); - l2 = countnumflds(r2); - if ((2<l1 || 2<l2) && cmpnum(r1,r2)!=0) { - /* not on main trunk or identical */ - l3 = 0; - while (cmpnumfld(r1, r2, l3+1)==0 && cmpnumfld(r1, r2, l3+2)==0) - l3 += 2; - /* This will terminate since r1 and r2 are not the same; see above. */ - if (l3==0) { - /* no common prefix; common ancestor on main trunk */ - VOID partialno(&t1, r1, l1>2 ? 2 : l1); - VOID partialno(&t2, r2, l2>2 ? 2 : l2); - r = cmpnum(t1.string,t2.string)<0 ? t1.string : t2.string; - if (cmpnum(r,r1)!=0 && cmpnum(r,r2)!=0) - return r; - } else if (cmpnumfld(r1, r2, l3+1)!=0) - return partialno(&t1,r1,l3); - } - rcserror("common ancestor of %s and %s undefined", r1, r2); - return 0; -} - - - - static int -buildjoin(initialfile) - char const *initialfile; -/* Function: merge pairs of elements in joinlist into initialfile - * If workstdout is set, copy result to stdout. - * All unlinking of initialfile, rev2, and rev3 should be done by tempunlink(). - */ -{ - struct buf commarg; - struct buf subs; - char const *rev2, *rev3; - int i; - char const *cov[10], *mergev[11]; - char const **p; - - bufautobegin(&commarg); - bufautobegin(&subs); - rev2 = maketemp(0); - rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */ - - cov[1] = CO; - /* cov[2] setup below */ - p = &cov[3]; - if (expandarg) *p++ = expandarg; - if (suffixarg) *p++ = suffixarg; - if (versionarg) *p++ = versionarg; - if (zonearg) *p++ = zonearg; - *p++ = quietarg; - *p++ = RCSname; - *p = 0; - - mergev[1] = MERGE; - mergev[2] = mergev[4] = "-L"; - /* rest of mergev setup below */ - - i=0; - while (i<lastjoin) { - /*prepare marker for merge*/ - if (i==0) - bufscpy(&subs, targetdelta->num); - else { - bufscat(&subs, ","); - bufscat(&subs, joinlist[i-2]); - bufscat(&subs, ":"); - bufscat(&subs, joinlist[i-1]); - } - diagnose("revision %s\n",joinlist[i]); - bufscpy(&commarg, "-p"); - bufscat(&commarg, joinlist[i]); - cov[2] = commarg.string; - if (runv(-1, rev2, cov)) - goto badmerge; - diagnose("revision %s\n",joinlist[i+1]); - bufscpy(&commarg, "-p"); - bufscat(&commarg, joinlist[i+1]); - cov[2] = commarg.string; - if (runv(-1, rev3, cov)) - goto badmerge; - diagnose("merging...\n"); - mergev[3] = subs.string; - mergev[5] = joinlist[i+1]; - p = &mergev[6]; - if (quietflag) *p++ = quietarg; - if (lastjoin<=i+2 && workstdout) *p++ = "-p"; - *p++ = initialfile; - *p++ = rev2; - *p++ = rev3; - *p = 0; - switch (runv(-1, (char*)0, mergev)) { - case DIFF_FAILURE: case DIFF_SUCCESS: - break; - default: - goto badmerge; - } - i=i+2; - } - bufautoend(&commarg); - bufautoend(&subs); - return true; - - badmerge: - nerror++; - bufautoend(&commarg); - bufautoend(&subs); - return false; -} |