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

📄 rcs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *                      RCS create/change operation *//* Copyright (C) 1982, 1988, 1989 Walter Tichy   Copyright 1990, 1991 by Paul Eggert   Distributed under license by the Free Software Foundation, Inc.This file is part of RCS.RCS is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.RCS is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with RCS; see the file COPYING.  If not, write tothe 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.12  1991/11/20  17:58:08  eggert * Don't read the delta tree from a nonexistent RCS file. * * Revision 5.11  1991/10/07  17:32:46  eggert * Remove lint. * * Revision 5.10  1991/08/19  23:17:54  eggert * Add -m, -r$, piece tables.  Revision separator is `:', not `-'.  Tune. * * Revision 5.9  1991/04/21  11:58:18  eggert * Add -x, RCSINIT, MS-DOS support. * * Revision 5.8  1991/02/25  07:12:38  eggert * strsave -> str_save (DG/UX name clash) * 0444 -> S_IRUSR|S_IRGRP|S_IROTH for portability * * Revision 5.7  1990/12/18  17:19:21  eggert * Fix bug with multiple -n and -N options. * * Revision 5.6  1990/12/04  05:18:40  eggert * Use -I for prompts and -q for diagnostics. * * Revision 5.5  1990/11/11  00:06:35  eggert * Fix `rcs -e' core dump. * * Revision 5.4  1990/11/01  05:03:33  eggert * Add -I and new -t behavior.  Permit arbitrary data in logs. * * Revision 5.3  1990/10/04  06:30:16  eggert * Accumulate exit status across files. * * Revision 5.2  1990/09/04  08:02:17  eggert * Standardize yes-or-no procedure. * * Revision 5.1  1990/08/29  07:13:51  eggert * Remove unused setuid support.  Clean old log messages too. * * Revision 5.0  1990/08/22  08:12:42  eggert * Don't lose names when applying -a option to multiple files. * Remove compile-time limits; use malloc instead.  Add setuid support. * Permit dates past 1999/12/31.  Make lock and temp files faster and safer. * Ansify and Posixate.  Add -V.  Fix umask bug.  Make linting easier.  Tune. * Yield proper exit status.  Check diff's output. * * 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/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 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 "rcsbase.h"struct  Lockrev {	char const *revno;        struct  Lockrev   * nextrev;};struct  Symrev {	char const *revno;	char const *ssymbol;        int     override;        struct  Symrev  * nextsym;};struct Message {	char const *revno;	struct cbuf message;	struct Message *nextmessage;};struct  Status {	char const *revno;	char const *status;        struct  Status  * nextstatus;};enum changeaccess {append, erase};struct chaccess {	char const *login;	enum changeaccess command;	struct chaccess *nextchaccess;};struct delrevpair {	char const *strt;	char const *end;        int     code;};static int buildeltatext P((struct hshentries const*));static int removerevs P((void));static int sendmail P((char const*,char const*));static struct Lockrev *rmnewlocklst P((struct Lockrev const*));static void breaklock P((struct hshentry const*));static void buildtree P((void));static void cleanup P((void));static void doaccess P((void));static void doassoc P((void));static void dolocks P((void));static void domessages P((void));static void getaccessor P((char*,enum changeaccess));static void getassoclst P((int,char*));static void getchaccess P((char const*,enum changeaccess));static void getdelrev P((char*));static void getmessage P((char*));static void getstates P((char*));static void rcs_setstate P((char const*,char const*));static void scanlogtext P((struct hshentry*,int));static void setlock P((char const*));static struct buf numrev;static char const *headstate;static int chgheadstate, exitstatus, lockhead, unlockcaller;static struct Lockrev *newlocklst, *rmvlocklst;static struct Message *messagelst, *lastmessage;static struct Status *statelst, *laststate;static struct Symrev *assoclst, *lastassoc;static struct chaccess *chaccess, **nextchaccess;static struct delrevpair delrev;static struct hshentry *cuthead, *cuttail, *delstrt;static struct hshentries *gendeltas;mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.12 1991/11/20 17:58:08 eggert Exp $"){	static char const cmdusage[] =		"\nrcs usage: rcs -{ae}logins -Afile -{blu}[rev] -cstring -{iLU} -{nNs}name[:rev] -orange -t[file] -Vn file ...";	char *a, **newargv, *textfile;	char const *branchsym, *commsyml;	int branchflag, expmode, initflag;	int e, r, strictlock, strict_selected, textflag;	mode_t defaultRCSmode;	/* default mode for new RCS files */	mode_t RCSmode;	struct buf branchnum;	struct stat workstat;        struct  Lockrev *curlock,  * rmvlock, *lockpt;        struct  Status  * curstate;	nosetid();	nextchaccess = &chaccess;	branchsym = commsyml = textfile = nil;	branchflag = strictlock = false;	bufautobegin(&branchnum);	curlock = rmvlock = nil;	defaultRCSmode = 0;	expmode = -1;	suffixes = X_DEFAULT;        initflag= textflag = false;        strict_selected = 0;        /*  preprocessing command options    */	argc = getRCSINIT(argc, argv, &newargv);	argv = newargv;	while (a = *++argv,  0<--argc && *a++=='-') {		switch (*a++) {		case 'i':   /*  initial version  */                        initflag = true;                        break;                case 'b':  /* change default branch */			if (branchflag) redefined('b');                        branchflag= true;			branchsym = a;                        break;                case 'c':   /*  change comment symbol   */			if (commsyml) redefined('c');			commsyml = a;                        break;                case 'a':  /*  add new accessor   */			getaccessor(*argv+1, append);                        break;                case 'A':  /*  append access list according to accessfile  */			if (!*a) {			    error("missing file name after -A");                            break;                        }			*argv = a;			if (0 < pairfilenames(1,argv,rcsreadopen,true,false)) {			    while (AccessList) {				getchaccess(str_save(AccessList->login),append);				AccessList = AccessList->nextaccess;			    }			    Izclose(&finptr);                        }                        break;                case 'e':    /*  remove accessors   */			getaccessor(*argv+1, erase);                        break;                case 'l':    /*   lock a revision if it is unlocked   */			if (!*a) {			    /* Lock head or default branch.  */                            lockhead = true;                            break;                        }			lockpt = talloc(struct Lockrev);			lockpt->revno = a;                        lockpt->nextrev = nil;                        if ( curlock )                            curlock->nextrev = lockpt;                        else                            newlocklst = lockpt;                        curlock = lockpt;                        break;                case 'u':   /*  release lock of a locked revision   */			if (!*a) {                            unlockcaller=true;                            break;                        }			lockpt = talloc(struct Lockrev);			lockpt->revno = a;                        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("-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("-L overrides -U.");                        }			else			    strictlock = false;                        break;                case 'n':    /*  add new association: error, if name exists */			if (!*a) {			    error("missing symbolic name after -n");                            break;                        }                        getassoclst(false, (*argv)+1);                        break;                case 'N':   /*  add or change association   */			if (!*a) {			    error("missing symbolic name after -N");                            break;                        }                        getassoclst(true, (*argv)+1);                        break;		case 'm':   /*  change log message  */			getmessage(a);			break;		case 'o':   /*  delete revisions  */			if (delrev.strt) redefined('o');			if (!*a) {			    error("missing revision range after -o");                            break;                        }                        getdelrev( (*argv)+1 );                        break;                case 's':   /*  change state attribute of a revision  */			if (!*a) {			    error("state missing after -s");                            break;                        }                        getstates( (*argv)+1);                        break;                case 't':   /*  change descriptive text   */                        textflag=true;			if (*a) {				if (textfile) redefined('t');				textfile = a;                        }                        break;		case 'I':			interactiveflag = true;			break;                case 'q':                        quietflag = true;                        break;		case 'x':			suffixes = a;			break;		case 'V':			setRCSversion(*argv);			break;		case 'k':    /*  set keyword expand mode  */			if (0 <= expmode) redefined('k');			if (0 <= (expmode = str2expmode(a)))			    break;			/* fall into */                default:			faterror("unknown option: %s%s", *argv, cmdusage);                };        }  /* end processing of options */	if (argc<1) faterror("no input file%s", cmdusage);        if (nerror) {	    diagnose("%s aborted\n",cmdid);	    exitmain(EXIT_FAILURE);        }	if (initflag) {	    defaultRCSmode = umask((mode_t)0);	    VOID umask(defaultRCSmode);	    defaultRCSmode = (S_IRUSR|S_IRGRP|S_IROTH) & ~defaultRCSmode;	}        /* now handle all filenames */        do {	ffree();        if ( initflag ) {	    switch (pairfilenames(argc, argv, rcswriteopen, false, false)) {                case -1: break;        /*  not exist; ok */                case  0: continue;     /*  error         */                case  1: error("file %s exists already", RCSfilename);                         continue;            }	}        else  {	    switch (pairfilenames(argc, argv, rcswriteopen, 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\n", RCSfilename);	RCSmode = defaultRCSmode;	if (initflag) {		if (stat(workfilename, &workstat) == 0)			RCSmode = workstat.st_mode;	} else {		if (!checkaccesslist()) continue;		gettree(); /* Read the delta tree.  */		RCSmode = RCSstat.st_mode;	}	RCSmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);        /*  update admin. node    */        if (strict_selected) StrictLocks = strictlock;	if (commsyml) {		Comment.string = commsyml;		Comment.size = strlen(commsyml);	}	if (0 <= expmode) Expand = expmode;        /* update default branch */	if (branchflag && expandsym(branchsym, &branchnum)) {	    if (countnumflds(branchnum.string)) {		Dbranch = branchnum.string;            } else                Dbranch = nil;        }	doaccess();	/* Update access list.  */	doassoc();	/* Update association list.  */	dolocks();	/* Update locks.  */	domessages();	/* Update log messages.  */        /*  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,headstate); /* Can't set directly */            }

⌨️ 快捷键说明

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