home *** CD-ROM | disk | FTP | other *** search
- /*
- * RCS create/change operation
- */
- #ifndef lint
- static char rcsid[]=
- "$Header: /site/tmp/dosrcs/src/RCS/rcs.c,v 5.3 90/07/15 20:24:19 lfk Release $ Purdue CS";
- #endif
- /* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Distributed under license by the Free Software Foundation, Inc.
-
- This file is part of RCS.
-
- RCS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- RCS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with RCS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Report problems and direct all questions to:
-
- rcs-bugs@cs.purdue.edu
-
- */
-
-
-
-
- /* $Log: rcs.c,v $
- * Revision 5.3 90/07/15 20:24:19 lfk
- * Most major fixes added between rev 5.1 and rev 5.5:
- * signals fixed so they work on MS-DOS
- * Added MKS arguments code so argv can be large
- * added code to handle slashes a'la Unix
- * added more file extensions to system from MS-DOS
- *
- * Revision 5.2 90/07/15 11:32:15 ROOT_DOS
- * DOS version of RCS 4.0 checked in for MODS
- * by lfk@athena.mit.edu
- * Also update to MSC 6.0
- *
- * Revision 4.11 89/05/01 15:12:06 narten
- * changed copyright header to reflect current distribution rules
- *
- * Revision 4.10 88/11/08 16:01:54 narten
- * didn't install previous patch correctly
- *
- * Revision 4.9 88/11/08 13:56:01 narten
- * removed include <sysexits.h> (not needed)
- * minor fix for -A option
- *
- * Revision 4.8 88/11/08 12:01:58 narten
- * changes from eggert@sm.unisys.com (Paul Eggert)
- *
- * Revision 4.8 88/08/09 19:12:27 eggert
- * Don't access freed storage.
- * Use execv(), not system(); yield proper exit status; remove lint.
- *
- * Revision 4.7 87/12/18 11:37:17 narten
- * lint cleanups (Guy Harris)
- *
- * Revision 4.6 87/10/18 10:28:48 narten
- * Updating verison numbers. Changes relative to 1.1 are actually
- * relative to 4.3
- *
- * Revision 1.4 87/09/24 13:58:52 narten
- * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- * warnings)
- *
- * Revision 1.3 87/03/27 14:21:55 jenkins
- * Port to suns
- *
- * Revision 1.2 85/12/17 13:59:09 albitz
- * Changed setstate to rcs_setstate because of conflict with random.o.
- *
- * Revision 1.1 84/01/23 14:50:09 kcs
- * Initial revision
- *
- * Revision 4.3 83/12/15 12:27:33 wft
- * rcs -u now breaks most recent lock if it can't find a lock by the caller.
- *
- * Revision 4.2 83/12/05 10:18:20 wft
- * Added conditional compilation for sending mail.
- * Alternatives: V4_2BSD, V6, USG, and other.
- *
- * Revision 4.1 83/05/10 16:43:02 wft
- * Simplified breaklock(); added calls to findlock() and getcaller().
- * Added option -b (default branch). Updated -s and -w for -b.
- * Removed calls to stat(); now done by pairfilenames().
- * Replaced most catchints() calls with restoreints().
- * Removed check for exit status of delivermail().
- * Directed all interactive output to stderr.
- *
- * Revision 3.9.1.1 83/12/02 22:08:51 wft
- * Added conditional compilation for 4.2 sendmail and 4.1 delivermail.
- *
- * Revision 3.9 83/02/15 15:38:39 wft
- * Added call to fastcopy() to copy remainder of RCS file.
- *
- * Revision 3.8 83/01/18 17:37:51 wft
- * Changed sendmail(): now uses delivermail, and asks whether to break the lock.
- *
- * Revision 3.7 83/01/15 18:04:25 wft
- * Removed putree(); replaced with puttree() in rcssyn.c.
- * Combined putdellog() and scanlogtext(); deleted putdellog().
- * Cleaned up diagnostics and error messages. Fixed problem with
- * mutilated files in case of deletions in 2 files in a single command.
- * Changed marking of selector from 'D' to DELETE.
- *
- * Revision 3.6 83/01/14 15:37:31 wft
- * Added ignoring of interrupts while new RCS file is renamed;
- * Avoids deletion of RCS files by interrupts.
- *
- * Revision 3.5 82/12/10 21:11:39 wft
- * Removed unused variables, fixed checking of return code from diff,
- * introduced variant COMPAT2 for skipping Suffix on -A files.
- *
- * Revision 3.4 82/12/04 13:18:20 wft
- * Replaced getdelta() with gettree(), changed breaklock to update
- * field lockedby, added some diagnostics.
- *
- * Revision 3.3 82/12/03 17:08:04 wft
- * Replaced getlogin() with getpwuid(), flcose() with ffclose(),
- * /usr/ucb/Mail with macro MAIL. Removed handling of Suffix (-x).
- * fixed -u for missing revno. Disambiguated structure members.
- *
- * Revision 3.2 82/10/18 21:05:07 wft
- * rcs -i now generates a file mode given by the umask minus write permission;
- * otherwise, rcs keeps the mode, but removes write permission.
- * I added a check for write error, fixed call to getlogin(), replaced
- * curdir() with getfullRCSname(), cleaned up handling -U/L, and changed
- * conflicting, long identifiers.
- *
- * Revision 3.1 82/10/13 16:11:07 wft
- * fixed type of variables receiving from getc() (char -> int).
- */
-
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "rcsbase.h"
- #ifndef lint
- static char rcsbaseid[] = RCSBASE;
- #endif
-
- extern FILE * fopen();
- extern char * bindex();
- extern int expandsym(); /* get numeric revision name */
- extern struct hshentry * getnum();
- extern struct lock * addlock(); /* add a lock */
- extern char * getid();
- extern char Klog[], Khead[], Kaccess[], Kbranch[], Ktext[];
- #ifdef COMPAT2
- extern char Ksuffix[];
- #endif
- extern char * getcaller(); /* get login of caller */
- extern struct hshentry * findlock(); /* find and remove lock */
- extern struct hshentry * genrevs();
- extern char * checkid(); /* check an identifier */
- extern char * getfullRCSname(); /* get full path name of RCS file */
- extern char * mktempfile(); /* temporary file name generator */
- extern free();
- extern void catchints();
- extern void ignoreints();
- extern int nerror; /* counter for errors */
- extern int quietflag; /* diagnoses suppressed if true */
- extern char curlogmsg[]; /* current log message */
- extern char * resultfile; /* filename for fcopy */
- extern FILE *fcopy; /* result file during editing */
- extern FILE * finptr; /* RCS input file */
- extern FILE * frewrite; /* new RCS file */
- extern int rewriteflag; /* indicates whether input should be*/
- /* echoed to frewrite */
-
- char * newRCSfilename, * diffilename, * cutfilename;
- char * RCSfilename, * workfilename;
- extern struct stat RCSstat, workstat; /* file status of RCS and work file */
- extern int haveRCSstat, haveworkstat;/* status indicators */
-
- char accessorlst[strtsize];
- FILE * fcut; /* temporary file to rebuild delta tree */
- int oldumask; /* save umask */
-
- int initflag, strictlock, strict_selected, textflag;
- char * textfile, * accessfile;
- char * caller, numrev[30]; /* caller's login; */
- struct access * newaccessor, * rmvaccessor, * rplaccessor;
- struct access *curaccess, *rmaccess;
- struct hshentry * gendeltas[hshsize];
-
- #ifdef MSDOS
- extern char *gettmpdir();
- char tmpdir[NCPPN];
- #endif /* MSDOS */
-
- struct Lockrev {
- char * revno;
- struct Lockrev * nextrev;
- };
-
- struct Symrev {
- char * revno;
- char * ssymbol;
- int override;
- struct Symrev * nextsym;
- };
-
- struct Status {
- char * revno;
- char * status;
- struct Status * nextstatus;
- };
-
- struct delrevpair {
- char * strt;
- char * end;
- int code;
- };
-
- struct Lockrev * newlocklst, * rmvlocklst;
- struct Symrev * assoclst, * lastassoc;
- struct Status * statelst, * laststate;
- struct delrevpair * delrev;
- struct hshentry * cuthead, *cuttail, * delstrt;
- char branchnum[revlength], * branchsym;
- struct hshentry branchdummy;
- char * commsyml;
- char * headstate;
- int lockhead,unlockcaller,chgheadstate,branchflag,commentflag;
- int delaccessflag;
- enum stringwork {copy, edit, empty}; /* expand and edit_expand not needed */
-
-
- #ifdef MKS
- main(int argc, char *argv[], char *env[])
- #else
- main (argc, argv)
- int argc;
- char * argv[];
- #endif /* MKS */
- {
- char *comdusge;
- int result;
- struct access *removeaccess(), * getaccessor();
- struct Lockrev *rmnewlocklst();
- struct Lockrev *curlock, * rmvlock, *lockpt;
- struct Status * curstate;
- struct access *temp, *temptr;
- int status;
- #ifdef MKS
- int z = 0;
- int ARGC = 0;
- char **tmp;
- char *env_name;
- # define MAXARGS 500 /* This means 500 items on the command line */
- if (!(tmp = (char **)malloc(sizeof(char *)*(MAXARGS+1)))) {
- fprintf(stderr, "%s: can't allocate space for arguments\n",argv[0]);
- exit(1);
- }
- for ( z = 0 ; env[z] != NULL; z++) { /* loop through environment */
- if (*env[z] == '~') { /* testing for entries begining with '~' */
- *++env[z]; /* increment pointer to delete '~' */
- tmp[ARGC++] = env[z]; /* add it to our new array */
- if (z >= MAXARGS) {
- fprintf(stderr, "%s: can't handle any more arguments\n", argv[0]);
- goto list;
- }
- }
- else if (*env[z] == '_') { /* testing for entries begining with _ */
- *++env[z] ; *++env[z]; /* move past the '_' and the '=' */
- env_name = env[z]; /* copy the name */
- }
- }
- list:
- if ( STREQ( (char *) argv[0] , env_name ) ) { /* test name against startup args */
- /* environment arguments meant for this program */
- # ifdef DEBUG
- printf("Using shell supplied args\n");
- # endif
- argc = ARGC;
- tmp[ARGC] = NULL; /* the terminal NULL */
- argv = tmp;
- }
- # ifdef DEBUG
- else
- printf("Using startup supplied args\n");
- # endif /* debug */
- #endif /* MKS */
-
- status = 0;
- nerror = 0;
- catchints();
- cmdid = "rcs";
- quietflag = false;
- comdusge ="command format:\nrcs -i -alogins -Alogins -e[logins] -b[rev] -c[commentleader] -l[rev] -u[rev] -L -U -nname[:rev] -Nname[:rev] -orange -sstate[:rev] -t[textfile] file....";
- rplaccessor = nil; delstrt = nil;
- accessfile = textfile = caller = nil;
- branchflag = commentflag = chgheadstate = false;
- lockhead = false; unlockcaller=false;
- initflag= textflag = false;
- strict_selected = 0;
-
- caller=getcaller();
- laststate = statelst = nil;
- lastassoc = assoclst = nil;
- curlock = rmvlock = newlocklst = rmvlocklst = nil;
- curaccess = rmaccess = rmvaccessor = newaccessor = nil;
- delaccessflag = false;
-
- /* preprocessing command options */
- while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
- switch ((*argv)[1]) {
-
- case 'i': /* initail version */
- initflag = true;
- break;
-
- case 'b': /* change default branch */
- if (branchflag)warn("Redfinition of option -b");
- branchflag= true;
- branchsym = (*argv)+2;
- break;
-
- case 'c': /* change comment symbol */
- if (commentflag)warn("Redefinition of option -c");
- commentflag = true;
- commsyml = (*argv)+2;
- break;
-
- case 'a': /* add new accessor */
- if ( (*argv)[2] == '\0') {
- error("Login name missing after -a");
- }
- if ( (temp = getaccessor((*argv)+1)) ) {
- if ( newaccessor )
- curaccess->nextaccess = temp->nextaccess;
- else
- newaccessor = temp->nextaccess;
- temp->nextaccess = nil;
- curaccess = temp;
- }
- break;
-
- case 'A': /* append access list according to accessfile */
- if ( (*argv)[2] == '\0') {
- error("Missing file name after -A");
- break;
- }
- if ( accessfile) warn("Redefinition of option -A");
- *argv = *argv+2;
- if( pairfilenames(1, argv, true, false) > 0) {
- releaselst(newaccessor);
- newaccessor = curaccess = nil;
- releaselst(rmvaccessor);
- rmvaccessor = rmaccess = nil;
- accessfile = RCSfilename;
- }
- else
- accessfile = nil;
- break;
-
- case 'e': /* remove accessors */
- if ( (*argv)[2] == '\0' ) {
- delaccessflag = true;
- break;
- }
- if ( (temp = getaccessor((*argv)+1)) ) {
- if ( rmvaccessor )
- rmaccess->nextaccess = temp->nextaccess;
- else
- rmvaccessor = temp->nextaccess;
- temptr = temp->nextaccess;
- temp->nextaccess = nil;
- rmaccess = temp;
- while( temptr ) {
- newaccessor = removeaccess(temptr,newaccessor,false);
- temptr = temptr->nextaccess;
- }
- curaccess = temp = newaccessor;
- while( temp){
- curaccess = temp;
- temp = temp->nextaccess;
- }
- }
- break;
-
- case 'l': /* lock a revision if it is unlocked */
- if ( (*argv)[2] == '\0'){ /* lock head or def. branch */
- lockhead = true;
- break;
- }
- lockpt = (struct Lockrev *)talloc(sizeof(struct Lockrev));
- lockpt->revno = (*argv)+2;
- lockpt->nextrev = nil;
- if ( curlock )
- curlock->nextrev = lockpt;
- else
- newlocklst = lockpt;
- curlock = lockpt;
- break;
-
- case 'u': /* release lock of a locked revision */
- if ( (*argv)[2] == '\0'){ /* unlock head */
- unlockcaller=true;
- break;
- }
- lockpt = (struct Lockrev *)talloc(sizeof(struct Lockrev));
- lockpt->revno = (*argv)+2;
- lockpt->nextrev = nil;
- if (rmvlock)
- rmvlock->nextrev = lockpt;
- else
- rmvlocklst = lockpt;
- rmvlock = lockpt;
-
- curlock = rmnewlocklst(lockpt);
- break;
-
- case 'L': /* set strict locking */
- if (strict_selected++) { /* Already selected L or U? */
- if (!strictlock) /* Already selected -U? */
- warn("Option -L overrides -U");
- }
- strictlock = true;
- break;
-
- case 'U': /* release strict locking */
- if (strict_selected++) { /* Already selected L or U? */
- if (strictlock) /* Already selected -L? */
- warn("Option -L overrides -U");
- }
- else
- strictlock = false;
- break;
-
- case 'n': /* add new association: error, if name exists */
- if ( (*argv)[2] == '\0') {
- error("Missing symbolic name after -n");
- break;
- }
- getassoclst(false, (*argv)+1);
- break;
-
- case 'N': /* add or change association */
- if ( (*argv)[2] == '\0') {
- error("Missing symbolic name after -N");
- break;
- }
- getassoclst(true, (*argv)+1);
- break;
-
- case 'o': /* delete revisins */
- if (delrev) warn("Redefinition of option -o");
- if ( (*argv)[2] == '\0' ) {
- error("Missing revision range after -o");
- break;
- }
- getdelrev( (*argv)+1 );
- break;
-
- case 's': /* change state attribute of a revision */
- if ( (*argv)[2] == '\0') {
- error("State missing after -s");
- break;
- }
- getstates( (*argv)+1);
- break;
-
- case 't': /* change descriptive text */
- textflag=true;
- if ((*argv)[2]!='\0'){
- if (textfile!=nil)warn("Redefinition of -t option");
- textfile = (*argv)+2;
- }
- break;
-
- case 'q':
- quietflag = true;
- break;
- default:
- faterror("Unknown option: %s\n%s", *argv, comdusge);
- };
- } /* end processing of options */
-
- if (argc<1) faterror("No input file\n%s", comdusge);
- if (nerror) { /* exit, if any error in command options */
- diagnose("%s aborted",cmdid);
- exit(1);
- }
- if (accessfile) /* get replacement for access list */
- getrplaccess();
- if (nerror) {
- diagnose("%s aborted",cmdid);
- exit(1);
- }
- #ifdef MSDOS
- strcpy( tmpdir, gettmpdir() );
- #endif /* MSDOS */
- /* now handle all filenames */
- do {
- rewriteflag = false;
- finptr=frewrite=NULL;
-
- if ( initflag ) {
- switch( pairfilenames(argc, argv, false, false) ) {
- case -1: break; /* not exist; ok */
- case 0: continue; /* error */
- case 1: error("file %s exists already", RCSfilename);
- VOID fclose(finptr);
- continue;
- }
- }
- else {
- switch( pairfilenames(argc, argv, true, false) ) {
- case -1: continue; /* not exist */
- case 0: continue; /* errors */
- case 1: break; /* file exists; ok*/
- }
- }
-
-
- /* now RCSfilename contains the name of the RCS file, and
- * workfilename contains the name of the working file.
- * if !initflag, finptr contains the file descriptor for the
- * RCS file. The admin node is initialized.
- */
-
- diagnose("RCS file: %s", RCSfilename);
-
- if (!trydiraccess(RCSfilename)) continue; /* give up */
- if (!initflag && !checkaccesslist(caller)) continue; /* give up */
- if (!trysema(RCSfilename,true)) continue; /* give up */
-
- gettree(); /* read in delta tree */
-
- /* update admin. node */
- if (strict_selected) StrictLocks = strictlock;
- if (commentflag) Comment = commsyml;
-
- /* update default branch */
- if (branchflag && expandsym(branchsym, branchnum)) {
- if (countnumflds(branchnum)>0) {
- branchdummy.num=branchnum;
- Dbranch = &branchdummy;
- } else
- Dbranch = nil;
- }
-
- /* update access list */
- if ( delaccessflag ) AccessList = nil;
- if ( accessfile ) {
- temp = rplaccessor;
- while( temp ) {
- temptr = temp->nextaccess;
- if ( addnewaccess(temp) )
- temp->nextaccess = nil;
- temp = temptr;
- }
- }
- temp = rmvaccessor;
- while(temp) { /* remove accessors from accesslist */
- AccessList = removeaccess(temp, AccessList,true);
- temp = temp->nextaccess;
- }
- temp = newaccessor;
- while( temp) { /* add new accessors */
- temptr = temp->nextaccess;
- if ( addnewaccess( temp ) )
- temp->nextaccess = nil;
- temp = temptr;
- }
-
- updateassoc(); /* update association list */
-
- updatelocks(); /* update locks */
-
- /* update state attribution */
- if (chgheadstate) {
- /* change state of default branch or head */
- if (Dbranch==nil) {
- if (Head==nil)
- warn("Can't change states in an empty tree");
- else Head->state = headstate;
- } else {
- rcs_setstate(Dbranch->num,headstate); /* Can't set directly */
- }
- }
- curstate = statelst;
- while( curstate ) {
- rcs_setstate(curstate->revno,curstate->status);
- curstate = curstate->nextstatus;
- }
-
- cuthead = cuttail = nil;
- if ( delrev && removerevs()) {
- /* rebuild delta tree if some deltas are deleted */
- if ( cuttail )
- VOID genrevs(cuttail->num, (char *)nil,(char *)nil,
- (char *)nil, gendeltas);
- buildtree();
- }
-
-
- /* prepare for rewriting the RCS file */
- #ifdef MSDOS
- newRCSfilename=mktempfile(RCSfilename,NEWRCSFILE);
- oldumask = umask(S_IWRITE); /* turn off write bits */
- #else
- newRCSfilename=mktempfile(RCSfilename,NEWRCSFILE);
- oldumask = umask(0222); /* turn off write bits */
- #endif /* MSDOS */
- if ((frewrite=fopen(newRCSfilename, "w"))==NULL) {
- VOID fclose(finptr);
- error("Can't open file %s",newRCSfilename);
- continue;
- }
- VOID umask(oldumask);
- putadmin(frewrite);
- if ( Head )
- puttree(Head, frewrite);
- putdesc(initflag,textflag,textfile,quietflag);
- rewriteflag = false;
-
- if ( Head) {
- if (!delrev) {
- /* no revision deleted */
- fastcopy(finptr,frewrite);
- } else {
- if ( cuttail )
- buildeltatext(gendeltas);
- else
- scanlogtext((struct hshentry *)nil,empty);
- /* copy rest of delta text nodes that are not deleted */
- }
- }
- ffclose(frewrite); frewrite = NULL;
- if ( ! nerror ) { /* move temporary file to RCS file if no error */
- ignoreints(); /* ignore interrupts */
- #ifdef MSDOS
- if(Rename(newRCSfilename,RCSfilename)<0) {
- #else
- if(rename(newRCSfilename,RCSfilename)<0) {
- #endif /* MSDOS */
- error("Can't create RCS file %s; saved in %s",
- RCSfilename, newRCSfilename);
- newRCSfilename[0] = '\0'; /* avoid deletion by cleanup */
- restoreints();
- VOID cleanup();
- break;
- }
- newRCSfilename[0]='\0'; /* avoid re-unlinking by cleanup()*/
- /* update mode */
- result=0;
- if (!initflag) /* preserve mode bits */
- result=chmod(RCSfilename,RCSstat.st_mode & ~0222);
- elsif (haveworkstat==0) /* initialization, and work file exists */
- result=chmod(RCSfilename,workstat.st_mode & ~0222);
- if (result<0) warn("Can't set mode of %s",RCSfilename);
-
- restoreints(); /* catch them all again */
- diagnose("done");
- } else {
- diagnose("%s aborted; %s unchanged.",cmdid,RCSfilename);
- status = 1;
- nerror = 0;
- }
- } while (cleanup(),
- ++argv, --argc >=1);
-
- exit(status);
- } /* end of main (rcs) */
-
-
-
- getassoclst(flag, sp)
- int flag;
- char * sp;
- /* Function: associate a symbolic name to a revision or branch, */
- /* and store in assoclst */
-
- {
- struct Symrev * pt;
- char * temp, *temp2;
- int c;
-
- while( (c=(*++sp)) == ' ' || c == '\t' || c =='\n') ;
- temp = sp;
- temp2=checkid(sp, ':'); /* check for invalid symbolic name */
- sp = temp2; c = *sp; *sp = '\0';
- while( c == ' ' || c == '\t' || c == '\n') c = *++sp;
-
- if ( c != ':' && c != '\0') {
- error("Invalid string %s after option -n or -N",sp);
- return;
- }
-
- pt = (struct Symrev *)talloc(sizeof(struct Symrev));
- pt->ssymbol = temp;
- pt->override = flag;
- if (c == '\0') /* delete symbol */
- pt->revno = nil;
- else {
- while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ;
- if ( c == '\0' )
- pt->revno = nil;
- else
- pt->revno = sp;
- }
- pt->nextsym = nil;
- if (lastassoc)
- lastassoc->nextsym = pt;
- else
- assoclst = pt;
- lastassoc = pt;
- return;
- }
-
-
-
- struct access * getaccessor( sp)
- char *sp;
- /* Function: get the accessor list of options -e and -a, */
- /* and store in curpt */
-
-
- {
- struct access * curpt, * pt, *pre;
- char *temp;
- register c;
-
- while( ( c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',') ;
- if ( c == '\0') {
- error("Missing login name after option -a or -e");
- return nil;
- }
-
- curpt = pt = nil;
- while( c != '\0') {
- temp=checkid(sp,',');
- pt = (struct access *)talloc(sizeof(struct access));
- pt->login = sp;
- if ( curpt )
- pre->nextaccess = pt;
- else
- curpt = pt;
- pt->nextaccess = curpt;
- pre = pt;
- sp = temp; c = *sp; *sp = '\0';
- while( c == ' ' || c == '\n' || c == '\t'|| c == ',')c =(*++sp);
- }
- return pt;
- }
-
-
-
- getstates(sp)
- char *sp;
- /* Function: get one state attribute and the corresponding */
- /* revision and store in statelst */
-
- {
- char *temp, *temp2;
- struct Status *pt;
- register c;
-
- while( (c=(*++sp)) ==' ' || c == '\t' || c == '\n') ;
- temp = sp;
- temp2=checkid(sp,':'); /* check for invalid state attribute */
- sp = temp2; c = *sp; *sp = '\0';
- while( c == ' ' || c == '\t' || c == '\n' ) c = *++sp;
-
- if ( c == '\0' ) { /* change state of def. branch or Head */
- chgheadstate = true;
- headstate = temp;
- return;
- }
- else if ( c != ':' ) {
- error("Missing ':' after state in option -s");
- return;
- }
-
- while( (c = *++sp) == ' ' || c == '\t' || c == '\n') ;
- pt = (struct Status *)talloc(sizeof(struct Status));
- pt->status = temp;
- pt->revno = sp;
- pt->nextstatus = nil;
- if (laststate)
- laststate->nextstatus = pt;
- else
- statelst = pt;
- laststate = pt;
- }
-
-
-
- getrplaccess()
- /* Function : get the accesslist of the 'accessfile' */
- /* and place in rplaccessor */
- {
- register char *id, *nextp;
- struct access *newaccess, *oldaccess;
-
- if ( (finptr=fopen(accessfile, "r")) == NULL) {
- faterror("Can't open file %s", accessfile);
- }
- Lexinit();
- nextp = &accessorlst[0];
-
- if ( ! getkey(Khead)) faterror("Missing head in %s", accessfile);
- VOID getnum();
- if ( ! getlex(SEMI) ) serror("Missing ';' after head in %s",accessfile);
-
- if (getkey(Kbranch)) { /* optional */
- Dbranch=getnum();
- if (!getlex(SEMI)) serror("Missing ';' after branch list");
- }
-
-
- #ifdef COMPAT2
- /* read suffix. Only in release 2 format */
- if (getkey(Ksuffix)) {
- if (nexttok==STRING) {
- readstring(); nextlex(); /*through away the suffix*/
- } elsif(nexttok==ID) {
- nextlex();
- }
- if ( ! getlex(SEMI) ) serror("Missing ';' after suffix in %s",accessfile);
- }
- #endif
-
- if (! getkey(Kaccess))fatserror("Missing access list in %s",accessfile);
- oldaccess = nil;
- while( id =getid() ) {
- newaccess = (struct access *)talloc(sizeof(struct access));
- newaccess->login = nextp;
- newaccess->nextaccess = nil;
- while( ( *nextp++ = *id++) != '\0') ;
- if ( oldaccess )
- oldaccess->nextaccess = newaccess;
- else
- rplaccessor = newaccess;
- oldaccess = newaccess;
- }
- if ( ! getlex(SEMI))serror("Missing ';' after access list in %s",accessfile);
- return;
- }
-
-
-
- getdelrev(sp)
- char *sp;
- /* Function: get revision range or branch to be deleted, */
- /* and place in delrev */
- {
- int c;
- struct delrevpair *pt;
-
- if (delrev) free((char *)delrev);
-
- pt = (struct delrevpair *)talloc(sizeof(struct delrevpair));
- while((c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;
-
- if ( c == '<' || c == '-' ) { /* -o -rev or <rev */
- while( (c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;
- pt->strt = sp; pt->code = 1;
- while( c != ' ' && c != '\n' && c != '\t' && c != '\0') c =(*++sp);
- *sp = '\0';
- pt->end = nil; delrev = pt;
- return;
- }
- else {
- pt->strt = sp;
- while( c != ' ' && c != '\n' && c != '\t' && c != '\0'
- && c != '-' && c != '<' ) c = *++sp;
- *sp = '\0';
- while( c == ' ' || c == '\n' || c == '\t' ) c = *++sp;
- if ( c == '\0' ) { /* -o rev or branch */
- pt->end = nil; pt->code = 0;
- delrev = pt;
- return;
- }
- if ( c != '-' && c != '<') {
- faterror("Invalid range %s %s after -o", pt->strt, sp);
- free((char *)pt);
- return;
- }
- while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ;
- if ( c == '\0') { /* -o rev- or rev< */
- pt->end = nil; pt->code = 2;
- delrev = pt;
- return;
- }
- }
- /* -o rev1-rev2 or rev1<rev2 */
- pt->end = sp; pt->code = 3; delrev = pt;
- while( c!= ' ' && c != '\n' && c != '\t' && c != '\0') c = *++sp;
- *sp = '\0';
- }
-
-
-
-
- scanlogtext(delta,func)
- struct hshentry * delta; enum stringwork func;
- /* Function: Scans delta text nodes up to and including the one given
- * by delta, or up to last one present, if delta==nil.
- * For the one given by delta (if delta!=nil), the log message is saved into
- * curlogmsg and the text is processed according to parameter func.
- * Assumes the initial lexeme must be read in first.
- * Does not advance nexttok after it is finished, except if delta==nil.
- */
- { struct hshentry * nextdelta;
-
- do {
- rewriteflag = false;
- nextlex();
- if (!(nextdelta=getnum())) {
- if(delta)
- faterror("Can't find delta for revision %s", delta->num);
- else return; /* no more delta text nodes */
- }
- if ( nextdelta->selector != DELETE) {
- rewriteflag = true;
- VOID fprintf(frewrite,DELNUMFORM,nextdelta->num,Klog);
- }
- if (!getkey(Klog) || nexttok!=STRING)
- serror("Missing log entry");
- elsif (delta==nextdelta) {
- VOID savestring(curlogmsg,logsize);
- delta->log=curlogmsg;
- } else {readstring();
- if (delta!=nil) delta->log="";
- }
- nextlex();
- if (!getkey(Ktext) || nexttok!=STRING)
- fatserror("Missing delta text");
-
- if(delta==nextdelta)
- /* got the one we're looking for */
- switch (func) {
- case copy: copystring();
- break;
- case edit: editstring((struct hshentry *)nil);
- break;
- default: faterror("Wrong scanlogtext");
- }
- else readstring(); /* skip over it */
-
- } while (delta!=nextdelta);
- }
-
-
-
- releaselst(sourcelst)
- struct access * sourcelst;
- /* Function: release the storages whose address are in sourcelst */
-
- {
- struct access * pt;
-
- pt = sourcelst;
- while(pt) {
- struct access *pn = pt->nextaccess;
- free((char *)pt);
- pt = pn;
- }
- }
-
-
-
- struct Lockrev * rmnewlocklst(which)
- struct Lockrev * which;
- /* Function: remove lock to revision which->revno from newlocklst */
-
- {
- struct Lockrev * pt, *pre;
-
- while( newlocklst && (! strcmp(newlocklst->revno, which->revno))){
- struct Lockrev *pn = newlocklst->nextrev;
- free((char *)newlocklst);
- newlocklst = pn;
- }
-
- pt = pre = newlocklst;
- while( pt ) {
- if ( ! strcmp(pt->revno, which->revno) ) {
- pre->nextrev = pt->nextrev;
- free((char *)pt);
- pt = pre->nextrev;
- }
- else {
- pre = pt;
- pt = pt->nextrev;
- }
- }
- return pre;
- }
-
-
-
- struct access * removeaccess( who, sourcelst,flag)
- struct access * who, * sourcelst;
- int flag;
- /* Function: remove the accessor-- who from sourcelst */
-
- {
- struct access *pt, *pre;
-
- pt = sourcelst;
- while( pt && (! strcmp(who->login, pt->login) )) {
- pre = pt->nextaccess;
- free((char *)pt);
- pt = pre;
- flag = false;
- }
- pre = sourcelst = pt;
- while( pt ) {
- if ( ! strcmp(who->login, pt->login) ) {
- pre->nextaccess = pt->nextaccess;
- free((char *)pt);
- pt = pre->nextaccess;
- flag = false;
- }
- else {
- pre = pt;
- pt = pt->nextaccess;
- }
- }
- if ( flag ) warn("Can't remove a nonexisting accessor %s",who->login);
- return sourcelst;
- }
-
-
-
- int addnewaccess( who )
- struct access * who;
- /* Function: add new accessor-- who into AccessList */
-
- {
- struct access *pt, *pre;
-
- pre = pt = AccessList;
-
- while( pt ) {
- if ( strcmp( who->login, pt->login) ) {
- pre = pt;
- pt = pt->nextaccess;
- }
- else
- return 0;
- }
- if ( pre == pt )
- AccessList = who;
- else
- pre->nextaccess = who;
- return 1;
- }
-
-
- sendmail(Delta, who)
- char * Delta, *who;
- /* Function: mail to who, informing him that his lock on delta was
- * broken by caller. Ask first whether to go ahead. Return false on
- * error or if user decides not to break the lock.
- */
- {
- char * messagefile;
- int old1, old2, c, response;
- FILE * mailmess;
-
-
- VOID fprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who);
- VOID fprintf(stderr, "Do you want to break the lock? [ny](n): ");
- response=c=getchar();
- while (!(c==EOF || c=='\n')) c=getchar();/*skip to end of line*/
- if (response=='\n'||response=='n'||response=='N') return false;
-
- /* go ahead with breaking */
- #ifdef MSDOS
- messagefile=mktempfile( tmpdir, "mmXXXXXX");
- #else
- messagefile=mktempfile("/tmp/", "RCSmailXXXXXX");
- #endif /* MSDOS */
- if ( (mailmess = fopen(messagefile, "w")) == NULL) {
- faterror("Can't open file %s", messagefile);
- }
-
- VOID fprintf(mailmess, "Subject: Broken lock on %s\n\n",bindex(RCSfilename,'/'));
- VOID fprintf(mailmess, "Your lock on revision %s of file %s\n",Delta, getfullRCSname());
- VOID fprintf(mailmess,"has been broken by %s for the following reason:\n",caller);
- VOID fputs("State the reason for breaking the lock:\n", stderr);
- VOID fputs("(terminate with ^D or single '.')\n>> ", stderr);
-
- old1 = '\n'; old2 = ' ';
- for (; ;) {
- c = getchar();
- if ( c == EOF ) {
- VOID putc('\n',stderr);
- VOID fprintf(mailmess, "%c\n", old1);
- break;
- }
- else if ( c == '\n' && old1 == '.' && old2 == '\n')
- break;
- else {
- VOID fputc( old1, mailmess);
- old2 = old1; old1 = c;
- if (c== '\n') VOID fputs(">> ", stderr);
- }
- }
- ffclose(mailmess);
-
- /* ignore the exit status, even if delivermail unsuccessful */
- VOID run(messagefile,(char*)nil,
- #ifdef SENDMAIL
- "/usr/lib/sendmail",
- #else
- # ifdef DELIVERMAIL
- "/etc/delivermail","-w",
- # else
- "/bin/mail",
- # endif
- #endif
- who,(char*)nil);
- VOID unlink(messagefile);
- return(true);
- }
-
-
-
- static breaklock(who,delta)
- char * who; struct hshentry * delta;
- /* function: Finds the lock held by who on delta,
- * and removes it.
- * Sends mail if a lock different from the caller's is broken.
- * Prints an error message if there is no such lock or error.
- */
- {
- register struct lock * next, * trail;
- char * num;
- struct lock dummy;
- int whor, numr;
-
- num=delta->num;
- dummy.nextlock=next=Locks;
- trail = &dummy;
- while (next!=nil) {
- if (num != nil)
- numr = strcmp(num, next->delta->num);
-
- whor=strcmp(who,next->login);
- if (whor==0 && numr==0) break; /* exact match */
- if (numr==0 && whor !=0) {
- if (!sendmail( num, next->login)){
- diagnose("%s still locked by %s",num,next->login);
- return;
- } else break; /* continue after loop */
- }
- trail=next;
- next=next->nextlock;
- }
- if (next!=nil) {
- /*found one */
- diagnose("%s unlocked",next->delta->num);
- trail->nextlock=next->nextlock;
- next->delta->lockedby=nil;
- Locks=dummy.nextlock;
- } else {
- error("no lock set on revision %s", num);
- }
- }
-
-
-
- struct hshentry *searchcutpt(object, length, store)
- char * object;
- int length;
- struct hshentry * * store;
- /* Function: Search store and return entry with number being object. */
- /* cuttail = nil, if the entry is Head; otherwise, cuttail */
- /* is the entry point to the one with number being object */
-
- {
- while( compartial( (*store++)->num, object, length) ) ;
- store--;
-
- if ( *store == Head)
- cuthead = nil;
- else
- cuthead = *(store -1);
- return *store;
- }
-
-
-
- int branchpoint(strt, tail)
- struct hshentry *strt, *tail;
- /* Function: check whether the deltas between strt and tail */
- /* are locked or branch point, return 1 if any is */
- /* locked or branch point; otherwise, return 0 and */
- /* mark DELETE on selector */
-
- {
- struct hshentry *pt;
- struct lock *lockpt;
- int flag;
-
-
- pt = strt;
- flag = false;
- while( pt != tail) {
- if ( pt->branches ){ /* a branch point */
- flag = true;
- error("Can't remove branch point %s", pt->num);
- }
- lockpt = Locks;
- while(lockpt && lockpt->delta != pt)
- lockpt = lockpt->nextlock;
- if ( lockpt ) {
- flag = true;
- error("Can't remove locked revision %s",pt->num);
- }
- pt = pt->next;
- }
-
- if ( ! flag ) {
- pt = strt;
- while( pt != tail ) {
- pt->selector = DELETE;
- diagnose("deleting revision %s ",pt->num);
- pt = pt->next;
- }
- }
- return flag;
- }
-
-
-
- removerevs()
- /* Function: get the revision range to be removed, and place the */
- /* first revision removed in delstrt, the revision before */
- /* delstrt in cuthead( nil, if delstrt is head), and the */
- /* revision after the last removed revision in cuttail(nil */
- /* if the last is a leaf */
-
- {
- struct hshentry *target, *target2, * temp, *searchcutpt();
- int length, flag;
-
- flag = false;
- if ( ! expandsym(delrev->strt, &numrev[0]) ) return 0;
- target = genrevs(&numrev[0], (char *)nil, (char *)nil, (char *)nil, gendeltas);
- if ( ! target ) return 0;
- if ( cmpnum(target->num, &numrev[0]) ) flag = true;
- length = countnumflds( &numrev[0] );
-
- if ( delrev->code == 0 ) { /* -o rev or -o branch */
- if ( length % 2)
- temp=searchcutpt(target->num,length+1,gendeltas);
- else if (flag) {
- error("Revision %s does not exist", &numrev[0]);
- return 0;
- }
- else
- temp = searchcutpt(&numrev[0],length,gendeltas);
- cuttail = target->next;
- if ( branchpoint(temp, cuttail) ) {
- cuttail = nil;
- return 0;
- }
- delstrt = temp; /* first revision to be removed */
- return 1;
- }
-
- if ( length % 2 ) { /* invalid branch after -o */
- error("Invalid branch range %s after -o", &numrev[0]);
- return 0;
- }
-
- if ( delrev->code == 1 ) { /* -o -rev */
- if ( length > 2 ) {
- temp = searchcutpt( target->num, length-1, gendeltas);
- cuttail = target->next;
- }
- else {
- temp = searchcutpt(target->num, length, gendeltas);
- cuttail = target;
- while( cuttail && ! cmpnumfld(target->num,cuttail->num,1) )
- cuttail = cuttail->next;
- }
- if ( branchpoint(temp, cuttail) ){
- cuttail = nil;
- return 0;
- }
- delstrt = temp;
- return 1;
- }
-
- if ( delrev->code == 2 ) { /* -o rev- */
- if ( length == 2 ) {
- temp = searchcutpt(target->num, 1,gendeltas);
- if ( flag)
- cuttail = target;
- else
- cuttail = target->next;
- }
- else {
- if ( flag){
- cuthead = target;
- if ( !(temp = target->next) ) return 0;
- }
- else
- temp = searchcutpt(target->num, length, gendeltas);
- getbranchno(temp->num, &numrev[0]); /* get branch number */
- target = genrevs(&numrev[0], (char *)nil, (char *)nil, (char *)nil, gendeltas);
- }
- if ( branchpoint( temp, cuttail ) ) {
- cuttail = nil;
- return 0;
- }
- delstrt = temp;
- return 1;
- }
-
- /* -o rev1-rev2 */
- if ( ! expandsym(delrev->end, &numrev[0]) ) return 0;
- if ( length != countnumflds( &numrev[0] ) ) {
- error("Invalid revision range %s-%s", target->num, &numrev[0]);
- return 0;
- }
- if ( length > 2 && compartial( &numrev[0], target->num, length-1) ) {
- error("Invalid revision range %s-%s", target->num, &numrev[0]);
- return 0;
- }
-
- target2 = genrevs( &numrev[0], (char *)nil, (char *)nil, (char *)nil,gendeltas);
- if ( ! target2 ) return 0;
-
- if ( length > 2) { /* delete revisions on branches */
- if ( cmpnum(target->num, target2->num) > 0) {
- if ( cmpnum(target2->num, &numrev[0]) )
- flag = true;
- else
- flag = false;
- temp = target;
- target = target2;
- target2 = temp;
- }
- if ( flag ) {
- if ( ! cmpnum(target->num, target2->num) ) {
- error("Revisions %s-%s don't exist", delrev->strt,delrev->end);
- return 0;
- }
- cuthead = target;
- temp = target->next;
- }
- else
- temp = searchcutpt(target->num, length, gendeltas);
- cuttail = target2->next;
- }
- else { /* delete revisions on trunk */
- if ( cmpnum( target->num, target2->num) < 0 ) {
- temp = target;
- target = target2;
- target2 = temp;
- }
- else
- if ( cmpnum(target2->num, &numrev[0]) )
- flag = true;
- else
- flag = false;
- if ( flag ) {
- if ( ! cmpnum(target->num, target2->num) ) {
- error("Revisions %s-%s don't exist", delrev->strt, delrev->end);
- return 0;
- }
- cuttail = target2;
- }
- else
- cuttail = target2->next;
- temp = searchcutpt(target->num, length, gendeltas);
- }
- if ( branchpoint(temp, cuttail) ) {
- cuttail = nil;
- return 0;
- }
- delstrt = temp;
- return 1;
- }
-
-
-
- updateassoc()
- /* Function: add or delete(if revno is nil) association */
- /* which is stored in assoclst */
-
- {
- struct Symrev * curassoc;
- struct assoc * pre, * pt;
- struct hshentry * target;
-
- /* add new associations */
- curassoc = assoclst;
- while( curassoc ) {
- if ( curassoc->revno == nil ) { /* delete symbol */
- pre = pt = Symbols;
- while( pt && strcmp(pt->symbol,curassoc->ssymbol) ) {
- pre = pt;
- pt = pt->nextassoc;
- }
- if ( pt )
- if ( pre == pt )
- Symbols = pt->nextassoc;
- else
- pre->nextassoc = pt->nextassoc;
- else
- warn("Can't delete nonexisting symbol %s",curassoc->ssymbol);
- }
- else if ( expandsym( curassoc->revno, &numrev[0] ) ) {
- /* add symbol */
- target = (struct hshentry *) talloc(sizeof(struct hshentry));
- target->num = &numrev[0];
- VOID addsymbol(target, curassoc->ssymbol, curassoc->override);
- }
- curassoc = curassoc->nextsym;
- }
-
- }
-
-
-
- updatelocks()
- /* Function: remove lock for caller or first lock if unlockcaller==true;
- * remove locks which are stored in rmvlocklst,
- * add new locks which are stored in newlocklst,
- * add lock for Dbranch or Head if lockhead==true.
- */
- {
- struct hshentry *target;
- struct Lockrev *lockpt;
-
- if(unlockcaller == true) { /* find lock for caller */
- if ( Head ) {
- if (Locks) {
- target=findlock(caller,true);
- if (target==nil) {
- breaklock(caller, Locks->delta); /* remove most recent lock */
- } else {
- diagnose("%s unlocked",target->num);
- }
- } else {
- warn("There are no locks set.");
- }
- } else {
- warn("Can't unlock an empty tree");
- }
- }
-
- /* remove locks which are stored in rmvlocklst */
- lockpt = rmvlocklst;
- while( lockpt ) {
- if (expandsym(lockpt->revno, numrev)) {
- target = genrevs(numrev, (char *)nil, (char *)nil, (char *)nil, gendeltas);
- if ( target )
- if ( !(countnumflds(numrev)%2) && cmpnum(target->num,numrev))
- error("Can't unlock nonexisting revision %s",lockpt->revno);
- else
- breaklock(caller, target);
- /* breaklock does its own diagnose */
- }
- lockpt = lockpt->nextrev;
- }
-
- /* add new locks which stored in newlocklst */
- lockpt = newlocklst;
- while( lockpt ) {
- setlock(lockpt->revno,caller);
- lockpt = lockpt->nextrev;
- }
-
- if ( lockhead == true) { /* lock default branch or head */
- if (Dbranch) {
- setlock(Dbranch->num,caller);
- } elsif ( Head) {
- if (addlock(Head, caller))
- diagnose("%s locked",Head->num);
- } else {
- warn("Can't lock an empty tree");
- }
- }
-
- }
-
-
-
- setlock(rev,who)
- char * rev, * who;
- /* Function: Given a revision or branch number, finds the correponding
- * delta and locks it for who.
- */
- {
- struct lock *lpt;
- struct hshentry *target;
-
- if (expandsym(rev, &numrev[0]) ){
- target = genrevs(&numrev[0],(char *) nil,(char *) nil,
- (char *)nil, gendeltas);
- if ( target )
- if ( !(countnumflds(&numrev[0])%2) && cmpnum(target->num,&numrev[0]))
- error("Can't lock nonexisting revision %s",numrev);
- else
- if(lpt=addlock(target, who))
- diagnose("%s locked",lpt->delta->num);
- }
- }
-
-
-
- rcs_setstate(rev,status)
- char * rev, * status;
- /* Function: Given a revision or branch number, finds the corresponding delta
- * and sets its state to status.
- */
- {
- struct hshentry *target;
-
- if ( expandsym(rev, &numrev[0]) ) {
- target = genrevs(&numrev[0],(char *) nil, (char *)nil,
- (char *) nil, gendeltas);
- if ( target )
- if ( !(countnumflds(&numrev[0])%2) && cmpnum(target->num, &numrev[0]) )
- error("Can't set state of nonexisting revision %s to %s",
- numrev,status);
- else
- target->state = status;
- }
- }
-
-
-
-
-
- buildeltatext(deltas)
- struct hshentry ** deltas;
- /* Function: put the delta text on frewrite and make necessary */
- /* change to delta text */
- {
- int i, c, exit_stats;
-
- cuttail->selector = DELETE;
- #ifdef MSDOS
- initeditfiles( tmpdir );
- #else
- initeditfiles("/tmp/");
- #endif /* MSDOS */
- scanlogtext(deltas[0], copy);
- i = 1;
- if ( cuthead ) {
- #ifdef MSDOS
- cutfilename=mktempfile( tmpdir, "ctXXXXXX");
- #else
- cutfilename=mktempfile("/tmp/", "RCScutXXXXXX");
- #endif /* MSDOS */
- if ( (fcut = fopen(cutfilename, "w")) == NULL) {
- faterror("Can't open temporary file %s", cutfilename);
- }
-
- while( deltas[i-1] != cuthead ) {
- scanlogtext(deltas[i++], edit);
- }
-
- finishedit((struct hshentry *)nil); rewind(fcopy);
- while( (c = getc(fcopy)) != EOF) VOID putc(c, fcut);
- swapeditfiles(false);
- ffclose(fcut);
- }
-
- while( deltas[i-1] != cuttail)
- scanlogtext(deltas[i++], edit);
- finishedit((struct hshentry *)nil); ffclose(fcopy);
-
- if ( cuthead ) {
- #ifdef MSDOS
- diffilename=mktempfile( tmpdir, "dfXXXXXX");
- #else
- diffilename=mktempfile("/tmp/", "RCSdifXXXXXX");
- #endif /* MSDOS */
- exit_stats = run((char*)nil,diffilename,
- #ifdef MSDOS
- # ifdef GNUDIFF
- DIFF,"-n","-a",cutfilename,resultfile,(char*)nil);
- # elif MKS
- DIFF,"-n",cutfilename,resultfile,(char*)nil);
- # endif
- #else
- DIFF,"-n",cutfilename,resultfile,(char*)nil);
- #endif /* MSDOS */
- #ifdef MSDOS
- if (exit_stats != 0 && exit_stats != 1 )
- #else
- if (exit_stats != 0 && exit_stats != (1 << BYTESIZ))
- #endif /* MSDOS */
- faterror ("diff failed");
- if(!putdtext(cuttail->num,curlogmsg,diffilename,frewrite)) return;
- }
- else
- if (!putdtext(cuttail->num,curlogmsg,resultfile,frewrite)) return;
-
- scanlogtext((struct hshentry *)nil,empty); /* read the rest of the deltas */
- }
-
-
-
- buildtree()
- /* Function: actually removes revisions whose selector field */
- /* is DELETE, and rebuilds the linkage of deltas. */
- /* asks for reconfirmation if deleting last revision*/
- {
- int c, response;
-
- struct hshentry * Delta;
- struct branchhead *pt, *pre;
-
- if ( cuthead )
- if ( cuthead->next == delstrt )
- cuthead->next = cuttail;
- else {
- pre = pt = cuthead->branches;
- while( pt && pt->hsh != delstrt ) {
- pre = pt;
- pt = pt->nextbranch;
- }
- if ( cuttail )
- pt->hsh = cuttail;
- else if ( pt == pre )
- cuthead->branches = pt->nextbranch;
- else
- pre->nextbranch = pt->nextbranch;
- }
- else {
- if ( cuttail == nil && !quietflag) {
- VOID fprintf(stderr,"Do you really want to delete all revisions ?[ny](n): ");
- c = response = getchar();
- while( c != EOF && c != '\n') c = getchar();
- if ( response != 'y' && response != 'Y') {
- diagnose("No revision deleted");
- Delta = delstrt;
- while( Delta) {
- Delta->selector = 'S';
- Delta = Delta->next;
- }
- return;
- }
- }
- Head = cuttail;
- }
- return;
- }
-
-