📄 rcsfnms.c
字号:
/* * RCS file name handling *//**************************************************************************** * creation and deletion of /tmp temporaries * pairing of RCS file names and working file names. * Testprogram: define PAIRTEST **************************************************************************** *//* 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: rcsfnms.c,v $ * Revision 5.8 1991/09/24 00:28:40 eggert * Don't export bindex(). * * Revision 5.7 1991/08/19 03:13:55 eggert * Fix messages when rcswriteopen fails. * Look in $TMP and $TEMP if $TMPDIR isn't set. Tune. * * Revision 5.6 1991/04/21 11:58:23 eggert * Fix errno bugs. Add -x, RCSINIT, MS-DOS support. * * Revision 5.5 1991/02/26 17:48:38 eggert * Fix setuid bug. Support new link behavior. * Define more portable getcwd(). * * Revision 5.4 1990/11/01 05:03:43 eggert * Permit arbitrary data in comment leaders. * * Revision 5.3 1990/09/14 22:56:16 hammer * added more filename extensions and their comment leaders * * Revision 5.2 1990/09/04 08:02:23 eggert * Fix typo when !RCSSEP. * * Revision 5.1 1990/08/29 07:13:59 eggert * Work around buggy compilers with defective argument promotion. * * Revision 5.0 1990/08/22 08:12:50 eggert * Ignore signals when manipulating the semaphore file. * Modernize list of file name extensions. * Permit paths of arbitrary length. Beware file names beginning with "-". * Remove compile-time limits; use malloc instead. * Permit dates past 1999/12/31. Make lock and temp files faster and safer. * Ansify and Posixate. * Don't use access(). Fix test for non-regular files. Tune. * * Revision 4.8 89/05/01 15:09:41 narten * changed getwd to not stat empty directories. * * Revision 4.7 88/08/09 19:12:53 eggert * Fix troff macro comment leader bug; add Prolog; allow cc -R; remove lint. * * Revision 4.6 87/12/18 11:40:23 narten * additional file types added from 4.3 BSD version, and SPARC assembler * comment character added. Also, more lint cleanups. (Guy Harris) * * Revision 4.5 87/10/18 10:34:16 narten * Updating version numbers. Changes relative to 1.1 actually relative * to verion 4.3 * * Revision 1.3 87/03/27 14:22:21 jenkins * Port to suns * * Revision 1.2 85/06/26 07:34:28 svb * Comment leader '% ' for '*.tex' files added. * * Revision 4.3 83/12/15 12:26:48 wft * Added check for KDELIM in file names to pairfilenames(). * * Revision 4.2 83/12/02 22:47:45 wft * Added csh, red, and sl file name suffixes. * * Revision 4.1 83/05/11 16:23:39 wft * Added initialization of Dbranch to InitAdmin(). Canged pairfilenames(): * 1. added copying of path from workfile to RCS file, if RCS file is omitted; * 2. added getting the file status of RCS and working files; * 3. added ignoring of directories. * * Revision 3.7 83/05/11 15:01:58 wft * Added comtable[] which pairs file name suffixes with comment leaders; * updated InitAdmin() accordingly. * * Revision 3.6 83/04/05 14:47:36 wft * fixed Suffix in InitAdmin(). * * Revision 3.5 83/01/17 18:01:04 wft * Added getwd() and rename(); these can be removed by defining * V4_2BSD, since they are not needed in 4.2 bsd. * Changed sys/param.h to sys/types.h. * * Revision 3.4 82/12/08 21:55:20 wft * removed unused variable. * * Revision 3.3 82/11/28 20:31:37 wft * Changed mktempfile() to store the generated file names. * Changed getfullRCSname() to store the file and pathname, and to * delete leading "../" and "./". * * Revision 3.2 82/11/12 14:29:40 wft * changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(), * checksuffix(), checkfullpath(). Semaphore name generation updated. * mktempfile() now checks for nil path; freefilename initialized properly. * Added Suffix .h to InitAdmin. Added testprogram PAIRTEST. * Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here. * * Revision 3.1 82/10/18 14:51:28 wft * InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h). * renamed checkpath() to checkfullpath(). */#include "rcsbase.h"libId(fnmsId, "$Id: rcsfnms.c,v 5.8 1991/09/24 00:28:40 eggert Exp $")char const *RCSfilename;char *workfilename;FILE *workstdout;struct stat RCSstat;char const *suffixes;static char const rcsdir[] = "RCS";#define rcsdirlen (sizeof(rcsdir)-1)static struct buf RCSbuf, RCSb;static int RCSerrno;/* Temp file names to be unlinked when done, if they are not nil. */#define TEMPNAMES 5 /* must be at least DIRTEMPNAMES (see rcsedit.c) */static char *volatile tfnames[TEMPNAMES];struct compair { char const *suffix, *comlead;};static struct compair const comtable[] = {/* comtable pairs each filename suffix with a comment leader. The comment *//* leader is placed before each line generated by the $Log keyword. This *//* table is used to guess the proper comment leader from the working file's *//* suffix during initial ci (see InitAdmin()). Comment leaders are needed *//* for languages without multiline comments; for others they are optional. */ "a", "-- ", /* Ada */ "ada", "-- ", "asm", ";; ", /* assembler (MS-DOS) */ "bat", ":: ", /* batch (MS-DOS) */ "c", " * ", /* C */ "c++", "// ", /* C++ in all its infinite guises */ "cc", "// ", "cpp", "// ", "cxx", "// ", "cl", ";;; ", /* Common Lisp */ "cmd", ":: ", /* command (OS/2) */ "cmf", "c ", /* CM Fortran */ "cs", " * ", /* C* */ "el", "; ", /* Emacs Lisp */ "f", "c ", /* Fortran */ "for", "c ", "h", " * ", /* C-header */ "hpp", "// ", /* C++ header */ "hxx", "// ", "l", " * ", /* lex NOTE: conflict between lex and franzlisp */ "lisp",";;; ", /* Lucid Lisp */ "lsp", ";; ", /* Microsoft Lisp */ "mac", ";; ", /* macro (DEC-10, MS-DOS, PDP-11, VMS, etc) */ "me", ".\\\" ",/* me-macros t/nroff*/ "ml", "; ", /* mocklisp */ "mm", ".\\\" ",/* mm-macros t/nroff*/ "ms", ".\\\" ",/* ms-macros t/nroff*/ "p", " * ", /* Pascal */ "pas", " * ", "pl", "% ", /* Prolog */ "tex", "% ", /* TeX */ "y", " * ", /* yacc */ nil, "# " /* default for unknown suffix; must always be last */};#if has_mktemp static char const *tmp()/* Yield the name of the tmp directory. */{ static char const *s; if (!s && !(s = cgetenv("TMPDIR")) /* Unix tradition */ && !(s = cgetenv("TMP")) /* DOS tradition */ && !(s = cgetenv("TEMP")) /* another DOS tradition */ ) s = TMPDIR; return s;}#endif char const *maketemp(n) int n;/* Create a unique filename using n and the process id and store it * into the nth slot in tfnames. * Because of storage in tfnames, tempunlink() can unlink the file later. * Returns a pointer to the filename created. */{ char *p; char const *t = tfnames[n]; if (t) return t; catchints(); {# if has_mktemp char const *tp = tmp(); p = testalloc(strlen(tp) + 10); VOID sprintf(p, "%s%cT%cXXXXXX", tp, SLASH, '0'+n); if (!mktemp(p) || !*p) faterror("can't make temporary file name `%s%cT%cXXXXXX'", tp, SLASH, '0'+n );# else static char tfnamebuf[TEMPNAMES][L_tmpnam]; p = tfnamebuf[n]; if (!tmpnam(p) || !*p)# ifdef P_tmpdir faterror("can't make temporary file name `%s...'",P_tmpdir);# else faterror("can't make temporary file name");# endif# endif } tfnames[n] = p; return p;} voidtempunlink()/* Clean up maketemp() files. May be invoked by signal handler. */{ register int i; register char *p; for (i = TEMPNAMES; 0 <= --i; ) if ((p = tfnames[i])) { VOID unlink(p); /* * We would tfree(p) here, * but this might dump core if we're handing a signal. * We're about to exit anyway, so we won't bother. */ tfnames[i] = 0; }} static char const *bindex(sp,ch) register char const *sp; int ch;/* Function: Finds the last occurrence of character c in string sp * and returns a pointer to the character just beyond it. If the * character doesn't occur in the string, sp is returned. */{ register char const c=ch, *r; r = sp; while (*sp) { if (*sp++ == c) r=sp; } return r;} static intsuffix_matches(suffix, pattern) register char const *suffix, *pattern;{ register int c; if (!pattern) return true; for (;;) switch (*suffix++ - (c = *pattern++)) { case 0: if (!c) return true; break; case 'A'-'a': if (ctab[c] == Letter) break; /* fall into */ default: return false; }} static voidInitAdmin()/* function: initializes an admin node */{ register char const *Suffix; register int i; Head=nil; Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil; StrictLocks=STRICT_LOCKING; /* guess the comment leader from the suffix*/ Suffix=bindex(workfilename, '.'); if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/ for (i=0; !suffix_matches(Suffix,comtable[i].suffix); i++) ; Comment.string = comtable[i].comlead; Comment.size = strlen(comtable[i].comlead); Lexinit(); /* note: if !finptr, reads nothing; only initializes */}#if defined(_POSIX_NO_TRUNC)# define LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED 0#else# define LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED 1#endif#if LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED#ifdef NAME_MAX# define filenametoolong(path) (NAME_MAX < strlen(basename(path)))#else static intfilenametoolong(path) char *path;/* Yield true if the last file name in PATH is too long. */{ static unsigned long dot_namemax; register size_t namelen; register char *base; register unsigned long namemax; base = path + dirlen(path); namelen = strlen(base); if (namelen <= _POSIX_NAME_MAX) /* fast check for shorties */ return false; if (base != path) { *--base = 0; namemax = pathconf(path, _PC_NAME_MAX); *base = SLASH; } else { /* Cache the results for the working directory, for speed. */ if (!dot_namemax) dot_namemax = pathconf(".", _PC_NAME_MAX); namemax = dot_namemax; } /* If pathconf() yielded -1, namemax is now ULONG_MAX. */ return namemax<namelen;}#endif#endif voidbufalloc(b, size) register struct buf *b; size_t size;/* Ensure *B is a name buffer of at least SIZE bytes. * *B's old contents can be freed; *B's new contents are undefined. */{ if (b->size < size) { if (b->size) tfree(b->string); else b->size = sizeof(malloc_type); while (b->size < size) b->size <<= 1; b->string = tnalloc(char, b->size); }} voidbufrealloc(b, size) register struct buf *b; size_t size;/* like bufalloc, except *B's old contents, if any, are preserved */{ if (b->size < size) { if (!b->size) bufalloc(b, size); else { while ((b->size <<= 1) < size) ; b->string = trealloc(char, b->string, b->size); } }} voidbufautoend(b) struct buf *b;/* Free an auto buffer at block exit. */{ if (b->size) tfree(b->string);} struct cbufbufremember(b, s) struct buf *b; size_t s;/* * Free the buffer B with used size S. * Yield a cbuf with identical contents. * The cbuf will be reclaimed when this input file is finished. */{ struct cbuf cb; if ((cb.size = s)) cb.string = fremember(trealloc(char, b->string, s)); else { bufautoend(b); /* not really auto */ cb.string = ""; } return cb;} char *bufenlarge(b, alim) register struct buf *b; char const **alim;/* Make *B larger. Set *ALIM to its new limit, and yield the relocated value * of its old limit. */{ size_t s = b->size; bufrealloc(b, s + 1); *alim = b->string + b->size; return b->string + s;} voidbufscat(b, s) struct buf *b; char const *s;/* Concatenate S to B's end. */{ size_t blen = b->string ? strlen(b->string) : 0; bufrealloc(b, blen+strlen(s)+1); VOID strcpy(b->string+blen, s);} voidbufscpy(b, s) struct buf *b; char const *s;/* Copy S into B. */{ bufalloc(b, strlen(s)+1); VOID strcpy(b->string, s);} char const *basename(p) char const *p;/* Yield the address of the base filename of the pathname P. */{ register char const *b = p, *q = p; for (;;) switch (*q++) { case SLASHes: b = q; break; case 0: return b; }} size_tdirlen(p) char const *p;/* Yield the length of P's directory, including its trailing SLASH. */{ return basename(p) - p;} static size_tsuffixlen(x) char const *x;/* Yield the length of X, an RCS filename suffix. */{ register char const *p; p = x; for (;;) switch (*p) { case 0: case SLASHes: return p - x; default: ++p; continue; }} char const *rcssuffix(name) char const *name;/* Yield the suffix of NAME if it is an RCS filename, 0 otherwise. */{ char const *x, *p, *nz; size_t dl, nl, xl; nl = strlen(name); nz = name + nl; x = suffixes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -