RCS 5.6.7.4

This commit is contained in:
mycroft 1995-02-24 02:07:40 +00:00
parent 09a91fa841
commit 03692cae32
12 changed files with 1603 additions and 1007 deletions

View File

@ -1,6 +1,6 @@
# $Id: Makefile,v 1.3 1994/03/28 12:32:25 cgd Exp $
# $Id: Makefile,v 1.4 1995/02/24 02:07:40 mycroft Exp $
SUBDIR+= lib
SUBDIR+= ci co ident merge rcs rcsclean rcsdiff rcsfreeze rcsmerge rlog
SUBDIR+=lib
SUBDIR+=ci co ident merge rcs rcsclean rcsdiff rcsfreeze rcsmerge rlog
.include <bsd.subdir.mk>

View File

@ -2,8 +2,10 @@
.ds Rv \\$3
.ds Dt \\$4
..
.Id $Id: ci.1,v 1.2 1993/07/24 02:50:11 jtc Exp $
.Id $Id: ci.1,v 1.3 1995/02/24 02:07:44 mycroft Exp $
.ds i \&\s-1ISO\s0
.ds r \&\s-1RCS\s0
.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH CI 1 \*(Dt GNU
@ -41,7 +43,7 @@ new branch can be created. This restriction is not enforced
for the owner of the file if non-strict locking is used
(see
.BR rcs (1)).
A lock held by someone else may be broken with the
A lock held by someone else can be broken with the
.B rcs
command.
.PP
@ -105,7 +107,9 @@ The number
.I rev
of the deposited revision can be given by any of the options
.BR \-f ,
.BR \-i ,
.BR \-I ,
.BR \-j ,
.BR \-k ,
.BR \-l ,
.BR \-M ,
@ -114,7 +118,15 @@ of the deposited revision can be given by any of the options
or
.BR \-u .
.I rev
may be symbolic, numeric, or mixed.
can be symbolic, numeric, or mixed.
Symbolic names in
.I rev
must already be defined;
see the
.B \-n
and
.B \-N
options for assigning names during checkin.
If
.I rev
is
@ -124,6 +136,15 @@ determines the revision number from keyword values in the working file.
.PP
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.
.PP
If
.I rev
is a revision number, it must be higher than the latest
one on the branch to which
.I rev
@ -172,25 +193,28 @@ Exception: On the trunk, revisions can be appended to the end, but
not inserted.
.SH OPTIONS
.TP
.BR \-r [\f2rev\fP]
checks in a revision, releases the corresponding lock, and
removes the working file. This is the default.
.RS
.PP
The
.BI \-r rev
Check in revision
.IR rev .
.TP
.BR \-r
The bare
.B \-r
option has an unusual meaning in
option (without any revision) has an unusual meaning in
.BR ci .
In other \*r commands,
With other \*r commands, a bare
.B \-r
merely specifies a revision number,
but in
.B ci
it also releases a lock and removes the working file.
See
option specifies the most recent revision on the default branch,
but with
.BR ci ,
a bare
.B \-r
option reestablishes the default behavior of releasing a lock and
removing the working file, and is used to override any default
.B \-l
or
.B \-u
for a tricky example.
.RE
options established by shell aliases or scripts.
.TP
.BR \-l [\f2rev\fP]
works like
@ -213,6 +237,7 @@ immediately after checkin.
.PP
The
.BR \-l ,
bare
.BR \-r ,
and
.B \-u
@ -221,7 +246,7 @@ For example,
.B "ci\ \-u\ \-r"
is equivalent to
.B "ci\ \-r"
because
because bare
.B \-r
overrides
.BR \-u .
@ -244,7 +269,7 @@ several sites should be checked in with the
.B \-k
option at these sites to
preserve the original number, date, author, and state.
The extracted keyword values and the default log message may be overridden
The extracted keyword values and the default log message can be overridden
with the options
.BR \-d ,
.BR \-m ,
@ -259,6 +284,14 @@ unless
.B \-f
is given.
.TP
.BR \-i [\f2rev\fP]
initial checkin; report an error if the \*r file already exists.
This avoids race conditions in certain applications.
.TP
.BR \-j [\f2rev\fP]
just checkin and do not initialize;
report an error if the \*r file does not already exist.
.TP
.BR \-I [\f2rev\fP]
interactive mode;
the user is prompted and questioned
@ -296,6 +329,18 @@ Use this option with care; it can confuse
uses the string
.I msg
as the log message for all revisions checked in.
By convention, log messages that start with
.B #
are comments and are ignored by programs like GNU Emacs's
.B vc
package.
Also, log messages that start with
.BI { clumpname }
(followed by white space) are meant to be clumped together if possible,
even if they are associated with different files; the
.BI { clumpname }
label is used only for clumping,
and is not considered to be part of the log message itself.
.TP
.BI \-n "name"
assigns the symbolic name
@ -326,7 +371,7 @@ into the \*r file,
deleting the existing text.
The
.I file
may not begin with
cannot begin with
.BR \- .
.TP
.BI \-t\- string
@ -356,6 +401,41 @@ For backward compatibility with older versions of \*r, a bare
option is ignored.
.RE
.TP
.B \-T
Set the \*r file's modification time to the new revision's time
if the former precedes the latter and there is a new revision;
preserve the \*r file's modification time otherwise.
If you have locked a revision,
.B ci
usually updates the \*r file's modification time to the current time,
because the lock is stored in the \*r file
and removing the lock requires changing the \*r file.
This can create an \*r file newer than the working file in one of two ways:
first,
.B "ci\ \-M"
can create a working file with a date before the current time;
second, when reverting to the previous revision
the \*r file can change while the working file remains unchanged.
These two cases can cause excessive recompilation caused by a
.BR make (1)
dependency of the working file on the \*r file.
The
.B \-T
option inhibits this recompilation by lying about the \*r file's date.
Use this option with care; it can suppress recompilation even when
a checkin of one working file should affect
another working file associated with the same \*r file.
For example, suppose the \*r file's time is 01:00,
the (changed) working file's time is 02:00,
some other copy of the working file has a time of 03:00,
and the current time is 04:00.
Then
.B "ci\ \-d\ \-T"
sets the \*r file's time to 02:00 instead of the usual 04:00;
this causes
.BR make (1)
to think (incorrectly) that the other copy is newer than the \*r file.
.TP
.BI \-w "login"
uses
.I login
@ -364,6 +444,9 @@ Useful for lying about the author, and for
.B \-k
if no author is available.
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.IR n .
@ -375,9 +458,9 @@ for details.
specifies the suffixes for \*r files.
A nonempty suffix matches any pathname ending in the suffix.
An empty suffix matches any pathname of the form
.BI RCS/ file
.BI RCS/ path
or
.IB path /RCS/ file.
.IB path1 /RCS/ path2.
The
.B \-x
option can specify a list of suffixes
@ -398,10 +481,44 @@ The default for
.IR suffixes
is installation-dependent; normally it is
.B ,v/
for hosts like Unix that permit commas in file names,
for hosts like Unix that permit commas in filenames,
and is empty (i.e. just the empty suffix) for other hosts.
.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
.B "1990/01/11 04:00:00"
with
.BR \-z ,
as
.B "1990-01-11 20:00:00\-0800"
with
.BR \-zLT ,
and as
.B "1990-01-11 09:30:00+0530"
with
.BR \-z+0530 .
This option does not affect dates in \*r file themselves,
which are always \*u.
.SH "FILE NAMING"
Pairs of \*r files and working files may be specified in three ways
Pairs of \*r files and working files can be specified in three ways
(see also the
example section).
.PP
@ -423,9 +540,9 @@ If
.I X
is empty,
.IB path1 /
must be
must start with
.B RCS/
or must end in
or must contain
.BR /RCS/ .
.PP
2) Only the \*r file is given. Then the working file is created in the current
@ -516,7 +633,7 @@ preserves its read and execute permissions.
.B ci
always turns off all write permissions of \*r files.
.SH FILES
Several temporary files may be created in the directory containing
Temporary files are created in the directory containing
the working file, and also in the temporary directory (see
.B \s-1TMPDIR\s0
under
@ -576,21 +693,23 @@ who can check in new revisions but cannot otherwise change the \*r files.
.SH "SETUID USE"
To prevent anybody but their \*r administrator from deleting revisions,
a set of users can employ setuid privileges as follows.
.nr n \w'\(bu '+1n-1/1n
.IP \(bu \nn
.nr n \w'\(bu'+2n-1/1n
.ds n \nn
.if \n(.g .if r an-tag-sep .ds n \w'\(bu'u+\n[an-tag-sep]u
.IP \(bu \*n
Check that the host supports \*r setuid use.
Consult a trustworthy expert if there are any doubts.
It is best if the
.B seteuid()
.B seteuid
system call works as described in Posix 1003.1a Draft 5,
because \*r can switch back and forth easily
between real and effective users, even if the real user is
.BR root .
If not, the second best is if the
.B setuid()
.B setuid
system call supports saved setuid
(the {\s-1_POSIX_SAVED_IDS\s0} behavior of Posix 1003.1-1990);
this fails only if the real user is
this fails only if the real or effective user is
.BR root .
If \*r detects any failure in setuid, it quits immediately.
.IP \(bu \nn
@ -599,7 +718,7 @@ Choose a user
to serve as \*r administrator for the set of users.
Only
.I A
will be able to invoke the
can invoke the
.B rcs
command on the users' \*r files.
.I A
@ -608,9 +727,9 @@ should not be
or any other user with special powers.
Mutually suspicious sets of users should use different administrators.
.IP \(bu \nn
Choose a path name
Choose a pathname
.I B
that will be a directory of files to be executed by the users.
to be a directory of files to be executed by the users.
.IP \(bu \nn
Have
.I A
@ -733,8 +852,9 @@ Useful
options include
.BR \-q ,
.BR \-V ,
.BR \-x ,
and
.BR \-x .
.BR \-z .
.TP
.B \s-1TMPDIR\s0
Name of the temporary directory.
@ -755,14 +875,16 @@ The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Revision Number: \*(Rv; Release Date: \*(Dt.
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991 by Paul Eggert.
Copyright \(co 1990, 1991, 1992, 1993, 1994 Paul Eggert.
.SH "SEE ALSO"
co(1), ident(1), make(1), rcs(1), rcsclean(1), rcsdiff(1),
rcsintro(1), rcsmerge(1), rlog(1), rcsfile(5)
co(1),
emacs(1),
ident(1), make(1), rcs(1), rcsclean(1), rcsdiff(1),
rcsintro(1), rcsmerge(1), rlog(1), setuid(2), rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,10 @@
.ds Rv \\$3
.ds Dt \\$4
..
.Id $Id: co.1,v 1.2 1993/07/24 02:51:10 jtc Exp $
.ds g \&\s-1UTC\s0
.Id $Id: co.1,v 1.3 1995/02/24 02:07:48 mycroft Exp $
.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
@ -23,12 +24,12 @@ all others denote working files.
Names are paired as explained in
.BR ci (1).
.PP
Revisions of an \*r file may be checked out locked or unlocked. Locking a
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 may be broken with
(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
@ -51,7 +52,7 @@ on the default branch (normally the trunk, see the
.B \-b
option of
.BR rcs (1)).
A revision or branch number may be attached
A revision or branch number can be attached
to any of the options
.BR \-f ,
.BR \-I ,
@ -88,7 +89,7 @@ always performs keyword substitution (see below).
.TP
.BR \-r [\f2rev\fP]
retrieves the latest revision whose number is less than or equal to
.I rev.
.IR rev .
If
.I rev
indicates a branch rather than a revision,
@ -108,7 +109,16 @@ is
.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. The numeric equivalent of a symbolic field
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
@ -176,9 +186,15 @@ For example, for the
keyword, generate the string
.B $\&Revision$
instead of
.BR "$\&Revision: \*(Rv $".
.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
.BR \-ko
Generate the old keyword string,
@ -201,7 +217,7 @@ For example, for the
keyword, generate the string
.B \*(Rv
instead of
.BR "$\&Revision: \*(Rv $".
.BR "$\&Revision: \*(Rv $" .
This can help generate files in programming languages where it is hard to
strip keyword delimiters like
.B "$\&Revision:\ $"
@ -233,8 +249,8 @@ even if the standard input is not a terminal.
.BI \-d date
retrieves the latest revision on the selected branch whose checkin date/time is
less than or equal to
.I date.
The date and time may be given in free format.
.IR date .
The date and time can be given in free format.
The time zone
.B LT
stands for local time;
@ -243,38 +259,43 @@ 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 (\*g):
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 9
.ne 10
\f38:00 pm lt\fP
\f34:00 AM, Jan. 12, 1990\fP note: default is \*g
\f31990/01/12 04:00:00\fP \*r date format
\f34:00 AM, Jan. 12, 1990\fP default is \*u
\f31990-01-12 04:00:00+0000\fP \*i 8601 (\*u)
\f31990-01-11 20:00:00\-0800\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
\f3Fri-JST, 1990, 1pm Jan 12\fP
\f312-January-1990, 04:00-WET\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 may be defaulted.
The default time zone is \*g.
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, the date
For example, without
.BR \-z ,
the date
.B "20, 10:30"
defaults to
10:30:00 \*g of the 20th of the \*g time zone's current month and year.
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
@ -286,12 +307,22 @@ Use this option with care; it can confuse
.TP
.BI \-s state
retrieves the latest revision on the selected branch whose state is set to
.I state.
.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
.I login.
.IR login .
If the argument
.I login
is
@ -299,7 +330,7 @@ omitted, the caller's login is assumed.
.TP
.BI \-j joinlist
generates a new revision which is the join of the revisions on
.I joinlist.
.IR joinlist .
This option is largely obsoleted by
.BR rcsmerge (1)
but is retained for backwards compatibility.
@ -335,13 +366,13 @@ joins revisions
and
.I rev3
with respect to
.I rev2.
.IR rev2 .
This means that all changes that transform
.I rev2
into
.I rev1
are applied to a copy of
.I rev3.
.IR rev3 .
This is particularly useful if
.I rev1
and
@ -372,7 +403,7 @@ reports overlaps as described in
.PP
For the initial pair,
.I rev2
may be omitted. The default is the common
can be omitted. The default is the common
ancestor.
If any of the arguments indicate branches, the latest revisions
on those branches are assumed.
@ -381,22 +412,28 @@ The options
and
.B \-u
lock or unlock
.I rev1.
.IR rev1 .
.RE
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.I n,
where
.I n
may be
can be
.BR 3 ,
.BR 4 ,
or
.BR 5 .
This may be useful when interchanging \*r files with others who are
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
@ -404,15 +441,14 @@ if none of the first few lines of output contain the string
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 will lose its default branch.
An \*r revision generated while emulating version 4 or earlier will have
a timestamp that is off by up to 13 hours.
A revision extracted while emulating version 4 or earlier will contain
dates of the form
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
instead of
.IB yyyy / mm / dd
and may also contain different white space in the substitution for
and can also contain different white space and line prefixes
in the substitution for
.BR $\&Log$ .
.TP
.BI \-x "suffixes"
@ -422,6 +458,46 @@ 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+0530\fP 'u +\w'\f31990-01-11 09:30:00+0530\fP 'u
.ne 4
\f2option\fP \f2time output\fP
\f3\-z\fP \f31990/01/11 04:00:00\fP \f2(default)\fP
\f3\-zLT\fP \f31990-01-11 20:00:00\-0800\fP
\f3\-z+0530\fP \f31990-01-11 09:30:00+0530\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 $
@ -436,7 +512,7 @@ where
and
.I value
are pairs listed below.
Keywords may be embedded in literal strings
Keywords can be embedded in literal strings
or comments to identify a revision.
.PP
Initially, the user enters strings of the form
@ -459,12 +535,18 @@ Keywords and their corresponding values:
The login name of the user who checked in the revision.
.TP
.B $\&Date$
The date and time (\*g) the revision was checked in.
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 (\*g), the author, the state,
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
@ -477,7 +559,10 @@ The login name of the user who locked the revision (empty if not locked).
.B $\&Log$
The log message supplied during checkin, preceded by a header
containing the \*r filename, the revision number, the author, and the date
(\*g).
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.
@ -485,6 +570,26 @@ Instead, the new log message is inserted after
.BR $\&Log: .\|.\|. $ .
This is useful for
accumulating a complete change log in a source file.
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 programming languages without multi-line comments.
.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.
@ -502,6 +607,22 @@ 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
@ -523,7 +644,10 @@ is given, the working file is deleted without asking.
.B co
accesses files much as
.BR ci (1)
does, except that it does not need to read the working file.
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
@ -539,14 +663,14 @@ The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Revision Number: \*(Rv; Release Date: \*(Dt.
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991 by Paul Eggert.
Copyright \(co 1990, 1991, 1992, 1993, 1994 Paul Eggert.
.SH "SEE ALSO"
ci(1), ctime(3), date(1), ident(1), make(1),
rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
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,
@ -562,8 +686,4 @@ by writing them differently. In nroff and troff, this is done by embedding the
null-character
.B \e&
into the keyword.
.SH BUGS
The
.B \-d
option sometimes gets confused, and accepts no date before 1970.
.br

View File

@ -1,5 +1,7 @@
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991 by Paul Eggert
/* Check out working files from revisions of RCS files. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@ -25,20 +27,36 @@ Report problems and direct all questions to:
*/
/*
* RCS checkout operation
*/
/*****************************************************************************
* check out revisions from RCS files
*****************************************************************************
*/
/* co.c,v
* Revision 1.1.1.1 1993/06/18 04:22:11 jkh
* Updated GNU utilities
* $Log: co.c,v $
* Revision 1.3 1995/02/24 02:07:49 mycroft
* RCS 5.6.7.4
*
* 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
* ci -u src/RCS/co.c,v src/co.c <<\.
* -k affects just working file, not RCS file.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
@ -146,6 +164,7 @@ Report problems and direct all questions to:
#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((void));
@ -155,8 +174,10 @@ static void cleanup P((void));
static char const quietarg[] = "-q";
static char const *expandarg, *join, *suffixarg, *versionarg;
static char const *joinlist[joinlength]; /* revisions to be joined */
static char *join;
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;
@ -167,25 +188,27 @@ static struct hshentries *gendeltas; /* deltas to be generated */
static struct hshentry *targetdelta; /* final delta to be generated */
static struct stat workstat;
mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
mainProg(coId, "co", "$Id: co.c,v 1.3 1995/02/24 02:07:49 mycroft Exp $")
{
static char const cmdusage[] =
"\nco usage: co -{flpqru}[rev] -ddate -jjoinlist -sstate -w[login] -Vn file ...";
"\nco usage: co -{fIlMpqru}[rev] -ddate -jjoins -ksubst -sstate -T -w[who] -Vn -xsuff -zzone file ...";
char *a, **newargv;
char const *author, *date, *rev, *state;
char const *joinfilename, *newdate, *neworkfilename;
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];
setrid();
author = date = rev = state = nil;
author = date = rev = state = 0;
bufautobegin(&numericrev);
expmode = -1;
suffixes = X_DEFAULT;
tostdout = false;
Ttimeflag = false;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
@ -206,14 +229,14 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
case 'l':
if (lockflag < 0) {
warn("-l overrides -u.");
warn("-u overridden by -l.");
}
lockflag = 1;
goto revno;
case 'u':
if (0 < lockflag) {
warn("-l overrides -u.");
warn("-l overridden by -u.");
}
lockflag = -1;
goto revno;
@ -255,6 +278,12 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
}
break;
case 'T':
if (*a)
goto unknown;
Ttimeflag = true;
break;
case 'w':
if (author) redefined('w');
if (*a)
@ -273,6 +302,11 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
setRCSversion(versionarg);
break;
case 'z':
zonearg = *argv;
zone_set(a);
break;
case 'k': /* set keyword expand mode */
expandarg = *argv;
if (0 <= expmode) redefined('k');
@ -280,69 +314,81 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
break;
/* fall into */
default:
faterror("unknown option: %s%s", *argv, cmdusage);
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
if (argc<1) faterror("no input file%s", cmdusage);
if (tostdout)
# if text_equals_binary_stdio || text_work_stdio
workstdout = stdout;
# else
if (!(workstdout = fdopen(STDOUT_FILENO, FOPEN_W_WORK)))
efaterror("stdout");
efaterror("standard output");
# endif
/* now handle all filenames */
do {
/* 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 (pairfilenames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
if (pairnames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
continue;
/* now RCSfilename contains the name of the RCS file, and finptr
* points at it. workfilename contains the name of the working file.
/*
* 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", RCSfilename,tostdout?"stdout":workfilename);
diagnose("%s --> %s\n", RCSname, tostdout?"standard output":workname);
workstatstat = -1;
if (tostdout) {
neworkfilename = 0;
neworkname = 0;
neworkptr = workstdout;
} else {
workstatstat = stat(workfilename, &workstat);
neworkfilename = makedirtemp(workfilename, 1);
if (!(neworkptr = fopen(neworkfilename, FOPEN_W_WORK))) {
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 = fopen(neworkname, FOPEN_W_WORK))) {
if (errno == EACCES)
error("%s: parent directory isn't writable",
workfilename
);
workerror("permission denied on parent directory");
else
eerror(neworkfilename);
eerror(neworkname);
continue;
}
}
gettree(); /* reads in the delta tree */
if (Head==nil) {
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;
/* Can't reserve a delta, so don't call addlock */
} else {
if (rev!=nil) {
int locks = lockflag ? findlock(false, &targetdelta) : 0;
if (rev) {
/* expand symbolic revision number */
if (!expandsym(rev, &numericrev))
continue;
} else
switch (lockflag<0 ? findlock(false,&targetdelta) : 0) {
} else {
switch (locks) {
default:
continue;
case 0:
@ -352,6 +398,7 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
bufscpy(&numericrev, targetdelta->num);
break;
}
}
/* get numbers of deltas to be generated */
if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas)))
continue;
@ -362,19 +409,19 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
: lockflag == 0 ?
0
:
addlock(targetdelta);
addlock(targetdelta, true);
if (
changelock < 0 ||
changelock && !checkaccesslist() ||
!dorewrite(lockflag, changelock)
changelock < 0
|| (changelock && !checkaccesslist())
|| dorewrite(lockflag, changelock) != 0
)
continue;
if (0 <= expmode)
Expand = expmode;
if (0 < lockflag && Expand == VAL_EXPAND) {
error("cannot combine -kv and -l");
rcserror("cannot combine -kv and -l");
continue;
}
@ -392,7 +439,8 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
getdesc(false); /* don't echo*/
locker_expansion = 0 < lockflag;
joinfilename = buildrevision(
targetdelta->name = namedrev(rev, targetdelta);
joinname = buildrevision(
gendeltas, targetdelta,
join&&tostdout ? (FILE*)0 : neworkptr,
Expand!=OLD_EXPAND
@ -405,46 +453,46 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1993/08/02 17:47:00 mycroft Exp $")
finptr, MADV_SEQUENTIAL
);
if (!donerewrite(changelock))
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 (join) {
newdate = 0;
if (!joinfilename) {
if (!joinname) {
aflush(neworkptr);
joinfilename = neworkfilename;
joinname = neworkname;
}
if (!buildjoin(joinfilename))
if (!buildjoin(joinname))
continue;
}
}
if (!tostdout) {
r = 0;
if (mtimeflag && newdate) {
if (!join)
aflush(neworkptr);
r = setfiledate(neworkfilename, newdate);
}
if (r == 0) {
ignoreints();
r = chnamemod(&neworkptr, neworkfilename, workfilename,
WORKMODE(RCSstat.st_mode,
!(Expand==VAL_EXPAND || lockflag<=0&&StrictLocks)
)
);
keepdirtemp(neworkfilename);
restoreints();
}
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(workfilename);
error("see %s", neworkfilename);
eerror(workname);
error("see %s", neworkname);
continue;
}
diagnose("done\n");
}
} while (cleanup(),
++argv, --argc >=1);
}
tempunlink();
Ofclose(workstdout);
@ -457,7 +505,7 @@ cleanup()
{
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
Ozclose(&frewrite);
ORCSclose();
# if !large_memory
if (fcopy!=workstdout) Ozclose(&fcopy);
# endif
@ -465,12 +513,13 @@ cleanup()
dirtempunlink();
}
#if lint
#if RCS_lint
# define exiterr coExit
#endif
exiting void
void
exiterr()
{
ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
@ -483,7 +532,8 @@ exiterr()
static int
rmworkfile()
/* Function: prepares to remove workfilename, if it exists, and if
/*
* 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);
@ -494,12 +544,12 @@ rmworkfile()
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): ",
workfilename,
workname,
myself(workstat.st_uid) ? "" : ", and you do not own it"
)) {
error(!quietflag && ttystdin()
? "checkout aborted"
: "writable %s exists; checkout aborted", workfilename);
: "writable %s exists; checkout aborted", workname);
return false;
}
}
@ -524,23 +574,25 @@ rmlock(delta)
num=delta->num;
dummy.nextlock=next=Locks;
trail = &dummy;
while (next!=nil) {
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)) {
error("revision %s locked by %s; use co -r or rcs -u",num,next->login);
rcserror("revision %s locked by %s; use co -r or rcs -u",
num, next->login
);
return -1;
}
trail=next;
next=next->nextlock;
}
if (next!=nil) {
if (next) {
/*found one; delete it */
trail->nextlock=next->nextlock;
Locks=dummy.nextlock;
next->delta->lockedby=nil; /* reset locked-by */
next->delta->lockedby = 0;
return 1; /*success*/
} else return 0; /*no lock on delta*/
}
@ -553,15 +605,15 @@ rmlock(delta)
*****************************************************************/
static char const *
static char *
addjoin(joinrev)
char *joinrev;
/* Add joinrev's number to joinlist, yielding address of char past joinrev,
* or nil if no such revision exists.
* or 0 if no such revision exists.
*/
{
register char *j;
register struct hshentry const *d;
register struct hshentry *d;
char terminator;
struct buf numrev;
struct hshentries *joindeltas;
@ -583,14 +635,14 @@ addjoin(joinrev)
bufautobegin(&numrev);
d = 0;
if (expandsym(joinrev, &numrev))
d = genrevs(numrev.string,(char*)nil,(char*)nil,(char*)nil,&joindeltas);
d = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&joindeltas);
bufautoend(&numrev);
*j = terminator;
if (d) {
joinlist[++lastjoin] = d->num;
return j;
}
return nil;
return 0;
}
static int
@ -599,7 +651,7 @@ preparejoin()
* revision numbers into joinlist.
*/
{
register char const *j;
register char *j;
j=join;
lastjoin= -1;
@ -607,8 +659,10 @@ preparejoin()
while ((*j==' ')||(*j=='\t')||(*j==',')) j++;
if (*j=='\0') break;
if (lastjoin>=joinlength-2) {
error("too many joins");
return(false);
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++;
@ -618,8 +672,7 @@ preparejoin()
if (*j!='\0') {
if (!(j = addjoin(j))) return false;
} else {
error("join pair incomplete");
return false;
rcsfaterror("join pair incomplete");
}
} else {
if (lastjoin==0) { /* first pair */
@ -630,15 +683,13 @@ preparejoin()
if (!(joinlist[0] = getancestor(targetdelta->num,joinlist[1])))
return false;
} else {
error("join pair incomplete");
return false;
rcsfaterror("join pair incomplete");
}
}
}
if (lastjoin<1) {
error("empty join");
return false;
} else return true;
if (lastjoin < 1)
rcsfaterror("empty join");
return true;
}
@ -646,13 +697,13 @@ preparejoin()
static char const *
getancestor(r1, r2)
char const *r1, *r2;
/* Yield the common ancestor of r1 and r2 if successful, nil otherwise.
/* 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;
unsigned l1, l2, l3;
int l1, l2, l3;
char const *r;
l1 = countnumflds(r1);
@ -665,16 +716,16 @@ getancestor(r1, r2)
/* 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 ? (unsigned)2 : l1);
VOID partialno(&t2, r2, l2>2 ? (unsigned)2 : l2);
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);
}
error("common ancestor of %s and %s undefined", r1, r2);
return nil;
rcserror("common ancestor of %s and %s undefined", r1, r2);
return 0;
}
@ -691,7 +742,7 @@ buildjoin(initialfile)
struct buf subs;
char const *rev2, *rev3;
int i;
char const *cov[10], *mergev[12];
char const *cov[10], *mergev[11];
char const **p;
bufautobegin(&commarg);
@ -699,22 +750,19 @@ buildjoin(initialfile)
rev2 = maketemp(0);
rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */
cov[0] = nil;
/* cov[1] setup below */
cov[2] = CO;
/* cov[3] setup below */
p = &cov[4];
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++ = RCSfilename;
*p = nil;
*p++ = RCSname;
*p = 0;
mergev[0] = nil;
mergev[1] = nil;
mergev[2] = MERGE;
mergev[3] = mergev[5] = "-L";
mergev[1] = MERGE;
mergev[2] = mergev[4] = "-L";
/* rest of mergev setup below */
i=0;
@ -731,28 +779,26 @@ buildjoin(initialfile)
diagnose("revision %s\n",joinlist[i]);
bufscpy(&commarg, "-p");
bufscat(&commarg, joinlist[i]);
cov[1] = rev2;
cov[3] = commarg.string;
if (runv(cov))
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[1] = rev3;
cov[3] = commarg.string;
if (runv(cov))
cov[2] = commarg.string;
if (runv(-1, rev3, cov))
goto badmerge;
diagnose("merging...\n");
mergev[4] = subs.string;
mergev[6] = joinlist[i+1];
p = &mergev[7];
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 = nil;
switch (runv(mergev)) {
*p = 0;
switch (runv(-1, (char*)0, mergev)) {
case DIFF_FAILURE: case DIFF_SUCCESS:
break;
default:

View File

@ -3,15 +3,6 @@
.\"
.\" \*s stands for $, and avoids problems when this file is checked in.
.ds s $
.\" PS and PE center pic diagrams. (The corresponding ms-macros may not.)
.de PS
.nr pE (\\n(.lu-\\$2u)/2u
.in +\\n(pEu
.ne \\$1u
..
.de PE
.in -\\n(pEu
..
.de D(
.DS
.nr VS 12p
@ -27,7 +18,7 @@
.de Id
.ND \\$4
..
.Id rcs.ms,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp
.Id $Id: rcs.ms,v 1.2 1995/02/24 02:07:52 mycroft Exp $
.RP
.TL
RCS\*-A System for Version Control
@ -421,7 +412,7 @@ between 1.3 and 1.3.1.1
into a revision at level 2. The operation \fIrcsmerge\fR automates this
process (see the Appendix).
.ne 7
.PS 4i
.PS 4i
.ps -2
box "1.1"
arrow
@ -460,7 +451,7 @@ that the customer has received revision 1.3, added his local modifications
as revision 1.3.1.1, then received revision 2.4, and merged
2.4 and 1.3.1.1, resulting in 2.4.1.1.
.ne 7
.PS 4i
.PS 4i
.ps -2
R13: box "1.3"
line invis
@ -561,7 +552,7 @@ branch revision is reached. Figure 5 illustrates a tree with
one side branch. Triangles pointing to the left and right represent
reverse and forward deltas, respectively.
.ne 8
.PS 4i
.PS 4i
.ps -2
define BD X [line invis $1 right .5;
line up .3 then left .5 down .3 then right .5 down .3 then up .3] X
@ -570,21 +561,21 @@ define FD X [line invis $1 right .5;
line left .5 down .3 then up .6 then right .5 down .3;] X
right
D11: BD(" 1.1")
D11: BD(" 1.1")
arrow right from D11.e
D12: BD(" 1.2")
arrow right from D12.e
D13: BD(" 1.3")
arrow right from D13.e
D21: BD(" 2.1")
arrow right from D21.e
D22: box "2.2"
D12: BD(" 1.2")
arrow right from D12.e
D13: BD(" 1.3")
arrow right from D13.e
D21: BD(" 2.1")
arrow right from D21.e
D22: box "2.2"
line invis down from D21.s
F1: FD("1.3.1.1 ")
F1: FD("1.3.1.1 ")
arrow from D13.se to F1.w
arrow from F1.e right
right
F2: FD("1.3.1.2 ")
F2: FD("1.3.1.2 ")
.ps +2
.PE
.ce 1
@ -1291,9 +1282,10 @@ locks, unlocks, breaks locks, toggles the strict-locking feature,
sets state attributes and symbolic revision numbers, changes the
description, and deletes revisions. A revision can
only be deleted if it is not the fork of a side branch.
.br
.ne 10
.IP "\fIrcsclean\fP \fB\- clean working directory\fP"
.sp 0
.ne 10
\fIRcsclean\fR removes working files that were checked out but never changed.*
.FS *
The \fIrcsclean\fP and \fIrcsfreeze\fP commands

View File

@ -3,25 +3,28 @@
.ds Dt \\$4
.ds iD \\$3 \\$4 \\$5 \\$6 \\$7
..
.Id $Id: ident.1,v 1.2 1993/07/24 02:51:17 jtc Exp $
.ds r \s-1RCS\s0
.Id $Id: ident.1,v 1.3 1995/02/24 02:07:54 mycroft Exp $
.ds r \&\s-1RCS\s0
.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH IDENT 1 \*(Dt GNU
.SH NAME
ident \- identify files
ident \- identify RCS keyword strings in files
.SH SYNOPSIS
.B ident
[
.B \-q
] [
.B \-V
] [
.I file
\&.\|.\|. ]
.SH DESCRIPTION
.B ident
searches for all occurrences of the pattern
.BI $ keyword : .\|.\|. $
in the named files or, if no file name appears, the standard input.
searches for all instances of the pattern
.BI $ keyword : "\ text\ " $
in the named files or, if no files are named, the standard input.
.PP
These patterns are normally inserted automatically by the \*r command
.BR co (1),
@ -30,6 +33,11 @@ The option
.B \-q
suppresses
the warning given if there are no patterns in a file.
The option
.B \-V
prints
.BR ident 's
version number.
.PP
.B ident
works on text files as well as object files and dumps.
@ -37,7 +45,15 @@ For example, if the C program in
.B f.c
contains
.IP
\f3char rcsid[] = \&"$\&Id: f.c,v \*(iD $\&";\fP
.ft 3
#include <stdio.h>
.br
static char const rcsid[] =
.br
\&"$\&Id: f.c,v \*(iD $\&";
.br
int main() { return printf(\&"%s\en\&", rcsid) == EOF; }
.ft P
.LP
and
.B f.c
@ -57,14 +73,104 @@ f.o:
$\&Id: f.c,v \*(iD $
.ft
.fi
.PP
If a C program defines a string like
.B rcsid
above but does not use it,
.BR lint (1)
may complain, and some C compilers will optimize away the string.
The most reliable solution is to have the program use the
.B rcsid
string, as shown in the example above.
.PP
.B ident
finds all instances of the
.BI $ keyword : "\ text\ " $
pattern, even if
.I keyword
is not actually an \*r-supported keyword.
This gives you information about nonstandard keywords like
.BR $\&XConsortium$ .
.SH KEYWORDS
Here is the list of keywords currently maintained by
.BR co (1).
All times are given in Coordinated Universal Time (\*u,
sometimes called \&\s-1GMT\s0) by default, but if the files
were checked out with
.BR co 's
.BI \-z zone
option, times are given with a numeric time zone indication appended.
.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.
.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).
.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.
For
.BR ident 's
purposes, this is equivalent to
.BR $\&RCSfile$ .
.TP
.B $\&Name$
The symbolic name used to check out the revision, if any.
.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
.BR co (1)
represents the following characters in keyword values 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 IDENTIFICATION
Author: Walter F. Tichy.
.br
Revision Number: \*(Rv; Release Date: \*(Dt.
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990 by Paul Eggert.
Copyright \(co 1990, 1992, 1993 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
rcsfile(5)

View File

@ -1,5 +1,7 @@
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991 by Paul Eggert
/* Identify RCS keyword strings in files. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@ -25,41 +27,119 @@ Report problems and direct all questions to:
*/
/*
* RCS identification operation
*/
* $Log: ident.c,v $
* Revision 1.3 1995/02/24 02:07:55 mycroft
* RCS 5.6.7.4
*
* Revision 5.7 1994/03/20 04:52:58 eggert
* Remove `exiting' from identExit.
*
* Revision 5.6 1993/11/09 17:40:15 eggert
* Add -V.
*
* Revision 5.5 1993/11/03 17:42:27 eggert
* Test for char == EOF, not char < 0.
*
* Revision 5.4 1992/01/24 18:44:19 eggert
* lint -> RCS_lint
*
* Revision 5.3 1991/09/10 22:15:46 eggert
* Open files with FOPEN_R, not FOPEN_R_WORK,
* because they might be executables, not working files.
*
* Revision 5.2 1991/08/19 03:13:55 eggert
* Report read errors immediately.
*
* Revision 5.1 1991/02/25 07:12:37 eggert
* Don't report empty keywords. Check for I/O errors.
*
* Revision 5.0 1990/08/22 08:12:37 eggert
* Don't limit output to known keywords.
* Remove arbitrary limits and lint. Ansify and Posixate.
*
* Revision 4.5 89/05/01 15:11:54 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 87/10/23 17:09:57 narten
* added exit(0) so exit return code would be non random
*
* Revision 4.3 87/10/18 10:23:55 narten
* Updating version numbers. Changes relative to 1.1 are actually relative
* to 4.1
*
* Revision 1.3 87/07/09 09:20:52 trinkle
* Added check to make sure there is at least one arg before comparing argv[1]
* with "-q". This necessary on machines that don't allow dereferncing null
* pointers (i.e. Suns).
*
* Revision 1.2 87/03/27 14:21:47 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:31:02 wft
* Added option -q and input from reading stdin.
* Marker matching is now done with trymatch() (independent of keywords).
*
* Revision 3.4 83/02/18 17:37:49 wft
* removed printing of new line after last file.
*
* Revision 3.3 82/12/04 12:48:55 wft
* Added LOCKER.
*
* Revision 3.2 82/11/28 18:24:17 wft
* removed Suffix; added ungetc to avoid skipping over trailing KDELIM.
*
* Revision 3.1 82/10/13 15:58:51 wft
* fixed type of variables receiving from getc() (char-->int).
*/
#include "rcsbase.h"
static int match P((FILE*));
static void scanfile P((FILE*,char const*,int));
mainProg(identId, "ident", "$Id: ident.c,v 1.2 1993/08/02 17:47:04 mycroft Exp $")
mainProg(identId, "ident", "$Id: ident.c,v 1.3 1995/02/24 02:07:55 mycroft Exp $")
/* Ident searches the named files for all occurrences
* of the pattern $keyword:...$, where the keywords are
* Author, Date, Header, Id, Log, RCSfile, Revision, Source, and State.
* of the pattern $keyword: text $.
*/
{
FILE *fp;
int quiet;
int quiet = 0;
int status = EXIT_SUCCESS;
char const *a;
if ((quiet = argc > 1 && strcmp("-q",argv[1])==0)) {
argc--; argv++;
}
while ((a = *++argv) && *a=='-')
while (*++a)
switch (*a) {
case 'q':
quiet = 1;
break;
if (argc<2)
case 'V':
VOID printf("RCS version %s\n", RCS_version_string);
exitmain(0);
default:
VOID fprintf(stderr,
"ident: usage: ident -{qV} [file...]\n"
);
exitmain(1);
break;
}
if (!a)
scanfile(stdin, (char*)0, quiet);
else
do {
if (!(fp = fopen(a, FOPEN_R))) {
VOID fprintf(stderr, "%s error: can't open %s\n", cmdid, a);
status = EXIT_FAILURE;
} else {
scanfile(fp, a, quiet);
if (argv[1]) VOID putchar('\n');
}
} while ((a = *++argv));
while ( --argc > 0 ) {
if (!(fp = fopen(*++argv, FOPEN_R))) {
VOID fprintf(stderr, "%s error: can't open %s\n", cmdid, *argv);
status = EXIT_FAILURE;
} else {
scanfile(fp, *argv, quiet);
if (argc>1) VOID putchar('\n');
}
}
if (ferror(stdout) || fclose(stdout)!=0) {
VOID fprintf(stderr, "%s error: write error\n", cmdid);
status = EXIT_FAILURE;
@ -67,8 +147,8 @@ mainProg(identId, "ident", "$Id: ident.c,v 1.2 1993/08/02 17:47:04 mycroft Exp $
exitmain(status);
}
#if lint
exiting void identExit() { _exit(EXIT_FAILURE); }
#if RCS_lint
void identExit() { _exit(EXIT_FAILURE); }
#endif
@ -89,7 +169,7 @@ scanfile(file, name, quiet)
name = "input";
c = 0;
for (;;) {
if (c < 0) {
if (c == EOF) {
if (feof(file))
break;
if (ferror(file))
@ -124,7 +204,7 @@ match(fp) /* group substring between two KDELIM's; then do pattern match */
tp = line;
while ((c = getc(fp)) != VDELIM) {
if (c < 0)
if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
case LETTER: case Letter:
@ -143,7 +223,7 @@ match(fp) /* group substring between two KDELIM's; then do pattern match */
return c ? c : '\n';
*tp++ = c;
while( (c = getc(fp)) != KDELIM ) {
if (c < 0 && feof(fp) | ferror(fp))
if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
default:

View File

@ -1,13 +1,13 @@
# $Id: Makefile,v 1.3 1993/10/06 21:28:25 cgd Exp $
# $Id: Makefile,v 1.4 1995/02/24 02:07:59 mycroft Exp $
# Define FSYNC_ALL to get slower but safer writes in case of crashes in
# the middle of CVS/RCS changes
CFLAGS += -DFSYNC_ALL
CFLAGS+=-DFSYNC_ALL
LIB = rcs
SRCS = maketime.c partime.c rcsedit.c rcsfcmp.c rcsfnms.c rcsgen.c \
rcskeep.c rcskeys.c rcslex.c rcsmap.c rcsrev.c rcssyn.c rcsutil.c \
merger.c
LIB= rcs
SRCS= maketime.c merger.c partime.c rcsedit.c rcsfcmp.c rcsfnms.c rcsgen.c \
rcskeep.c rcskeys.c rcslex.c rcsmap.c rcsrev.c rcssyn.c rcstime.c \
rcsutil.c version.c
NOPROFILE=noprofile
NOPIC=nopic

View File

@ -1,5 +1,7 @@
/* RCS compile-time configuration */
/* $Id: conf.h,v 1.7 1995/02/24 02:08:00 mycroft Exp $ */
/*
* This file is generated automatically.
* If you edit it by hand your changes may be lost.
@ -21,11 +23,13 @@
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
/* #include <siginfo.h> */
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
/* #include <ucontext.h> */
#include <unistd.h>
#include <utime.h>
/* #include <vfork.h> */
@ -33,21 +37,10 @@
/* Define the following symbols to be 1 or 0. */
#define has_sys_dir_h 1 /* Does #include <sys/dir.h> work? */
#define has_sys_param_h 1 /* Does #include <sys/param.h> work? */
/* extern int errno; */ /* Uncomment if <errno.h> doesn't declare errno. */
#define has_readlink 1 /* Does readlink() work? */
#define readlink_isreg_errno EINVAL /* errno after readlink on regular file */
/* #undef NAME_MAX */ /* Uncomment this if NAME_MAX is broken. */
#if !defined(NAME_MAX) && !defined(_POSIX_NAME_MAX)
# if has_sys_dir_h
# include <sys/dir.h>
# endif
# ifndef NAME_MAX
# ifndef MAXNAMLEN
# define MAXNAMLEN 14
# endif
# define NAME_MAX MAXNAMLEN
# endif
#endif
#if !defined(PATH_MAX) && !defined(_POSIX_PATH_MAX)
# if has_sys_param_h
# include <sys/param.h>
@ -69,13 +62,10 @@
# endif
#endif
/* Comment out the keyword definitions below if the keywords work. */
/* #define const */
/* #define volatile */
/* Comment out the typedefs below if the types are already declared. */
/* Fix any uncommented typedefs that are wrong. */
/* typedef int mode_t; */
/* typedef long off_t; */
/* typedef int pid_t; */
/* typedef int sig_atomic_t; */
/* typedef unsigned size_t; */
@ -83,6 +73,10 @@
/* typedef long time_t; */
/* typedef int uid_t; */
/* Comment out the keyword definitions below if the keywords work. */
/* #define const */
/* #define volatile */
/* Define the following symbols to be 1 or 0. */
#define has_prototypes 1 /* Do function prototypes work? */
#define has_stdarg 1 /* Does <stdarg.h> work? */
@ -119,80 +113,122 @@
# define FOPEN_R "r"
# define FOPEN_W "w"
# define FOPEN_WPLUS "w+"
# define OPEN_O_BINARY 0
#else
/* Text and binary i/o behave differently. */
/* This is incompatible with Posix and Unix. */
# define FOPEN_R "rb"
# define FOPEN_W "wb"
# define FOPEN_WPLUS "w+b"
# define OPEN_O_BINARY O_BINARY
# ifndef O_BINARY
# define O_BINARY 0
# endif
#endif
#if text_work_stdio
# define FOPEN_R_WORK "r"
# define FOPEN_W_WORK "w"
# define FOPEN_WPLUS_WORK "w+"
# define OPEN_O_WORK 0
#else
# define FOPEN_R_WORK FOPEN_R
# define FOPEN_W_WORK FOPEN_W
# define FOPEN_WPLUS_WORK FOPEN_WPLUS
# define OPEN_O_WORK OPEN_O_BINARY
#endif
/* This may need changing on non-Unix systems (notably DOS). */
#define OPEN_CREAT_READONLY (S_IRUSR|S_IRGRP|S_IROTH) /* lock file mode */
#define OPEN_O_LOCK 0 /* extra open flags for creating lock file */
/* Define or comment out the following symbols as needed. */
#define bad_chmod_close 0 /* Can chmod() close file descriptors? */
#define bad_creat0 0 /* Do writes fail after creat(f,0)? */
#define bad_fopen_wplus 0 /* Does fopen(f,FOPEN_WPLUS) fail to truncate f? */
#define getlogin_is_secure 0 /* Is getlogin() secure? Usually it's not. */
#define has_attribute_noreturn 1 /* Does __attribute__((noreturn)) work? */
#if has_attribute_noreturn
# define exiting __attribute__((noreturn))
#else
# define exiting
#endif
#define has_dirent 1 /* Do opendir(), readdir(), closedir() work? */
#define has_fchmod 0 /* Does fchmod() work? */
#define has_fputs 0 /* Does fputs() work? */
#define void_closedir 0 /* Does closedir() yield void? */
#define has_fchmod 1 /* Does fchmod() work? */
#define has_fflush_input 0 /* Does fflush() work on input files? */
#define has_fputs 1 /* Does fputs() work? */
#define has_ftruncate 1 /* Does ftruncate() work? */
#define has_getuid 1 /* Does getuid() work? */
#define has_getpwuid 1 /* Does getpwuid() work? */
#define has_link 1 /* Does link() work? */
#define has_memcmp 1 /* Does memcmp() work? */
#define has_memcpy 1 /* Does memcpy() work? */
#define has_memmove 1 /* Does memmove() work? */
#define has_madvise 0 /* Does madvise() work? */
#define has_mmap 0 /* Does mmap() work on regular files? */
#define has_mmap 1 /* Does mmap() work on regular files? */
/* typedef char *caddr_t; */ /* mmap argument type */
#define mmap_signal SIGBUS /* signal received if you reference nonexistent part of mmapped file */
#define has_rename 1 /* Does rename() work? */
#define bad_a_rename 0 /* Does rename(A,B) fail if A is unwritable? */
#define bad_b_rename 0 /* Does rename(A,B) fail if B is unwritable? */
/* typedef int void; */ /* Some ancient compilers need this. */
#define VOID (void) /* 'VOID e;' discards the value of an expression 'e'. */
#define has_seteuid 0 /* Does seteuid() work? See README. */
#define has_seteuid 1 /* Does seteuid() work? See INSTALL. */
#define has_setreuid 0 /* Does setreuid() work? See INSTALL. */
#define has_setuid 1 /* Does setuid() exist? */
#define has_sigaction 1 /* Does struct sigaction work? */
#define has_signal 1 /* Does signal() work? */
#define signal_args P((int)) /* arguments of signal handlers */
#define signal_type void /* type returned by signal handlers */
#define sig_zaps_handler 0 /* Must a signal handler reinvoke signal()? */
#define has_sigaction 1 /* Does struct sigaction work? */
/* #define has_sigblock ? */ /* Does sigblock() work? */
/* #define sigmask(s) (1 << ((s)-1)) */ /* Yield mask for signal number. */
#define has_sys_siglist 1 /* Does sys_siglist[] work? */
typedef size_t fread_type; /* type returned by fread() and fwrite() */
typedef size_t freadarg_type; /* type of their size arguments */
typedef void *malloc_type; /* type returned by malloc() */
#define has_getcwd 1 /* Does getcwd() work? */
/* #define has_getwd ? */ /* Does getwd() work? */
#define needs_getabsname 0 /* Must we define getabsname? */
#define has_mktemp 1 /* Does mktemp() work? */
#define has_NFS 1 /* Might NFS be used? */
#define has_psiginfo 0 /* Does psiginfo() work? */
#define has_psignal 1 /* Does psignal() work? */
#define has_sys_siglist 1 /* Does sys_siglist[] work? */
/* #define strchr index */ /* Use old-fashioned name for strchr()? */
/* #define strrchr rindex */ /* Use old-fashioned name for strrchr()? */
#define bad_unlink 0 /* Does unlink() fail on unwritable files? */
#define has_vfork 0 /* Does vfork() work? */
#define has_vfork 1 /* Does vfork() work? */
#define has_fork 1 /* Does fork() work? */
#define has_spawn 0 /* Does spawn*() work? */
#define has_wait 1 /* Does wait() work? */
#define has_waitpid 0 /* Does waitpid() work? */
#define has_waitpid 1 /* Does waitpid() work? */
#define RCS_SHELL "/bin/sh" /* shell to run RCS subprograms */
#define has_printf_dot 1 /* Does "%.2d" print leading 0? */
#define has_vfprintf 1 /* Does vfprintf() work? */
#define has_attribute_format_printf 1 /* Does __attribute__((format(printf,N,N+1))) work? */
#if has_attribute_format_printf
# define printf_string(m, n) __attribute__((format(printf, m, n)))
#else
# define printf_string(m, n)
#endif
#if has_attribute_format_printf && has_attribute_noreturn
/* Work around a bug in GCC 2.5.x. */
# define printf_string_exiting(m, n) __attribute__((format(printf, m, n), noreturn))
#else
# define printf_string_exiting(m, n) printf_string(m, n) exiting
#endif
/* #define has__doprintf ? */ /* Does _doprintf() work? */
/* #define has__doprnt ? */ /* Does _doprnt() work? */
/* #undef EXIT_FAILURE */ /* Uncomment this if EXIT_FAILURE is broken. */
#define large_memory 0 /* Can main memory hold entire RCS files? */
/* #undef ULONG_MAX */ /* Uncomment this if ULONG_MAX is broken (e.g. < 0). */
/* struct utimbuf { time_t actime, modtime; }; */ /* Uncomment this if needed. */
#define CO "/usr/bin/co" /* name of 'co' program */
#define large_memory 1 /* Can main memory hold entire RCS files? */
#ifndef LONG_MAX
#define LONG_MAX 2147483647L /* long maximum */
#endif
/* Do struct stat s and t describe the same file? Answer d if unknown. */
#define same_file(s,t,d) ((s).st_ino==(t).st_ino && (s).st_dev==(t).st_dev)
#define has_utimbuf 1 /* Does struct utimbuf work? */
#define CO "/usr/local/bin/co" /* name of 'co' program */
#define COMPAT2 0 /* Are version 2 files supported? */
#define DATEFORM "%.2d.%.2d.%.2d.%.2d.%.2d.%.2d" /* e.g. 01.01.01.01.01.01 */
#define DIFF "/usr/bin/diff" /* name of 'diff' program */
#define DIFF3 "/usr/bin/diff3" /* name of 'diff3' program */
#define DIFF "/usr/local/bin/diff" /* name of 'diff' program */
#define DIFF3 "/usr/local/bin/diff3" /* name of 'diff3' program */
#define DIFF3_A 1 /* Does diff3 -A work? */
#define DIFF3_BIN 1 /* Is diff3 user-visible (not the /usr/lib auxiliary)? */
#define DIFF_FLAGS , "-an" /* Make diff output suitable for RCS. */
#define DIFF_L 1 /* Does diff -L work? */
@ -200,16 +236,17 @@ typedef void *malloc_type; /* type returned by malloc() */
#define DIFF_FAILURE 1 /* DIFF status if differences are found */
#define DIFF_TROUBLE 2 /* DIFF status if trouble */
#define ED "/bin/ed" /* name of 'ed' program (used only if !DIFF3_BIN) */
#define MERGE "/usr/bin/merge" /* name of 'merge' program */
#define MERGE "/usr/local/bin/merge" /* name of 'merge' program */
#define TMPDIR "/tmp" /* default directory for temporary files */
#define SLASH '/' /* principal pathname separator */
#define SLASHes '/' /* `case SLASHes:' labels all pathname separators */
#define isSLASH(c) ((c) == SLASH) /* Is arg a pathname separator? */
#define SLASH '/' /* principal filename separator */
#define SLASHes '/' /* `case SLASHes:' labels all filename separators */
#define isSLASH(c) ((c) == SLASH) /* Is arg a filename separator? */
#define ROOTPATH(p) isSLASH((p)[0]) /* Is p an absolute pathname? */
#define X_DEFAULT ",v/" /* default value for -x option */
#define SLASHSLASH_is_SLASH 1 /* Are // and / the same directory? */
#define ALL_ABSOLUTE 1 /* Do all subprograms satisfy ROOTPATH? */
#define DIFF_ABSOLUTE 1 /* Is ROOTPATH(DIFF) true? */
#define ALL_ABSOLUTE 1 /* Are all subprograms absolute pathnames? */
#define SENDMAIL "/usr/bin/mail" /* how to send mail */
#define SENDMAIL "/bin/mail" /* how to send mail */
#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work? */
@ -217,40 +254,21 @@ typedef void *malloc_type; /* type returned by malloc() */
/* Adjust the following declarations as needed. */
#if __GNUC__ && !__STRICT_ANSI__
# define exiting volatile /* GCC extension: function cannot return */
#else
# define exiting
#endif
/* The rest is for the benefit of non-standard, traditional hosts. */
/* Don't bother to declare functions that in traditional hosts do not appear, */
/* or are declared in .h files, or return int or void. */
#if has_ftruncate
int ftruncate P((int,off_t));
#endif
/* <sys/mman.h> */
#if has_madvise
int madvise P((caddr_t,size_t,int));
#endif
#if has_mmap
caddr_t mmap P((caddr_t,size_t,int,int,int,off_t));
int munmap P((caddr_t,size_t));
/* traditional BSD */
#if has_sys_siglist && !defined(sys_siglist)
extern char const * const sys_siglist[];
#endif
/* Posix (ISO/IEC 9945-1: 1990 / IEEE Std 1003.1-1990) */
/* These definitions are for the benefit of non-Posix hosts, and */
/* Posix hosts that have Standard C compilers but traditional include files. */
/* Unfortunately, mixed-up hosts are all too common. */
/* <fcntl.h> */
#ifdef F_DUPFD
int fcntl P((int,int,...));
#else
int dup2 P((int,int));
#endif
#ifndef O_BINARY /* some non-Posix hosts need O_BINARY */
# define O_BINARY 0 /* no effect on Posix */
#endif
#ifdef O_CREAT
# define open_can_creat 1
#else
@ -260,43 +278,12 @@ typedef void *malloc_type; /* type returned by malloc() */
# define O_RDWR 2
# define O_CREAT 01000
# define O_TRUNC 02000
int creat P((char const*,mode_t));
#endif
#ifndef O_EXCL
# define O_EXCL 0
#define O_EXCL 0
#endif
/* <pwd.h> */
#if has_getpwuid
struct passwd *getpwuid P((uid_t));
#endif
/* <signal.h> */
#if has_sigaction
int sigaction P((int,struct sigaction const*,struct sigaction*));
int sigaddset P((sigset_t*,int));
int sigemptyset P((sigset_t*));
#else
#if has_sigblock
/* BSD */
int sigblock P((int));
int sigmask P((int));
int sigsetmask P((int));
#endif
#endif
/* <stdio.h> */
FILE *fdopen P((int,char const*));
int fileno P((FILE*));
/* <sys/stat.h> */
int chmod P((char const*,mode_t));
int fstat P((int,struct stat*));
int stat P((char const*,struct stat*));
mode_t umask P((mode_t));
#if has_fchmod
int fchmod P((int,mode_t));
#endif
#ifndef S_IRUSR
# ifdef S_IREAD
# define S_IRUSR S_IREAD
@ -324,168 +311,102 @@ mode_t umask P((mode_t));
# endif
#endif
#ifndef S_ISREG
# define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
#define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
#endif
/* <sys/wait.h> */
#if has_wait
pid_t wait P((int*));
#endif
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
# undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val) (!((stat_val) & 255))
#define WIFEXITED(stat_val) (((stat_val) & 0377) == 0)
#endif
#ifndef WTERMSIG
#define WTERMSIG(stat_val) ((stat_val) & 0177)
#undef WIFSIGNALED /* Avoid 4.3BSD incompatibility with Posix. */
#endif
#ifndef WIFSIGNALED
#define WIFSIGNALED(stat_val) ((unsigned)(stat_val) - 1 < 0377)
#endif
/* <unistd.h> */
char *getlogin P((void));
int close P((int));
int isatty P((int));
int link P((char const*,char const*));
int open P((char const*,int,...));
int unlink P((char const*));
int _filbuf P((FILE*)); /* keeps lint quiet in traditional C */
int _flsbuf P((int,FILE*)); /* keeps lint quiet in traditional C */
long pathconf P((char const*,int));
ssize_t write P((int,void const*,size_t));
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
#endif
#if has_fork
# if !has_vfork
# undef vfork
# define vfork fork
# endif
pid_t vfork P((void)); /* vfork is nonstandard but faster */
#if has_fork && !has_vfork
# undef vfork
# define vfork fork
#endif
#if has_getcwd || !has_getwd
char *getcwd P((char*,size_t));
#else
char *getwd P((char*));
#endif
#if has_getuid
uid_t getuid P((void));
#endif
#if has_readlink
/* ssize_t readlink P((char const*,char*,size_t)); *//* BSD; not standard yet */
#endif
#if has_setuid
# if !has_seteuid
# undef seteuid
# define seteuid setuid
# endif
int seteuid P((uid_t));
uid_t geteuid P((void));
#if has_setuid && !has_seteuid
# undef seteuid
# define seteuid setuid
#endif
#if has_spawn
int spawnv P((int,char const*,char*const*));
# if ALL_ABSOLUTE
# define spawn_RCS spawnv
# else
# define spawn_RCS spawnvp
int spawnvp P((int,char const*,char*const*));
# endif
#else
int execv P((char const*,char*const*));
# if ALL_ABSOLUTE
# define exec_RCS execv
# else
# define exec_RCS execvp
int execvp P((char const*,char*const*));
# endif
#endif
/* utime.h */
int utime P((char const*,struct utimbuf const*));
#if !has_utimbuf
struct utimbuf { time_t actime, modtime; };
#endif
/* Standard C library */
/* These definitions are for the benefit of hosts that have */
/* traditional C include files, possibly with Standard C compilers. */
/* Unfortunately, mixed-up hosts are all too common. */
/* <errno.h> */
extern int errno;
/* <limits.h> */
#ifndef ULONG_MAX
/* This does not work in #ifs, but it's good enough for us. */
# define ULONG_MAX ((unsigned long)-1)
#endif
/* <signal.h> */
#if has_signal
signal_type (*signal P((int,signal_type(*)signal_args)))signal_args;
#endif
/* <stdio.h> */
FILE *fopen P((char const*,char const*));
fread_type fread P((void*,freadarg_type,freadarg_type,FILE*));
fread_type fwrite P((void const*,freadarg_type,freadarg_type,FILE*));
int fclose P((FILE*));
int feof P((FILE*));
int ferror P((FILE*));
int fflush P((FILE*));
int fprintf P((FILE*,char const*,...));
int fputs P((char const*,FILE*));
int fseek P((FILE*,long,int));
int printf P((char const*,...));
int rename P((char const*,char const*));
int sprintf P((char*,char const*,...));
/* long ftell P((FILE*)); */
void clearerr P((FILE*));
void perror P((char const*));
#ifndef L_tmpnam
# define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
#define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
#endif
#ifndef SEEK_SET
# define SEEK_SET 0
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#if has_mktemp
char *mktemp P((char*)); /* traditional */
#else
char *tmpnam P((char*));
#endif
#if has_vfprintf
int vfprintf P((FILE*,char const*,va_list));
#else
#if has__doprintf
void _doprintf P((FILE*,char const*,va_list)); /* Minix */
#else
void _doprnt P((char const*,va_list,FILE*)); /* BSD */
#endif
#endif
/* <stdlib.h> */
char *getenv P((char const*));
#ifndef __NetBSD__
exiting void _exit P((int));
exiting void exit P((int));
void _exit P((int)) exiting;
void exit P((int)) exiting;
#endif
malloc_type malloc P((size_t));
malloc_type realloc P((malloc_type,size_t));
void free P((malloc_type));
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
#if !has_fork && !has_spawn
int system P((char const*));
#define EXIT_SUCCESS 0
#endif
/* <string.h> */
char *strcpy P((char*,char const*));
char *strchr P((char const*,int));
char *strrchr P((char const*,int));
int memcmp P((void const*,void const*,size_t));
int strcmp P((char const*,char const*));
size_t strlen P((char const*));
void *memcpy P((void*,void const*,size_t));
#if has_memmove
void *memmove P((void*,void const*,size_t));

View File

@ -1,295 +1,314 @@
/* Convert struct partime into time_t. */
/* Copyright 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#include "conf.h"
#include "partime.h"
#include "maketime.h"
char const maketId[]
= "$Id: maketime.c,v 1.3 1995/02/24 02:08:02 mycroft Exp $";
static int isleap P((int));
static int month_days P((struct tm const*));
static time_t maketime P((struct partime const*,time_t));
/*
* MAKETIME derive 32-bit time value from TM structure.
*
* Usage:
* int zone; Minutes west of GMT, or
* 48*60 for localtime
* time_t t;
* struct tm *tp; Pointer to TM structure from <time.h>
* t = maketime(tp,zone);
*
* Returns:
* -1 if failure; parameter out of range or nonsensical.
* else time-value.
* Notes:
* This code is quasi-public; it may be used freely in like software.
* It is not to be sold, nor used in licensed software without
* permission of the author.
* For everyone's benefit, please report bugs and improvements!
* Copyright 1981 by Ken Harrenstien, SRI International.
* (ARPANET: KLH @ SRI)
*/
* For maximum portability, use only localtime and gmtime.
* Make no assumptions about the time_t epoch or the range of time_t values.
* Avoid mktime because it's not universal and because there's no easy,
* portable way for mktime to yield the inverse of gmtime.
*/
#include "rcsbase.h"
#define TM_YEAR_ORIGIN 1900
libId(maketId, "$Id: maketime.c,v 1.2 1993/08/02 17:47:15 mycroft Exp $")
static int
isleap(y)
int y;
{
return (y&3) == 0 && (y%100 != 0 || y%400 == 0);
}
static struct tm const *time2tm P((time_t));
#define given(v) (0 <= (v)) /* Negative values are unspecified. */
static int const daytb[] = {
/* # days in year thus far, indexed by month (0-12!!) */
static int const month_yday[] = {
/* days in year before start of months 0-12 */
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
static time_t
maketime(atm,zone)
struct tm const *atm;
int zone;
/* Yield the number of days in TM's month. */
static int
month_days(tm)
struct tm const *tm;
{
register struct tm const *tp;
register int i;
int year, yday, mon, day, hour, min, sec, leap, localzone;
int attempts;
time_t t, tres;
attempts = 2;
localzone = zone==48*60;
tres = -1;
year = mon = day = 0; /* Keep lint happy. */
do {
if (localzone || !given(atm->tm_year)) {
if (tres == -1)
if ((tres = time((time_t*)0)) == -1)
return -1;
tp = time2tm(tres);
/* Get breakdowns of default time, adjusting to zone. */
year = tp->tm_year; /* Use to set up defaults */
yday = tp->tm_yday;
mon = tp->tm_mon;
day = tp->tm_mday;
hour = tp->tm_hour;
min = tp->tm_min;
if (localzone) {
tp = localtime(&tres);
zone =
min - tp->tm_min + 60*(
hour - tp->tm_hour + 24*(
/* If years differ, it's by one day. */
year - tp->tm_year
? year - tp->tm_year
: yday - tp->tm_yday));
}
/* Adjust the default day, month and year according to zone. */
if ((min -= zone) < 0) {
if (hour-(59-min)/60 < 0 && --day <= 0) {
if (--mon < 0) {
--year;
mon = 11;
}
day = daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3));
}
} else
if (
24 <= hour+min/60 &&
daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3)) < ++day
) {
if (11 < ++mon) {
++year;
mon = 0;
}
day = 1;
}
}
if (zone < -24*60 || 24*60 < zone)
return -1;
#ifdef DEBUG
printf("first YMD: %d %d %d\n",year,mon,day);
#endif
tp = atm;
/* First must find date, using specified year, month, day.
* If one of these is unspecified, it defaults either to the
* current date (if no more global spec was given) or to the
* zero-value for that spec (i.e. a more global spec was seen).
* Reject times that do not fit in time_t,
* without assuming that time_t is 32 bits or is signed.
*/
if (given(tp->tm_year))
{
year = tp->tm_year;
mon = 0; /* Since year was given, default */
day = 1; /* for remaining specs is zero */
}
if (year < 69) /* 1969/12/31 OK in some timezones. */
return -1; /* ERR: year out of range */
leap = !(year&3) && (year%100 || !((year+300)%400));
year -= 70; /* UNIX time starts at 1970 */
/*
* Find day of year.
*/
{
if (given(tp->tm_mon))
{ mon = tp->tm_mon; /* Month was specified */
day = 1; /* so set remaining default */
}
if (11 < (unsigned)mon)
return -1; /* ERR: bad month */
if (given(tp->tm_mday)) day = tp->tm_mday;
if(day < 1
|| (((daytb[mon+1]-daytb[mon]) < day)
&& (day!=29 || mon!=1 || !leap) ))
return -1; /* ERR: bad day */
yday = daytb[mon] /* Add # of days in months so far */
+ ((leap /* Leap year, and past Feb? If */
&& mon>1)? 1:0) /* so, add leap day for this year */
+ day-1; /* And finally add # days this mon */
}
if (leap+365 <= (unsigned)yday)
return -1; /* ERR: bad YDAY */
if (year < 0) {
if (yday != 364)
return -1; /* ERR: too early */
t = -1;
} else {
tres = year*365; /* Get # days of years so far */
if (tres/365 != year)
return -1; /* ERR: overflow */
t = tres
+ ((year+1)>>2) /* plus # of leap days since 1970 */
+ yday; /* and finally add # days this year */
if (t+4 < tres)
return -1; /* ERR: overflow */
}
tres = t;
if (given(i = tp->tm_wday)) /* Check WDAY if present */
if (i != (tres+4)%7) /* 1970/01/01 was Thu = 4 */
return -1; /* ERR: bad WDAY */
#ifdef DEBUG
printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
#endif
/*
* Now determine time. If not given, default to zeros
* (since time is always the least global spec)
*/
tres *= 86400L; /* Get # seconds (24*60*60) */
if (tres/86400L != t)
return -1; /* ERR: overflow */
hour = min = sec = 0;
if (given(tp->tm_hour)) hour = tp->tm_hour;
if (given(tp->tm_min )) min = tp->tm_min;
if (given(tp->tm_sec )) sec = tp->tm_sec;
if (60 <= (unsigned)min || 60 < (unsigned)sec)
return -1; /* ERR: MS out of range */
if (24 <= (unsigned)hour)
if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */
return -1; /* ERR: H out of range */
t = tres;
tres += sec + 60L*(zone + min + 60*hour);
#ifdef DEBUG
printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
#endif
if (!localzone) /* check for overflow */
return (year<0 ? (tres<0||86400L<=tres) : tres<t) ? -1 : tres;
/* Check results; LT may have had a different GMT offset back then. */
tp = localtime(&tres);
if (given(atm->tm_sec) && atm->tm_sec != tp->tm_sec)
return -1; /* If seconds don't match, we're in trouble. */
if (!(
given(atm->tm_min) && atm->tm_min != tp->tm_min ||
given(atm->tm_hour) && atm->tm_hour != tp->tm_hour ||
given(atm->tm_mday) && atm->tm_mday != tp->tm_mday ||
given(atm->tm_mon) && atm->tm_mon != tp->tm_mon ||
given(atm->tm_year) && atm->tm_year != tp->tm_year
))
return tres; /* Everything matches. */
} while (--attempts);
return -1;
int m = tm->tm_mon;
return month_yday[m+1] - month_yday[m]
+ (m==1 && isleap(tm->tm_year + TM_YEAR_ORIGIN));
}
/*
* Convert Unix time to struct tm format.
* Use Coordinated Universal Time (UTC) if version 5 or newer;
* use local time otherwise.
* Convert UNIXTIME to struct tm form.
* Use gmtime if available and if !LOCALZONE, localtime otherwise.
*/
static struct tm const *
time2tm(unixtime)
struct tm *
time2tm(unixtime, localzone)
time_t unixtime;
int localzone;
{
struct tm const *tm;
struct tm *tm;
# if TZ_must_be_set
static char const *TZ;
if (!TZ && !(TZ = getenv("TZ")))
faterror("TZ is not set");
faterror("The TZ environment variable is not set; please set it to your timezone");
# endif
if (!(tm = (RCSversion<VERSION(5) ? localtime : gmtime)(&unixtime)))
faterror("UTC is not available; perhaps TZ is not set?");
if (localzone || !(tm = gmtime(&unixtime)))
tm = localtime(&unixtime);
return tm;
}
/* Yield A - B, measured in seconds. */
time_t
difftm(a, b)
struct tm const *a, *b;
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
return
(
(
(
/* difference in day of year */
a->tm_yday - b->tm_yday
/* + intervening leap days */
+ ((ay >> 2) - (by >> 2))
- (ay/100 - by/100)
+ ((ay/100 >> 2) - (by/100 >> 2))
/* + difference in years * 365 */
+ (time_t)(ay-by) * 365
)*24 + (a->tm_hour - b->tm_hour)
)*60 + (a->tm_min - b->tm_min)
)*60 + (a->tm_sec - b->tm_sec);
}
/*
* Convert Unix time to RCS format.
* For compatibility with older versions of RCS,
* dates before AD 2000 are stored without the leading "19".
* Adjust T by adding MINUTES. MINUTES must be at most 24 hours' worth.
* Adjust only T's year, mon, mday, hour and min members;
* plus adjust wday if it is defined.
*/
void
time2date(unixtime,date)
time_t unixtime;
char date[datesize];
adjzone(t, minutes)
register struct tm *t;
int minutes;
{
register struct tm const *tm = time2tm(unixtime);
VOID sprintf(date, DATEFORM,
tm->tm_year + (tm->tm_year<100 ? 0 : 1900),
tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec
);
if ((t->tm_min += minutes) < 0) {
if ((t->tm_hour -= (59-t->tm_min)/60) < 0) {
t->tm_hour += 24;
if (TM_DEFINED(t->tm_wday) && --t->tm_wday < 0)
t->tm_wday = 6;
if (--t->tm_mday <= 0) {
if (--t->tm_mon < 0) {
--t->tm_year;
t->tm_mon = 11;
}
t->tm_mday = month_days(t);
}
}
t->tm_min += 24*60;
} else
if (24 <= (t->tm_hour += t->tm_min/60)) {
t->tm_hour -= 24;
if (TM_DEFINED(t->tm_wday) && ++t->tm_wday == 7)
t->tm_wday = 0;
if (month_days(t) < ++t->tm_mday) {
if (11 < ++t->tm_mon) {
++t->tm_year;
t->tm_mon = 0;
}
t->tm_mday = 1;
}
}
t->tm_min %= 60;
}
/*
* Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
* Use only TM's year, mon, mday, hour, min, and sec members.
* Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
* Yield -1 on failure (e.g. a member out of range).
* Posix 1003.1-1990 doesn't allow leap seconds, but some implementations
* have them anyway, so allow them if localtime/gmtime does.
*/
time_t
tm2time(tm, localzone)
struct tm *tm;
int localzone;
{
/* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */
static time_t t_cache[2];
static struct tm tm_cache[2];
time_t d, gt;
struct tm const *gtm;
/*
* The maximum number of iterations should be enough to handle any
* combinations of leap seconds, time zone rule changes, and solar time.
* 4 is probably enough; we use a bigger number just to be safe.
*/
int remaining_tries = 8;
/* Avoid subscript errors. */
if (12 <= (unsigned)tm->tm_mon)
return -1;
tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday
- (tm->tm_mon<2 || ! isleap(tm->tm_year + TM_YEAR_ORIGIN));
/* Make a first guess. */
gt = t_cache[localzone];
gtm = gt ? &tm_cache[localzone] : time2tm(gt,localzone);
/* Repeatedly use the error from the guess to improve the guess. */
while ((d = difftm(tm, gtm)) != 0) {
if (--remaining_tries == 0)
return -1;
gt += d;
gtm = time2tm(gt,localzone);
}
t_cache[localzone] = gt;
tm_cache[localzone] = *gtm;
/*
* Check that the guess actually matches;
* overflow can cause difftm to yield 0 even on differing times,
* or tm may have members out of range (e.g. bad leap seconds).
*/
if ( (tm->tm_year ^ gtm->tm_year)
| (tm->tm_mon ^ gtm->tm_mon)
| (tm->tm_mday ^ gtm->tm_mday)
| (tm->tm_hour ^ gtm->tm_hour)
| (tm->tm_min ^ gtm->tm_min)
| (tm->tm_sec ^ gtm->tm_sec))
return -1;
tm->tm_wday = gtm->tm_wday;
return gt;
}
/*
* Check *PT and convert it to time_t.
* If it is incompletely specified, use DEFAULT_TIME to fill it out.
* Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
* Yield -1 on failure.
* ISO 8601 day-of-year and week numbers are not yet supported.
*/
static time_t
str2time(source)
char const *source;
maketime(pt, default_time)
struct partime const *pt;
time_t default_time;
{
int localzone, wday;
struct tm tm;
struct tm *tm0 = 0;
time_t r;
tm0 = 0; /* Keep gcc -Wall happy. */
localzone = pt->zone==TM_LOCAL_ZONE;
tm = pt->tm;
if (TM_DEFINED(pt->ymodulus) || !TM_DEFINED(tm.tm_year)) {
/* Get tm corresponding to current time. */
tm0 = time2tm(default_time, localzone);
if (!localzone)
adjzone(tm0, pt->zone);
}
if (TM_DEFINED(pt->ymodulus))
tm.tm_year +=
(tm0->tm_year + TM_YEAR_ORIGIN)/pt->ymodulus * pt->ymodulus;
else if (!TM_DEFINED(tm.tm_year)) {
/* Set default year, month, day from current time. */
tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN;
if (!TM_DEFINED(tm.tm_mon)) {
tm.tm_mon = tm0->tm_mon;
if (!TM_DEFINED(tm.tm_mday))
tm.tm_mday = tm0->tm_mday;
}
}
/* Convert from partime year (Gregorian) to Posix year. */
tm.tm_year -= TM_YEAR_ORIGIN;
/* Set remaining default fields to be their minimum values. */
if (!TM_DEFINED(tm.tm_mon)) tm.tm_mon = 0;
if (!TM_DEFINED(tm.tm_mday)) tm.tm_mday = 1;
if (!TM_DEFINED(tm.tm_hour)) tm.tm_hour = 0;
if (!TM_DEFINED(tm.tm_min)) tm.tm_min = 0;
if (!TM_DEFINED(tm.tm_sec)) tm.tm_sec = 0;
if (!localzone)
adjzone(&tm, -pt->zone);
wday = tm.tm_wday;
/* Convert and fill in the rest of the tm. */
r = tm2time(&tm, localzone);
/* Check weekday. */
if (r != -1 && TM_DEFINED(wday) && wday != tm.tm_wday)
return -1;
return r;
}
/* Parse a free-format date in SOURCE, yielding a Unix format time. */
{
int zone;
time_t unixtime;
struct tm parseddate;
if (!partime(source, &parseddate, &zone))
faterror("can't parse date/time: %s", source);
if ((unixtime = maketime(&parseddate, zone)) == -1)
faterror("bad date/time: %s", source);
return unixtime;
}
void
str2date(source, target)
time_t
str2time(source, default_time, default_zone)
char const *source;
char target[datesize];
/* Parse a free-format date in SOURCE, convert it
* into RCS internal format, and store the result into TARGET.
*/
time_t default_time;
int default_zone;
{
time2date(str2time(source), target);
struct partime pt;
if (*partime(source, &pt))
return -1;
if (pt.zone == TM_UNDEFINED_ZONE)
pt.zone = default_zone;
return maketime(&pt, default_time);
}
#if TEST
#include <stdio.h>
int
setfiledate(file, date)
char const *file, date[datesize];
/* Set the access and modification time of FILE to DATE. */
main(argc, argv) int argc; char **argv;
{
static struct utimbuf times; /* static so unused fields are zero */
char datebuf[datesize];
if (!date)
return 0;
times.actime = times.modtime = str2time(date2str(date, datebuf));
return utime(file, &times);
time_t default_time = time((time_t *)0);
int default_zone = argv[1] ? atoi(argv[1]) : 0;
char buf[1000];
while (gets(buf)) {
time_t t = str2time(buf, default_time, default_zone);
printf("%s", asctime(gmtime(&t)));
}
return 0;
}
#endif

View File

@ -15,10 +15,10 @@
# The current directory and ./RCS must be readable, writable, and searchable.
# rcstest,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp
# $Id: rcstest,v 1.2 1995/02/24 02:07:42 mycroft Exp $
# Copyright 1990, 1991 by Paul Eggert
# Copyright 1990, 1991, 1992, 1993, 1994 Paul Eggert
# Distributed under license by the Free Software Foundation, Inc.
#
# This file is part of RCS.
@ -41,6 +41,15 @@
#
# rcs-bugs@cs.purdue.edu
# The Makefile overrides the following defaults.
: ${CC=cc}
: ${CFLAGS=-O}
: ${DIFF=diff}
# : ${LDFLAGS=} ${LDLIBS=} tickles old shell bug
CL="$CC $CFLAGS $LDFLAGS"
L=$LDLIBS
RCSINIT=-x
export RCSINIT
@ -55,26 +64,26 @@ case $1 in
*) echo >&2 "$0: usage: $0 [-v]"; exit 2
esac
test -d RCS || {
echo >&2 "$0: RCS: not a directory; please \`mkdir RCS' first."
exit 1
}
if test -d RCS
then rmdir=:
else rmdir=rmdir; mkdir RCS || exit
fi
rm -f a.* $RCSfile $RCS_alt $lockfile &&
echo 1.1 >a.11 &&
echo 1.1.1.1 >a.3x1 &&
echo 1.2 >a.12 || { echo "#initialization failed"; exit 2; }
case `diff -c a.11 a.3x1` in
*'! 1.1.1.1')
diff='diff -c';;
case "`$DIFF -c a.11 a.3x1`" in
*!\ 1.1.1.1)
diff="$DIFF -c";;
*)
echo "#warning: diff -c does not work, so diagnostics may be cryptic"
diff=diff
echo "#warning: $DIFF -c does not work, so diagnostics may be cryptic"
diff=$DIFF
esac
rcs -i -L -ta.11 $q a.c &&
<$RCSfile || {
test -r $RCSfile || {
echo "#rcs -i -L failed; perhaps RCS is not properly installed."
exit 1
}
@ -84,7 +93,7 @@ rm -f $RCSfile || exit 2
cp a.11 a.c &&
ci -ta.11 -mm $q a.c &&
<$RCSfile &&
test -r $RCSfile &&
rcs -L $q a.c || { echo "#ci+rcs -L failed"; exit 1; }
test ! -f a.c || { echo "#ci did not remove working file"; exit 1; }
for l in '' '-l'
@ -99,6 +108,7 @@ ci -mm $q a.c &&
co $q a.c &&
$diff a.12 a.c || { echo "#ci+co failed"; exit 1; }
rm -f a.c &&
co -r1.1 $q a.c &&
$diff a.11 a.c || { echo "#can't retrieve first revision"; exit 1; }
@ -108,21 +118,24 @@ ci -r1.1.1 -mm $q a.c &&
co -r1.1.1.1 $q a.c &&
$diff a.3x1 a.c || { echo "#branches failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
ci -f -mm $q a.c &&
co -r1.3 $q a.c &&
$diff a.12 a.c || { echo "#(co -l; ci -f) failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 1.4 >a.c &&
ci -l -mm $q a.c &&
echo error >a.c &&
ci -mm $q a.c || { echo "#ci -l failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 1.5 >a.c &&
ci -u -mm $q a.c &&
<a.c || { echo "#ci -u didn't create a working file"; exit 1; }
test -r a.c || { echo "#ci -u didn't create a working file"; exit 1; }
rm -f a.c &&
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#ci -u didn't unlock the file"; exit 1; }
@ -166,42 +179,28 @@ case $LOGNAME in
esac
esac
esac
date=`date -u 2>/dev/null` ||
date=`TZ=GMT0 date 2>/dev/null` ||
date=`TZ= date` || exit 2
set $date
case $2 in
Jan) m=01;; Feb) m=02;; Mar) m=03;; Apr) m=04;; May) m=05;; Jun) m=06;;
Jul) m=07;; Aug) m=08;; Sep) m=09;; Oct) m=10;; Nov) m=11;; Dec) m=12;;
*) echo >&2 "$0: $2: unknown month name"; exit 2
# Get the date of the previous revision in UTC.
date=`rlog -r a.c | sed -n '/^date: /{ s///; s/;.*//; p; q; }'` || exit
case $date in
[0-9][0-9][0-9]*[0-9]/[0-1][0-9]/[0-3][0-9]\ [0-2][0-9]:[0-5][0-9]:[0-6][0-9]);;
*) echo >&2 "$0: $date: bad rlog date output"; exit 1
esac
case $3 in
?) d=0$3;;
*) d=$3
esac
case $6 in
[0-9][0-9][0-9][0-9]*) D=$6/$m/$d;;
*)
case $5 in
[0-9][0-9][0-9][0-9]*) D=$5/$m/$d;;
*) echo >&2 "$0: bad date format: $date"; exit 2
esac
esac
T=$4
case $PWD in
'') PWD=`pwd`
esac &&
PWD=`pwd` && export PWD &&
rm -f a.c &&
co -l $q a.c &&
sed 's/@/$/g' >a.kv <<EOF
@Author: w @
@Date: $D $T @
@Header: $PWD$SLASH$RCSfile 2.1 $D $T w s @
@Id: a.c 2.1 $D $T w s @
@Date: $date @
@Header: $PWD$SLASH$RCSfile 2.1 $date w s @
@Id: a.c 2.1 $date w s @
@Locker: @
@Log: a.c @
* Revision 2.1 $D $T w
* @Log: a.c @
* Revision 2.1 $date w
* m
*
@Name: Oz @
@RCSfile: a.c @
@Revision: 2.1 @
@Source: $PWD$SLASH$RCSfile @
@ -210,25 +209,28 @@ EOF
test $? = 0 &&
sed 's/:.*\$/$/' a.kv >a.k &&
sed -e 's/w s [$]/w s '"$me"' $/' -e 's/[$]Locker: /&'"$me/" a.kv >a.kvl &&
sed -e '/^\$/!d' -e 's/\$$/: old $/' a.k >a.o &&
sed s/Oz//g a.kv >a.e &&
sed s/Oz/N/g a.kv >a.N &&
sed -e '/\$/!d' -e 's/\$$/: old $/' a.k >a.o &&
sed -e 's/\$[^ ]*: //' -e 's/ \$//' a.kv >a.v &&
cp a.o a.c &&
ci -d"$date" -ss -ww -u2.1 -mm $q a.c &&
ci -d"$date" -nOz -ss -ww -u2.1 -mm $q a.c &&
$diff a.kv a.c || { echo "#keyword expansion failed"; exit 1; }
co -p -ko $q a.c >a.oo &&
co -pOz -ko $q a.c >a.oo &&
$diff a.o a.oo || { echo "#co -p -ko failed"; exit 1; }
cp a.kv a.o || exit 2
rcs -o2.1 $q a.c &&
rcs -oOz $q a.c &&
rcs -l $q a.c &&
ci -k -u $q a.c &&
$diff a.kv a.c || { echo "#ci -k failed"; exit 1; }
sed '/^[^$]/d' a.kv >a.i &&
sed -n 's/^[^$]*\$/$/p' a.kv >a.i &&
ident a.c >a.i1 &&
sed -e 1d -e 's/^[ ]*//' a.i1 >a.i2 &&
$diff a.i a.i2 || { echo "#ident failed"; exit 1; }
rcs -i $q a.c 2>/dev/null && { echo "#rcs -i permitted existing file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 2.2 >a.c &&
ci -mm $q a.c &&
@ -259,21 +261,23 @@ rcs -nN:1.1 $q a.c &&
co -rN $q a.c &&
$diff a.11 a.c || { echo "#rcs -n failed"; exit 1; }
rm -f a.c &&
rcs -NN:2.1 $q a.c &&
co -rN $q a.c &&
$diff a.kv a.c || { echo "#rcs -N failed"; exit 1; }
$diff a.N a.c || { echo "#rcs -N failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
rcs -c':::' $q a.c &&
echo '$''Log$' >a.c &&
echo ':::$''Log$' >a.c &&
ci -u -mm $q a.c &&
test " `sed '$!d' a.c`" = ' :::' || { echo "#rcs -c failed"; exit 1; }
test " `sed '$!d' a.c`" = ' :::' || { echo "#comment leader failed"; exit 1; }
rm -f a.c &&
rcs -o2.2: $q a.c &&
co $q a.c &&
$diff a.kv a.c || { echo "#rcs -o failed"; exit 1; }
$diff a.e a.c || { echo "#rcs -o failed"; exit 1; }
rcsdiff -r1.1 -r2.1 $q a.c >a.0
rcsdiff -r1.1 -rOz $q a.c >a.0
case $? in
1) ;;
*) echo "#rcsdiff bad status"; exit 1
@ -286,12 +290,43 @@ for i in k kv kvl o v
do
rm -f a.c &&
cp a.$i a.c &&
rcsdiff -k$i $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; }
rcsdiff -k$i -rOz $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; }
done
co -p1.1 -ko $q a.c >a.t &&
$diff a.11 a.t || { echo "#co -p1.1 -ko failed"; exit 1; }
rcs -u2.1 $q a.c || { echo "#rcs -u2.1 failed"; exit 1; }
rm -f a.c &&
rcsclean $q a.c &&
rcsclean -u $q a.c || { echo "#rcsclean botched a nonexistent file"; exit 1; }
rm -f a.c &&
co $q a.c &&
rcsclean -n $q a.c &&
rcsclean -n -u $q a.c &&
test -f a.c || { echo "#rcsclean -n removed a file"; exit 1; }
rm -f a.c &&
co $q a.c &&
rcsclean $q a.c &&
test ! -f a.c || { echo "#rcsclean missed an unlocked file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
rcsclean $q a.c &&
test -f a.c || { echo "#rcsclean removed a locked file"; exit 1; }
rcsclean -u $q a.c &&
test ! -f a.c || {
echo "#rcsclean -u missed an unchanged locked file"; exit 1;
}
rm -f a.c &&
co -l $q a.c &&
echo change >>a.c &&
rcsclean $q a.c &&
rcsclean $q -u a.c &&
test -f a.c || { echo "#rcsclean removed a changed file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
cat >a.c <<'EOF'
@ -324,7 +359,7 @@ b1
c
d1
EOF
rcsmerge -r2.2 -r2.3 $q a.c
rcsmerge -E -r2.2 -r2.3 $q a.c
case $? in
0)
if $diff a.0 a.c >/dev/null
@ -343,16 +378,36 @@ case $? in
echo "#rcsmerge bad status"; exit 1
esac
nl='
'
# Avoid `tr' if possible; it's not portable, and it can't handle null bytes.
# Our substitute exclusive-ORs with '\n';
# this ensures null bytes on output, which is even better than `tr',
# since some diffs think a file is binary only if it contains null bytes.
cat >a.c <<'EOF'
#include <stdio.h>
int main() {
int c;
while ((c=getchar()) != EOF)
putchar(c ^ '\n');
return 0;
}
EOF
tr=tr
if (rm -f a.exe a.out && $CL a.c $L >&2) >/dev/null 2>&1
then
if test -s a.out
then tr=./a.out
elif test -s a.exe
then tr=./a.exe
fi
fi
{
co -p $q a.c | tr "$nl" '\200' >a.24 &&
co -p $q a.c | $tr '\012' '\200' >a.24 &&
cp a.24 a.c &&
ciOut=`(ci -l -mm $q a.c 2>&1)` &&
case $ciOut in
?*) echo >&2 "$ciOut"
esac &&
co -p $q a.c | tr '\200' "$nl" >a.c &&
co -p $q a.c | $tr '\200' '\012' >a.c &&
rcsdiff -r2.3 $q a.c >/dev/null &&
echo 2.5 >a.c &&
@ -378,15 +433,15 @@ locks: strict
access list:
symbolic names:
N: 2.1
Oz: 2.1
n: 1.8
comment leader: ":::"
keyword substitution: kv
total revisions: 13; selected revisions: 1
description:
1.1
----------------------------
revision 2.1
date: $D $T; author: w; state: s; lines: +13 -1
date: $date; author: w; state: s; lines: +14 -1
=============================================================================
EOF
test $? = 0 || { echo "#rlog failed"; exit 1; }
@ -394,4 +449,5 @@ test $? = 0 || { echo "#rlog failed"; exit 1; }
test ! -f $lockfile || { echo "#lock file not removed"; exit 1; }
exec rm -f a.* $RCSfile $RCS_alt
rm -f a.* $RCSfile $RCS_alt
$rmdir RCS