⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
        }        curstate = statelst;        while( curstate ) {            rcs_setstate(curstate->revno,curstate->status);            curstate = curstate->nextstatus;        }        cuthead = cuttail = nil;	if (delrev.strt && removerevs()) {            /*  rebuild delta tree if some deltas are deleted   */            if ( cuttail )		VOID genrevs(cuttail->num, (char *)nil,(char *)nil,			     (char *)nil, &gendeltas);            buildtree();        }	if (nerror)		continue;        putadmin(frewrite);        if ( Head )           puttree(Head, frewrite);	putdesc(textflag,textfile);        if ( Head) {	    if (!delrev.strt && !messagelst) {		/* No revision was deleted and no message was changed.  */		fastcopy(finptr, frewrite);            } else {		if (!cuttail || buildeltatext(gendeltas)) {		    advise_access(finptr, MADV_SEQUENTIAL);		    scanlogtext((struct hshentry *)nil, false);                    /* copy rest of delta text nodes that are not deleted      */		}            }        }	Izclose(&finptr);        if ( ! nerror ) {  /*  move temporary file to RCS file if no error */	    /* update mode */	    ignoreints();	    r = chnamemod(&frewrite, newRCSfilename, RCSfilename, RCSmode);	    e = errno;	    keepdirtemp(newRCSfilename);	    restoreints();	    if (r != 0) {		enerror(e, RCSfilename);		error("saved in %s", newRCSfilename);		dirtempunlink();                break;            }	    diagnose("done\n");        } else {	    diagnose("%s aborted; %s unchanged.\n",cmdid,RCSfilename);        }	} while (cleanup(),                 ++argv, --argc >=1);	tempunlink();	exitmain(exitstatus);}       /* end of main (rcs) */	static voidcleanup(){	if (nerror) exitstatus = EXIT_FAILURE;	Izclose(&finptr);	Ozclose(&fcopy);	Ozclose(&frewrite);	dirtempunlink();}	exiting voidexiterr(){	dirtempunlink();	tempunlink();	_exit(EXIT_FAILURE);}	static voidgetassoclst(flag, sp)int     flag;char    * sp;/*  Function:   associate a symbolic name to a revision or branch,      *//*              and store in assoclst                                   */{        struct   Symrev  * pt;	char const *temp;        int                c;        while( (c=(*++sp)) == ' ' || c == '\t' || c =='\n')  ;        temp = sp;	sp = checkid(sp, ':');  /*  check for invalid symbolic name  */	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 = talloc(struct Symrev);        pt->ssymbol = temp;        pt->override = flag;	if (c == '\0')  /*  delete symbol  */            pt->revno = nil;        else {            while( (c = *++sp) == ' ' || c == '\n' || c == '\t')  ;	    pt->revno = sp;        }        pt->nextsym = nil;        if (lastassoc)            lastassoc->nextsym = pt;        else            assoclst = pt;        lastassoc = pt;        return;}	static voidgetchaccess(login, command)	char const *login;	enum changeaccess command;{	register struct chaccess *pt;	*nextchaccess = pt = talloc(struct chaccess);	pt->login = login;	pt->command = command;	pt->nextchaccess = nil;	nextchaccess = &pt->nextchaccess;}	static voidgetaccessor(opt, command)	char *opt;	enum changeaccess command;/*   Function:  get the accessor list of options -e and -a,     *//*		and store in chaccess				*/{        register c;	register char *sp;	sp = opt;        while( ( c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',') ;        if ( c == '\0') {	    if (command == erase  &&  sp-opt == 1) {		getchaccess((char const*)nil, command);		return;	    }	    error("missing login name after option -a or -e");	    return;        }        while( c != '\0') {		getchaccess(sp, command);		sp = checkid(sp,',');		c = *sp;   *sp = '\0';                while( c == ' ' || c == '\n' || c == '\t'|| c == ',')c =(*++sp);        }}	static voidgetmessage(option)	char *option;{	struct Message *pt;	struct cbuf cb;	char *m;	if (!(m = strchr(option, ':'))) {		error("-m option lacks revision number");		return;	}	*m++ = 0;	cb = cleanlogmsg(m, strlen(m));	if (!cb.size) {		error("-m option lacks log message");		return;	}	pt = talloc(struct Message);	pt->revno = option;	pt->message = cb;	pt->nextmessage = 0;	if (lastmessage)		lastmessage->nextmessage = pt;	else		messagelst = pt;	lastmessage = pt;}	static voidgetstates(sp)char    *sp;/*   Function:  get one state attribute and the corresponding   *//*              revision and store in statelst                  */{	char const *temp;        struct  Status  *pt;        register        c;        while( (c=(*++sp)) ==' ' || c == '\t' || c == '\n')  ;        temp = sp;	sp = checkid(sp,':');  /* check for invalid state attribute */	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 = talloc(struct Status);        pt->status     = temp;        pt->revno      = sp;        pt->nextstatus = nil;        if (laststate)            laststate->nextstatus = pt;        else            statelst = pt;        laststate = pt;}	static voidgetdelrev(sp)char    *sp;/*   Function:  get revision range or branch to be deleted,     *//*              and place in delrev                             */{        int    c;        struct  delrevpair      *pt;	int separator;	pt = &delrev;        while((c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;	/* Support old ambiguous '-' syntax; this will go away.  */	if (strchr(sp,':'))		separator = ':';	else {		if (strchr(sp,'-')  &&  VERSION(5) <= RCSversion)		    warn("`-' is obsolete in `-o%s'; use `:' instead", sp);		separator = '-';	}	if (c == separator) { /* -o: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;            return;        }        else {            pt->strt = sp;            while( c != ' ' && c != '\n' && c != '\t' && c != '\0'		   && c != separator )  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;                return;            }	    if (c != separator) {		faterror("invalid range %s %s after -o", pt->strt, sp);            }            while( (c = *++sp) == ' ' || c == '\n' || c == '\t')  ;	    if (!c) {  /* -orev: */                pt->end = nil;   pt->code = 2;                return;            }        }	/* -orev1:rev2 */	pt->end = sp;  pt->code = 3;        while( c!= ' ' && c != '\n' && c != '\t' && c != '\0') c = *++sp;        *sp = '\0';}	static voidscanlogtext(delta,edit)	struct hshentry *delta;	int edit;/* 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 * delta->log if delta==cuttail; the text is edited if EDIT is set, else copied. * Assumes the initial lexeme must be read in first. * Does not advance nexttok after it is finished, except if delta==nil. */{	struct hshentry const *nextdelta;	struct cbuf cb;	for (;;) {		foutptr = 0;		if (eoflex()) {                    if(delta)			faterror("can't find delta for revision %s", delta->num);		    return; /* no more delta text nodes */                }		nextlex();		if (!(nextdelta=getnum()))		    faterror("delta number corrupted");		if (nextdelta->selector) {			foutptr = frewrite;			aprintf(frewrite,DELNUMFORM,nextdelta->num,Klog);                }		getkeystring(Klog);		if (nextdelta == cuttail) {			cb = savestring(&curlogbuf);			if (!delta->log.string)			    delta->log = cleanlogmsg(curlogbuf.string, cb.size);		} else if (nextdelta->log.string && nextdelta->selector) {			foutptr = 0;			readstring();			foutptr = frewrite;			putstring(foutptr, false, nextdelta->log, true);			afputc(nextc, foutptr);                } else {readstring();                }                nextlex();		while (nexttok==ID && strcmp(NextString,Ktext)!=0)			ignorephrase();		getkeystring(Ktext);		if (delta==nextdelta)			break;		readstring(); /* skip over it */	}	/* got the one we're looking for */	if (edit)		editstring((struct hshentry *)nil);	else		enterstring();}	static struct Lockrev *rmnewlocklst(which)	struct Lockrev const *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;	    tfree(newlocklst);	    newlocklst = pn;        }        pt = pre = newlocklst;        while( pt ) {            if ( ! strcmp(pt->revno, which->revno) ) {                pre->nextrev = pt->nextrev;		tfree(pt);		pt = pre->nextrev;            }            else {                pre = pt;                pt = pt->nextrev;            }        }        return pre;}	static voiddoaccess(){	register struct chaccess *ch;	register struct access **p, *t;	for (ch = chaccess;  ch;  ch = ch->nextchaccess) {		switch (ch->command) {		case erase:			if (!ch->login)			    AccessList = nil;			else			    for (p = &AccessList;  (t = *p);  )				if (strcmp(ch->login, t->login) == 0)					*p = t->nextaccess;				else					p = &t->nextaccess;			break;		case append:			for (p = &AccessList;  ;  p = &t->nextaccess)				if (!(t = *p)) {					*p = t = ftalloc(struct access);					t->login = ch->login;					t->nextaccess = nil;					break;				} else if (strcmp(ch->login, t->login) == 0)					break;			break;		}	}}	static intsendmail(Delta, who)	char const *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. */{#ifdef SENDMAIL	char const *messagefile;	int old1, old2, c;        FILE    * mailmess;#endif	aprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who);	if (!yesorno(false, "Do you want to break the lock? [ny](n): "))		return false;        /* go ahead with breaking  */#ifdef SENDMAIL	messagefile = maketemp(0);	if (!(mailmess = fopen(messagefile, "w"))) {	    efaterror(messagefile);        }	aprintf(mailmess, "Subject: Broken lock on %s\n\nYour lock on revision %s of file %s\nhas been broken by %s for the following reason:\n",		basename(RCSfilename), Delta, getfullRCSname(), getcaller()	);	aputs("State the reason for breaking the lock:\n(terminate with single '.' or end of file)\n>> ", stderr);        old1 = '\n';    old2 = ' ';        for (; ;) {	    c = getcstdin();	    if (feof(stdin)) {		aprintf(mailmess, "%c\n", old1);                break;            }            else if ( c == '\n' && old1 == '.' && old2 == '\n')                break;            else {		afputc(old1, mailmess);                old2 = old1;   old1 = c;		if (c=='\n') aputs(">> ", stderr);            }        }	Ozclose(&mailmess);	if (run(messagefile, (char*)nil, SENDMAIL, who, (char*)nil))		warn("Mail may have failed."),#else		warn("Mail notification of broken locks is not available."),#endif		warn("Please tell `%s' why you broke the lock.", who);	return(true);}	static voidbreaklock(delta)	struct hshentry const *delta;/* function: Finds the lock held by caller 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 const *num;        struct lock dummy;	num=delta->num;        dummy.nextlock=next=Locks;        trail = &dummy;        while (next!=nil) {		if (strcmp(num, next->delta->num) == 0) {			if (				strcmp(getcaller(),next->login) != 0			    &&	!sendmail(num, next->login)			) {			    error("%s still locked by %s", num, next->login);			    return;			}			break; /* exact match */                }                trail=next;                next=next->nextlock;        }        if (next!=nil) {                /*found one */		diagnose("%s unlocked\n",next->delta->num);                trail->nextlock=next->nextlock;                next->delta->lockedby=nil;                Locks=dummy.nextlock;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -