brent@capmkt.COM (Brent Chapman) (08/03/89)
It seems to me that many people and organizations, over the past few years, must have written tools to augment and compliment RCS. If you have, I urge you to consider sharing your tools with the rest of us, before we all go out and "reinvent the wheel". Things I'm particularly interested in include, but aren't necessarily limited to, the following: + A report of files in a source tree that are currently checked out, by who, and since when. + A report of files in a source tree that have not yet been placed under RCS control. + Tools for creating, managing, and using "S-lists", or lists of the various components (and the version of each of those components) in a given product. Thanks! -Brent -- Brent Chapman Capital Market Technology, Inc. Computer Operations Manager 1995 University Ave., Suite 390 brent@capmkt.com Berkeley, CA 94704 {apple,lll-tis,uunet}!capmkt!brent Phone: 415/540-6400
len@array.UUCP (Leonard Vanek) (08/04/89)
In article <342@capmkt.COM> brent@capmkt.COM (Brent Chapman) writes: >It seems to me that many people and organizations, over the past few >years, must have written tools to augment and compliment RCS. If you >have, I urge you to consider sharing your tools with the rest of us, >before we all go out and "reinvent the wheel". Things I'm particularly >interested in include, but aren't necessarily limited to, the following: > > + A report of files in a source tree that are currently checked out, > by who, and since when. > > + A report of files in a source tree that have not yet been placed > under RCS control. > > + Tools for creating, managing, and using "S-lists", or lists of the > various components (and the version of each of those components) in > a given product. > The following shell/awk script partially satisifies your first request. To get what you want you would have to modify the awk script to skip records containing a null "locked by" field. Actually, I would do this by passing it through awk twice, the first time as shown below (which reduces each file to a single record) and then another pass to select the records of interest. With shell and awk scripts it is possible to produce lots of interesting reports, such as a tabular revision history for a single file or a list sorted by latest revision date. I have also included shell scripts for these. Of course, these tools can only produce what is already present in the RCS files, so they cannot help in your second request and I am not sure about the third one. Perhaps using special naming conventions can encode what you want in the RCS files, so that a script can be used to produce the desired report. --------------------------- cut here ------------------------------ #! /bin/sh # Tabular list of RCS files # Usage: trlst path_to_project_library # rlog /usr2/YOUR_BASE_PATH/$1/RCS/*,v | awk '\ BEGIN {print "\n Configuration Listing\n";\ print "file name revision locked by date and time revised";\ print "--------- -------- --------- ---------------------"}\ /RCS file:/ {printf "%-16s ", $6; flag = 0}\ /^head:/ {printf "%6s ", $2}\ /^locks:/ {if ($2==";") $2=" "; printf "%-9s ", $2}\ /^date:/ {if (flag==0) {\ printf " %-s %-s\n", $2, substr($3,1,8);\ flag = 1\ } } END {print " "}' --------------------------- cut here ------------------------------ #! /bin/sh # Tabular list of RCS files sorted by last modification date # Usage: traged path_to_project_library # echo echo " Configuration Listing by Date and Time" echo echo "file name revision locked by date and time revised" echo "--------- -------- --------- ---------------------"; rlog /usr2/YOUR_BASE_PATH/$1/RCS/*,v | awk '\ /RCS file:/ {printf "%-16s ", $6; flag = 0}\ /^head:/ {printf "%6s ", $2}\ /^locks:/ {if ($2==";") $2=" "; printf "%-9s ", $2}\ /^date:/ {if (flag==0) {\ printf " %-s %-s\n", $2, substr($3,1,8);\ flag = 1\ } }' | sort +0.36 echo --------------------------- cut here ------------------------------ #! /bin/sh # Tabular revision history of a single RCS file # Usage: trhist filename path_to_project_library # echo echo Revision history summary of $1 echo rlog /usr2/YOUR_BASE_PATH/$2/RCS/$1,v | awk '\ /^description:/ {flag=1; next} {if (flag==1) {print;\ printf "\n";\ printf "revision date time who description\n";\ printf "-------- -------- -------- ----- -----------\n";\ flag=0}\ }\ /^revision / {printf "%-6s ", $2}\ /^date: / {printf "%4s %4s %-6s ", $2, substr($3,1,8), $5; flag=2; next}\ {if (flag==2) {printf "%-40s\n", substr($0,1,40);\ printf "%34s%-40s\n", " ", substr($0,41,40); flag=0}\ }' --------------------------- cut here ------------------------------ Leonard Vanek UUCP: ... uunet!attcan!lsuc!array!len Array Systems Computing Inc. or ... utzoo!dciem!array!len 5000 Dufferin St. Suite 200 or lsuc!array!len@ai.toronto.edu Downsview, Ont. M3H 5T5 Phone: (416) 736-0900 Canada FAX: (416) 736-4715
len@array.UUCP (Leonard Vanek) (08/04/89)
In article <49@array.UUCP> I (len@array.UUCP) wrote: >The following shell/awk script partially satisifies your first >request. > I have also included >shell scripts for these. > Sorry about the embedded tabs. I normally edit using tabstops of 4, so they look alright when I edit the scripts. You can replace each tab by four blanks to make the scripts read better, Leonard Vanek UUCP: ... uunet!attcan!lsuc!array!len Array Systems Computing Inc. or ... utzoo!dciem!array!len 5000 Dufferin St. Suite 200 or lsuc!array!len@ai.toronto.edu Downsview, Ont. M3H 5T5 Phone: (416) 736-0900 Canada FAX: (416) 736-4715
diomidis@ecrcvax.UUCP (Diomidis Spinellis) (08/09/89)
In article <342@capmkt.COM> brent@capmkt.COM (Brent Chapman) writes: >It seems to me that many people and organizations, over the past few >years, must have written tools to augment and compliment RCS. If you >have, I urge you to consider sharing your tools with the rest of us, >before we all go out and "reinvent the wheel". > [...] I am including the source and manual pages for three tools that can be helpful when using RCS. - Rcstell reports files checked out as locked and optionaly their lockers. - Slist helps creating S-lists, for sets of files, or executables. - Rcsclean removes all files that can be recreated by RCS. I have used these scripts over some time and they function for the style of work I do. They have not been tested in other working environments. >-Brent Diomidis #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # rcsclean # rcsclean.1 # rcstell # rcstell.1 # slist # slist.1 # This archive created: Mon Aug 7 17:00:49 1989 export PATH; PATH=/bin:$PATH echo shar: extracting "'rcsclean'" '(471 characters)' if test -f 'rcsclean' then echo shar: will not over-write existing file "'rcsclean'" else sed 's/^X//' << \SHAR_EOF > 'rcsclean' X#!/bin/sh - X# X# Delete RCS files that can be safelly recreated by RCS using co. X# X# (C) Copyright 1989 Diomidis Spinellis. All rights reserved. X# Permission to copy for any purpose is hereby granted so long X# as this copyright notice remains intact. X# Xrlog -h RCS/*,v *,v 2>/dev/null | Xawk ' X/^RCS file:/ { fname = $6 } X/^locks:/ { X if( NF == 3 ) X printf "test -r %s && co -p %s 2>/dev/null | diff - %s >/dev/null && rm '$*' %s\n", fname, fname, fname, fname X}' | Xsh SHAR_EOF if test 471 -ne "`wc -c < 'rcsclean'`" then echo shar: error transmitting "'rcsclean'" '(should have been 471 characters)' fi chmod +x 'rcsclean' fi # end of overwriting check echo shar: extracting "'rcsclean.1'" '(1272 characters)' if test -f 'rcsclean.1' then echo shar: will not over-write existing file "'rcsclean.1'" else sed 's/^X//' << \SHAR_EOF > 'rcsclean.1' X.\" Copyright (C) 1989 Diomidis Spinellis. All rights reserved. X.\" Permission to copy for any purpose is hereby granted so long X.\" as this copyright notice remains intact. X.\" X.TH RCSCLEAN 1 "Jun 14, 1989" X.UC 4 X.SH NAME Xrcsclean \- delete files that can be recreated by co X.SH SYNOPSIS X.B rcsclean X[ X.B rm options X] X.br X.SH DESCRIPTION X.I Rcsclean Xdeletes any files in the current directory that can be recreated Xby checking out the latest version of the revision tree. XIt is conservative in its approach, comparing only unlocked files ending in X.I ,v Xin the current and the X.I './RCS' Xdirectories against the working versions. X.PP XAny of the rm options can be given as options to X.I rcsclean. XIn particular the X.B \-f Xoption can be used to force the deletion of all files without Xasking and the X.B \-i Xoption for interactive prompting before each deletion. X.PP X.SH FILES X.I *,v RCS/*,v XThe files examined. X.SH AUTHOR XDiomidis Spinellis (dds@cc.ic.ac.uk) X.SH "SEE ALSO" Xrcs(1), co (1), ci (1), rlog (1). X.sp 0 XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. X.SH BUGS XDepends a lot on the format of the X.I rlog Xoutput. SHAR_EOF if test 1272 -ne "`wc -c < 'rcsclean.1'`" then echo shar: error transmitting "'rcsclean.1'" '(should have been 1272 characters)' fi fi # end of overwriting check echo shar: extracting "'rcstell'" '(918 characters)' if test -f 'rcstell' then echo shar: will not over-write existing file "'rcstell'" else sed 's/^X//' << \SHAR_EOF > 'rcstell' X#!/bin/sh X# X# Tell what rcs files are currently being edited (ie. are `locked' out) X# X# (C) Copyright 1988 D. Spinellis. All rights reserved. X# Permission to copy for any purpose is hereby granted so long X# as this copyright notice remains intact. X# Xcase $# in X0) X rlog -L -h RCS/*,v *,v 2>/dev/null | X sed -n -e '/^RCS file:/s/.*Working file:[ ]*\(.*\)$/\1/p' X ;; X1) X case $1 in X -l) X rlog -L -h RCS/*,v *,v 2>/dev/null | X sed -n -e ' X /^RCS file:/s/.*Working file:[ ]*\(.*\)$/\1/p X /locks:/s/^locks:[ ]*\([^:]*\):[ ]\([^;]*\).*/\1 \2/p X ' | X while read FNAME && read LOCKER REV X do X echo $FNAME $REV $LOCKER ` X ( X ypmatch $LOCKER passwd || X egrep "^$LOCKER:" /etc/passwd X ) 2>/dev/null | X sed 's/[^:]*:[^:]*:[^:]*:[^:]*:\([^,:]*\).*$/(\1)/' X ` X done X ;; X *) X echo 1>&2 "Usage `basename $0` [-l]" ; exit 1 X ;; X esac X ;; X*) X echo 1>&2 "Usage `basename $0` [-l]" ; exit 1 X ;; Xesac SHAR_EOF if test 918 -ne "`wc -c < 'rcstell'`" then echo shar: error transmitting "'rcstell'" '(should have been 918 characters)' fi chmod +x 'rcstell' fi # end of overwriting check echo shar: extracting "'rcstell.1'" '(1231 characters)' if test -f 'rcstell.1' then echo shar: will not over-write existing file "'rcstell.1'" else sed 's/^X//' << \SHAR_EOF > 'rcstell.1' X.\" Copyright (C) 1988 Diomidis Spinellis. All rights reserved. X.\" Permission to copy for any purpose is hereby granted so long X.\" as this copyright notice remains intact. X.\" X.TH RCSTELL 1 "Nov 11, 1988" X.UC 4 X.SH NAME Xrcstell \- tell which RCS files are checked out as locked X.SH SYNOPSIS X.B rcstell X[ X.B \-l X] X.br X.SH DESCRIPTION X.I Rcstell Xprints a list of any files that are checked out as locked in the Xcurrent directory. It does so by examining all the files ending in X.I ,v Xin the current and the X.I './RCS' Xdirectories. X.PP XThe X.B \-l Xoption displays a longer output that consists of the file name, the Xrevision name, the locker login name and the locker real name for Xeach locked file. X.PP X.SH FILES X.I *,v RCS/*,v XThe files examined. X.SH AUTHOR XDiomidis Spinellis (dds@cc.ic.ac.uk) X.SH "SEE ALSO" Xrcs(1), co (1), ci (1), rlog (1). X.sp 0 XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. X.SH BUGS XDepends a lot on the format of the X.I rlog Xoutput as well as the the X.I passwd Xfile. In particular it uses the ``,'' to distinguish the real name from the X.I GCOS Xfield. SHAR_EOF if test 1231 -ne "`wc -c < 'rcstell.1'`" then echo shar: error transmitting "'rcstell.1'" '(should have been 1231 characters)' fi fi # end of overwriting check echo shar: extracting "'slist'" '(802 characters)' if test -f 'slist' then echo shar: will not over-write existing file "'slist'" else sed 's/^X//' << \SHAR_EOF > 'slist' X#!/bin/sh X# X# Create a list of files and their revisions. X# X# (C) Copyright 1989 Diomidis Spinellis. All rights reserved. X# Permission to copy for any purpose is hereby granted so long X# as this copyright notice remains intact. X# Xcase $# in X0) X echo 1>&2 "Usage `basename $0` [-h] file ..." ; exit 1 X ;; X1) X case $1 in X -*) X echo 1>&2 "Usage `basename $0` [-h] file ..." ; exit 1 X ;; X *) X ident $* | X awk '/\$Header/ {print substr($2, 1, length($2)-2), $3}' | X sort -u X ;; X esac X ;; X*) X case $1 in X -h) X rlog -h $* | X awk '/^RCS file/ {printf "%s ", substr($3, 5, length($3)-7)} /^head:/ { print $2}' | X sort -u X ;; X -*) X echo 1>&2 "Usage `basename $0` [-h] file ..." ; exit 1 X ;; X *) X ident $* | X awk '/\$Header/ {print substr($2, 1, length($2)-2), $3}' | X sort -u X ;; X esac X ;; Xesac SHAR_EOF if test 802 -ne "`wc -c < 'slist'`" then echo shar: error transmitting "'slist'" '(should have been 802 characters)' fi chmod +x 'slist' fi # end of overwriting check echo shar: extracting "'slist.1'" '(1778 characters)' if test -f 'slist.1' then echo shar: will not over-write existing file "'slist.1'" else sed 's/^X//' << \SHAR_EOF > 'slist.1' X.\" Copyright (C) 1989 Diomidis Spinellis. All rights reserved. X.\" Permission to copy for any purpose is hereby granted so long X.\" as this copyright notice remains intact. X.\" X.TH SLIST 1 "Aug 7, 1989" X.UC 4 X.SH NAME Xslist \- display the names and revision numbers of RCS files X.SH SYNOPSIS X.B slist X[ X.B \-h X] file ... X.br X.SH DESCRIPTION X.I Slist Xprints the names and revision numbers of the files given as arguments. X.PP XThe X.B \-h Xoption prints the revision number of the latest file in the trunk, Xthus an slist of the X.I head X(frontier) of the RCS tree is printed. This is useful for comparing against Xthe output of X.I slist Xfrom an executable to check that the latest revisions were indeed used. X.PP XIf the X.B \-h Xoption is not used then the file name arguments need be Xworking or executable Xfile names containing valid X.I Header Xidentifiers. X.SH EXAMPLES XCreate an slist from an executable: X.RS X.nf X.ft B X% slist executable >executable.slist X.ft R X.RE X.br X.ne 4 XCompare the working files against the latest revisions: X.RS X.nf X.ft B X% slist -h RCS/*.c,v >latest.slist X% slist *.c | diff - latest.slist X.ft R X.fi X.RE X.SH DIAGNOSTICS XComplaints from ident for files not containing identifiers. X.br XComplaints from rlog about non-existing RCS files. X.SH AUTHOR XDiomidis Spinellis (dds@cc.ic.ac.uk) X.SH "SEE ALSO" Xrcs(1), co (1), ci (1), rlog (1), ident(1). X.sp 0 XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. X.SH BUGS XDepends a lot on the format of the X.I rlog Xand X.I ident Xoutput. X.PP XIf a file contains no header keyword, but contains other keywords no Xentry will be generated for that file, unless X.B \-h Xis used. SHAR_EOF if test 1778 -ne "`wc -c < 'slist.1'`" then echo shar: error transmitting "'slist.1'" '(should have been 1778 characters)' fi fi # end of overwriting check # End of shell archive exit 0 -- Diomidis Spinellis European Computer-Industry Research Centre (ECRC) Arabellastrasse 17, D-8000 Muenchen 81, West Germany +49 (89) 92699199 USA: diomidis%ecrcvax.uucp@pyramid.pyramid.com ...!pyramid!ecrcvax!diomidis Europe: diomidis@ecrcvax.uucp ...!unido!ecrcvax!diomidis
johnm@occam.ksr.com (John Martin) (08/11/89)
In article <342@capmkt.COM> brent@capmkt.COM (Brent Chapman) requests: > > + A report of files in a source tree that are currently checked out, > by who, and since when. > > + A report of files in a source tree that have not yet been placed > under RCS control. > > + Tools for creating, managing, and using "S-lists", or lists of the > various components (and the version of each of those components) in > a given product. > len@array.UUCP (Leonard Vanek) has recently provided a set of scripts that can be used for the first of these. Below I provide a UNIX script that I sometimes use to perform the second. I've added some comments to help any non-experts who want to modify it. It runs for me on Sun-3's and -4's; I'd expect any BSD4.x-derived *X to do OK on it, and I think it would work on a SysV system but don't have one handy to try it out. With that caveat: --------------------------- cut here ------------------------------ #! /bin/sh # # find .c, .h, and [Mm]akefile without RCS equivalents # Usage: norcs [srcdir] [-r rcsdirspec] [-s wildfilespec] [-v] # Defaults to norcs . -r RCS # # # John Martin, Kendall Square Research Corp., Waltham, MA # # defaults() { srcdir="${srcdir:-.}" rcsdir="${rcsdir:-RCS}" srcspec="${srcpec:-*.[ch] [Mm]akefile}" } # usage() { echo "Usage: norcs [srcdirs] [-s srcspec] [-r rcsdirspec ] [-v]" echo "Deflt: norcs . -r RCS -s \"*.[ch] [Mm]akefile\"" echo " You may have multiple -s and -r options; remember to quote srcspecs" echo " to avoid immediate filename expansion." exit 1 } # verbose() { if [ -z "$vbose" ]; then return 1; else return 0; fi } # # parse the args; you can give as many specs as you want for the source # and for the RCS specs (i.e., you can do something like # norcs src/* -r RCS -r /usr/local/include/RCS ) # while [ ! -z "$1" ]; do if [ $1 = "-v" ]; then vbose=T shift elif [ $1 = "-s" ]; then if [ -z "$2" ]; then usage; fi srcspec="$srcspec $2" shift 2 elif [ $1 = "-r" ]; then if [ -z "$2" ]; then usage; fi rcsdir="$rcsdir $2" shift 2 else srcdir="$srcdir $1" shift fi done # load defaults for anything not found above defaults if verbose; then echo "Source spec: < $srcspec >" echo "Source dirs: < $srcdir >" echo "RCSfile dirs: < $rcsdir >" echo "" fi origdir=`pwd` # for sd in $srcdir; do # # only report nonexistent source dir's if verbose (makes a better filter) # cd $origdir if [ ! -d $sd ]; then if verbose; then echo "($sd is not a directory)"; fi continue fi # cd $sd # The shell's filename expansion will leave things it can't find; "*.c *.h" # may expand to "a.c b.c *.h". Accordingly, first we check that # "file" is actually a file. The -f establishes that file isn't too # weird, like a directory. However, a symbolic link to a plain file is # OK with -f, and we're not interested in symbolic links, so we check # that separately. Then we see if the RCS file exists somewhere in # rcsdir (normally the ./RCS directory relative to the source dir, but # bigger projects may have special tools and rules). # Some folks might want to test "-w", on the theory that a file that's # read-only doesn't need to be checked for RCSness. That can be a # bad idea in some development environments, so this script checks # everything. # for file in $srcspec; do if [ ! -f "$file" ]; then continue; fi if [ -h $file ]; then continue; fi for rd in $rcsdir; do if [ -d "$rd" ]; then if [ -f $rd/$file,v ]; then continue 2; fi else if verbose; then echo " ($rd is not a directory for $sd)"; fi fi done # rd (RCS directory) # # if we didn't "continue 2", we didn't find the RCS file, so say the name. echo $sd/$file # done # file # done # sd (source directory) # # EOF norcs --------------------------- cut here ------------------------------ John H. Martin harvard!ksr!johnm Kendall Square Research Corporation johnm@ksr.com 170 Tracer Lane Waltham, MA 02154 "A creative economy is the fuel of magnificence." -- Emerson Disclaimer: My only organizationally-endorsed position is prone.
scs@adam.pika.mit.edu (Steve Summit) (08/18/89)
In article <342@capmkt.COM> brent@capmkt.COM (Brent Chapman) writes: >It seems to me that many people and organizations, over the past few >years, must have written tools to augment and compliment RCS. Here's one I threw together some years ago. It performs rlog's on multiple files, shuffling all of the logs together and sorting on the time. Performed on all RCS files in a project directory, usually with a command like cd RCS; rcshist *,v , this command gives you a chronological listing of everything that's been done to any of the source files. This code was built under 4bsd and has not, as yet, been ported much. No particular efforts were expended to ensure its widespread portability, other than my usual care, so it may need slight adjustments to run in your environment. Beware: it's a memory hog; I wrote it on a virtual memory system and took advantage of that fact. All of the log messages for all the revisions of all of the files being examined are kept in memory for sorting, which can be a considerable amount of text for a large project with frequent checkins. The usual disclaimers apply: if you find this code useful, you're welcome to it, but if you spread it around, please leave my name on it. Steve Summit scs@adam.pika.mit.edu -------8<--------8<--------8<--------8<--------8<--------8<------ echo extracting rcshist.c sed 's/^X//' > rcshist.c <<\% X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X X/* X * rcshist RCSfiles X * X * Performs rlog's on multiple files, shuffling all of the logs X * together and sorting on the time. Performed on all RCS files X * in a project directory, gives a chronological listing of X * everything that's been done to any of the source files. X * X * Usual usage is something like X * X * cd RCS X * rcshist *,v X * X * Steve Summit 1/5/87 X */ X X#define TRUE 1 X#define FALSE 0 X X#define SEP "----------------------------" X Xstruct logmess X { X time_t date; X char **text; X int ntext; X } *messages = NULL; X Xint nmess = 0; Xint allocmess = 0; X Xint messcmp(); Xchar *alloc(); Xextern time_t makedate(); X Xextern char *index(); Xextern char *malloc(); Xextern FILE *popen(); Xextern char *realloc(); Xextern char *strcpy(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ Xchar *p; Xint i, j; Xstruct logmess *messp; X Xwhile(argc > 1 && argv[1][0] == '-') X { X for(p = &argv[1][1]; *p != '\0'; p++) X { X switch(*p) X { X default: X fprintf(stderr, "rcshist: unknown flag -%c\n", X *p); X } X } X X argv++; X argc--; X } X Xif(argc < 2) X { X fprintf(stderr, "usage: rcshist rcsfiles...\n"); X exit(1); X } X Xfor(i = 1; i < argc; i++) X rlog(argv[i]); X Xqsort((char *)messages, nmess, sizeof(struct logmess), messcmp); X Xfor(i = 0; i < nmess; i++) X { X if(i > 0) X printf("%s\n", SEP); X messp = &messages[i]; X for(j = 0; j < messp->ntext; j++) X printf("%s\n", messp->text[j]); X } X Xexit(0); X} X Xrlog(rcsname) Xchar *rcsname; X{ Xchar command[200]; XFILE *fd; Xchar buf[BUFSIZ]; Xchar *line; Xint r; Xint lineno; Xint year, month, day; Xint hour, minute, second; Xstruct logmess *messp; X X(void)sprintf(command, "rlog %s", rcsname); X Xif((fd = popen(command, "r")) == NULL) X { X fprintf(stderr, "rcshist: can't popen %s\n", command); X exit(1); X } X Xlineno = 0; X Xwhile(getline(fd, buf, BUFSIZ) != EOF) X { X if(strncmp(buf, "==========", 10) == 0) X break; X X if(strncmp(buf, SEP, sizeof(SEP) - 1) == 0) X { X if(nmess >= allocmess) X { X allocmess += 10; X messages = (struct logmess *) X realloc((char *)messages, X allocmess * sizeof(struct logmess)); X if(messages == NULL) X { X fprintf(stderr, "rcshist: out of memory\n"); X exit(1); X } X } X X messp = &messages[nmess]; X X messp->text = NULL; X messp->ntext = 0; X X nmess++; X X lineno = 1; X continue; X } X X switch(lineno) X { X case 0: /* somewhere in header */ X continue; X X case 1: /* revision line */ X line = alloc(strlen(rcsname) + 1 + strlen(buf) + 1); X (void)sprintf(line, "%s %s", rcsname, buf); X break; X X case 2: /* date/author line */ X X r = sscanf(buf, "date: %d/%d/%d %d:%d:%d;", X &year, &month, &day, &hour, &minute, &second); X X if(r != 6) X fprintf(stderr, X "rcshist: garbage in rlog: \"%s\"\n", X buf); X else messp->date = X makedate(year, month, day, X hour, minute, second); X /* FALL THROUGH */ X X default: /* log message */ X line = alloc(strlen(buf) + 1); X (void)strcpy(line, buf); X } X X messp->text = (char **)realloc((char *)messp->text, X (messp->ntext + 1) * sizeof(char **)); X X messp->text[messp->ntext] = line; X messp->ntext++; X X lineno++; X } X Xpclose(fd); X} X Xmesscmp(m1, m2) Xstruct logmess *m1, *m2; X{ Xif(m1->date < m2->date) X return(-1); X Xif(m1->date > m2->date) X return(1); X Xreturn(strcmp(m1->text[0], m2->text[0])); X} X Xchar * Xalloc(size) Xint size; X{ Xchar *ret; X Xret = malloc((unsigned)size); X Xif(ret == NULL) X { X fprintf(stderr, "rcshist: out of memory\n"); X exit(1); X } X Xreturn(ret); X} % chmod 644 rcshist.c if test `wc -c < rcshist.c` -ne 3486; then echo "error extracting rcshist.c" 1>&2 fi echo extracting Makefile sed 's/^X//' > Makefile <<\% XCFLAGS = -DBSD42 X Xrcshist: rcshist.o makedate.o getline.o X cc -o rcshist rcshist.o makedate.o getline.o X Xmdt: mdt.o makedate.o getline.o X cc -o mdt mdt.o makedate.o getline.o % chmod 644 Makefile if test `wc -c < Makefile` -ne 175; then echo "error extracting Makefile" 1>&2 fi echo extracting makedate.c sed 's/^X//' > makedate.c <<\% X#include <sys/types.h> X#include <sys/timeb.h> X#ifndef BSD42 X#include <time.h> X#else X#include <sys/time.h> /* !@#$^%* berkeley 4.2... */ X#endif X Xextern struct tm *localtime(); X Xint mday[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; X Xtime_t Xmakedate(year, month, day, hour, minute, second) Xint year, month, day; Xint hour, minute, second; X{ Xtime_t ret; Xint i; Xstruct timeb tp; X Xret = (year - 70) * 365; Xret += (year - 69) / 4; /* leap years in previous years */ Xfor(i = 1; i < month; i++) X ret += mday[i]; Xif(year % 4 == 0 && month > 2) X ret++; Xret += day - 1; Xret *= 24; Xret += hour; Xret *= 60; Xret += minute; Xftime(&tp); Xret += tp.timezone; Xret *= 60; Xret += second; X Xret -= 60 * 60; /* assume dst */ X Xif(!localtime(&ret)->tm_isdst) X ret += 60 * 60; /* it wasn't */ X Xreturn(ret); X} % chmod 644 makedate.c if test `wc -c < makedate.c` -ne 797; then echo "error extracting makedate.c" 1>&2 fi echo extracting getline.c sed 's/^X//' > getline.c <<\% X/* X * reads from fi until newline or EOF. Puts at most max characters (but never X * the newline) into string and appends \0. Returns number of characters in X * string, exclusive of \0. (i.e. returns 0 for blank line terminated by X * newline.) Reads properly a string terminated with an EOF, but returns EOF X * on a blank line with no newline, terminated with an EOF. X */ X X#include <stdio.h> X Xgetline(fi, string, max) XFILE *fi; Xchar string[]; Xregister int max; X{ Xregister int i; Xregister int c; Xi = 0; Xwhile((c = getc(fi)) != EOF && c != '\n') if(i < max) string[i++] = c; Xstring[i] = '\0'; Xreturn(c == EOF && i == 0 ? EOF : i); X} % chmod 644 getline.c if test `wc -c < getline.c` -ne 634; then echo "error extracting getline.c" 1>&2 fi