[comp.sources.amiga] v89i227: rcs - revision control system, Part12/14

page%swap@Sun.COM (Bob Page) (11/19/89)

Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
Posting-number: Volume 89, Issue 227
Archive-name: unix/rcs.12

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	rcs/rcs.rcsfiles/snoop.c,v
#	rcs/rcs.rcsfiles/time.h,v
#	rcs/rcs.rcsfiles/rcsfreeze.sh,v
#	rcs/rcs.rcsfiles/amiga.c,v
#	rcs/rcs.rcsfiles/stat.h,v
#	rcs/rcs.rcsfiles/ci.c,v
# This is archive 12 of a 14-part kit.
# This archive created: Sun Nov 19 01:12:12 1989
if `test ! -d rcs`
then
  mkdir rcs
  echo "mkdir rcs"
fi
if `test ! -d rcs/rcs.rcsfiles`
then
  mkdir rcs/rcs.rcsfiles
  echo "mkdir rcs/rcs.rcsfiles"
fi
echo "extracting rcs/rcs.rcsfiles/snoop.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/snoop.c,v
Xhead     4.4;
Xbranch   4.4.2;
Xaccess   ;
Xsymbols  amiga_rcs:4.4.2 cbmvax_source:4.4.1 uunet_june89_dist:4.4;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X4.4
Xdate     89.05.01.15.14.00;  author narten;  state Exp;
Xbranches 4.4.1.1 4.4.2.1;
Xnext     ;
X
X4.4.1.1
Xdate     89.08.11.01.43.23;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X4.4.2.1
Xdate     89.10.13.19.19.37;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.4.2.2;
X
X4.4.2.2
Xdate     89.10.15.15.45.25;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@Logging of RCS commands co and ci.
X@
X
X
X
X4.4
Xlog
X@checked in with -k by rsbx at 89.08.10.16.23.48.
X@
Xtext
X@/*
X *                     Logging of RCS commands co and ci
X */
X#ifndef lint
X static char rcsid[]=
X "$Header: /usr/src/local/bin/rcs/src/RCS/snoop.c,v 4.4 89/05/01 15:14:00 narten Exp $ Purdue CS";
X#endif
X/*******************************************************************
X * This program appends argv[1] to the file SNOOPFILE.
X * To avoid overlaps, it creates a lockfile with name lock in the same
X * directory as SNOOPFILE. SNOOPFILE must be defined in the cc command. 
X * Prints an error message if lockfile doesn't get deleted after
X * MAXTRIES tries.
X *******************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X *   rcs-bugs@@cs.purdue.edu
X * 
X
X
X
X
X
X
X
X*/
X
X
X/* $Log:	snoop.c,v $
X * Revision 4.4  89/05/01  15:14:00  narten
X * changed copyright header to reflect current distribution rules
X * 
X * Revision 4.3  87/12/18  11:46:52  narten
X * more lint cleanups (Guy Harris)
X * 
X * Revision 4.2  87/10/18  10:41:47  narten
X * Changing version numbers. Changes relative to 1.1 actually relative to 
X * 4.1
X * 
X * Revision 1.2  87/09/24  14:01:41  narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
X * warnings)
X * 
X * Revision 1.1  84/01/23  14:50:49  kcs
X * Initial revision
X * 
X * Revision 4.1  83/03/28  13:23:42  wft
X * No change; just new revision number.
X * 
X * Revision 3.2  82/12/04  17:14:31  wft
X * Added rcsbase.h, changed SNOOPDIR to SNOOPFILE, reintroduced
X * error message in case of permanent locking.
X * 
X * Revision 3.1  82/10/18  21:22:03  wft
X * Number of polls now 20, no error message if critical section can't
X * be entered.
X * 
X * Revision 2.3  82/07/01  23:49:28  wft
X * changed copyright notice only.
X * 
X * Revision 2.2  82/06/03  20:00:10  wft
X * changed name from rcslog to snoop, replaced LOGDIR with SNOOPDIR.
X * 
X * Revision 2.1  82/05/06  17:55:54  wft
X * Initial revision
X *
X */
X
X
X#include "rcsbase.h"
X#define fflsbuf _flsbuf
X/* undo redefinition of putc in rcsbase.h */
X
Xchar  lockfname[NCPPN];
XFILE * logfile;
Xint lockfile;
X
X#define MAXTRIES 20
X
Xmain(argc,argv)
Xint argc; char * argv[];
X/* writes argv[1] to SNOOPFILE and appends a newline. Invoked as follows:
X * rcslog logmessage
X */
X{       int tries;
X        register char * lastslash, *sp;
X
X        VOID strcpy(lockfname,(char *) SNOOPFILE);
X        lastslash = sp = lockfname;
X        while (*sp) if (*sp++ =='/') lastslash=sp; /* points beyond / */
X        VOID strcpy(lastslash,",lockfile");
X        tries=0;
X        while (((lockfile=creat(lockfname, 000)) == -1) && (tries<=MAXTRIES)) {
X                tries++;
X                sleep(5);
X        }
X        if (tries<=MAXTRIES) {
X                VOID close(lockfile);
X                if ((logfile=fopen(SNOOPFILE,"a")) ==NULL) {
X                        VOID fprintf(stderr,"Can't open logfile %s\n",SNOOPFILE);
X                } else {
X                        VOID fputs(argv[1],logfile);
X                        VOID putc('\n',logfile);
X                        VOID fclose(logfile);
X                }
X                VOID unlink(lockfname);
X        } else {
X                VOID fprintf(stderr,"RCS logfile %s seems permanently locked.\n",SNOOPFILE);
X                VOID fprintf(stderr,"Please alert system administrator\n");
X        }
X}
X@
X
X
X4.4.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d6 1
Xa6 5
X<<<<<<< snoop.c
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/snoop.c,v 4.4.1.1 89/08/11 01:43:23 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/snoop.c,v 1.2 89/09/17 13:37:13 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa43 11
X<<<<<<< snoop.c
X * Revision 4.4.1.1  89/08/11  01:43:23  rsbx
X * Start of cbmvax RCS source branch.
X=======
X * Revision 1.2  89/09/17  13:37:13  rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA).  This version
X * compiles correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X * 
X<<<<<<< snoop.c
Xa44 3
X * checked in with -k by rsbx at 89.08.10.16.23.48.
X * 
X * Revision 4.4  89/05/01  15:14:00  narten
Xa45 4
X=======
X * Revision 1.2  88/09/03  15:13:53  rick
X * Port to AmigaDos.  All done with conditional compiles
X>>>>>>> 1.2
X@
X
X
X4.4.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d6 5
Xa10 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/snoop.c,v 4.4.2.1 89/10/13 19:19:37 rsbx Exp Locker: rsbx $ Purdue CS";
Xd48 1
Xa48 3
X * Revision 4.4.2.1  89/10/13  19:19:37  rsbx
X * Start of Amiga RCS port branch.
X * 
Xd51 6
Xd58 1
Xd64 4
X@
X
X
X4.4.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@d6 1
Xa6 1
X "$Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/snoop.c,v 4.4 89/05/01 15:14:00 narten Exp $ Purdue CS";
Xa43 3
X * Revision 4.4  89/05/01  15:14:00  narten
X * checked in with -k by rsbx at 89.08.10.16.23.48.
X * 
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/time.h,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/time.h,v
Xhead     1.1;
Xbranch   1.1.2;
Xaccess   ;
Xsymbols  amiga_rcs:1.1.2 cbmvax_source:1.1.1 uunet_june89_dist:1.1;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X1.1
Xdate     84.01.23.14.50.50;  author kcs;  state Exp;
Xbranches 1.1.1.1 1.1.2.1;
Xnext     ;
X
X1.1.1.1
Xdate     89.08.11.01.43.25;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X1.1.2.1
Xdate     89.10.13.19.16.42;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@Structure for use by time manipulation subroutines.
X@
X
X
X
X1.1
Xlog
X@Initial revision
X@
Xtext
X@
X/* Structure for use by time manipulating subroutines.
X * The following library routines use it:
X *	libc: ctime, localtime, gmtime, asctime
X *	libcx: partime, maketime (may not be installed yet)
X */
X
X#define TIMEID "$Id: time.h,v 1.1 84/01/23 14:50:50 kcs Exp $"
X
X/* $Log:	time.h,v $
X * Revision 1.1  84/01/23  14:50:50  kcs
X * Initial revision
X * 
X * Revision 1.1  82/05/06  11:34:29  wft
X * Initial revision
X * 
X */
X
Xstruct tm {     /* See defines below for allowable ranges */
X	int tm_sec;
X	int tm_min;
X	int tm_hour;
X	int tm_mday;
X	int tm_mon;
X	int tm_year;
X	int tm_wday;
X	int tm_yday;
X	int tm_isdst;
X	int tm_zon;	/* NEW: mins westward of Greenwich */
X	int tm_ampm;	/* NEW: 1 if AM, 2 if PM */
X};
X
X#define LCLZONE (5*60)	/* Until V7 ftime(2) works, this defines local zone*/
X#define TMNULL (-1)	/* Items not specified are given this value
X			 * in order to distinguish null specs from zero
X			 * specs.  This is only used by partime and
X			 * maketime. */
X
X	/* Indices into TM structure */
X#define TM_SEC 0	/* 0-59			*/
X#define TM_MIN 1	/* 0-59			*/
X#define TM_HOUR 2	/* 0-23			*/
X#define TM_MDAY 3	/* 1-31			day of month */
X#define TM_DAY TM_MDAY	/*  "			synonym      */
X#define TM_MON 4	/* 0-11			*/
X#define TM_YEAR 5	/* (year-1900) (year)	*/
X#define TM_WDAY 6	/* 0-6			day of week (0 = Sunday) */
X#define TM_YDAY 7	/* 0-365		day of year */
X#define TM_ISDST 8	/* 0 Std, 1 DST		*/
X	/* New stuff */
X#define TM_ZON 9	/* 0-(24*60) minutes west of Greenwich */
X#define TM_AMPM 10	/* 1 AM, 2 PM		*/
X@
X
X
X1.1.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d8 1
Xa8 1
X#define TIMEID "$Id: time.h,v 1.1.1.1 89/08/11 01:43:25 rsbx Exp Locker: rsbx $"
Xa10 6
X * Revision 1.1.1.1  89/08/11  01:43:25  rsbx
X * Start of cbmvax RCS source branch.
X * 
X * Revision 1.1  84/01/23  14:50:50  kcs
X * Initial revision
X * 
X@
X
X
X1.1.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a13 3
X * Revision 1.1  84/01/23  14:50:50  kcs
X * Initial revision
X * 
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsfreeze.sh,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfreeze.sh,v
Xhead     1.1;
Xbranch   1.1.2;
Xaccess   ;
Xsymbols  amiga_rcs:1.1.2 cbmvax_source:1.1.1 uunet_june89_dist:1.1;
Xlocks    ; strict;
Xcomment  @# @;
X
X
X1.1
Xdate     89.08.10.16.29.10;  author rsbx;  state Exp;
Xbranches 1.1.1.1 1.1.2.1;
Xnext     ;
X
X1.1.1.1
Xdate     89.08.11.01.42.39;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X1.1.2.1
Xdate     89.10.13.19.20.11;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@RCS rcsfreeze operation.
X@
X
X
X
X1.1
Xlog
X@Initial revision
X@
Xtext
X@#! /bin/sh
XPATH=/usr/local/bin:/bin:/usr/bin:/usr/ucb
X#       'rcsfreeze' has the purpose of assigning a symbolic revision
X#       number to a set of RCS files, which form a valid configuration.
X#
X#       The idea is to run rcsfreeze each time a new version is checked
X#       in. A unique symbolic revision number (C_[number], where number
X#       is increased each time rcsfreeze is run) is then assigned to the most
X#       recent revision of each RCS file of the main trunk.
X#
X#       If the command is invoked with an argument, then this
X#       argument is used as the symbolic name to freeze a configuration.
X#       The unique identifier is still generated
X#       and is listed in the log file but it will not appear as
X#       part of the symbolic revision name in the actual RCS file.
X#
X#       A log message is requested from the user which is saved for future
X#       references.
X#
X#       The shell script works only on all RCS files at one time.
X#       It is important that all changed files are checked in (there are
X#       no precautions against any error in this respect).
X#       file names:
X#       {RCS/}rcsfreeze.version         for the version number
X#       {RCS/}rscfreeze.log             for the log messages, most recent
X#                                       logmessage first.
X
Xprogname=`basename $0`
XDATE=`date`
X# Check whether we have an RCS subdirectory, so we can have the right
X# prefix for our paths.
Xif [ -d RCS ] ; then
X	RCSDIR=RCS
Xelse
X	RCSDIR=.
Xfi
X
X# Version number stuff, log message file
XVERSIONFILE=$RCSDIR/.rcsfreeze.version
XLOGFILE=$RCSDIR/.rcsfreeze.log
Xif [ ! -r $VERSIONFILE ] ; then
X# Initialize, rcsfreeze never run before in the current directory
X    cat << EOF > $VERSIONFILE
X0
XEOF
X    touch       $LOGFILE
Xfi
X
X# Get Version number, increase it, write back to file.
XVERSIONNUMBER=`cat $VERSIONFILE`
XVERSIONNUMBER=`expr $VERSIONNUMBER + 1`
X    cat << EOF > $VERSIONFILE
X$VERSIONNUMBER
XEOF
X
X# Symbolic Revision Number
XSYMREV=C_$VERSIONNUMBER
X# Allow the user to give a meaningful symbolic name to the revision.
XSYMREVNAME=${1-$SYMREV}
Xecho    "$progname: symbolic revision number computed: \"$SYMREV\""
Xecho    "$progname: symbolic revision number used:     \"$SYMREVNAME\""
Xecho    "$progname: the two differ only when $progname invoked with argument"
X
X# Stamp the logfile. Because we order the logfile the most recent
X# first we will have to save everything right now in a temporary file.
XTMPLOG=/tmp/rcsfreeze.$$.log.tmp
Xecho "Version: $SYMREVNAME($SYMREV), Date: $DATE"     > $TMPLOG
Xecho "-----------"                      >> $TMPLOG
X# Now ask for a log message, continously add to the log file
Xecho    "$progname: give log message, summarizing changes"
Xecho    "       (terminate with ^D or single '.')"
Xwhile read MESS ; do
X    if [ "$MESS" = '.' ] ; then break ; fi
X    echo "  $MESS"      >> $TMPLOG
Xdone
Xecho "-----------"                      >> $TMPLOG
Xecho                                    >> $TMPLOG
X
X# combine old and new logfiles
XTMPLOG2=$TMPLOG.2
Xcat $TMPLOG $LOGFILE >  $TMPLOG2
Xcp $TMPLOG2     $LOGFILE
Xrm -f  $TMPLOG $TMPLOG2
X
X# Now the real work begins by assigning a symbolic revision number
X# to each rcs file. Take the most recent version of the main trunk.
X
Xfor FILE in $RCSDIR/* ; do
X#   get the revision number of the most recent revision
X    REV=`rlog -h -d"$DATE" $FILE | fgrep 'head:' | awk ' { print $2 } ' `
X    echo        "$progname: file name: \"$FILE\", Revision Number: $REV"
X#   assign symbolic name to it.
X    rcs -q -n$SYMREVNAME:$REV $FILE
Xdone
X@
X
X
X1.1.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@@
X
X
X1.1.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/amiga.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/amiga.c,v
Xhead     1.11;
Xbranch   1;
Xaccess   ;
Xsymbols  amiga_rcs:1;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X1.11
Xdate     89.11.03.20.20.33;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.10;
X
X1.10
Xdate     89.11.02.23.27.51;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.9;
X
X1.9
Xdate     89.11.01.14.43.57;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.8;
X
X1.8
Xdate     89.10.29.14.50.07;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.7;
X
X1.7
Xdate     89.10.29.14.23.50;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.6;
X
X1.6
Xdate     89.10.17.18.38.23;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.5;
X
X1.5
Xdate     89.10.17.15.03.46;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.4;
X
X1.4
Xdate     89.10.16.15.07.49;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.3;
X
X1.3
Xdate     89.10.15.18.26.30;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.2;
X
X1.2
Xdate     89.10.15.15.38.36;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.1;
X
X1.1
Xdate     89.10.13.19.26.17;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@Glue routines for Amiga RCS port.
X@
X
X
X1.11
Xlog
X@Changes to run() and run_back() for use with LaunchChild().
X@
Xtext
X@/*
X *  Glue functions for the RCS system needed for the Amiga
X */
X
X#ifndef lint
Xstatic char rcsid[]=
X"$Id: amiga.c,v 1.10 89/11/02 23:27:51 rsbx Exp $";
X#endif
X
X#include <stdio.h>
X#include <errno.h>
X#include <proto/exec.h>
X#include <exec/tasks.h>
X#include <ios1.h>
X#include <dos.h>
X#include <fcntl.h>
X#include <exec/exec.h>
X#include <libraries/dosextens.h>
X#include "stat.h"
X#include <stdarg.h>
X#include <rsbx/childtasking.h>
X
X
Xextern char *talloc(int size);
Xextern char *fnamepart(char *name);
X
Xextern char *RCSfilename;
X
X/*
X * this should be NCPPN but I can't include rcsbase.h without getting
X * 'redefinition of "VOID"' message because <exec/types.h> thinks that
X * it owns VOID and the rest of the world can goto hell.
X */
X#define PATHSIZE 1024
X
X
Xumask(mode)
X{
X	return mode;
X}
X
Xint stat(name,buf)
Xchar	*name;
Xstruct stat *buf;
X{
X	long l;
X	struct FileInfoBlock *fp,*malloc();
X
X	if ((l=Lock(name, ACCESS_READ)) == 0)
X		return(-1);
X	fp = malloc(sizeof(struct FileInfoBlock));
X	Examine(l, fp);
X	buf->st_attr = ~fp->fib_Protection;
X	buf->st_size = fp->fib_Size;
X	buf->st_type = fp->fib_DirEntryType;
X	UnLock(l);
X	free(fp);
X	buf->st_mtime = getft(name);
X	return 0;
X}
X
Xisatty(fd)
Xint		fd;
X{
X	long IsInteractive();
X	struct UFB	*ufb;
X
X	ufb = chkufb(fd);
X	if (ufb == NULL)
X		return(-1);
X	return(IsInteractive(ufb->ufbfh) != 0);
X}
X
X
Xint run_back(BPTR infh, BPTR outfh, char ** inoutargs)
X{
X	struct LAUNCHENV env = { 0,0,0,0,0,0,0 };
X	struct Task *task = FindTask(0);
X
X	env.priority = task->tc_Node.ln_Pri;
X	env.stack = (char *)task->tc_SPUpper - (char *)task->tc_SPLower;
X	env.std_in = infh;
X	env.std_out =  outfh;
X
X	return (int)LaunchChildv(&env, *inoutargs, inoutargs);
X}
X
X
X#define CARGSMAX 20
X
X/*
X * Run a command.
X * The first two arguments are the input and output files (if nonnil);
X * the rest specify the command and its arguments.
X */
Xint run(char *arg0, char *arg1, ...)
X{
X	va_list ap;
X	int pid, status;
X	char *rgargs[CARGSMAX];
X	register int i;
X	BPTR Binfh, Boutfh;
X
X	va_start(ap, arg1);
X	Binfh = Boutfh = 0;
X	status = -1;
X
X	if (arg0)
X		{
X		if (!(Binfh = (BPTR)Open(arg0, MODE_OLDFILE)))
X			{
X			return -1;
X			}
X		}
X
X	if (arg1)
X		{
X		if (!(Boutfh = (BPTR)Open(arg1, MODE_NEWFILE)))
X			{
X			if (Binfh)
X				{
X				Close(Binfh);
X				}
X			return -1;
X			}
X		}
X
X	for (i=0; i< CARGSMAX; i++) {
X	    rgargs[i] = va_arg(ap, char *);
X	    if (rgargs[i] == NULL)
X		break;
X	}
X	va_end(ap);
X	if (pid = run_back(Binfh, Boutfh, rgargs))
X		{
X		if (!WaitChild((struct ChildNode *)pid, &status))
X			{
X			status = -1;
X			}
X		}
X
X	if (Binfh)
X		{
X		Close(Binfh);
X		}
X	if (Boutfh)
X		{
X		Close(Boutfh);
X		}
X
X	return status;
X}
X
X
X
Xstatic char *path = "ENV:";
X
Xchar *getenv(char *name)
X	{
X	char *fullname, *buff;
X	FILE *f;
X	int len;
X	struct stat varstats;
X
X	if (!(len = strlen(name)))
X		{
X		return NULL;
X		}
X
X	fullname = talloc(strlen(path)+len+1);
X	sprintf(fullname, "%s%s", path, name);
X
X	if (stat(fullname, &varstats))
X		{
X		free(fullname);
X		return NULL;
X		}
X
X	buff = talloc((len = varstats.st_size)+1);
X	if (!(f = fopen(fullname, "r")))
X		{
X		free(buff);
X		free(fullname);
X		return NULL;
X		}
X
X	if (!(len = fread(buff, 1, len, f)))
X		{
X		fclose(f);
X		free(buff);
X		free(fullname);
X		return NULL;
X		}
X
X	*(buff+len) = '\0';
X	fclose(f);
X	free(fullname);
X	return buff;
X	}
X
X
Xchar * getfullRCSname( void )
X/*
X * Function: returns a pointer to the full path name of the RCS file.
X */
X	{
X	static char pathbuf[PATHSIZE];
X	static char namebuf[PATHSIZE];
X
X	char *namestart;
X	BPTR lock, plock;
X	char c;
X	int len;
X
X	strcpy(pathbuf, RCSfilename);
X	namestart = fnamepart(pathbuf);
X	c = *namestart;
X	*namestart = '\0';
X
X	if (!(lock = Lock(pathbuf, ACCESS_READ)))
X		{
X		faterror("Can't build full RCS file name");
X		}
X
X	if (getpath(lock, namebuf))
X		{
X		UnLock(lock);
X		faterror("Can't build full RCS file name");
X		}
X
X	*namestart = c;
X	len = strlen(namebuf);
X
X	if (plock = ParentDir(lock))
X		{
X		UnLock(plock);
X		c = '/';
X		}
X	else
X		{
X		c = ':';
X		}
X
X	UnLock(lock);
X	namebuf[len] = c;
X	namebuf[len+1] = '\0';
X
X	return strcat(namebuf, namestart);
X	}
X@
X
X
X1.10
Xlog
X@Changed to use LaunchChild() and WaitChild() instead of forkv() and
Xwait().
X@
Xtext
X@d7 1
Xa7 1
X"$Id: amiga.c,v 1.9 89/11/01 14:43:57 rsbx Exp $";
Xd106 1
Xd120 1
Xa120 1
X			if (arg0)
Xd134 1
Xa134 1
X	if (!(pid = run_back(Binfh, Boutfh, rgargs)))
Xd136 4
Xa139 3
X		Close(Binfh);
X		Close(Boutfh);
X		return -1;
Xd142 1
Xa142 1
X	if (!WaitChild((struct ChildNode *)pid, &status))
Xd144 5
Xa148 1
X		return -1;
X@
X
X
X1.9
Xlog
X@Removed private chmod() and changed stat() to make protection bit
Xmanipulation less insane.
X@
Xtext
X@d7 1
Xa7 1
X"$Id: amiga.c,v 1.8 89/10/29 14:50:07 rsbx Exp $";
Xd21 1
Xd23 1
Xd75 1
Xa75 1
Xint run_back(BPTR infh, BPTR outfh, char ** inoutargs, struct ProcID *child)
Xd77 2
Xa78 1
X	struct FORKENV env = { 0,32768,0,0,0,NULL };
Xd80 2
Xa81 1
X	env.priority = ((struct Task *)FindTask(NULL))->tc_Node.ln_Pri;
Xd85 1
Xa85 1
X	return forkv(*inoutargs,inoutargs,&env,child);
Xd99 1
Xa99 1
X	int pid;
Xa102 1
X	struct ProcID child;
Xd133 1
Xa133 1
X	if (run_back(Binfh, Boutfh, rgargs, &child) != 0)
Xd140 4
Xa143 1
X	pid = wait(&child);
Xd145 1
Xa145 1
X	return pid;
X@
X
X
X1.8
Xlog
X@Added rcsid string.
X@
Xtext
X@d7 1
Xa7 1
X"$Id$";
Xa39 19
X/*
X** This function is used in place of the lattice library function of
X** the same name.  It handles all modes, not just "rwed".
X*/
Xchmod(name,mode)
Xchar	*name;
Xint	mode;
X{
X	long	amigamode;
X	int	success;
X
X	amigamode = mode;
X	success = SetProtection(name,amigamode);
X	if (success)
X		return(0);
X	errno = ENOENT;
X	return(-1);
X}
X
Xd51 1
Xa51 1
X	buf->st_attr = fp->fib_Protection;
X@
X
X
X1.7
Xlog
X@Changed run() to not close the stdin and stdout files used by a child. This
Xis because my forkl/forkv function will close them for you.
X@
Xtext
X@d2 7
Xa8 2
X**  Glue functions for the RCS system needed for the Amiga
X*/
X@
X
X
X1.6
Xlog
X@getfullRCSname() fixed up.
X@
Xtext
X@d109 1
Xa109 1
X	int infh, outfh, pid;
Xa116 1
X	infh = outfh = 0;
Xd120 4
Xa123 2
X		infh = open(arg0, O_RDONLY, S_IREAD|S_IWRITE|S_IDELETE);
X		Binfh = (BPTR)(chkufb(infh)->ufbfh);
Xd128 8
Xa135 2
X		outfh = creat(arg1, S_IREAD|S_IWRITE|S_IDELETE);
X		Boutfh = (BPTR)(chkufb(outfh)->ufbfh);
Xd144 1
Xa144 2
X	pid = run_back(Binfh, Boutfh, rgargs, &child);
X	if (pid < 0)
Xd146 3
Xa148 1
X		return pid;
Xa151 9
X
X	if (infh)
X		{
X		close(infh);
X		}
X	if (outfh)
X		{
X		close(outfh);
X		}
X@
X
X
X1.5
Xlog
X@Yet more changes to getcaller().
X@
Xtext
X@d18 1
Xd20 10
Xd202 50
X@
X
X
X1.4
Xlog
X@run() move from rcsutil.c to amiga.c and made to work.
X@
Xtext
X@d17 1
Xd145 47
X@
X
X
X1.3
Xlog
X@stat() made more unix compatible.
X@
Xtext
X@d15 1
Xd17 1
Xd74 2
Xa75 1
Xint run_back(char ** inoutargs)
Xa76 1
X	struct ProcID child;
Xa77 1
X	int infh, outfh, retval;
Xd79 3
Xa81 2
X#ifdef DEBUG
X	char **args = inoutargs;
Xd83 2
Xa84 26
X	fprintf(stderr,"runback: ");
X	if (*args)
X		{
X		fprintf(stderr,"%%%s%%  ",*args);
X		}
X	else
X		{
X		fprintf(stderr,"NULL  ");
X		}
X	args++;
X	if (*args)
X		{
X		fprintf(stderr,"%%%s%%  ",*args);
X		}
X	else
X		{
X		fprintf(stderr,"NULL  ");
X		}
X	args++;
X	while (*args)
X		{
X		fprintf(stderr,"%%%s%%  ",*args++);
X		}
X	fprintf(stderr,"\n--------------------------------------\n");
X	fflush(stderr);
X#endif
Xa85 1
X	env.priority = ((struct Task *)FindTask(NULL))->tc_Node.ln_Pri;
Xd87 21
Xa107 1
X	if (inoutargs[0])
Xd109 2
Xa110 2
X		infh = open(inoutargs[0], O_RDONLY, S_IREAD|S_IWRITE|S_IDELETE);
X		env.std_in = (BPTR)(chkufb(infh)->ufbfh);
Xd113 1
Xa113 1
X	if (inoutargs[1])
Xd115 2
Xa116 2
X		outfh = creat(inoutargs[1], S_IREAD|S_IWRITE|S_IDELETE);
X		env.std_out = (BPTR)(chkufb(infh)->ufbfh);
Xd119 8
Xa126 1
X	if ((forkv(inoutargs[2],&inoutargs[2],&env,&child)) != 0)
Xd128 1
Xa128 1
X		retval = -1;
Xa129 4
X	else
X		{
X		retval = wait(&child);
X		}
Xd131 2
Xd142 1
Xa142 1
X	return(retval);
X@
X
X
X1.2
Xlog
X@Removed run_back() from rcsutil.c and put it here since its rather
Xsystem dependant
X@
Xtext
X@d5 1
Xd40 1
Xa40 1
Xstat(name,buf)
Xd57 1
Xd77 30
X@
X
X
X1.1
Xlog
X@Initial revision
X@
Xtext
X@d6 3
Xd10 1
Xa10 1
X#include <ios1.h>
Xd26 1
Xa26 1
Xint		mode;
Xd28 2
Xa29 2
X	long		amigamode;
X	int			success;
Xd52 1
Xd70 40
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/stat.h,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/stat.h,v
Xhead     1.2;
Xbranch   1;
Xaccess   ;
Xsymbols  amiga_rcs:1;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X1.2
Xdate     89.10.15.15.45.30;  author rsbx;  state Exp;
Xbranches ;
Xnext     1.1;
X
X1.1
Xdate     89.10.13.19.26.38;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@Part of Amiga RCS port glue.
X@
X
X
X1.2
Xlog
X@Added new field for file type.
X@
Xtext
X@#include <fcntl.h>
X
Xstruct stat {
X	long st_attr;
X	long st_mtime;
X	long st_size;
X	long st_type;
X};
X@
X
X
X1.1
Xlog
X@Initial revision
X@
Xtext
X@d4 1
Xa4 1
X	char st_attr;
Xd7 1
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/ci.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/ci.c,v
Xhead     4.9;
Xbranch   4.9.2;
Xaccess   ;
Xsymbols  amiga_rcs:4.9.2 cbmvax_source:4.9.1 uunet_june89_dist:4.9;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X4.9
Xdate     89.05.01.15.10.54;  author narten;  state Exp;
Xbranches 4.9.1.1 4.9.2.1;
Xnext     ;
X
X4.9.1.1
Xdate     89.08.11.01.41.27;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X4.9.2.1
Xdate     89.10.13.19.17.07;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.9.2.2;
X
X4.9.2.2
Xdate     89.10.15.15.40.32;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.9.2.3;
X
X4.9.2.3
Xdate     89.10.15.18.26.56;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.9.2.4;
X
X4.9.2.4
Xdate     89.10.30.13.36.06;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.9.2.5;
X
X4.9.2.5
Xdate     89.11.01.14.40.05;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.9.2.6;
X
X4.9.2.6
Xdate     89.11.09.21.28.00;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.9.2.7;
X
X4.9.2.7
Xdate     89.11.12.15.05.20;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@RCS checkin operation.
X@
X
X
X
X4.9
Xlog
X@checked in with -k by rsbx at 89.08.10.16.00.43.
X@
Xtext
X@/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X *   rcs-bugs@@cs.purdue.edu
X * 
X
X
X
X
X
X
X
X*/
X
X/*
X *                     RCS checkin operation
X */
X#ifndef lint
X static char rcsid[]=
X "$Header: /usr/src/local/bin/rcs/src/RCS/ci.c,v 4.9 89/05/01 15:10:54 narten Exp $ Purdue CS";
X#endif
X/*******************************************************************
X *                       check revisions into RCS files
X *******************************************************************
X */
X
X
X
X/* $Log:	ci.c,v $
X * Revision 4.9  89/05/01  15:10:54  narten
X * changed copyright header to reflect current distribution rules
X * 
X * Revision 4.8  88/11/08  13:38:23  narten
X * changes from root@@seismo.CSS.GOV (Super User)
X * -d with no arguments uses the mod time of the file it is checking in
X * 
X * Revision 4.7  88/11/08  10:59:04  narten
X * changes from eggert
X * 
X * Revision 4.7  88/08/09  19:12:07  eggert
X * Make sure workfile is a regular file; use its mode if RCSfile doesn't have one.
X * Use execv(), not system(); allow cc -R; remove lint.
X * isatty(fileno(stdin)) -> ttystdin()
X * 
X * Revision 4.6  87/12/18  11:34:41  narten
X * lint cleanups (from Guy Harris)
X * 
X * Revision 4.5  87/10/18  10:18:48  narten
X * Updating version numbers. Changes relative to revision 1.1 are actually
X * relative to 4.3
X * 
X * Revision 1.3  87/09/24  13:57:19  narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
X * warnings)
X * 
X * Revision 1.2  87/03/27  14:21:33  jenkins
X * Port to suns
X * 
X * Revision 1.1  84/01/23  14:49:54  kcs
X * Initial revision
X * 
X * Revision 4.3  83/12/15  12:28:54  wft
X * ci -u and ci -l now set mode of working file properly.
X * 
X * Revision 4.2  83/12/05  13:40:54  wft
X * Merged with 3.9.1.1: added calls to clearerr(stdin).
X * made rewriteflag external.
X * 
X * Revision 4.1  83/05/10  17:03:06  wft
X * Added option -d and -w, and updated assingment of date, etc. to new delta.
X * Added handling of default branches.
X * Option -k generates std. log message; fixed undef. pointer in reading of log.
X * Replaced getlock() with findlock(), link--unlink with rename(),
X * getpwuid() with getcaller().
X * Moved all revision number generation to new routine addelta().
X * Removed calls to stat(); now done by pairfilenames().
X * Changed most calls to catchints() with restoreints().
X * Directed all interactive messages to stderr.
X * 
X * Revision 3.9.1.1  83/10/19  04:21:03  lepreau
X * Added clearerr(stdin) to getlogmsg() for re-reading stdin.
X * 
X * Revision 3.9  83/02/15  15:25:44  wft
X * 4.2 prerelease
X * 
X * Revision 3.9  83/02/15  15:25:44  wft
X * Added call to fastcopy() to copy remainder of RCS file.
X *
X * Revision 3.8  83/01/14  15:34:05  wft
X * Added ignoring of interrupts while new RCS file is renamed;
X * Avoids deletion of RCS files by interrupts.
X *
X * Revision 3.7  82/12/10  16:09:20  wft
X * Corrected checking of return code from diff.
X *
X * Revision 3.6  82/12/08  21:34:49  wft
X * Using DATEFORM to prepare date of checked-in revision;
X * Fixed return from addbranch().
X *
X * Revision 3.5  82/12/04  18:32:42  wft
X * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE. Updated
X * field lockedby in removelock(), moved getlogmsg() before calling diff.
X *
X * Revision 3.4  82/12/02  13:27:13  wft
X * added option -k.
X *
X * Revision 3.3  82/11/28  20:53:31  wft
X * Added mustcheckin() to check for redundant checkins.
X * Added xpandfile() to do keyword expansion for -u and -l;
X * -m appends linefeed to log message if necessary.
X * getlogmsg() suppresses prompt if stdin is not a terminal.
X * Replaced keeplock with lockflag, fclose() with ffclose(),
X * %02d with %.2d, getlogin() with getpwuid().
X *
X * Revision 3.2  82/10/18  20:57:23  wft
X * An RCS file inherits its mode during the first ci from the working file,
X * otherwise it stays the same, except that write permission is removed.
X * Fixed ci -l, added ci -u (both do an implicit co after the ci).
X * Fixed call to getlogin(), added call to getfullRCSname(), added check
X * for write error.
X * Changed conflicting identifiers.
X *
X * Revision 3.1  82/10/13  16:04:59  wft
X * fixed type of variables receiving from getc() (char -> int).
X * added include file dbm.h for getting BYTESIZ. This is used
X * to check the return code from diff portably.
X */
X
X#include "rcsbase.h"
X#ifndef lint
Xstatic char rcsbaseid[] = RCSBASE;
X#endif
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "time.h"
X
Xextern int    rename();                /*rename files                       */
Xextern char * getcaller();             /*login of caller                    */
Xextern struct hshentry * genrevs();    /*generate delta numbers             */
Xextern quietflag;                      /*suppresses diagnostics if true     */
Xextern int  nerror;                    /*counter for errors                 */
Xextern char * buildrevision();         /*constructs desired revision        */
Xextern char * checkid();               /*check identifiers                  */
Xextern int    partime();               /*parse free-format date/time        */
Xextern long   maketime();              /*convert parsed time to unix time.  */
Xextern long   time();                  /*get date and time                  */
Xextern struct tm * localtime();        /*convert unixtime into tm-structure */
Xextern char * getdate();               /*formates current date  (forward)   */
Xextern char * mktempfile();            /*temporary file name generator      */
Xextern struct lock * addlock();        /*adds a new lock                    */
Xextern char * getlogmsg();             /*obtains log message; forward       */
Xextern struct hshentry * removelock(); /*finds a caller's lock  (forward)   */
Xextern struct hshentry * findlock();   /*finds a lock                       */
Xextern char * xpandfile();             /*perform keyword expansion; forward */
X
Xextern char prevauthor[];
Xextern char prevdate[];
Xextern char prevrev[];
Xextern char prevstate [];
Xextern FILE * finptr;                  /* RCS input file                    */
Xextern FILE * frewrite;                /* new RCS file                      */
Xextern int    rewriteflag;             /* indicates whether input should be */
X				       /* echoed to frewrite                */
X
Xchar * newRCSfilename, * diffilename;
Xchar * RCSfilename,*workfilename,*expfilename,*newworkfilename;
Xextern struct stat RCSstat, workstat; /* file status of RCS and work file   */
Xextern int  haveRCSstat, haveworkstat;/* status indicators                  */
X
X
Xint    copyflag;    /* indicates whether a string should be copied into memory*/
X
Xchar * rev, * state, *msg;
X
Xint initflag, rcsinitflag;
Xint lockflag, keepworkingfile,keepflag;
Xint forceciflag;                      /* forces check in                    */
Xint symrebindflag; char * symbol;
Xint textflag; char * textfile;
Xchar * caller;                        /* caller's login;                    */
Xchar * author;                        /* alternate author for -w option     */
Xchar altdate[datelength];             /* alternate date for -d              */
Xint usestatdate;		      /* use mod time of file for -d 	    */
Xstruct hshentry * targetdelta;        /* old delta to be generated          */
Xchar   * olddeltanum;                 /* number of old delta                */
Xstruct hshentry * gendeltas[hshsize]; /* stores deltas to be generated      */
Xchar   newdelnum[revlength];          /* holds new revision number          */
Xint    newdnumlength;                 /* actual length of new rev. num.     */
Xchar   branchpointnum[revlength];     /* number of branchpoint              */
Xstruct hshentry newdelta;             /* new delta to be inserted           */
Xstruct branchhead newbranch;          /* new branch to be inserted          */
Xchar   logmsg[logsize];               /* buffer for log message             */
X
Xmain (argc, argv)
Xint argc;
Xchar * argv[];
X{
X	char * nametest;
X        char * cmdusage;         /* holds command format                    */
X        struct stat filestatus;  /* used for getting the mode               */
X        int  msglen;             /* length of message given by -m           */
X	int exit_stats;		 /* return code for command invocations     */
X	int newRCSmode;          /* mode for RCS file                       */
X	long unixtime;
X	struct tm  parseddate, *ftm;
X
X	catchints();
X        cmdid = "ci";
X        cmdusage = "command format:\nci -r[rev] -l[rev] -u[rev] -f[rev] -k[rev] -q[rev] -mmsg -nname -Nname -sstate -t[txtfile] file ...";
X	rev = state = msg = symbol = textfile = nil;
X        initflag= rcsinitflag= symrebindflag= textflag= quietflag= false;
X        forceciflag= lockflag= keepworkingfile= keepflag= false;
X	caller = getcaller(); author = nil; /* author may be reset by -w */
X	altdate[0]= '\0'; /* empty alternate date for -d */
X	usestatdate=false;
X
X        while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
X                switch ((*argv)[1]) {
X
X                case 'r':
X                        lockflag=false;
X                revno:  if ((*argv)[2]!='\0') {
X                                if (rev!=nil) warn("Redefinition of revision number");
X                                rev = (*argv)+2;
X                        }
X                        break;
X
X                case 'l':
X                        keepworkingfile=lockflag=true;
X                        goto revno;
X
X                case 'u':
X                        keepworkingfile=true; lockflag=false;
X                        goto revno;
X
X                case 'q':
X                        quietflag=true;
X                        goto revno;
X
X                case 'f':
X                        forceciflag=true;
X                        goto revno;
X
X                case 'k':
X                        keepflag=true;
X                        goto revno;
X
X                case 'm':
X                        if ((*argv)[2]!='\0'){
X                                if (msg!=nil)warn("Redefinition of -m option");
X                                msg = (*argv)+2;
X                                msglen=strlen(msg);
X                                if (msglen >= logsize) {
X                                   warn("log message truncated to %d characters",
X                                        logsize);
X                                   msg[logsize-2]='\n';
X                                   msg[logsize-1]='\0';
X                                }
X                                if (msg[msglen-1]!='\n') {
X                                   /*append linefeed*/
X                                   VOID strcpy(logmsg,msg);msg=logmsg;
X                                   msg[msglen]  = '\n';
X                                   msg[++msglen]= '\0';
X                                }
X                        } else warn("Missing message for -m option");
X                        break;
X
X                case 'n':
X                        symrebindflag=false;
X                        if ((*argv)[2]!='\0'){
X                                if (symbol!=nil)warn("Redefinition of symbolic name");
X                                symbol = (*argv)+2;
X				if (!(nametest=checkid(symbol,' '))||*nametest)
X					faterror("Name %s must be one word",symbol);
X                        } else warn("Missing name for -n option");
X                        break;
X
X                case 'N':
X                        symrebindflag=true;
X                        if ((*argv)[2]!='\0'){
X                                if (symbol!=nil)warn("Redefinition of symbolic name");
X                                symbol = (*argv)+2;
X				if (!(nametest=checkid(symbol,' '))||*nametest)
X					faterror("Name %s must be one word",symbol);
X                        } else warn("Missing name for -N option");
X                        break;
X
X                case 's':
X                        if ((*argv)[2]!='\0'){
X                                if (state!=nil)warn("Redefinition of -s option");
X                                state = (*argv)+2;
X                                VOID checkid(state,' ');
X                        } else warn("Missing state for -s option");
X                        break;
X
X                case 't':
X                        textflag=true;
X                        if ((*argv)[2]!='\0'){
X                                if (textfile!=nil)warn("Redefinition of -t option");
X                                textfile = (*argv)+2;
X                        }
X                        break;
X
X		case 'd':
X                        if ((*argv)[2]!='\0'){
X				if (altdate[0]!='\0' || usestatdate==true)
X				    warn("Redefinition of -d option");
X				/* process the date */
X				if ( partime((*argv)+2, &parseddate) == 0) {
X				    faterror("Can't parse date/time: %s", (*argv)+2);
X				    break;
X				}
X				if ( (unixtime = maketime(&parseddate)) == 0L) {
X				    faterror("Inconsistent date/time: %s",(*argv)+2);
X				    break;
X				}
X				ftm = localtime(&unixtime);
X				VOID sprintf(altdate,DATEFORM,
X				ftm->tm_year,ftm->tm_mon+1,ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec);
X			} else 
X				usestatdate++;
X                        break;
X
X		case 'w':
X                        if ((*argv)[2]!='\0'){
X				if (author!=nil)warn("Redefinition of -w option");
X				author = (*argv)+2;
X				VOID checkid(author,' ');
X			} else warn("Missing author for -w option");
X                        break;
X
X
X
X
X                default:
X                        faterror("unknown option: %s\n%s", *argv,cmdusage);
X                };
X        }  /* end processing of options */
X
X        if (argc<1) faterror("No input file\n%s",cmdusage);
X
X        if (!ttystdin() && msg==nil && textflag && textfile==nil) {
X                /* would need both log message and descriptive text from a file */
X                faterror("Can't take both log and description from redirected stdin; use -ttextfile");
X        }
X        /* now handle all filenames */
X        do {
X        gendeltas[0] = nil;
X        copyflag=rewriteflag=false;
X        finptr=frewrite=NULL;
X        targetdelta=nil;
X        olddeltanum=nil;
X
X        switch (pairfilenames(argc,argv,false,false)) {
X
X        case -1:                /* New RCS file */
X                initflag=true; rcsinitflag=false;
X                break;
X
X        case 0:                 /* Error */
X                continue;
X
X        case 1:                 /* Normal checkin with prev . RCS file */
X                initflag=false; rcsinitflag=(Head==nil);
X        }
X
X        /* now RCSfilename contains the name of the RCS file, and
X         * workfilename contains the name of the working file.
X         * if !initflag, finptr contains the file descriptor for the
X         * RCS file. The admin node is initialized.
X         * workstat and RCSstat are set.
X         */
X
X        diagnose("%s  <--  %s", RCSfilename,workfilename);
X
X        if (access(workfilename,4)!=0) {
X                error("working file %s not readable or nonexistent",
X                       workfilename);
X                continue;
X        }
X
X        /*
X         * make sure workfile is a regular file.
X         */
X        VOID stat(workfilename, &filestatus);
X        if ((filestatus.st_mode & S_IFMT) != S_IFREG) {
X                error("working file %s isn't a regular file", workfilename);
X                continue;
X        }
X
X        /*
X         * if RCSfile doesn't exist, use mode from workfile, otherwise
X         * keep the one from the RCSfile.
X         */
X        if (! (initflag || rcsinitflag))
X            VOID fstat(fileno(finptr), &filestatus);
X
X        if (!trydiraccess(RCSfilename)) continue; /* give up */
X        if (!initflag && !checkaccesslist(caller))   continue; /* give up */
X        if (!trysema(RCSfilename,true)) continue; /* give up */
X
X        if (keepflag) {
X                /* get keyword values from working file */
X                if (!getoldkeys(workfilename)) continue;
X                if (rev==nil && *(rev=prevrev)=='\0') {
X                        error("Can't find a revision number in %s",workfilename);
X                        continue;
X                }
X		if (*prevdate=='\0' && *altdate=='\0' && usestatdate==false)
X			warn("Can't find a date in %s",workfilename);
X		if (*prevauthor=='\0' && author==nil)
X                        warn("Can't find an author in %s", workfilename);
X		if (*prevstate=='\0' && state==nil)
X                        warn("Can't find a state in %s", workfilename);
X        } /* end processing keepflag */
X
X        gettree(); /* reads in the delta tree.*/
X
X        /* expand symbolic revision number */
X        if (!expandsym(rev,newdelnum)) continue;
X
X        /* splice new delta into tree */
X        if (!addelta()) continue;
X
X        if (initflag||rcsinitflag) {
X                diagnose("initial revision: %s",newdelnum);
X        } else  diagnose("new revision: %s; previous revision: %s",
X                newdelnum,olddeltanum);
X
X        newdelta.num=newdelnum;
X        newdelta.branches=nil;
X        newdelta.log=nil;
X        newdelta.lockedby=nil; /*might be changed by addlock() */
X	/* set author */
X	if (author!=nil)
X		newdelta.author=author;     /* set author given by -w         */
X	elsif (keepflag && *prevauthor!='\0')
X		newdelta.author=prevauthor; /* preserve old author of possible*/
X	else    newdelta.author=caller;     /* otherwise use caller's id      */
X	if (state!=nil)
X		newdelta.state=state;       /* set state given by -s          */
X	elsif (keepflag && *prevstate!='\0')
X		newdelta.state=prevstate;   /* preserve old state if possilbe */
X	else    newdelta.state=DEFAULTSTATE;/* otherwise use default state    */
X	if (usestatdate==true) {
X	    if(haveworkstat<0) {
X		error("can't stat %s",workfilename);
X		continue;
X	    } 
X	    ftm = localtime(&workstat.st_mtime);
X	    VOID sprintf(altdate,DATEFORM,ftm->tm_year,ftm->tm_mon+1,
X	    ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec);
X	}
X	if (*altdate!='\0')
X		newdelta.date=altdate;      /* set date given by -d           */
X	elsif (keepflag && *prevdate!='\0') /* preserve old date if possible  */
X                newdelta.date  =prevdate;
X	else
X		newdelta.date = getdate();  /* use current date               */
X	/* now check validity of date -- needed because of -d and -k          */
X	if (targetdelta!=nil &&
X	    cmpnum(newdelta.date,targetdelta->date)<=0) {
X		error("Date %s is not later than %s in existing revision %s",
X		       newdelta.date,targetdelta->date, targetdelta->num);
X		continue;
X	}
X
X
X        if (lockflag && !addlock(&newdelta,caller)) continue;
X        if (symbol && !addsymbol(&newdelta,symbol,symrebindflag)) continue;
X
X        /* prepare for rewriting the RCS file */
X        newRCSfilename=mktempfile(RCSfilename,NEWRCSFILE);
X        if ((frewrite=fopen(newRCSfilename, "w"))==NULL) {
X                error("Can't open file %s",newRCSfilename);
X                continue;
X        }
X        putadmin(frewrite);
X        puttree(Head,frewrite);
X        putdesc(initflag,textflag,textfile,quietflag);
X
X
X        /* build rest of file */
X        if (initflag||rcsinitflag) {
X                /* get logmessage */
X                newdelta.log=getlogmsg();
X                if(!putdtext(newdelnum,newdelta.log,workfilename,frewrite)) continue;
X                ffclose(frewrite); frewrite=NULL;
X        } else {
X                diffilename=mktempfile("/tmp/",DIFFILE);
X                if (&newdelta==Head) {
X                        /* prepend new one */
X                        rewriteflag=false;
X                        if (!(expfilename=
X                              buildrevision(gendeltas,targetdelta,"/tmp/",false))) continue;
X                        if (!mustcheckin(expfilename,targetdelta)) continue;
X                                /* don't check in files that aren't different, unless forced*/
X                        newdelta.log=getlogmsg();
X                        exit_stats = run((char*)nil, diffilename,
X				DIFF,"-n",workfilename,expfilename, (char*)nil);
X                        if (exit_stats != 0 && exit_stats != (1 << BYTESIZ))
X                            faterror ("diff failed");
X                        /* diff returns 2 in the upper byte on failure */
X                        if(!putdtext(newdelnum,newdelta.log,workfilename,frewrite)) continue;
X                        if(!putdtext(olddeltanum,targetdelta->log,diffilename,frewrite)) continue;
X                } else {
X                        /* insert new delta text */
X                        rewriteflag=true;
X                        if (!(expfilename=
X                              buildrevision(gendeltas,targetdelta,"/tmp/",false))) continue;
X                        if (!mustcheckin(expfilename,targetdelta)) continue;
X                                /* don't check in files that aren't different, unless forced*/
X                        newdelta.log=getlogmsg();
X                        exit_stats = run((char*)nil, diffilename,
X				DIFF,"-n",expfilename,workfilename, (char*)nil);
X                        if (exit_stats != 0 && exit_stats != (1 << BYTESIZ))
X                            faterror ("diff failed");
X                        if(!putdtext(newdelnum,newdelta.log,diffilename,frewrite)) continue;
X                }
X
X                /* rewrite rest of RCS file */
X                fastcopy(finptr,frewrite);
X                ffclose(frewrite); frewrite=NULL;
X        }
X	ignoreints();
X        if (rename(newRCSfilename,RCSfilename)<0) {
X                error("Can't write new RCS file %s; saved in %s",
X                      RCSfilename,newRCSfilename);
X                newRCSfilename[0]='\0'; /* avoid deletion by cleanup*/
X                restoreints();
X                VOID cleanup();
X                break;
X        }
X        newRCSfilename[0]='\0'; /* avoid re-unlinking by cleanup()*/
X
X	newRCSmode= (initflag|rcsinitflag?workstat.st_mode:RCSstat.st_mode)& ~0222;
X	/* newRCSmode is also used to adjust mode of working file for -u and -l */
X	if (chmod(RCSfilename,newRCSmode)<0)
X                warn("Can't set mode of %s",RCSfilename);
X
X        restoreints();
X#       ifdef SNOOPFILE
X        logcommand("ci",&newdelta,gendeltas,caller);
X#       endif
X
X        if (!keepworkingfile) {
X                VOID unlink(workfilename); /* get rid of old file */
X        } else {
X                /* expand keywords in file */
X                newworkfilename=
X                xpandfile(workfilename,workfilename /*for directory*/,&newdelta);
X                if (!newworkfilename) continue; /* expand failed */
X		ignoreints();
X		if (rename(newworkfilename,workfilename) <0) {
X                    error("Can't expand keywords in %s",workfilename);
X                    restoreints();
X                    continue;
X                }
X		newworkfilename[0]='\0'; /* avoid re-unlink by cleanup */
X		if (chmod(workfilename, WORKMODE(newRCSmode))<0)
X                    warn("Can't adjust mode of %s",workfilename);
X                restoreints();
X        }
X        diagnose("done");
X
X        } while (cleanup(),
X                 ++argv, --argc >=1);
X
X        exit(nerror!=0);
X	/*NOTREACHED*/
X}       /* end of main (ci) */
X/*****************************************************************/
X/* the rest are auxiliary routines                               */
X
X
Xint addelta()
X/* Function: Appends a delta to the delta tree, whose number is
X * given by newdelnum[]. Updates Head, newdelnum, newdenumlength,
X * olddeltanum and the links in newdelta.
X * Retruns false on error, true on success.
X */
X{
X        register char * sp, * tp;
X        register int i;
X
X        newdnumlength=countnumflds(newdelnum);
X
X        if (initflag || rcsinitflag ) {
X                /* this covers non-existing RCS file and a file initialized with rcs -i */
X		if ((newdnumlength==0)&&(Dbranch!=nil)) {
X			VOID strcpy(newdelnum,Dbranch->num);
X			newdnumlength=countnumflds(newdelnum);
X		}
X                if (newdnumlength==0) VOID strcpy(newdelnum,"1.1");
X                elsif (newdnumlength==1) VOID strcat(newdelnum,".1");
X                elsif (newdnumlength>2) {
X                    error("Branch point does not exist for %s",newdelnum);
X                    return false;
X                } /* newdnumlength == 2 is OK;  */
X                olddeltanum=nil;
X                Head = &newdelta;
X                newdelta.next=nil;
X                return true;
X        }
X        if (newdnumlength==0) {
X                /* derive new revision number from locks */
X		targetdelta=findlock(caller,true); /*find and delete it*/
X                if (targetdelta) {
X                    /* found an old lock */
X                    olddeltanum=targetdelta->num;
X                    /* check whether locked revision exists */
X                    if (!genrevs(olddeltanum,(char *)nil,(char *)nil,(char *)nil,gendeltas)) return false;
X                    if (targetdelta==Head) {
X                        /* make new head */
X                        newdelta.next=Head;
X                        Head= &newdelta;
X                        incnum(olddeltanum, newdelnum);
X                    } elsif ((targetdelta->next==nil)&&(countnumflds(olddeltanum)>2)) {
X                        /* new tip revision on side branch */
X                        targetdelta->next= &newdelta;
X                        newdelta.next = nil;
X                        incnum(olddeltanum, newdelnum);
X                    } else {
X                        /* middle revision; start a new branch */
X                        newdelnum[0]='\0';
X                        if (!addbranch(targetdelta,newdelnum)) return false;
X                    }
X                    return true; /* successfull use of existing lock */
X                } else {
X                    /* no existing lock; try Dbranch */
X                    /* update newdelnum */
X                    if (!((StrictLocks==false) && (getuid() == RCSstat.st_uid))) {
X                        error("no lock set by %s",caller);
X                        return false;
X                    }
X                    if (Dbranch) {
X                        VOID strcpy(newdelnum,Dbranch->num);
X                    } else {
X                        incnum(Head->num,newdelnum);
X                    }
X                    newdnumlength=countnumflds(newdelnum);
X                    /* now fall into next statement */
X                }
X        }
X        if (newdnumlength<=2) {
X                /* add new head per given number */
X                olddeltanum=Head->num;
X                if(newdnumlength==1) {
X                    /* make a two-field number out of it*/
X                    if (cmpnumfld(newdelnum,olddeltanum,1)==0)
X                          incnum(olddeltanum,newdelnum);
X                    else  VOID strcat(newdelnum, ".1");
X                }
X                if (cmpnum(newdelnum,olddeltanum) <= 0) {
X                    error("deltanumber %s too low; must be higher than %s",
X                          newdelnum,Head->num);
X                    return false;
X                }
X                if (!(targetdelta=removelock(caller,Head))) return false;
X                if (!(genrevs(olddeltanum,(char *)nil,(char *)nil,(char *)nil,gendeltas))) return false;
X                newdelta.next=Head;
X                Head= &newdelta;
X        } else {
X                /* put new revision on side branch */
X                /*first, get branch point */
X                tp=branchpointnum; sp=newdelnum;
X                for(i=newdnumlength-(newdnumlength%2==1?1:2);i>0;i--) {
X                    while (*sp != '.') *tp++ = *sp++; /*copy field*/
X                    *tp++ = *sp++;                    /*copy dot  */
X                }
X                *(tp-1) = '\0'; /* kill final dot */
X                olddeltanum=branchpointnum; /*temporary old delta*/
X                if (!(targetdelta=genrevs(branchpointnum,(char *)nil,(char *)nil,(char *)nil,gendeltas)))
X                     return false;
X                if (cmpnum(targetdelta->num,branchpointnum)!=0) {
X                    error("Cannot find branchpoint %s",branchpointnum);
X                    return false;
X                }
X                if (!addbranch(targetdelta,newdelnum)) return false;
X        }
X        return true;
X}
X
X
X
Xint addbranch(branchpoint,num)
Xstruct hshentry * branchpoint;
Xchar * num;
X/* adds a new branch and branch delta at branchpoint.
X * If num is the null string, appends the new branch, incrementing
X * the highest branch number (initially 1), and setting the level number to 1.
X * the new delta and branchhead are in globals newdelta and newbranch, resp.
X * the new number is placed into num.
X * returns false on error.
X */
X{
X        struct branchhead * bhead, * btrail;
X        char branchnum[revlength];
X        int numlength, result, field;
X
X        numlength = countnumflds(num);
X
X        if (branchpoint->branches==nil) {
X                /* start first branch */
X                branchpoint->branches = &newbranch;
X                if (numlength==0) {
X                        VOID strcpy(num, branchpoint->num);
X                        VOID strcat(num,".1.1");
X                } elsif(countnumflds(num)%2 == 1)
X                        VOID strcat(num, ".1");
X                newbranch.nextbranch=nil;
X
X        } elsif (numlength==0) {
X                /* append new branch to the end */
X                bhead=branchpoint->branches;
X                while (bhead->nextbranch) bhead=bhead->nextbranch;
X                bhead->nextbranch = &newbranch;
X                getbranchno(bhead->hsh->num,branchnum);
X                incnum(branchnum,num);
X                VOID strcat(num,".1");
X                newbranch.nextbranch=nil;
X        } else {
X                /* place the branch properly */
X                field = numlength - (numlength%2 ==1?0:1);
X                /* field of branch number */
X                bhead=branchpoint->branches;
X                while ((bhead!=nil) &&
X                       ((result=cmpnumfld(num,bhead->hsh->num,field))>0)) {
X                        btrail=bhead;
X                        bhead=bhead->nextbranch;
X                }
X                if (bhead==nil || result<0) {
X                        /* insert/append new branchhead */
X                        if (bhead==branchpoint->branches)
X                                branchpoint->branches= &newbranch;
X                        else    btrail->nextbranch= &newbranch;
X                        newbranch.nextbranch=bhead;
X                        if (numlength%2 ==1) VOID strcat(num,".1");
X                } else {
X                        /* branch exists; append to end */
X                        getbranchno(num,branchnum);
X                        if (!(targetdelta=genrevs(branchnum,(char *)nil,(char *)nil,(char *)nil,
X                                gendeltas))) return false;
X                        olddeltanum=targetdelta->num;
X                        if (cmpnum(num,olddeltanum) <= 0) {
X                                error("deltanumber %s too low; must be higher than %s",
X                                      num,olddeltanum);
X                                return false;
X                        }
X                        if (!removelock(caller,targetdelta)) return false;
X                        if (numlength%2==1) incnum(olddeltanum,num);
X                        targetdelta->next= &newdelta;
X                        newdelta.next=nil;
X                        return true; /* Don't do anything to newbranch */
X                }
X        }
X        newbranch.hsh = &newdelta;
X        newdelta.next=nil;
X        return true;
X}
X
X
X
Xstruct hshentry * removelock(who,delta)
Xchar * who; struct hshentry * delta;
X/* function: Finds the lock held by who on delta,
X * removes it, and returns a pointer to the delta.
X * Prints an error message and returns nil if there is no such lock.
X * An exception is if StrictLocks==false, and who is the owner of
X * the RCS file. If who does not have a lock in this case,
X * delta is returned.
X */
X{
X        register struct lock * next, * trail;
X        char * num;
X        struct lock dummy;
X        int whomatch, nummatch;
X
X        num=delta->num;
X        dummy.nextlock=next=Locks;
X        trail = &dummy;
X        while (next!=nil) {
X                whomatch=strcmp(who,next->login);
X                nummatch=strcmp(num,next->delta->num);
X                if ((whomatch==0) && (nummatch==0)) break;
X                     /*found a lock on delta by who*/
X                if ((whomatch!=0)&&(nummatch==0)) {
X                    error("revision %s locked by %s",num,next->login);
X                    return nil;
X                }
X                trail=next;
X                next=next->nextlock;
X        }
X        if (next!=nil) {
X                /*found one; delete it */
X                trail->nextlock=next->nextlock;
X                Locks=dummy.nextlock;
X                next->delta->lockedby=nil; /* reset locked-by */
X                return next->delta;
X        } else {
X                if (!((StrictLocks==false) && (getuid() == RCSstat.st_uid))) {
X                    error("no lock set by %s for revision %s",who,num);
X                    return nil;
X                } else {
X                        return delta;
X                }
X        }
X}
X
X
X
Xchar * getdate()
X/* Function: returns a pointer to the current date in the form
X * YY.MM.DD.hh.mm.ss\0
X */
X{
X        long clock;
X        struct tm * tm;
X	static char buffer[datelength]; /* date buffer */
X        clock=time((long *)0);
X        tm=localtime(&clock);
X        VOID sprintf(buffer, DATEFORM,
X                tm->tm_year, tm->tm_mon+1, tm->tm_mday,
X                tm->tm_hour, tm->tm_min, tm->tm_sec);
X        return buffer;
X}
X
X
Xchar * xpandfile (unexfname,dir,delta)
Xchar * unexfname, * dir;
Xstruct hshentry * delta;
X/* Function: Reads file unexpfname and copies it to a
X * file in dir, performing keyword substitution with data from delta.
X * returns the name of the expanded file if successful, nil otherwise.
X */
X{       char * targetfname;
X        FILE * unexfile, *exfile;
X
X        targetfname=mktempfile(dir,TMPFILE3);
X        if ((unexfile=fopen(unexfname,  "r" ))==NULL ||
X            (exfile  =fopen(targetfname,"w"))==NULL) {
X                error("Can't expand file %s",unexfname);
X                return nil;
X        }
X        while (expandline(unexfile,exfile,delta,false,false)); /*expand*/
X        ffclose(unexfile);ffclose(exfile);
X        return targetfname;
X}
X
X
Xmustcheckin (unexfname,delta)
Xchar * unexfname; struct hshentry * delta;
X/* Function: determines whether checkin should proceed.
X * Compares the wrkfilename with unexfname, disregarding keywords.
X * If the 2 files differ, returns true. If they do not differ, asks the user
X * whether to return true or false (i.e., whether to checkin the file anyway.
X * If the files do not differ, and quietflag==true, returns false.
X * Shortcut: If forceciflag==true, mustcheckin() always returns true.
X */
X{       register int c;
X        int response, result;
X
X        if (forceciflag) return true;
X
X        if (!rcsfcmp(workfilename,unexfname,delta)) return true;
X        /* If files are different, must check them in. */
X
X        /* files are the same */
X        diagnose("File %s is unchanged with respect to revision %s",
X                workfilename,delta->num);
X        if (quietflag || !ttystdin()) {
X                /* Files are the same, but can't ask, so don't checkin*/
X                result=false;
X        } else {
X                /* ask user whether to check in */
X                VOID fputs("checkin anyway? [ny](n): ",stderr);
X                response=c=getchar();
X                while (!(c==EOF || c=='\n')) c=getchar();/*skip to end of line*/
X                result=(response=='y'||response=='Y');
X        }
X        if (result==false) {
X                if (quietflag) {
X                    warn("checkin aborted since %s was not changed; %s %sdeleted.",
X                             workfilename,workfilename,keepworkingfile?"not ":"");
X                } else {
X                    diagnose("checkin aborted; %s %sdeleted.",
X                             workfilename,keepworkingfile?"not ":"");
X                }
X                if (!keepworkingfile) VOID unlink(workfilename);
X        }
X        return result;
X}
X
X
X
X
X/* --------------------- G E T L O G M S G --------------------------------*/
Xextern int stdinread; /* is >0 if redirected stdin has been read once.     */
X
X
Xchar * getlogmsg()
X/* Function: obtains a log message and returns a pointer to it.
X * If a log message is given via the -m option, a pointer to that
X * string is returned.
X * If this is the initial revision, a standard log message is returned.
X * Otherwise, reads a character string from the terminal.
X * The string must be terminated with a control-d or a single '.' on a
X * line. getlogmsg prompts the first time it is called for the
X * log message; during all later calls it asks whether the previous
X * log message can be reused.
X * returns a pointer to the character string; the pointer is always non-nil.
X */
X{
X        static logyet;      /*indicates whether previous log present*/
X        static char emptylog[]  = "*** empty log message ***\n";
X        static char initiallog[]= "Initial revision\n";
X        char response;
X	int cin;
X        register char c, old1, old2, * tp;
X
X        if (msg) return msg;
X
X        if ((olddeltanum==nil)&&
X	    ((cmpnum(newdelnum,"1.1")==0)||(cmpnum(newdelnum,"1.0")==0))) {
X                return initiallog;
X	}
X	if (keepflag) {
X		/* generate std. log message */
X		VOID sprintf(logmsg, "checked in with -k by %s at %s.\n",caller,getdate());
X		return(logmsg);
X	}
X        if (logyet) {
X                /*previous log available*/
X                if (!ttystdin()) return logmsg; /* reuse if stdin is not a terminal*/
X                /* otherwise ask */
X		clearerr(stdin);		/* reset EOF ptr */
X		VOID fputs("reuse log message of previous file? [yn](y): ",stderr);
X                cin=getchar();
X		response=cin;
X                while (!(cin==EOF || cin=='\n')) cin=getchar();/*skip to end of line*/
X                if (response=='\n'||response=='y'||response=='Y')
X                        return logmsg;
X                else
X                        logmsg[0]='\0'; /*kill existing log message */
X        }
X
X        /* now read string from stdin */
X        if (ttystdin()) {
X                VOID fputs("enter log message:\n(terminate with ^D or single '.')\n>> ",stderr);
X        } else {  /* redirected stdin */
X                if (stdinread>0)
X                    faterror("Can't reread redirected stdin for log message; use -m");
X                stdinread++;
X        }
X
X	tp=logmsg; old1='\n'; old2=' ';
X	if (feof(stdin))
X		clearerr(stdin);
X        for (;;) {
X                cin=getchar();
X                if (cin==EOF) {
X			if(ttystdin()) {
X				VOID printf("\n");
X				clearerr(stdin);
X			}
X			if ((tp==logmsg)||(*(tp-1)!='\n')) *tp++ = '\n'; /* append newline */
X                        *tp = '\0'; /*terminate*/
X                        break;
X                }
X                if (cin=='\n' && old1=='.' && old2=='\n') {
X                        *(tp-1) = '\0'; /*kill last period */
X                        break;
X                }
X                if (tp>=logmsg+logsize-2) { /* overflow */
X                        if (!ttystdin()) {
X                                warn("log message truncated to %d characters",logsize);
X                                logmsg[logsize-2]='\n';logmsg[logsize-1]='\0';
X                                return logmsg;
X                        }
X                        VOID fprintf(stderr,"log message too long. Maximum: %d\n",logsize);
X                        VOID fputs("reenter log message:\n>> ",stderr);
X                        tp=logmsg; old1='\n'; old2=' ';
X                        while (cin!='\n') cin=getchar(); /*skip line */
X                        continue;
X                }
X                if (cin=='\n' && ttystdin()) VOID fputs(">> ",stderr);
X                *tp++ = cin; old2=old1; old1=cin; /* this is the actual work!*/
X                /*SDELIM will be changed to double SDELIM by putdtext*/
X        } /* end for */
X
X        /* now check whether the log message is not empty */
X        tp=logmsg;
X        while ((c= *tp++)==' '||c=='\t'||c=='\n'||c=='\f');
X        if (*tp=='\0') {
X                logyet=false;
X                return emptylog;
X        } else {
X                logyet=true;
X                return logmsg;
X        }
X}
X@
X
X
X4.9.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d31 1
Xa31 5
X<<<<<<< ci.c
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/ci.c,v 4.9.1.1 89/08/11 01:41:27 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 1.2 89/09/17 13:09:11 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa40 10
X<<<<<<< ci.c
X * Revision 4.9.1.1  89/08/11  01:41:27  rsbx
X * Start of cbmvax RCS source branch.
X=======
X * Revision 1.2  89/09/17  13:09:11  rick
X * Port to AmigaDos done by Rick Schaeffer
X * All changes done with conditional compile.  This version only compiles
X * correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X * 
Xa41 3
X * checked in with -k by rsbx at 89.08.10.16.00.43.
X * 
X * Revision 4.9  89/05/01  15:10:54  narten
Xa143 7
X#ifdef AMIGA
X#include "stat.h"
X#undef WORKMODE
X#define WORKMODE(RCSmode) (RCSmode | S_IWRITE)&~((lockflag||!StrictLocks)?S_IWRITE:0)
X#undef putc
X#define putc(x,y) fputc(x,y)
X#else
Xa145 1
X#endif
Xa500 3
X#ifdef AMIGA
X				diffilename=mktempfile("t:",DIFFILE);
X#else
Xa501 1
X#endif
Xa505 3
X#ifdef AMIGA
X                              buildrevision(gendeltas,targetdelta,"t:",false))) continue;
X#else
Xa506 1
X#endif
Xa509 1
X<<<<<<< ci.c
Xa511 5
X=======
X                        VOID sprintf(command,"%s -n %s %s >%s\n", DIFF,
X                                workfilename,expfilename,diffilename);
X                        exit_stats = system (command);
X>>>>>>> 1.2
Xa520 3
X#ifdef AMIGA
X                              buildrevision(gendeltas,targetdelta,"t:",false))) continue;
X#else
Xa521 1
X#endif
Xa524 1
X<<<<<<< ci.c
Xa526 5
X=======
X                        VOID sprintf(command,"%s -n %s %s >%s\n", DIFF,
X                                expfilename,workfilename,diffilename);
X                        exit_stats = system (command);
X>>>>>>> 1.2
Xa536 4
X#ifdef AMIGA
X	fclose(finptr);
X	unlink(RCSfilename);
X#endif
Xd546 1
Xa546 3
X#ifdef AMIGA
X	newRCSmode =(initflag|rcsinitflag?workstat.st_attr:RCSstat.st_attr)|S_IWRITE;
X#else
Xa547 1
X#endif
Xa564 3
X#ifdef AMIGA
X		unlink(workfilename);
X#endif
Xa642 3
X#ifdef AMIGA
X		    if (StrictLocks != false) {
X#else
Xa643 1
X#endif
Xa811 3
X#ifdef AMIGA
X                if (StrictLocks !=false) {
X#else
Xa812 1
X#endif
Xa887 3
X#ifdef AMIGA
X		fflush(stderr);
X#endif
Xa948 3
X#ifdef AMIGA
X		fflush(stderr);
X#endif
Xd961 1
Xa961 4
X#ifdef AMIGA
X		fflush(stderr);
X#endif
X	       } else {  /* redirected stdin */
Xa992 3
X#ifdef AMIGA
X			fflush(stderr);
X#endif
Xa996 1
X<<<<<<< ci.c
Xa997 8
X=======
X                if (cin=='\n' && isatty(fileno(stdin))) {
X                	 VOID fputs(">> ",stderr);
X#ifdef AMIGA
X			fflush(stderr);
X#endif
X			}
X>>>>>>> 1.2
X@
X
X
X4.9.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d31 5
Xa35 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 4.9.2.1 89/10/13 19:17:07 rsbx Exp Locker: rsbx $ Purdue CS";
Xd45 1
Xa45 3
X * Revision 4.9.2.1  89/10/13  19:17:07  rsbx
X * Start of Amiga RCS port branch.
X * 
Xd48 6
Xa421 3
X#ifdef AMIGA
X	if (filestatus.st_type >= 0) {
X#else
Xa422 1
X#endif
Xd432 1
Xa432 1
X            VOID stat(RCSfilename, &filestatus);
Xd543 1
Xd546 5
Xd568 1
Xd571 5
Xd1076 3
Xd1085 1
X@
X
X
X4.9.2.3
Xlog
X@More changes to make Amiga port work.
X@
Xtext
X@d31 1
Xa31 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 4.9.2.2 89/10/15 15:40:32 rsbx Exp $ Purdue CS";
Xa40 4
X * Revision 4.9.2.2  89/10/15  15:40:32  rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X * 
Xd523 1
Xa523 1
X		diffilename=mktempfile("t:",DIFFILE);
X@
X
X
X4.9.2.4
Xlog
X@NULL finptr after closing it.
X@
Xtext
X@d31 1
Xa31 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 4.9.2.3 89/10/15 18:26:56 rsbx Exp $ Purdue CS";
Xa40 3
X * Revision 4.9.2.3  89/10/15  18:26:56  rsbx
X * More changes to make Amiga port work.
X * 
Xd575 1
Xa575 1
X	fclose(finptr); finptr = NULL;
X@
X
X
X4.9.2.5
Xlog
X@Changes to make the delete bit to track the write bit. Made protection
Xbit manipulation less insane.
X@
Xtext
X@d31 1
Xa31 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 4.9.2.4 89/10/30 13:36:06 rsbx Exp $ Purdue CS";
Xa40 3
X * Revision 4.9.2.4  89/10/30  13:36:06  rsbx
X * NULL finptr after closing it.
X * 
Xd162 2
Xd578 2
Xa579 8
X	if (finptr) {
X		fclose(finptr); finptr = NULL;
X		if (chmod(RCSfilename, RCSstat.st_attr|S_IDELETE)<0)
X			warn("Can't adjust mode of %s",RCSfilename);
X		if (unlink(RCSfilename) != 0) {            /* Remove failed   */
X			error("Can't unlink %s",RCSfilename);
X			}
X		}
Xd591 1
Xa591 1
X	newRCSmode =(initflag|rcsinitflag?workstat.st_attr:RCSstat.st_attr)& ~(S_IWRITE|S_IDELETE);
Xa604 7
X#ifdef AMIGA
X		if (chmod(workfilename, workstat.st_attr|S_IDELETE)<0)
X			warn("Can't adjust mode of %s",workfilename);
X       		if (unlink(workfilename) != 0) {            /* Remove failed   */
X       			error("Can't unlink %s",workfilename);
X       			}
X#else
Xa605 1
X#endif
Xd613 1
Xa613 5
X		if (chmod(workfilename, workstat.st_attr|S_IDELETE)<0)
X			warn("Can't adjust mode of %s",workfilename);
X       		if (unlink(workfilename) != 0) {            /* Remove failed   */
X       			error("Can't unlink %s",workfilename);
X       			}
Xa960 9
X#ifdef AMIGA
X		if (!keepworkingfile) {
X			if (chmod(workfilename, workstat.st_attr|S_IDELETE)<0)
X				warn("Can't adjust mode of %s",workfilename);
X			if (unlink(workfilename) != 0) {            /* Remove failed   */
X				error("Can't unlink %s",workfilename);
X				}
X			}
X#else
Xa961 1
X#endif
X@
X
X
X4.9.2.6
Xlog
X@Changed "^D" to "^\".
X@
Xtext
X@d31 1
Xa31 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 4.9.2.5 89/11/01 14:40:05 rsbx Exp Locker: rsbx $ Purdue CS";
Xa40 4
X * Revision 4.9.2.5  89/11/01  14:40:05  rsbx
X * Changes to make the delete bit to track the write bit. Made protection
X * bit manipulation less insane.
X * 
Xd1053 1
Xa1054 1
X                VOID fputs("enter log message:\n(terminate with ^\\ or single '.')\n>> ",stderr);
Xa1055 2
X#else
X                VOID fputs("enter log message:\n(terminate with ^D or single '.')\n>> ",stderr);
X@
X
X
X4.9.2.7
Xlog
X@WaitChild() on the Amiga returns the completion code from a child process
Xwithout shifting it up 8 bits like the Unix wait() does.
X@
Xtext
X@d31 1
Xa31 1
X "$Header: /u/softeng/rsbx/rcs/amiga/RCS/ci.c,v 4.9.2.6 89/11/09 21:28:00 rsbx Exp $ Purdue CS";
Xa40 3
X * Revision 4.9.2.6  89/11/09  21:28:00  rsbx
X * Changed "^D" to "^\".
X * 
Xa552 3
X#ifdef AMIGA
X                        if (exit_stats != 0 && exit_stats != 1)
X#else
Xa553 1
X#endif
Xa571 3
X#ifdef AMIGA
X                        if (exit_stats != 0 && exit_stats != 1)
X#else
Xa572 1
X#endif
X@
X
X
X4.9.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@d31 1
Xa31 1
X "$Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/ci.c,v 4.9 89/05/01 15:10:54 narten Exp $ Purdue CS";
Xa40 3
X * Revision 4.9  89/05/01  15:10:54  narten
X * checked in with -k by rsbx at 89.08.10.16.00.43.
X * 
X@
SHAR_EOF
echo "End of archive 12 (of 14)"
# if you want to concatenate archives, remove anything after this line
exit