home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-25 | 110.6 KB | 4,074 lines |
- head 5.11;
- branch 5.11.1;
- access;
- symbols
- HWGRCSP12F:5.11.1.10
- HWGRCSP11F:5.11.1.10
- HWGRCSP10F:5.11.1.7
- HWGRCSP9:5.11.1.7
- HWGRCSP8F:5.11.1.6
- HWGRCSP7F:5.11.1.3
- HWGRCSP6F:5.11.1.3
- HWGRCSP5F:5.11.1.1
- HWGRCSp4:5.11.1.1
- HWGRCSp3:5.11.1
- HWGRCS_Fish:5.11.1
- HWGRCS:5.11.1;
- locks; strict;
- comment @ * @;
-
-
- 5.11
- date 91.11.03.01.11.44; author eggert; state Exp;
- branches
- 5.11.1.1;
- next ;
-
- 5.11.1.1
- date 93.01.18.14.38.13; author heinz; state Exp;
- branches;
- next 5.11.1.2;
-
- 5.11.1.2
- date 93.12.04.08.40.36; author heinz; state Exp;
- branches;
- next 5.11.1.3;
-
- 5.11.1.3
- date 93.12.18.16.12.22; author heinz; state Exp;
- branches;
- next 5.11.1.4;
-
- 5.11.1.4
- date 94.02.12.19.20.21; author heinz; state Exp;
- branches;
- next 5.11.1.5;
-
- 5.11.1.5
- date 94.02.14.19.29.45; author heinz; state Exp;
- branches;
- next 5.11.1.6;
-
- 5.11.1.6
- date 94.03.14.09.19.05; author heinz; state Exp;
- branches;
- next 5.11.1.7;
-
- 5.11.1.7
- date 94.03.31.18.38.48; author heinz; state Exp;
- branches;
- next 5.11.1.8;
-
- 5.11.1.8
- date 94.08.01.20.53.56; author heinz; state Exp;
- branches;
- next 5.11.1.9;
-
- 5.11.1.9
- date 94.08.05.16.43.13; author heinz; state Exp;
- branches;
- next 5.11.1.10;
-
- 5.11.1.10
- date 94.08.05.17.35.57; author heinz; state Exp;
- branches;
- next ;
-
-
- desc
- @Checked in with -k 16.jan.93 HWG
- @
-
-
- 5.11
- log
- @checked in with -k by heinz at 1993/01/17 01:53:17
- @
- text
- @/*
- * RCS stream editor
- */
- /**********************************************************************************
- * edits the input file according to a
- * script from stdin, generated by diff -n
- * performs keyword expansion
- **********************************************************************************
- */
-
- /* 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 modify
- it under the terms of the GNU General Public License as published by
- the 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 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: rcsedit.c,v $
- * Revision 5.11 1991/11/03 01:11:44 eggert
- * Move the warning about link breaking to where they're actually being broken.
- *
- * Revision 5.10 1991/10/07 17:32:46 eggert
- * Support piece tables even if !has_mmap. Fix rare NFS bugs.
- *
- * Revision 5.9 1991/09/17 19:07:40 eggert
- * SGI readlink() yields ENXIO, not EINVAL, for nonlinks.
- *
- * Revision 5.8 1991/08/19 03:13:55 eggert
- * Add piece tables, NFS bug workarounds. Catch odd filenames. Tune.
- *
- * Revision 5.7 1991/04/21 11:58:21 eggert
- * Fix errno bugs. Add -x, RCSINIT, MS-DOS support.
- *
- * Revision 5.6 1991/02/25 07:12:40 eggert
- * Fix setuid bug. Support new link behavior. Work around broken "w+" fopen.
- *
- * Revision 5.5 1990/12/30 05:07:35 eggert
- * Fix report of busy RCS files when !defined(O_CREAT) | !defined(O_EXCL).
- *
- * Revision 5.4 1990/11/01 05:03:40 eggert
- * Permit arbitrary data in comment leaders.
- *
- * Revision 5.3 1990/09/11 02:41:13 eggert
- * Tune expandline().
- *
- * Revision 5.2 1990/09/04 08:02:21 eggert
- * Count RCS lines better. Improve incomplete line handling.
- *
- * Revision 5.1 1990/08/29 07:13:56 eggert
- * Add -kkvl.
- * Fix bug when getting revisions to files ending in incomplete lines.
- * Fix bug in comment leader expansion.
- *
- * Revision 5.0 1990/08/22 08:12:47 eggert
- * Don't require final newline.
- * Don't append "checked in with -k by " to logs,
- * so that checking in a program with -k doesn't change it.
- * Don't generate trailing white space for empty comment leader.
- * Remove compile-time limits; use malloc instead. Add -k, -V.
- * Permit dates past 1999/12/31. Make lock and temp files faster and safer.
- * Ansify and Posixate. Check diff's output.
- *
- * Revision 4.8 89/05/01 15:12:35 narten
- * changed copyright header to reflect current distribution rules
- *
- * Revision 4.7 88/11/08 13:54:14 narten
- * misplaced semicolon caused infinite loop
- *
- * Revision 4.6 88/08/09 19:12:45 eggert
- * Shrink stdio code size; allow cc -R.
- *
- * Revision 4.5 87/12/18 11:38:46 narten
- * Changes from the 43. version. Don't know the significance of the
- * first change involving "rewind". Also, additional "lint" cleanup.
- * (Guy Harris)
- *
- * Revision 4.4 87/10/18 10:32:21 narten
- * Updating version numbers. Changes relative to version 1.1 actually
- * relative to 4.1
- *
- * Revision 1.4 87/09/24 13:59:29 narten
- * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- * warnings)
- *
- * Revision 1.3 87/09/15 16:39:39 shepler
- * added an initializatin of the variables editline and linecorr
- * this will be done each time a file is processed.
- * (there was an obscure bug where if co was used to retrieve multiple files
- * it would dump)
- * fix attributed to Roy Morris @@FileNet Corp ...!felix!roy
- *
- * Revision 1.2 87/03/27 14:22:17 jenkins
- * Port to suns
- *
- * Revision 4.1 83/05/12 13:10:30 wft
- * Added new markers Id and RCSfile; added locker to Header and Id.
- * Overhauled expandline completely() (problem with $01234567890123456789@@).
- * Moved trymatch() and marker table to rcskeys.c.
- *
- * Revision 3.7 83/05/12 13:04:39 wft
- * Added retry to expandline to resume after failed match which ended in $.
- * Fixed truncation problem for $19chars followed by@@@@.
- * Log no longer expands full path of RCS file.
- *
- * Revision 3.6 83/05/11 16:06:30 wft
- * added retry to expandline to resume after failed match which ended in $.
- * Fixed truncation problem for $19chars followed by@@@@.
- *
- * Revision 3.5 82/12/04 13:20:56 wft
- * Added expansion of keyword Locker.
- *
- * Revision 3.4 82/12/03 12:26:54 wft
- * Added line number correction in case editing does not start at the
- * beginning of the file.
- * Changed keyword expansion to always print a space before closing KDELIM;
- * Expansion for Header shortened.
- *
- * Revision 3.3 82/11/14 14:49:30 wft
- * removed Suffix from keyword expansion. Replaced fclose with ffclose.
- * keyreplace() gets log message from delta, not from curlogmsg.
- * fixed expression overflow in while(c=putc(GETC....
- * checked nil printing.
- *
- * Revision 3.2 82/10/18 21:13:39 wft
- * I added checks for write errors during the co process, and renamed
- * expandstring() to xpandstring().
- *
- * Revision 3.1 82/10/13 15:52:55 wft
- * changed type of result of getc() from char to int.
- * made keyword expansion loop in expandline() portable to machines
- * without sign-extension.
- */
-
-
- #include "rcsbase.h"
-
- libId(editId, "$Id: rcsedit.c,v 5.11 1991/11/03 01:11:44 eggert Exp $")
-
- static void keyreplace P((enum markers,struct hshentry const*,FILE*));
-
-
- FILE *fcopy; /* result file descriptor */
- char const *resultfile; /* result file name */
- int locker_expansion; /* should the locker name be appended to Id val? */
- #if !large_memory
- static RILE *fedit; /* edit file descriptor */
- static char const *editfile; /* edit pathname */
- #endif
- static unsigned long editline; /* edit line counter; #lines before cursor */
- static long linecorr; /* #adds - #deletes in each edit run. */
- /*used to correct editline in case file is not rewound after */
- /* applying one delta */
-
- #define DIRTEMPNAMES 2
- enum maker {notmade, real, effective};
- struct buf dirtfname[DIRTEMPNAMES]; /* unlink these when done */
- static enum maker volatile dirtfmaker[DIRTEMPNAMES]; /* if these are set */
-
-
- #if has_NFS || bad_unlink
- int
- un_link(s)
- char const *s;
- /*
- * Remove S, even if it is unwritable.
- * Ignore unlink() ENOENT failures; NFS generates bogus ones.
- */
- {
- # if bad_unlink
- int e;
- if (unlink(s) == 0)
- return 0;
- e = errno;
- # if has_NFS
- if (e == ENOENT)
- return 0;
- # endif
- if (chmod(s, S_IWUSR) != 0) {
- errno = e;
- return -1;
- }
- # endif
- # if has_NFS
- return unlink(s)==0 || errno==ENOENT ? 0 : -1;
- # else
- return unlink(s);
- # endif
- }
- #endif
-
- #if !has_rename
- # if !has_NFS
- # define do_link(s,t) link(s,t)
- # else
- static int
- do_link(s, t)
- char const *s, *t;
- /* Link S to T, ignoring bogus EEXIST problems due to NFS failures. */
- {
- struct stat sb, tb;
-
- if (link(s,t) == 0)
- return 0;
- if (errno != EEXIST)
- return -1;
- if (
- stat(s, &sb) == 0 &&
- stat(t, &tb) == 0 &&
- sb.st_ino == tb.st_ino &&
- sb.st_dev == tb.st_dev
- )
- return 0;
- errno = EEXIST;
- return -1;
- }
- # endif
- #endif
-
-
- static exiting void
- editEndsPrematurely()
- {
- fatserror("edit script ends prematurely");
- }
-
- static exiting void
- editLineNumberOverflow()
- {
- fatserror("edit script refers to line past end of file");
- }
-
-
- #if large_memory
-
- #if has_memmove
- # define movelines(s1, s2, n) VOID memmove(s1, s2, (n)*sizeof(Iptr_type))
- #else
- static void
- movelines(s1, s2, n)
- register Iptr_type *s1;
- register Iptr_type const *s2;
- register unsigned long n;
- {
- if (s1 < s2)
- do {
- *s1++ = *s2++;
- } while (--n);
- else {
- s1 += n;
- s2 += n;
- do {
- *--s1 = *--s2;
- } while (--n);
- }
- }
- #endif
-
- /*
- * `line' contains pointers to the lines in the currently `edited' file.
- * It is a 0-origin array that represents linelim-gapsize lines.
- * line[0..gap-1] and line[gap+gapsize..linelim-1] contain pointers to lines.
- * line[gap..gap+gapsize-1] contains garbage.
- *
- * Any @@s in lines are duplicated.
- * Lines are terminated by \n, or (for a last partial line only) by single @@.
- */
- static Iptr_type *line;
- static unsigned long gap, gapsize, linelim;
-
-
- static void
- insertline(n, l)
- unsigned long n;
- Iptr_type l;
- /* Before line N, insert line L. N is 0-origin. */
- {
- if (linelim-gapsize < n)
- editLineNumberOverflow();
- if (!gapsize)
- line =
- !linelim ?
- tnalloc(Iptr_type, linelim = gapsize = 1024)
- : (
- gap = gapsize = linelim,
- trealloc(Iptr_type, line, linelim <<= 1)
- );
- if (n < gap)
- movelines(line+n+gapsize, line+n, gap-n);
- else if (gap < n)
- movelines(line+gap, line+gap+gapsize, n-gap);
-
- line[n] = l;
- gap = n + 1;
- gapsize--;
- }
-
- static void
- deletelines(n, nlines)
- unsigned long n, nlines;
- /* Delete lines N through N+NLINES-1. N is 0-origin. */
- {
- unsigned long l = n + nlines;
- if (linelim-gapsize < l || l < n)
- editLineNumberOverflow();
- if (l < gap)
- movelines(line+l+gapsize, line+l, gap-l);
- else if (gap < n)
- movelines(line+gap, line+gap+gapsize, n-gap);
-
- gap = n;
- gapsize += nlines;
- }
-
- static void
- snapshotline(f, l)
- register FILE *f;
- register Iptr_type l;
- {
- register int c;
- do {
- if ((c = *l++) == SDELIM && *l++ != SDELIM)
- return;
- aputc(c, f);
- } while (c != '\n');
- }
-
- void
- snapshotedit(f)
- FILE *f;
- /* Copy the current state of the edits to F. */
- {
- register Iptr_type *p, *lim, *l=line;
- for (p=l, lim=l+gap; p<lim; )
- snapshotline(f, *p++);
- for (p+=gapsize, lim=l+linelim; p<lim; )
- snapshotline(f, *p++);
- }
-
- static void
- finisheditline(fin, fout, l, delta)
- RILE *fin;
- FILE *fout;
- Iptr_type l;
- struct hshentry const *delta;
- {
- Iseek(fin, l);
- if (expandline(fin, fout, delta, true, (FILE*)0) < 0)
- faterror("finisheditline internal error");
- }
-
- void
- finishedit(delta, outfile, done)
- struct hshentry const *delta;
- FILE *outfile;
- int done;
- /*
- * Doing expansion if DELTA is set, output the state of the edits to OUTFILE.
- * But do nothing unless DONE is set (which means we are on the last pass).
- */
- {
- if (done) {
- openfcopy(outfile);
- outfile = fcopy;
- if (!delta)
- snapshotedit(outfile);
- else {
- register Iptr_type *p, *lim, *l = line;
- register RILE *fin = finptr;
- Iptr_type here = Itell(fin);
- for (p=l, lim=l+gap; p<lim; )
- finisheditline(fin, outfile, *p++, delta);
- for (p+=gapsize, lim=l+linelim; p<lim; )
- finisheditline(fin, outfile, *p++, delta);
- Iseek(fin, here);
- }
- }
- }
-
- /* Open a temporary FILENAME for output, truncating any previous contents. */
- # define fopen_update_truncate(filename) fopen(filename, FOPEN_W_WORK)
- #else /* !large_memory */
- static FILE *
- fopen_update_truncate(filename)
- char const *filename;
- {
- # if bad_fopen_wplus
- if (un_link(filename) != 0)
- efaterror(filename);
- # endif
- return fopen(filename, FOPEN_WPLUS_WORK);
- }
- #endif
-
-
- void
- openfcopy(f)
- FILE *f;
- {
- if (!(fcopy = f)) {
- if (!resultfile)
- resultfile = maketemp(2);
- if (!(fcopy = fopen_update_truncate(resultfile)))
- efaterror(resultfile);
- }
- }
-
-
- #if !large_memory
-
- static void
- swapeditfiles(outfile)
- FILE *outfile;
- /* Function: swaps resultfile and editfile, assigns fedit=fcopy,
- * and rewinds fedit for reading. Set fcopy to outfile if nonnull;
- * otherwise, set fcopy to be resultfile opened for reading and writing.
- */
- {
- char const *tmpptr;
-
- editline = 0; linecorr = 0;
- if (fseek(fcopy, 0L, SEEK_SET) != 0)
- Oerror();
- fedit = fcopy;
- tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
- openfcopy(outfile);
- }
-
- void
- snapshotedit(f)
- FILE *f;
- /* Copy the current state of the edits to F. */
- {
- finishedit((struct hshentry *)nil, (FILE*)0, false);
- fastcopy(fedit, f);
- Irewind(fedit);
- }
-
- void
- finishedit(delta, outfile, done)
- struct hshentry const *delta;
- FILE *outfile;
- int done;
- /* copy the rest of the edit file and close it (if it exists).
- * if delta!=nil, perform keyword substitution at the same time.
- * If DONE is set, we are finishing the last pass.
- */
- {
- register RILE *fe;
- register FILE *fc;
-
- fe = fedit;
- if (fe) {
- fc = fcopy;
- if (delta!=nil) {
- while (1 < expandline(fe,fc,delta,false,(FILE*)0))
- ;
- } else {
- fastcopy(fe,fc);
- }
- Ifclose(fe);
- }
- if (!done)
- swapeditfiles(outfile);
- }
- #endif
-
-
-
- #if large_memory
- # define copylines(upto,delta) (editline = (upto))
- #else
- static void
- copylines(upto,delta)
- register unsigned long upto;
- struct hshentry const *delta;
- /*
- * Copy input lines editline+1..upto from fedit to fcopy.
- * If delta != nil, keyword expansion is done simultaneously.
- * editline is updated. Rewinds a file only if necessary.
- */
- {
- register int c;
- declarecache;
- register FILE *fc;
- register RILE *fe;
-
- if (upto < editline) {
- /* swap files */
- finishedit((struct hshentry *)nil, (FILE*)0, false);
- /* assumes edit only during last pass, from the beginning*/
- }
- fe = fedit;
- fc = fcopy;
- if (editline < upto)
- if (delta)
- do {
- if (expandline(fe,fc,delta,false,(FILE*)0) <= 1)
- editLineNumberOverflow();
- } while (++editline < upto);
- else {
- setupcache(fe); cache(fe);
- do {
- do {
- cachegeteof(c, editLineNumberOverflow(););
- aputc(c, fc);
- } while (c != '\n');
- } while (++editline < upto);
- uncache(fe);
- }
- }
- #endif
-
-
-
- void
- xpandstring(delta)
- struct hshentry const *delta;
- /* Function: Reads a string terminated by SDELIM from finptr and writes it
- * to fcopy. Double SDELIM is replaced with single SDELIM.
- * Keyword expansion is performed with data from delta.
- * If foutptr is nonnull, the string is also copied unchanged to foutptr.
- */
- {
- while (1 < expandline(finptr,fcopy,delta,true,foutptr))
- ;
- }
-
-
- void
- copystring()
- /* Function: copies a string terminated with a single SDELIM from finptr to
- * fcopy, replacing all double SDELIM with a single SDELIM.
- * If foutptr is nonnull, the string also copied unchanged to foutptr.
- * editline is incremented by the number of lines copied.
- * Assumption: next character read is first string character.
- */
- { register c;
- declarecache;
- register FILE *frew, *fcop;
- register int amidline;
- register RILE *fin;
-
- fin = finptr;
- setupcache(fin); cache(fin);
- frew = foutptr;
- fcop = fcopy;
- amidline = false;
- for (;;) {
- GETC(frew,c);
- switch (c) {
- case '\n':
- ++editline;
- ++rcsline;
- amidline = false;
- break;
- case SDELIM:
- GETC(frew,c);
- if (c != SDELIM) {
- /* end of string */
- nextc = c;
- editline += amidline;
- uncache(fin);
- return;
- }
- /* fall into */
- default:
- amidline = true;
- break;
- }
- aputc(c,fcop);
- }
- }
-
-
- void
- enterstring()
- /* Like copystring, except the string is put into the edit data structure. */
- {
- #if !large_memory
- editfile = 0;
- fedit = 0;
- editline = linecorr = 0;
- resultfile = maketemp(1);
- if (!(fcopy = fopen_update_truncate(resultfile)))
- efaterror(resultfile);
- copystring();
- #else
- register int c;
- declarecache;
- register FILE *frew;
- register unsigned long e, oe;
- register int amidline, oamidline;
- register Iptr_type optr;
- register RILE *fin;
-
- e = 0;
- gap = 0;
- gapsize = linelim;
- fin = finptr;
- setupcache(fin); cache(fin);
- advise_access(fin, MADV_NORMAL);
- frew = foutptr;
- amidline = false;
- for (;;) {
- optr = cachetell();
- GETC(frew,c);
- oamidline = amidline;
- oe = e;
- switch (c) {
- case '\n':
- ++e;
- ++rcsline;
- amidline = false;
- break;
- case SDELIM:
- GETC(frew,c);
- if (c != SDELIM) {
- /* end of string */
- nextc = c;
- editline = e + amidline;
- linecorr = 0;
- uncache(fin);
- return;
- }
- /* fall into */
- default:
- amidline = true;
- break;
- }
- if (!oamidline)
- insertline(oe, optr);
- }
- #endif
- }
-
-
-
-
- void
- #if large_memory
- edit_string()
- #else
- editstring(delta)
- struct hshentry const *delta;
- #endif
- /*
- * Read an edit script from finptr and applies it to the edit file.
- #if !large_memory
- * The result is written to fcopy.
- * If delta!=nil, keyword expansion is performed simultaneously.
- * If running out of lines in fedit, fedit and fcopy are swapped.
- * editfile is the name of the file that goes with fedit.
- #endif
- * If foutptr is set, the edit script is also copied verbatim to foutptr.
- * Assumes that all these files are open.
- * resultfile is the name of the file that goes with fcopy.
- * Assumes the next input character from finptr is the first character of
- * the edit script. Resets nextc on exit.
- */
- {
- int ed; /* editor command */
- register int c;
- declarecache;
- register FILE *frew;
- # if !large_memory
- register FILE *f;
- unsigned long line_lim = ULONG_MAX;
- register RILE *fe;
- # endif
- register unsigned long i;
- register RILE *fin;
- # if large_memory
- register unsigned long j;
- # endif
- struct diffcmd dc;
-
- editline += linecorr; linecorr=0; /*correct line number*/
- frew = foutptr;
- fin = finptr;
- setupcache(fin);
- initdiffcmd(&dc);
- while (0 <= (ed = getdiffcmd(fin,true,frew,&dc)))
- #if !large_memory
- if (line_lim <= dc.line1)
- editLineNumberOverflow();
- else
- #endif
- if (!ed) {
- copylines(dc.line1-1, delta);
- /* skip over unwanted lines */
- i = dc.nlines;
- linecorr -= i;
- editline += i;
- # if large_memory
- deletelines(editline+linecorr, i);
- # else
- fe = fedit;
- do {
- /*skip next line*/
- do {
- Igeteof(fe, c, { if (i!=1) editLineNumberOverflow(); line_lim = dc.dafter; break; } );
- } while (c != '\n');
- } while (--i);
- # endif
- } else {
- copylines(dc.line1, delta); /*copy only; no delete*/
- i = dc.nlines;
- # if large_memory
- j = editline+linecorr;
- # endif
- linecorr += i;
- #if !large_memory
- f = fcopy;
- if (delta)
- do {
- switch (expandline(fin,f,delta,true,frew)) {
- case 0: case 1:
- if (i==1)
- return;
- /* fall into */
- case -1:
- editEndsPrematurely();
- }
- } while (--i);
- else
- #endif
- {
- cache(fin);
- do {
- # if large_memory
- insertline(j++, cachetell());
- # endif
- for (;;) {
- GETC(frew, c);
- # if !large_memory
- aputc(c, f);
- # endif
- if (c == '\n')
- break;
- if (c==SDELIM) {
- GETC(frew, c);
- if (c!=SDELIM) {
- if (--i)
- editEndsPrematurely();
- nextc = c;
- uncache(fin);
- return;
- }
- }
- }
- ++rcsline;
- } while (--i);
- uncache(fin);
- }
- }
- }
-
-
-
- /* The rest is for keyword expansion */
-
-
-
- int
- expandline(infile, outfile, delta, delimstuffed, frewfile)
- RILE *infile;
- FILE *outfile, *frewfile;
- struct hshentry const *delta;
- int delimstuffed;
- /*
- * Read a line from INFILE and write it to OUTFILE.
- * If DELIMSTUFFED is true, double SDELIM is replaced with single SDELIM.
- * Keyword expansion is performed with data from delta.
- * If FREWFILE is set, copy the line unchanged to FREWFILE.
- * DELIMSTUFFED must be true if FREWFILE is set.
- * Yields -1 if no data is copied, 0 if an incomplete line is copied,
- * 2 if a complete line is copied; adds 1 to yield if expansion occurred.
- */
- {
- register c;
- declarecache;
- register FILE *out, *frew;
- register char * tp;
- register int e, ds, r;
- char const *tlim;
- static struct buf keyval;
- enum markers matchresult;
-
- setupcache(infile); cache(infile);
- out = outfile;
- frew = frewfile;
- ds = delimstuffed;
- bufalloc(&keyval, keylength+3);
- e = 0;
- r = -1;
-
- for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto uncache_exit;);
- for (;;) {
- switch (c) {
- case SDELIM:
- if (ds) {
- GETC(frew, c);
- if (c != SDELIM) {
- /* end of string */
- nextc=c;
- goto uncache_exit;
- }
- }
- /* fall into */
- default:
- aputc(c,out);
- r = 0;
- break;
-
- case '\n':
- rcsline += ds;
- aputc(c,out);
- r = 2;
- goto uncache_exit;
-
- case KDELIM:
- r = 0;
- /* check for keyword */
- /* first, copy a long enough string into keystring */
- tp = keyval.string;
- *tp++ = KDELIM;
- for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto keystring_eof;);
- if (tp < keyval.string+keylength+1)
- switch (ctab[c]) {
- case LETTER: case Letter:
- *tp++ = c;
- continue;
- default:
- break;
- }
- break;
- }
- *tp++ = c; *tp = '\0';
- matchresult = trymatch(keyval.string+1);
- if (matchresult==Nomatch) {
- tp[-1] = 0;
- aputs(keyval.string, out);
- continue; /* last c handled properly */
- }
-
- /* Now we have a keyword terminated with a K/VDELIM */
- if (c==VDELIM) {
- /* try to find closing KDELIM, and replace value */
- tlim = keyval.string + keyval.size;
- for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto keystring_eof;);
- if (c=='\n' || c==KDELIM)
- break;
- *tp++ =c;
- if (tlim <= tp)
- tp = bufenlarge(&keyval, &tlim);
- if (c==SDELIM && ds) { /*skip next SDELIM */
- GETC(frew, c);
- if (c != SDELIM) {
- /* end of string before closing KDELIM or newline */
- nextc = c;
- goto keystring_eof;
- }
- }
- }
- if (c!=KDELIM) {
- /* couldn't find closing KDELIM -- give up */
- *tp = 0;
- aputs(keyval.string, out);
- continue; /* last c handled properly */
- }
- }
- /* now put out the new keyword value */
- keyreplace(matchresult,delta,out);
- e = 1;
- break;
- }
- break;
- }
- }
-
- keystring_eof:
- *tp = 0;
- aputs(keyval.string, out);
- uncache_exit:
- uncache(infile);
- return r + e;
- }
-
-
- char const ciklog[ciklogsize] = "checked in with -k by ";
-
- static void
- keyreplace(marker,delta,out)
- enum markers marker;
- register struct hshentry const *delta;
- register FILE *out;
- /* function: outputs the keyword value(s) corresponding to marker.
- * Attributes are derived from delta.
- */
- {
- register char const *sp, *cp, *date;
- register char c;
- register size_t cs, cw, ls;
- char const *sp1;
- char datebuf[datesize];
- int RCSv;
-
- sp = Keyword[(int)marker];
-
- if (Expand == KEY_EXPAND) {
- aprintf(out, "%c%s%c", KDELIM, sp, KDELIM);
- return;
- }
-
- date= delta->date;
- RCSv = RCSversion;
-
- if (Expand == KEYVAL_EXPAND || Expand == KEYVALLOCK_EXPAND)
- aprintf(out, "%c%s%c%c", KDELIM, sp, VDELIM,
- marker==Log && RCSv<VERSION(5) ? '\t' : ' '
- );
-
- switch (marker) {
- case Author:
- aputs(delta->author, out);
- break;
- case Date:
- aputs(date2str(date,datebuf), out);
- break;
- case Id:
- case Header:
- aprintf(out, "%s %s %s %s %s",
- marker==Id || RCSv<VERSION(4)
- ? basename(RCSfilename)
- : getfullRCSname(),
- delta->num,
- date2str(date, datebuf),
- delta->author,
- RCSv==VERSION(3) && delta->lockedby ? "Locked"
- : delta->state
- );
- if (delta->lockedby!=nil)
- if (VERSION(5) <= RCSv) {
- if (locker_expansion || Expand==KEYVALLOCK_EXPAND)
- aprintf(out, " %s", delta->lockedby);
- } else if (RCSv == VERSION(4))
- aprintf(out, " Locker: %s", delta->lockedby);
- break;
- case Locker:
- if (delta->lockedby)
- if (
- locker_expansion
- || Expand == KEYVALLOCK_EXPAND
- || RCSv <= VERSION(4)
- )
- aputs(delta->lockedby, out);
- break;
- case Log:
- case RCSfile:
- aputs(basename(RCSfilename), out);
- break;
- case Revision:
- aputs(delta->num, out);
- break;
- case Source:
- aputs(getfullRCSname(), out);
- break;
- case State:
- aputs(delta->state, out);
- break;
- default:
- break;
- }
- if (Expand == KEYVAL_EXPAND || Expand == KEYVALLOCK_EXPAND) {
- afputc(' ', out);
- afputc(KDELIM, out);
- }
- if (marker == Log) {
- sp = delta->log.string;
- ls = delta->log.size;
- if (sizeof(ciklog)-1<=ls && !memcmp(sp,ciklog,sizeof(ciklog)-1))
- return;
- afputc('\n', out);
- cp = Comment.string;
- cw = cs = Comment.size;
- awrite(cp, cs, out);
- /* oddity: 2 spaces between date and time, not 1 as usual */
- sp1 = strchr(date2str(date,datebuf), ' ');
- aprintf(out, "Revision %s %.*s %s %s",
- delta->num, (int)(sp1-datebuf), datebuf, sp1, delta->author
- );
- /* Do not include state: it may change and is not updated. */
- /* Comment is the comment leader. */
- if (VERSION(5) <= RCSv)
- for (; cw && (cp[cw-1]==' ' || cp[cw-1]=='\t'); --cw)
- ;
- for (;;) {
- afputc('\n', out);
- awrite(cp, cw, out);
- if (!ls)
- break;
- --ls;
- c = *sp++;
- if (c != '\n') {
- awrite(cp+cw, cs-cw, out);
- do {
- afputc(c,out);
- if (!ls)
- break;
- --ls;
- c = *sp++;
- } while (c != '\n');
- }
- }
- }
- }
-
- #if has_readlink
- static int
- resolve_symlink(L)
- struct buf *L;
- /*
- * If L is a symbolic link, resolve it to the name that it points to.
- * If unsuccessful, set errno and yield -1.
- * If it points to an existing file, yield 1.
- * Otherwise, set errno=ENOENT and yield 0.
- */
- {
- char *b, a[SIZEABLE_PATH];
- int e;
- size_t s;
- ssize_t r;
- struct buf bigbuf;
- unsigned linkcount = MAXSYMLINKS + 1;
-
- b = a;
- s = sizeof(a);
- bufautobegin(&bigbuf);
- while ((r = readlink(L->string,b,s)) != -1)
- if (r == s) {
- bufalloc(&bigbuf, s<<1);
- b = bigbuf.string;
- s = bigbuf.size;
- } else if (!--linkcount) {
- errno = ELOOP;
- return -1;
- } else {
- /* Splice symbolic link into L. */
- b[r] = '\0';
- L->string[ROOTPATH(b) ? (size_t)0 : dirlen(L->string)] = '\0';
- bufscat(L, b);
- }
- e = errno;
- bufautoend(&bigbuf);
- errno = e;
- switch (e) {
- case ENXIO:
- case EINVAL: return 1;
- case ENOENT: return 0;
- default: return -1;
- }
- }
- #endif
-
- RILE *
- rcswriteopen(RCSbuf, status, mustread)
- struct buf *RCSbuf;
- struct stat *status;
- int mustread;
- /*
- * Create the lock file corresponding to RCSNAME.
- * Then try to open RCSNAME for reading and yield its FILE* descriptor.
- * Put its status into *STATUS too.
- * MUSTREAD is true if the file must already exist, too.
- * If all goes well, discard any previously acquired locks,
- * and set frewrite to the FILE* descriptor of the lock file,
- * which will eventually turn into the new RCS file.
- */
- {
- register char *tp;
- register char const *sp, *RCSname, *x;
- RILE *f;
- size_t l;
- int e, exists, fdesc, previouslock, r;
- struct buf *dirt;
- struct stat statbuf;
-
- previouslock = frewrite != 0;
- exists =
- # if has_readlink
- resolve_symlink(RCSbuf);
- # else
- stat(RCSbuf->string, &statbuf) == 0 ? 1
- : errno==ENOENT ? 0 : -1;
- # endif
- if (exists < (mustread|previouslock))
- /*
- * There's an unusual problem with the RCS file;
- * or the RCS file doesn't exist,
- * and we must read or we already have a lock elsewhere.
- */
- return 0;
-
- RCSname = RCSbuf->string;
- sp = basename(RCSname);
- l = sp - RCSname;
- dirt = &dirtfname[previouslock];
- bufscpy(dirt, RCSname);
- tp = dirt->string + l;
- x = rcssuffix(RCSname);
- # if has_readlink
- if (!x) {
- error("symbolic link to non RCS filename `%s'", RCSname);
- errno = EINVAL;
- return 0;
- }
- # endif
- if (*sp == *x) {
- error("RCS filename `%s' incompatible with suffix `%s'", sp, x);
- errno = EINVAL;
- return 0;
- }
- /* Create a lock file whose name is a function of the RCS filename. */
- if (*x) {
- /*
- * The suffix is nonempty.
- * The lock filename is the first char of of the suffix,
- * followed by the RCS filename with last char removed. E.g.:
- * foo,v RCS filename with suffix ,v
- * ,foo, lock filename
- */
- *tp++ = *x;
- while (*sp)
- *tp++ = *sp++;
- *--tp = 0;
- } else {
- /*
- * The suffix is empty.
- * The lock filename is the RCS filename
- * with last char replaced by '_'.
- */
- while ((*tp++ = *sp++))
- ;
- tp -= 2;
- if (*tp == '_') {
- error("RCS filename `%s' ends with `%c'", RCSname, *tp);
- errno = EINVAL;
- return 0;
- }
- *tp = '_';
- }
-
- sp = tp = dirt->string;
-
- f = 0;
-
- /*
- * good news:
- * open(f, O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, READONLY) is atomic
- * according to Posix 1003.1-1990.
- * bad news:
- * NFS ignores O_EXCL and doesn't comply with Posix 1003.1-1990.
- * good news:
- * (O_TRUNC,READONLY) normally guarantees atomicity even with NFS.
- * bad news:
- * If you're root, (O_TRUNC,READONLY) doesn't guarantee atomicity.
- * good news:
- * Root-over-the-wire NFS access is rare for security reasons.
- * This bug has never been reported in practice with RCS.
- * So we don't worry about this bug.
- *
- * An even rarer NFS bug can occur when clients retry requests.
- * Suppose client A renames the lock file ",f," to "f,v"
- * at about the same time that client B creates ",f,",
- * and suppose A's first rename request is delayed, so A reissues it.
- * The sequence of events might be:
- * A sends rename(",f,", "f,v")
- * B sends create(",f,")
- * A sends retry of rename(",f,", "f,v")
- * server receives, does, and acknowledges A's first rename()
- * A receives acknowledgment, and its RCS program exits
- * server receives, does, and acknowledges B's create()
- * server receives, does, and acknowledges A's retry of rename()
- * This not only wrongly deletes B's lock, it removes the RCS file!
- * Most NFS implementations have idempotency caches that usually prevent
- * this scenario, but such caches are finite and can be overrun.
- * This problem afflicts programs that use the traditional
- * Unix method of using link() and unlink() to get and release locks,
- * as well as RCS's method of using open() and rename().
- * There is no easy workaround for either link-unlink or open-rename.
- * Any new method based on lockf() seemingly would be incompatible with
- * the old methods; besides, lockf() is notoriously buggy under NFS.
- * Since this problem afflicts scads of Unix programs, but is so rare
- * that nobody seems to be worried about it, we won't worry either.
- */
- # define READONLY (S_IRUSR|S_IRGRP|S_IROTH)
- # if !open_can_creat
- # define create(f) creat(f, READONLY)
- # else
- # define create(f) open(f, O_BINARY|O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, READONLY)
- # endif
-
- catchints();
- ignoreints();
-
- /*
- * Create a lock file for an RCS file. This should be atomic, i.e.
- * if two processes try it simultaneously, at most one should succeed.
- */
- seteid();
- fdesc = create(sp);
- e = errno;
- setrid();
-
- if (fdesc < 0) {
- if (e == EACCES && stat(tp,&statbuf) == 0)
- /* The RCS file is busy. */
- e = EEXIST;
- } else {
- dirtfmaker[0] = effective;
- e = ENOENT;
- if (exists) {
- f = Iopen(RCSname, FOPEN_R, status);
- e = errno;
- if (f && previouslock) {
- /* Discard the previous lock in favor of this one. */
- Ozclose(&frewrite);
- seteid();
- if ((r = un_link(newRCSfilename)) != 0)
- e = errno;
- setrid();
- if (r != 0)
- enfaterror(e, newRCSfilename);
- bufscpy(&dirtfname[0], tp);
- }
- }
- if (!(frewrite = fdopen(fdesc, FOPEN_W))) {
- efaterror(newRCSfilename);
- }
- }
-
- restoreints();
-
- errno = e;
- return f;
- }
-
- void
- keepdirtemp(name)
- char const *name;
- /* Do not unlink name, either because it's not there any more,
- * or because it has already been unlinked.
- */
- {
- register int i;
- for (i=DIRTEMPNAMES; 0<=--i; )
- if (dirtfname[i].string == name) {
- dirtfmaker[i] = notmade;
- return;
- }
- faterror("keepdirtemp");
- }
-
- char const *
- makedirtemp(name, n)
- register char const *name;
- int n;
- /*
- * Have maketemp() do all the work if name is null.
- * Otherwise, create a unique filename in name's dir using n and name
- * and store it into the dirtfname[n].
- * Because of storage in tfnames, dirtempunlink() can unlink the file later.
- * Return a pointer to the filename created.
- */
- {
- register char *tp, *np;
- register size_t dl;
- register struct buf *bn;
-
- if (!name)
- return maketemp(n);
- dl = dirlen(name);
- bn = &dirtfname[n];
- bufalloc(bn,
- # if has_mktemp
- dl + 9
- # else
- strlen(name) + 3
- # endif
- );
- bufscpy(bn, name);
- np = tp = bn->string;
- tp += dl;
- *tp++ = '_';
- *tp++ = '0'+n;
- catchints();
- # if has_mktemp
- VOID strcpy(tp, "XXXXXX");
- if (!mktemp(np) || !*np)
- faterror("can't make temporary file name `%.*s%c_%cXXXXXX'",
- (int)dl, name, SLASH, '0'+n
- );
- # else
- /*
- * Posix 1003.1-1990 has no reliable way
- * to create a unique file in a named directory.
- * We fudge here. If the working file name is abcde,
- * the temp filename is _Ncde where N is a digit.
- */
- name += dl;
- if (*name) name++;
- if (*name) name++;
- VOID strcpy(tp, name);
- # endif
- dirtfmaker[n] = real;
- return np;
- }
-
- void
- dirtempunlink()
- /* Clean up makedirtemp() files. May be invoked by signal handler. */
- {
- register int i;
- enum maker m;
-
- for (i = DIRTEMPNAMES; 0 <= --i; )
- if ((m = dirtfmaker[i]) != notmade) {
- if (m == effective)
- seteid();
- VOID un_link(dirtfname[i].string);
- if (m == effective)
- setrid();
- dirtfmaker[i] = notmade;
- }
- }
-
-
- int
- #if has_prototypes
- chnamemod(FILE **fromp, char const *from, char const *to, mode_t mode)
- /* The `#if has_prototypes' is needed because mode_t might promote to int. */
- #else
- chnamemod(fromp,from,to,mode) FILE **fromp; char const *from,*to; mode_t mode;
- #endif
- /*
- * Rename a file (with optional stream pointer *FROMP) from FROM to TO.
- * FROM already exists.
- * Change its mode to MODE, before renaming if possible.
- * If FROMP, close and clear *FROMP before renaming it.
- * Unlink TO if it already exists.
- * Return -1 on error (setting errno), 0 otherwise.
- */
- {
- # if bad_a_rename
- /*
- * This host is brain damaged. A race condition is possible
- * while the lock file is temporarily writable.
- * There doesn't seem to be a workaround.
- */
- mode_t mode_while_renaming = mode|S_IWUSR;
- # else
- # define mode_while_renaming mode
- # endif
- if (fromp) {
- # if has_fchmod
- if (fchmod(fileno(*fromp), mode_while_renaming) != 0)
- return -1;
- # endif
- Ozclose(fromp);
- }
- # if has_fchmod
- else
- # endif
- if (chmod(from, mode_while_renaming) != 0)
- return -1;
-
- # if !has_rename || bad_b_rename
- VOID un_link(to);
- /*
- * We need not check the result;
- * link() or rename() will catch it.
- * No harm is done if TO does not exist.
- * However, there's a short window of inconsistency
- * during which TO does not exist.
- */
- # endif
-
- return
- # if !has_rename
- do_link(from,to) != 0 ? -1 : un_link(from)
- # else
- rename(from, to) != 0
- # if has_NFS
- && errno != ENOENT
- # endif
- ? -1
- # if bad_a_rename
- : mode != mode_while_renaming ? chmod(to, mode)
- # endif
- : 0
- # endif
- ;
-
- # undef mode_while_renaming
- }
-
-
-
- int
- findlock(delete, target)
- int delete;
- struct hshentry **target;
- /*
- * Find the first lock held by caller and return a pointer
- * to the locked delta; also removes the lock if DELETE.
- * If one lock, put it into *TARGET.
- * Return 0 for no locks, 1 for one, 2 for two or more.
- */
- {
- register struct lock *next, **trail, **found;
-
- found = 0;
- for (trail = &Locks; (next = *trail); trail = &next->nextlock)
- if (strcmp(getcaller(), next->login) == 0) {
- if (found) {
- error("multiple revisions locked by %s; please specify one", getcaller());
- return 2;
- }
- found = trail;
- }
- if (!found)
- return 0;
- next = *found;
- *target = next->delta;
- if (delete) {
- next->delta->lockedby = nil;
- *found = next->nextlock;
- }
- return 1;
- }
-
- int
- addlock(delta)
- struct hshentry * delta;
- /*
- * Add a lock held by caller to DELTA and yield 1 if successful.
- * Print an error message and yield -1 if no lock is added because
- * DELTA is locked by somebody other than caller.
- * Return 0 if the caller already holds the lock.
- */
- {
- register struct lock *next;
-
- next=Locks;
- for (next = Locks; next; next = next->nextlock)
- if (cmpnum(delta->num, next->delta->num) == 0)
- if (strcmp(getcaller(), next->login) == 0)
- return 0;
- else {
- error("revision %s already locked by %s",
- delta->num, next->login
- );
- return -1;
- }
- next = ftalloc(struct lock);
- delta->lockedby = next->login = getcaller();
- next->delta = delta;
- next->nextlock = Locks;
- Locks = next;
- return 1;
- }
-
-
- int
- addsymbol(num, name, rebind)
- char const *num, *name;
- int rebind;
- /*
- * Associate with revision NUM the new symbolic NAME.
- * If NAME already exists and REBIND is set, associate NAME with NUM;
- * otherwise, print an error message and return false;
- * Return true if successful.
- */
- {
- register struct assoc *next;
-
- for (next = Symbols; next; next = next->nextassoc)
- if (strcmp(name, next->symbol) == 0)
- if (rebind || strcmp(next->num,num) == 0) {
- next->num = num;
- return true;
- } else {
- error("symbolic name %s already bound to %s",
- name, next->num
- );
- return false;
- }
- next = ftalloc(struct assoc);
- next->symbol = name;
- next->num = num;
- next->nextassoc = Symbols;
- Symbols = next;
- return true;
- }
-
-
-
- char const *
- getcaller()
- /* Get the caller's login name. */
- {
- # if has_setuid
- return getusername(euid()!=ruid());
- # else
- return getusername(false);
- # endif
- }
-
-
- int
- checkaccesslist()
- /*
- * Return true if caller is the superuser, the owner of the
- * file, the access list is empty, or caller is on the access list.
- * Otherwise, print an error message and return false.
- */
- {
- register struct access const *next;
-
- if (!AccessList || myself(RCSstat.st_uid) || strcmp(getcaller(),"root")==0)
- return true;
-
- next = AccessList;
- do {
- if (strcmp(getcaller(), next->login) == 0)
- return true;
- } while ((next = next->nextaccess));
-
- error("user %s not on the access list", getcaller());
- return false;
- }
-
-
- int
- dorewrite(lockflag, changed)
- int lockflag, changed;
- /*
- * Do nothing if LOCKFLAG is zero.
- * Prepare to rewrite an RCS file if CHANGED is positive.
- * Stop rewriting if CHANGED is zero, because there won't be any changes.
- * Fail if CHANGED is negative.
- * Return true on success.
- */
- {
- int r, e;
-
- if (lockflag)
- if (changed) {
- if (changed < 0)
- return false;
- putadmin(frewrite);
- puttree(Head, frewrite);
- aprintf(frewrite, "\n\n%s%c", Kdesc, nextc);
- foutptr = frewrite;
- } else {
- Ozclose(&frewrite);
- seteid();
- ignoreints();
- r = un_link(newRCSfilename);
- e = errno;
- keepdirtemp(newRCSfilename);
- restoreints();
- setrid();
- if (r != 0) {
- enerror(e, RCSfilename);
- return false;
- }
- }
- return true;
- }
-
- int
- donerewrite(changed)
- int changed;
- /*
- * Finish rewriting an RCS file if CHANGED is nonzero.
- * Return true on success.
- */
- {
- int r, e;
-
- if (changed && !nerror) {
- if (finptr) {
- fastcopy(finptr, frewrite);
- Izclose(&finptr);
- }
- if (1 < RCSstat.st_nlink)
- warn("breaking hard link to %s", RCSfilename);
- seteid();
- ignoreints();
- r = chnamemod(&frewrite, newRCSfilename, RCSfilename,
- RCSstat.st_mode & ~(S_IWUSR|S_IWGRP|S_IWOTH)
- );
- e = errno;
- keepdirtemp(newRCSfilename);
- restoreints();
- setrid();
- if (r != 0) {
- enerror(e, RCSfilename);
- error("saved in %s", newRCSfilename);
- dirtempunlink();
- return false;
- }
- }
- return true;
- }
-
- void
- aflush(f)
- FILE *f;
- {
- if (fflush(f) != 0)
- Oerror();
- }
- @
-
-
- 5.11.1.1
- log
- @Start of the AMIGA port of RCS 5.6. I call it HWGRCS now ;^)
- @
- text
- @d2 1
- a2 1
- * RCS stream editor
- d5 3
- a7 3
- * edits the input file according to a
- * script from stdin, generated by diff -n
- * performs keyword expansion
- d39 1
- a39 1
- * Revision 5.11 1991/11/03 01:11:44 eggert
- d42 1
- a42 1
- * Revision 5.10 1991/10/07 17:32:46 eggert
- d55 1
- a55 1
- * Fix setuid bug. Support new link behavior. Work around broken "w+" fopen.
- d85 1
- a85 1
- *
- d88 1
- a88 1
- *
- d91 1
- a91 1
- *
- d96 1
- a96 1
- *
- d100 1
- a100 1
- *
- d102 1
- a102 1
- * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- d104 1
- a104 1
- *
- d111 1
- a111 1
- *
- d114 1
- a114 1
- *
- d119 1
- a119 1
- *
- d124 1
- a124 1
- *
- d128 1
- a128 1
- *
- d171 2
- a172 2
- /*used to correct editline in case file is not rewound after */
- /* applying one delta */
- d444 1
- a444 1
- tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
- d474 1
- a474 1
- if (delta!=nil) {
- d477 1
- a477 1
- } else {
- d479 1
- a479 1
- }
- d481 1
- a481 1
- }
- d508 1
- a508 1
- /* swap files */
- d510 2
- a511 2
- /* assumes edit only during last pass, from the beginning*/
- }
- d589 1
- a589 1
- }
- d591 1
- a591 1
- }
- d681 2
- a682 2
- int ed; /* editor command */
- register int c;
- d697 1
- a697 1
- editline += linecorr; linecorr=0; /*correct line number*/
- d710 1
- a710 1
- /* skip over unwanted lines */
- d719 1
- a719 1
- /*skip next line*/
- d775 1
- a775 1
- }
- d807 1
- a807 1
- enum markers matchresult;
- d817 1
- a817 1
- for (;;) {
- d828 2
- a829 2
- /* end of string */
- nextc=c;
- d847 2
- a848 2
- /* check for keyword */
- /* first, copy a long enough string into keystring */
- d865 1
- a865 1
- }
- d901 1
- a901 1
- continue; /* last c handled properly */
- d908 1
- a908 1
- }
- d911 1
- a911 1
- }
- d947 1
- a947 1
- date= delta->date;
- d955 2
- a956 2
- switch (marker) {
- case Author:
- d958 2
- a959 2
- break;
- case Date:
- d961 2
- a962 2
- break;
- case Id:
- d980 2
- a981 2
- break;
- case Locker:
- d989 3
- a991 3
- break;
- case Log:
- case RCSfile:
- d993 2
- a994 2
- break;
- case Revision:
- d996 2
- a997 2
- break;
- case Source:
- d999 2
- a1000 2
- break;
- case State:
- d1002 1
- a1002 1
- break;
- d1005 1
- a1005 1
- }
- d1239 1
- a1239 1
- * Create a lock file for an RCS file. This should be atomic, i.e.
- a1247 7
- #ifdef AMIGA
- /* Workaround for a bug in SAS/C 6.1!! */
- if(!e)
- {
- e = EACCES;
- } /* if */
- #endif
- a1361 11
- #ifdef AMIGA
- /* Could this be a still open frewrite file? */
- if((i == 0) && (frewrite != NULL))
- {
- /* This should be Ozclose, but Ozclose does
- too much error checking for this. This should be
- just a try to get rid of this file, too! */
- fclose(frewrite);
- frewrite = NULL;
- } /* if */
- #endif
- d1388 1
- a1388 1
- * This host is brain damaged. A race condition is possible
- d1430 1
- a1430 1
- : mode != mode_while_renaming ? chmod(to, mode)
- @
-
-
- 5.11.1.2
- log
- @Removed the SAS/C create patch, as the problem has been fixed for 6.3.
- @
- text
- @d2 1
- a2 1
- * RCS stream editor
- d5 3
- a7 3
- * edits the input file according to a
- * script from stdin, generated by diff -n
- * performs keyword expansion
- d39 1
- a39 4
- * Revision 5.11.1.1 1993/01/18 14:38:13 heinz
- * Start of the AMIGA port of RCS 5.6. I call it HWGRCS now ;^)
- *
- * Revision 5.11 1991/11/03 01:11:44 eggert
- d42 1
- a42 1
- * Revision 5.10 1991/10/07 17:32:46 eggert
- d55 1
- a55 1
- * Fix setuid bug. Support new link behavior. Work around broken "w+" fopen.
- d157 1
- a157 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.1 1993/01/18 14:38:13 heinz Exp heinz $")
- d162 3
- a164 3
- FILE *fcopy; /* result file descriptor */
- char const *resultfile; /* result file name */
- int locker_expansion; /* should the locker name be appended to Id val? */
- d166 2
- a167 2
- static RILE *fedit; /* edit file descriptor */
- static char const *editfile; /* edit pathname */
- d170 3
- a172 3
- static long linecorr; /* #adds - #deletes in each edit run. */
- /*used to correct editline in case file is not rewound after */
- /* applying one delta */
- d176 2
- a177 2
- struct buf dirtfname[DIRTEMPNAMES]; /* unlink these when done */
- static enum maker volatile dirtfmaker[DIRTEMPNAMES]; /* if these are set */
- d181 1
- a181 1
- int
- d183 1
- a183 1
- char const *s;
- d189 19
- a207 19
- # if bad_unlink
- int e;
- if (unlink(s) == 0)
- return 0;
- e = errno;
- # if has_NFS
- if (e == ENOENT)
- return 0;
- # endif
- if (chmod(s, S_IWUSR) != 0) {
- errno = e;
- return -1;
- }
- # endif
- # if has_NFS
- return unlink(s)==0 || errno==ENOENT ? 0 : -1;
- # else
- return unlink(s);
- # endif
- d213 1
- a213 1
- # define do_link(s,t) link(s,t)
- d215 1
- a215 1
- static int
- d217 1
- a217 1
- char const *s, *t;
- d220 1
- a220 1
- struct stat sb, tb;
- d222 13
- a234 13
- if (link(s,t) == 0)
- return 0;
- if (errno != EEXIST)
- return -1;
- if (
- stat(s, &sb) == 0 &&
- stat(t, &tb) == 0 &&
- sb.st_ino == tb.st_ino &&
- sb.st_dev == tb.st_dev
- )
- return 0;
- errno = EEXIST;
- return -1;
- d240 1
- a240 1
- static exiting void
- d243 1
- a243 1
- fatserror("edit script ends prematurely");
- d246 1
- a246 1
- static exiting void
- d249 1
- a249 1
- fatserror("edit script refers to line past end of file");
- d256 1
- a256 1
- # define movelines(s1, s2, n) VOID memmove(s1, s2, (n)*sizeof(Iptr_type))
- d258 1
- a258 1
- static void
- d260 15
- a274 15
- register Iptr_type *s1;
- register Iptr_type const *s2;
- register unsigned long n;
- {
- if (s1 < s2)
- do {
- *s1++ = *s2++;
- } while (--n);
- else {
- s1 += n;
- s2 += n;
- do {
- *--s1 = *--s2;
- } while (--n);
- }
- d291 1
- a291 1
- static void
- d293 2
- a294 2
- unsigned long n;
- Iptr_type l;
- d297 18
- a314 18
- if (linelim-gapsize < n)
- editLineNumberOverflow();
- if (!gapsize)
- line =
- !linelim ?
- tnalloc(Iptr_type, linelim = gapsize = 1024)
- : (
- gap = gapsize = linelim,
- trealloc(Iptr_type, line, linelim <<= 1)
- );
- if (n < gap)
- movelines(line+n+gapsize, line+n, gap-n);
- else if (gap < n)
- movelines(line+gap, line+gap+gapsize, n-gap);
-
- line[n] = l;
- gap = n + 1;
- gapsize--;
- d317 1
- a317 1
- static void
- d319 1
- a319 1
- unsigned long n, nlines;
- d322 7
- a328 7
- unsigned long l = n + nlines;
- if (linelim-gapsize < l || l < n)
- editLineNumberOverflow();
- if (l < gap)
- movelines(line+l+gapsize, line+l, gap-l);
- else if (gap < n)
- movelines(line+gap, line+gap+gapsize, n-gap);
- d330 2
- a331 2
- gap = n;
- gapsize += nlines;
- d334 1
- a334 1
- static void
- d336 2
- a337 2
- register FILE *f;
- register Iptr_type l;
- d339 6
- a344 6
- register int c;
- do {
- if ((c = *l++) == SDELIM && *l++ != SDELIM)
- return;
- aputc(c, f);
- } while (c != '\n');
- d347 1
- a347 1
- void
- d349 1
- a349 1
- FILE *f;
- d352 5
- a356 5
- register Iptr_type *p, *lim, *l=line;
- for (p=l, lim=l+gap; p<lim; )
- snapshotline(f, *p++);
- for (p+=gapsize, lim=l+linelim; p<lim; )
- snapshotline(f, *p++);
- d359 1
- a359 1
- static void
- d361 4
- a364 4
- RILE *fin;
- FILE *fout;
- Iptr_type l;
- struct hshentry const *delta;
- d366 3
- a368 3
- Iseek(fin, l);
- if (expandline(fin, fout, delta, true, (FILE*)0) < 0)
- faterror("finisheditline internal error");
- d371 1
- a371 1
- void
- d373 3
- a375 3
- struct hshentry const *delta;
- FILE *outfile;
- int done;
- d381 16
- a396 16
- if (done) {
- openfcopy(outfile);
- outfile = fcopy;
- if (!delta)
- snapshotedit(outfile);
- else {
- register Iptr_type *p, *lim, *l = line;
- register RILE *fin = finptr;
- Iptr_type here = Itell(fin);
- for (p=l, lim=l+gap; p<lim; )
- finisheditline(fin, outfile, *p++, delta);
- for (p+=gapsize, lim=l+linelim; p<lim; )
- finisheditline(fin, outfile, *p++, delta);
- Iseek(fin, here);
- }
- }
- d406 5
- a410 5
- # if bad_fopen_wplus
- if (un_link(filename) != 0)
- efaterror(filename);
- # endif
- return fopen(filename, FOPEN_WPLUS_WORK);
- d415 1
- a415 1
- void
- d417 1
- a417 1
- FILE *f;
- d419 6
- a424 6
- if (!(fcopy = f)) {
- if (!resultfile)
- resultfile = maketemp(2);
- if (!(fcopy = fopen_update_truncate(resultfile)))
- efaterror(resultfile);
- }
- d430 1
- a430 1
- static void
- d432 1
- a432 1
- FILE *outfile;
- d438 1
- a438 1
- char const *tmpptr;
- d440 6
- a445 6
- editline = 0; linecorr = 0;
- if (fseek(fcopy, 0L, SEEK_SET) != 0)
- Oerror();
- fedit = fcopy;
- tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
- openfcopy(outfile);
- d448 1
- a448 1
- void
- d450 1
- a450 1
- FILE *f;
- d453 3
- a455 3
- finishedit((struct hshentry *)nil, (FILE*)0, false);
- fastcopy(fedit, f);
- Irewind(fedit);
- d458 1
- a458 1
- void
- d460 3
- a462 3
- struct hshentry const *delta;
- FILE *outfile;
- int done;
- d468 2
- a469 2
- register RILE *fe;
- register FILE *fc;
- d471 13
- a483 13
- fe = fedit;
- if (fe) {
- fc = fcopy;
- if (delta!=nil) {
- while (1 < expandline(fe,fc,delta,false,(FILE*)0))
- ;
- } else {
- fastcopy(fe,fc);
- }
- Ifclose(fe);
- }
- if (!done)
- swapeditfiles(outfile);
- d490 1
- a490 1
- # define copylines(upto,delta) (editline = (upto))
- d492 1
- a492 1
- static void
- d494 2
- a495 2
- register unsigned long upto;
- struct hshentry const *delta;
- d502 28
- a529 28
- register int c;
- declarecache;
- register FILE *fc;
- register RILE *fe;
-
- if (upto < editline) {
- /* swap files */
- finishedit((struct hshentry *)nil, (FILE*)0, false);
- /* assumes edit only during last pass, from the beginning*/
- }
- fe = fedit;
- fc = fcopy;
- if (editline < upto)
- if (delta)
- do {
- if (expandline(fe,fc,delta,false,(FILE*)0) <= 1)
- editLineNumberOverflow();
- } while (++editline < upto);
- else {
- setupcache(fe); cache(fe);
- do {
- do {
- cachegeteof(c, editLineNumberOverflow(););
- aputc(c, fc);
- } while (c != '\n');
- } while (++editline < upto);
- uncache(fe);
- }
- d535 1
- a535 1
- void
- d537 1
- a537 1
- struct hshentry const *delta;
- d544 2
- a545 2
- while (1 < expandline(finptr,fcopy,delta,true,foutptr))
- ;
- d549 1
- a549 1
- void
- d557 35
- a591 35
- { register c;
- declarecache;
- register FILE *frew, *fcop;
- register int amidline;
- register RILE *fin;
-
- fin = finptr;
- setupcache(fin); cache(fin);
- frew = foutptr;
- fcop = fcopy;
- amidline = false;
- for (;;) {
- GETC(frew,c);
- switch (c) {
- case '\n':
- ++editline;
- ++rcsline;
- amidline = false;
- break;
- case SDELIM:
- GETC(frew,c);
- if (c != SDELIM) {
- /* end of string */
- nextc = c;
- editline += amidline;
- uncache(fin);
- return;
- }
- /* fall into */
- default:
- amidline = true;
- break;
- }
- aputc(c,fcop);
- }
- d595 1
- a595 1
- void
- d600 7
- a606 7
- editfile = 0;
- fedit = 0;
- editline = linecorr = 0;
- resultfile = maketemp(1);
- if (!(fcopy = fopen_update_truncate(resultfile)))
- efaterror(resultfile);
- copystring();
- d608 45
- a652 45
- register int c;
- declarecache;
- register FILE *frew;
- register unsigned long e, oe;
- register int amidline, oamidline;
- register Iptr_type optr;
- register RILE *fin;
-
- e = 0;
- gap = 0;
- gapsize = linelim;
- fin = finptr;
- setupcache(fin); cache(fin);
- advise_access(fin, MADV_NORMAL);
- frew = foutptr;
- amidline = false;
- for (;;) {
- optr = cachetell();
- GETC(frew,c);
- oamidline = amidline;
- oe = e;
- switch (c) {
- case '\n':
- ++e;
- ++rcsline;
- amidline = false;
- break;
- case SDELIM:
- GETC(frew,c);
- if (c != SDELIM) {
- /* end of string */
- nextc = c;
- editline = e + amidline;
- linecorr = 0;
- uncache(fin);
- return;
- }
- /* fall into */
- default:
- amidline = true;
- break;
- }
- if (!oamidline)
- insertline(oe, optr);
- }
- d659 1
- a659 1
- void
- d664 1
- a664 1
- struct hshentry const *delta;
- d681 22
- a702 22
- int ed; /* editor command */
- register int c;
- declarecache;
- register FILE *frew;
- # if !large_memory
- register FILE *f;
- unsigned long line_lim = ULONG_MAX;
- register RILE *fe;
- # endif
- register unsigned long i;
- register RILE *fin;
- # if large_memory
- register unsigned long j;
- # endif
- struct diffcmd dc;
-
- editline += linecorr; linecorr=0; /*correct line number*/
- frew = foutptr;
- fin = finptr;
- setupcache(fin);
- initdiffcmd(&dc);
- while (0 <= (ed = getdiffcmd(fin,true,frew,&dc)))
- d704 3
- a706 3
- if (line_lim <= dc.line1)
- editLineNumberOverflow();
- else
- d708 24
- a731 24
- if (!ed) {
- copylines(dc.line1-1, delta);
- /* skip over unwanted lines */
- i = dc.nlines;
- linecorr -= i;
- editline += i;
- # if large_memory
- deletelines(editline+linecorr, i);
- # else
- fe = fedit;
- do {
- /*skip next line*/
- do {
- Igeteof(fe, c, { if (i!=1) editLineNumberOverflow(); line_lim = dc.dafter; break; } );
- } while (c != '\n');
- } while (--i);
- # endif
- } else {
- copylines(dc.line1, delta); /*copy only; no delete*/
- i = dc.nlines;
- # if large_memory
- j = editline+linecorr;
- # endif
- linecorr += i;
- d733 13
- a745 13
- f = fcopy;
- if (delta)
- do {
- switch (expandline(fin,f,delta,true,frew)) {
- case 0: case 1:
- if (i==1)
- return;
- /* fall into */
- case -1:
- editEndsPrematurely();
- }
- } while (--i);
- else
- d747 29
- a775 29
- {
- cache(fin);
- do {
- # if large_memory
- insertline(j++, cachetell());
- # endif
- for (;;) {
- GETC(frew, c);
- # if !large_memory
- aputc(c, f);
- # endif
- if (c == '\n')
- break;
- if (c==SDELIM) {
- GETC(frew, c);
- if (c!=SDELIM) {
- if (--i)
- editEndsPrematurely();
- nextc = c;
- uncache(fin);
- return;
- }
- }
- }
- ++rcsline;
- } while (--i);
- uncache(fin);
- }
- }
- d784 1
- a784 1
- int
- d786 4
- a789 4
- RILE *infile;
- FILE *outfile, *frewfile;
- struct hshentry const *delta;
- int delimstuffed;
- d800 112
- a911 112
- register c;
- declarecache;
- register FILE *out, *frew;
- register char * tp;
- register int e, ds, r;
- char const *tlim;
- static struct buf keyval;
- enum markers matchresult;
-
- setupcache(infile); cache(infile);
- out = outfile;
- frew = frewfile;
- ds = delimstuffed;
- bufalloc(&keyval, keylength+3);
- e = 0;
- r = -1;
-
- for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto uncache_exit;);
- for (;;) {
- switch (c) {
- case SDELIM:
- if (ds) {
- GETC(frew, c);
- if (c != SDELIM) {
- /* end of string */
- nextc=c;
- goto uncache_exit;
- }
- }
- /* fall into */
- default:
- aputc(c,out);
- r = 0;
- break;
-
- case '\n':
- rcsline += ds;
- aputc(c,out);
- r = 2;
- goto uncache_exit;
-
- case KDELIM:
- r = 0;
- /* check for keyword */
- /* first, copy a long enough string into keystring */
- tp = keyval.string;
- *tp++ = KDELIM;
- for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto keystring_eof;);
- if (tp < keyval.string+keylength+1)
- switch (ctab[c]) {
- case LETTER: case Letter:
- *tp++ = c;
- continue;
- default:
- break;
- }
- break;
- }
- *tp++ = c; *tp = '\0';
- matchresult = trymatch(keyval.string+1);
- if (matchresult==Nomatch) {
- tp[-1] = 0;
- aputs(keyval.string, out);
- continue; /* last c handled properly */
- }
-
- /* Now we have a keyword terminated with a K/VDELIM */
- if (c==VDELIM) {
- /* try to find closing KDELIM, and replace value */
- tlim = keyval.string + keyval.size;
- for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto keystring_eof;);
- if (c=='\n' || c==KDELIM)
- break;
- *tp++ =c;
- if (tlim <= tp)
- tp = bufenlarge(&keyval, &tlim);
- if (c==SDELIM && ds) { /*skip next SDELIM */
- GETC(frew, c);
- if (c != SDELIM) {
- /* end of string before closing KDELIM or newline */
- nextc = c;
- goto keystring_eof;
- }
- }
- }
- if (c!=KDELIM) {
- /* couldn't find closing KDELIM -- give up */
- *tp = 0;
- aputs(keyval.string, out);
- continue; /* last c handled properly */
- }
- }
- /* now put out the new keyword value */
- keyreplace(matchresult,delta,out);
- e = 1;
- break;
- }
- break;
- }
- }
- d914 2
- a915 2
- *tp = 0;
- aputs(keyval.string, out);
- d917 2
- a918 2
- uncache(infile);
- return r + e;
- d924 1
- a924 1
- static void
- d926 3
- a928 3
- enum markers marker;
- register struct hshentry const *delta;
- register FILE *out;
- d933 115
- a1047 115
- register char const *sp, *cp, *date;
- register char c;
- register size_t cs, cw, ls;
- char const *sp1;
- char datebuf[datesize];
- int RCSv;
-
- sp = Keyword[(int)marker];
-
- if (Expand == KEY_EXPAND) {
- aprintf(out, "%c%s%c", KDELIM, sp, KDELIM);
- return;
- }
-
- date= delta->date;
- RCSv = RCSversion;
-
- if (Expand == KEYVAL_EXPAND || Expand == KEYVALLOCK_EXPAND)
- aprintf(out, "%c%s%c%c", KDELIM, sp, VDELIM,
- marker==Log && RCSv<VERSION(5) ? '\t' : ' '
- );
-
- switch (marker) {
- case Author:
- aputs(delta->author, out);
- break;
- case Date:
- aputs(date2str(date,datebuf), out);
- break;
- case Id:
- case Header:
- aprintf(out, "%s %s %s %s %s",
- marker==Id || RCSv<VERSION(4)
- ? basename(RCSfilename)
- : getfullRCSname(),
- delta->num,
- date2str(date, datebuf),
- delta->author,
- RCSv==VERSION(3) && delta->lockedby ? "Locked"
- : delta->state
- );
- if (delta->lockedby!=nil)
- if (VERSION(5) <= RCSv) {
- if (locker_expansion || Expand==KEYVALLOCK_EXPAND)
- aprintf(out, " %s", delta->lockedby);
- } else if (RCSv == VERSION(4))
- aprintf(out, " Locker: %s", delta->lockedby);
- break;
- case Locker:
- if (delta->lockedby)
- if (
- locker_expansion
- || Expand == KEYVALLOCK_EXPAND
- || RCSv <= VERSION(4)
- )
- aputs(delta->lockedby, out);
- break;
- case Log:
- case RCSfile:
- aputs(basename(RCSfilename), out);
- break;
- case Revision:
- aputs(delta->num, out);
- break;
- case Source:
- aputs(getfullRCSname(), out);
- break;
- case State:
- aputs(delta->state, out);
- break;
- default:
- break;
- }
- if (Expand == KEYVAL_EXPAND || Expand == KEYVALLOCK_EXPAND) {
- afputc(' ', out);
- afputc(KDELIM, out);
- }
- if (marker == Log) {
- sp = delta->log.string;
- ls = delta->log.size;
- if (sizeof(ciklog)-1<=ls && !memcmp(sp,ciklog,sizeof(ciklog)-1))
- return;
- afputc('\n', out);
- cp = Comment.string;
- cw = cs = Comment.size;
- awrite(cp, cs, out);
- /* oddity: 2 spaces between date and time, not 1 as usual */
- sp1 = strchr(date2str(date,datebuf), ' ');
- aprintf(out, "Revision %s %.*s %s %s",
- delta->num, (int)(sp1-datebuf), datebuf, sp1, delta->author
- );
- /* Do not include state: it may change and is not updated. */
- /* Comment is the comment leader. */
- if (VERSION(5) <= RCSv)
- for (; cw && (cp[cw-1]==' ' || cp[cw-1]=='\t'); --cw)
- ;
- for (;;) {
- afputc('\n', out);
- awrite(cp, cw, out);
- if (!ls)
- break;
- --ls;
- c = *sp++;
- if (c != '\n') {
- awrite(cp+cw, cs-cw, out);
- do {
- afputc(c,out);
- if (!ls)
- break;
- --ls;
- c = *sp++;
- } while (c != '\n');
- }
- }
- }
- d1051 1
- a1051 1
- static int
- d1053 1
- a1053 1
- struct buf *L;
- d1061 33
- a1093 33
- char *b, a[SIZEABLE_PATH];
- int e;
- size_t s;
- ssize_t r;
- struct buf bigbuf;
- unsigned linkcount = MAXSYMLINKS + 1;
-
- b = a;
- s = sizeof(a);
- bufautobegin(&bigbuf);
- while ((r = readlink(L->string,b,s)) != -1)
- if (r == s) {
- bufalloc(&bigbuf, s<<1);
- b = bigbuf.string;
- s = bigbuf.size;
- } else if (!--linkcount) {
- errno = ELOOP;
- return -1;
- } else {
- /* Splice symbolic link into L. */
- b[r] = '\0';
- L->string[ROOTPATH(b) ? (size_t)0 : dirlen(L->string)] = '\0';
- bufscat(L, b);
- }
- e = errno;
- bufautoend(&bigbuf);
- errno = e;
- switch (e) {
- case ENXIO:
- case EINVAL: return 1;
- case ENOENT: return 0;
- default: return -1;
- }
- d1097 1
- a1097 1
- RILE *
- d1099 3
- a1101 3
- struct buf *RCSbuf;
- struct stat *status;
- int mustread;
- d1112 168
- a1279 161
- register char *tp;
- register char const *sp, *RCSname, *x;
- RILE *f;
- size_t l;
- int e, exists, fdesc, previouslock, r;
- struct buf *dirt;
- struct stat statbuf;
-
- previouslock = frewrite != 0;
- exists =
- # if has_readlink
- resolve_symlink(RCSbuf);
- # else
- stat(RCSbuf->string, &statbuf) == 0 ? 1
- : errno==ENOENT ? 0 : -1;
- # endif
- if (exists < (mustread|previouslock))
- /*
- * There's an unusual problem with the RCS file;
- * or the RCS file doesn't exist,
- * and we must read or we already have a lock elsewhere.
- */
- return 0;
-
- RCSname = RCSbuf->string;
- sp = basename(RCSname);
- l = sp - RCSname;
- dirt = &dirtfname[previouslock];
- bufscpy(dirt, RCSname);
- tp = dirt->string + l;
- x = rcssuffix(RCSname);
- # if has_readlink
- if (!x) {
- error("symbolic link to non RCS filename `%s'", RCSname);
- errno = EINVAL;
- return 0;
- }
- # endif
- if (*sp == *x) {
- error("RCS filename `%s' incompatible with suffix `%s'", sp, x);
- errno = EINVAL;
- return 0;
- }
- /* Create a lock file whose name is a function of the RCS filename. */
- if (*x) {
- /*
- * The suffix is nonempty.
- * The lock filename is the first char of of the suffix,
- * followed by the RCS filename with last char removed. E.g.:
- * foo,v RCS filename with suffix ,v
- * ,foo, lock filename
- */
- *tp++ = *x;
- while (*sp)
- *tp++ = *sp++;
- *--tp = 0;
- } else {
- /*
- * The suffix is empty.
- * The lock filename is the RCS filename
- * with last char replaced by '_'.
- */
- while ((*tp++ = *sp++))
- ;
- tp -= 2;
- if (*tp == '_') {
- error("RCS filename `%s' ends with `%c'", RCSname, *tp);
- errno = EINVAL;
- return 0;
- }
- *tp = '_';
- }
-
- sp = tp = dirt->string;
-
- f = 0;
-
- /*
- * good news:
- * open(f, O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, READONLY) is atomic
- * according to Posix 1003.1-1990.
- * bad news:
- * NFS ignores O_EXCL and doesn't comply with Posix 1003.1-1990.
- * good news:
- * (O_TRUNC,READONLY) normally guarantees atomicity even with NFS.
- * bad news:
- * If you're root, (O_TRUNC,READONLY) doesn't guarantee atomicity.
- * good news:
- * Root-over-the-wire NFS access is rare for security reasons.
- * This bug has never been reported in practice with RCS.
- * So we don't worry about this bug.
- *
- * An even rarer NFS bug can occur when clients retry requests.
- * Suppose client A renames the lock file ",f," to "f,v"
- * at about the same time that client B creates ",f,",
- * and suppose A's first rename request is delayed, so A reissues it.
- * The sequence of events might be:
- * A sends rename(",f,", "f,v")
- * B sends create(",f,")
- * A sends retry of rename(",f,", "f,v")
- * server receives, does, and acknowledges A's first rename()
- * A receives acknowledgment, and its RCS program exits
- * server receives, does, and acknowledges B's create()
- * server receives, does, and acknowledges A's retry of rename()
- * This not only wrongly deletes B's lock, it removes the RCS file!
- * Most NFS implementations have idempotency caches that usually prevent
- * this scenario, but such caches are finite and can be overrun.
- * This problem afflicts programs that use the traditional
- * Unix method of using link() and unlink() to get and release locks,
- * as well as RCS's method of using open() and rename().
- * There is no easy workaround for either link-unlink or open-rename.
- * Any new method based on lockf() seemingly would be incompatible with
- * the old methods; besides, lockf() is notoriously buggy under NFS.
- * Since this problem afflicts scads of Unix programs, but is so rare
- * that nobody seems to be worried about it, we won't worry either.
- */
- # define READONLY (S_IRUSR|S_IRGRP|S_IROTH)
- # if !open_can_creat
- # define create(f) creat(f, READONLY)
- # else
- # define create(f) open(f, O_BINARY|O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, READONLY)
- # endif
-
- catchints();
- ignoreints();
-
- /*
- * Create a lock file for an RCS file. This should be atomic, i.e.
- * if two processes try it simultaneously, at most one should succeed.
- */
- seteid();
- fdesc = create(sp);
- e = errno;
- setrid();
-
- if (fdesc < 0) {
- if (e == EACCES && stat(tp,&statbuf) == 0)
- /* The RCS file is busy. */
- e = EEXIST;
- } else {
- dirtfmaker[0] = effective;
- e = ENOENT;
- if (exists) {
- f = Iopen(RCSname, FOPEN_R, status);
- e = errno;
- if (f && previouslock) {
- /* Discard the previous lock in favor of this one. */
- Ozclose(&frewrite);
- seteid();
- if ((r = un_link(newRCSfilename)) != 0)
- e = errno;
- setrid();
- if (r != 0)
- enfaterror(e, newRCSfilename);
- bufscpy(&dirtfname[0], tp);
- }
- }
- if (!(frewrite = fdopen(fdesc, FOPEN_W))) {
- efaterror(newRCSfilename);
- }
- }
- d1281 1
- a1281 1
- restoreints();
- d1283 2
- a1284 2
- errno = e;
- return f;
- d1287 1
- a1287 1
- void
- d1289 1
- a1289 1
- char const *name;
- d1294 7
- a1300 7
- register int i;
- for (i=DIRTEMPNAMES; 0<=--i; )
- if (dirtfname[i].string == name) {
- dirtfmaker[i] = notmade;
- return;
- }
- faterror("keepdirtemp");
- d1303 1
- a1303 1
- char const *
- d1305 2
- a1306 2
- register char const *name;
- int n;
- d1315 41
- a1355 41
- register char *tp, *np;
- register size_t dl;
- register struct buf *bn;
-
- if (!name)
- return maketemp(n);
- dl = dirlen(name);
- bn = &dirtfname[n];
- bufalloc(bn,
- # if has_mktemp
- dl + 9
- # else
- strlen(name) + 3
- # endif
- );
- bufscpy(bn, name);
- np = tp = bn->string;
- tp += dl;
- *tp++ = '_';
- *tp++ = '0'+n;
- catchints();
- # if has_mktemp
- VOID strcpy(tp, "XXXXXX");
- if (!mktemp(np) || !*np)
- faterror("can't make temporary file name `%.*s%c_%cXXXXXX'",
- (int)dl, name, SLASH, '0'+n
- );
- # else
- /*
- * Posix 1003.1-1990 has no reliable way
- * to create a unique file in a named directory.
- * We fudge here. If the working file name is abcde,
- * the temp filename is _Ncde where N is a digit.
- */
- name += dl;
- if (*name) name++;
- if (*name) name++;
- VOID strcpy(tp, name);
- # endif
- dirtfmaker[n] = real;
- return np;
- d1358 1
- a1358 1
- void
- d1362 2
- a1363 2
- register int i;
- enum maker m;
- d1365 4
- a1368 4
- for (i = DIRTEMPNAMES; 0 <= --i; )
- if ((m = dirtfmaker[i]) != notmade) {
- if (m == effective)
- seteid();
- d1370 9
- a1378 9
- /* Could this be a still open frewrite file? */
- if((i == 0) && (frewrite != NULL))
- {
- /* This should be Ozclose, but Ozclose does
- too much error checking for this. This should be
- just a try to get rid of this file, too! */
- fclose(frewrite);
- frewrite = NULL;
- } /* if */
- d1380 5
- a1384 5
- VOID un_link(dirtfname[i].string);
- if (m == effective)
- setrid();
- dirtfmaker[i] = notmade;
- }
- d1388 1
- a1388 1
- int
- d1404 49
- a1452 49
- # if bad_a_rename
- /*
- * This host is brain damaged. A race condition is possible
- * while the lock file is temporarily writable.
- * There doesn't seem to be a workaround.
- */
- mode_t mode_while_renaming = mode|S_IWUSR;
- # else
- # define mode_while_renaming mode
- # endif
- if (fromp) {
- # if has_fchmod
- if (fchmod(fileno(*fromp), mode_while_renaming) != 0)
- return -1;
- # endif
- Ozclose(fromp);
- }
- # if has_fchmod
- else
- # endif
- if (chmod(from, mode_while_renaming) != 0)
- return -1;
-
- # if !has_rename || bad_b_rename
- VOID un_link(to);
- /*
- * We need not check the result;
- * link() or rename() will catch it.
- * No harm is done if TO does not exist.
- * However, there's a short window of inconsistency
- * during which TO does not exist.
- */
- # endif
-
- return
- # if !has_rename
- do_link(from,to) != 0 ? -1 : un_link(from)
- # else
- rename(from, to) != 0
- # if has_NFS
- && errno != ENOENT
- # endif
- ? -1
- # if bad_a_rename
- : mode != mode_while_renaming ? chmod(to, mode)
- # endif
- : 0
- # endif
- ;
- d1454 1
- a1454 1
- # undef mode_while_renaming
- d1459 1
- a1459 1
- int
- d1461 2
- a1462 2
- int delete;
- struct hshentry **target;
- d1470 1
- a1470 1
- register struct lock *next, **trail, **found;
- d1472 18
- a1489 18
- found = 0;
- for (trail = &Locks; (next = *trail); trail = &next->nextlock)
- if (strcmp(getcaller(), next->login) == 0) {
- if (found) {
- error("multiple revisions locked by %s; please specify one", getcaller());
- return 2;
- }
- found = trail;
- }
- if (!found)
- return 0;
- next = *found;
- *target = next->delta;
- if (delete) {
- next->delta->lockedby = nil;
- *found = next->nextlock;
- }
- return 1;
- d1492 1
- a1492 1
- int
- d1494 1
- a1494 1
- struct hshentry * delta;
- d1502 1
- a1502 1
- register struct lock *next;
- d1504 17
- a1520 17
- next=Locks;
- for (next = Locks; next; next = next->nextlock)
- if (cmpnum(delta->num, next->delta->num) == 0)
- if (strcmp(getcaller(), next->login) == 0)
- return 0;
- else {
- error("revision %s already locked by %s",
- delta->num, next->login
- );
- return -1;
- }
- next = ftalloc(struct lock);
- delta->lockedby = next->login = getcaller();
- next->delta = delta;
- next->nextlock = Locks;
- Locks = next;
- return 1;
- d1524 1
- a1524 1
- int
- d1526 2
- a1527 2
- char const *num, *name;
- int rebind;
- d1535 1
- a1535 1
- register struct assoc *next;
- d1537 17
- a1553 17
- for (next = Symbols; next; next = next->nextassoc)
- if (strcmp(name, next->symbol) == 0)
- if (rebind || strcmp(next->num,num) == 0) {
- next->num = num;
- return true;
- } else {
- error("symbolic name %s already bound to %s",
- name, next->num
- );
- return false;
- }
- next = ftalloc(struct assoc);
- next->symbol = name;
- next->num = num;
- next->nextassoc = Symbols;
- Symbols = next;
- return true;
- d1558 1
- a1558 1
- char const *
- d1562 5
- a1566 5
- # if has_setuid
- return getusername(euid()!=ruid());
- # else
- return getusername(false);
- # endif
- d1570 1
- a1570 1
- int
- d1578 1
- a1578 1
- register struct access const *next;
- d1580 2
- a1581 2
- if (!AccessList || myself(RCSstat.st_uid) || strcmp(getcaller(),"root")==0)
- return true;
- d1583 5
- a1587 5
- next = AccessList;
- do {
- if (strcmp(getcaller(), next->login) == 0)
- return true;
- } while ((next = next->nextaccess));
- d1589 2
- a1590 2
- error("user %s not on the access list", getcaller());
- return false;
- d1594 1
- a1594 1
- int
- d1596 1
- a1596 1
- int lockflag, changed;
- d1605 1
- a1605 1
- int r, e;
- d1607 23
- a1629 23
- if (lockflag)
- if (changed) {
- if (changed < 0)
- return false;
- putadmin(frewrite);
- puttree(Head, frewrite);
- aprintf(frewrite, "\n\n%s%c", Kdesc, nextc);
- foutptr = frewrite;
- } else {
- Ozclose(&frewrite);
- seteid();
- ignoreints();
- r = un_link(newRCSfilename);
- e = errno;
- keepdirtemp(newRCSfilename);
- restoreints();
- setrid();
- if (r != 0) {
- enerror(e, RCSfilename);
- return false;
- }
- }
- return true;
- d1632 1
- a1632 1
- int
- d1634 1
- a1634 1
- int changed;
- d1640 1
- a1640 1
- int r, e;
- d1642 24
- a1665 24
- if (changed && !nerror) {
- if (finptr) {
- fastcopy(finptr, frewrite);
- Izclose(&finptr);
- }
- if (1 < RCSstat.st_nlink)
- warn("breaking hard link to %s", RCSfilename);
- seteid();
- ignoreints();
- r = chnamemod(&frewrite, newRCSfilename, RCSfilename,
- RCSstat.st_mode & ~(S_IWUSR|S_IWGRP|S_IWOTH)
- );
- e = errno;
- keepdirtemp(newRCSfilename);
- restoreints();
- setrid();
- if (r != 0) {
- enerror(e, RCSfilename);
- error("saved in %s", newRCSfilename);
- dirtempunlink();
- return false;
- }
- }
- return true;
- d1668 1
- a1668 1
- void
- d1670 1
- a1670 1
- FILE *f;
- d1672 2
- a1673 2
- if (fflush(f) != 0)
- Oerror();
- @
-
-
- 5.11.1.3
- log
- @Changed all checks for AMIGA to _AMIGA. This is more standard like
- and helps future updates. Major patch cleanup on the way.
- [Note: Added a VOID_CLOSEDIR define for this global change, too!]
- @
- text
- @a38 3
- * Revision 5.11.1.2 1993/12/04 08:40:36 heinz
- * Removed the SAS/C create patch, as the problem has been fixed for 6.3.
- *
- d160 1
- a160 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.2 1993/12/04 08:40:36 heinz Exp heinz $")
- d1365 1
- a1365 3
- #ifdef _AMIGA
- /* AMIGA fix for delete before close! */
-
- d1375 1
- a1375 1
- #endif /* _AMIGA */
- @
-
-
- 5.11.1.4
- log
- @Support for the new keywords VER, AmigaREV, and AmigaProtection.
- @
- text
- @a38 5
- * Revision 5.11.1.3 1993/12/18 16:12:22 heinz
- * Changed all checks for AMIGA to _AMIGA. This is more standard like
- * and helps future updates. Major patch cleanup on the way.
- * [Note: Added a VOID_CLOSEDIR define for this global change, too!]
- *
- d163 1
- a163 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.3 1993/12/18 16:12:22 heinz Exp heinz $")
- a813 6
- #ifdef _AMIGA
- /* We need this bufferfor a CBMVersion string increment. This might not be
- a very nice way to do all this. But it is easy for now. */
-
- char CBMbuf[BUFSIZ];
- #endif /* _AMIGA */
- a902 21
- #ifdef _AMIGA
- /* Only with CBMVersion, a newline end is allowed. We want
- to be able to specify C= style version strings without a trailing `$'.
- */
-
- if(matchresult == CBMVersion)
- {
- /* We keep the delimiting KDELIM for CBMVersion! */
- if(c == KDELIM)
- {
- *tp++ = c;
- if(tlim <= tp)
- {
- tp = bufenlarge(&keyval, &tlim);
- } /* if */
- } /* if */
-
- /* We are ok! */
- c = KDELIM;
- } /* if */
- #endif /* _AMIGA */
- a909 266
- #ifdef _AMIGA
- /* This is really ugly. For Amiga keywords, we need to take their current
- value und set it in the delta unless there is already a value set. The
- ugly thing about it is that the delta is const. So we have to cast the
- pointer to non const for modifying the delta contents. Hmpfh.
- */
- /* Terminate the string for sure. */
- *tp = 0;
- if(matchresult == CBMVersion ||
- matchresult == CBMRevision ||
- matchresult == CBMProtection)
- {
- char *vp = strchr(keyval.string + 1, VDELIM);
- char **dp;
- int incflag = delta->CBMVersionIncFlag;
-
- if(vp)
- {
- vp++;
-
- /* Skip leading space. */
- while(*vp == ' ' || *vp == '\t')
- {
- vp++;
- } /* while */
-
- if(*vp == 0)
- {
- /* No entry, no nothing! */
- vp = NULL;
- } /* if */
- } /* if */
-
- switch(matchresult)
- {
- case CBMVersion:
- dp = (char **)&delta->CBMVersion;
- if(!vp)
- {
- strcpy(CBMbuf, workfilename);
- strcat(CBMbuf, " 0.0 (xx.xx.xx) $");
-
- vp = CBMbuf;
-
- /* Force expansion of the fragment */
- incflag = true;
- } /* if */
-
- if(incflag)
- {
- /* Ouch. Now it gets tricky.
- We don't use sscanf here to be sure of
- what we do. */
- const char *s;
- char *d;
- int ver, rev, l;
- int stcd_i(const char *, int *);
-
- s = vp;
- d = CBMbuf;
-
- /* Read the prg name */
- while(*s && *s != ' ' && *s != '\t')
- {
- *d++ = *s++;
- } /* while */
-
- /* Skip space after prg name */
- while(*s == ' ' || *s == '\t')
- {
- s++;
- } /* while */
-
- l = stcd_i(s, &ver);
- s += l;
- if(!l || *s++ != '.' || ver < 0)
- {
- break;
- } /* if */
-
- l = stcd_i(s, &rev);
- s += l;
-
- /* Skip space after ver.rev */
- while(*s == ' ' || *s == '\t')
- {
- s++;
- } /* while */
-
- if(!l || *s != '(' || rev < 0)
- {
- break;
- } /* if */
-
- /* Skip over to ')' and skip trailing space */
- while(*s && *s != ')')
- {
- s++;
- } /* while */
-
- if(*s == ')')
- {
- s++;
- } /* if */
-
- /* Skip space after date */
- while(*s == ' ' || *s == '\t')
- {
- s++;
- } /* while */
-
- sprintf(d, " %d.%d (", ver, rev + 1);
- d += strlen(d);
-
- /* We always insert the current date! */
- {
- time_t t;
-
- time(&t);
-
- l = strftime(d, 11, "%d.%m.%y) ", localtime(&t));
- d += l;
- }
-
- /* For VERSION FULL */
- strcpy(d, s);
-
- vp = CBMbuf;
- } /* if */
- break;
- case CBMRevision:
- dp = (char **)&delta->CBMRevision;
- if(!vp)
- {
- strcpy(CBMbuf, "0");
-
- vp = CBMbuf;
-
- /* Force expansion of the fragment */
- incflag = true;
- } /* if */
-
- if(incflag)
- {
- /* Ouch. Now it gets tricky.
- We don't use sscanf here to be sure of
- what we do. */
- const char *s;
- char *d;
- int ver, rev, l;
- int stcd_i(const char *, int *);
-
- s = vp;
- d = CBMbuf;
-
- /* Skip to a digit */
- while(*s && !isdigit(*s))
- {
- *d++ = *s++;
- } /* while */
-
- l = stcd_i(s, &rev);
- s += l;
-
- if(!l || rev < 0)
- {
- break;
- } /* if */
-
- {
- char numbuf[12];
-
- sprintf(numbuf, "%d", rev + 1);
- l = strlen(numbuf);
-
- memmove(d + l, s, strlen(s) + 1);
- memmove(d, numbuf, l);
- }
-
- /* Trim off trailing space */
- l = strlen(CBMbuf);
- while(l &&
- (CBMbuf[l - 1] == ' ' ||
- CBMbuf[l - 1] == '\t'))
- {
- CBMbuf[--l] = 0;
- } /* while */
-
- vp = CBMbuf;
- } /* if */
- break;
- case CBMProtection:
- dp = (char **)&delta->CBMProtection;
- if(!vp)
- {
- char *d = CBMbuf;
-
- if(RCSstat.st_mode & S_IPURE)
- {
- *d ++ = 'P';
- } /* if */
-
- if(RCSstat.st_mode & S_ISCRIPT)
- {
- *d ++ = 'S';
- } /* if */
-
- *d = 0;
- }
- else
- {
- char *s, *d;
-
- s = vp;
-
- /* Here we have the most ugly hack
- today. Not much I can do about it.
- Unless there can be more information
- of generic value kept per revision,
- I have to hack around. */
- RCSstat.st_mode &= ~(S_IPURE|S_ISCRIPT);
- d = CBMbuf;
- while(*d = *s++)
- {
- if(*d != ' ' && *d != '\t')
- {
- switch(*d)
- {
- case 'P':
- case 'p':
- RCSstat.st_mode |= S_IPURE;
- break;
- case 'S':
- case 's':
- RCSstat.st_mode |= S_ISCRIPT;
- break;
- default:
- break;
- } /* switch */
- d++;
- } /* if */
- } /* while */
- } /* if */
-
- if(!CBMbuf[0])
- {
- strcpy(CBMbuf, "--");
- } /* if */
-
- vp = CBMbuf;
- break;
- default:
- dp = NULL;
- break;
- } /* switch */
-
- /* Do we have a value? */
- if(dp)
- {
- /* Set the value in the delta.
- This is just for keyreplace below. */
- *dp = vp;
- } /* if */
- } /* if */
-
- #endif /* _AMIGA */
- a1008 12
- #ifdef _AMIGA
- /* The Amiga keywords CBMVersion and CBMProtection! */
- case CBMVersion:
- aputs(delta->CBMVersion, out);
- break;
- case CBMRevision:
- aputs(delta->CBMRevision, out);
- break;
- case CBMProtection:
- aputs(delta->CBMProtection, out);
- break;
- #endif /* _AMIGA */
- a1012 21
- #ifdef _AMIGA
- /* Only with CBMVersion, a newline end is allowed. We want
- to be able to specify C= style version strings without a trailing `$'.
- So the trailing KDELIM is included in the version string. We don't have
- to add it here!
- */
- if(marker != CBMVersion)
- {
- afputc(' ', out);
- afputc(KDELIM, out);
- }
- else
- {
- int l = strlen(delta->CBMVersion);
-
- if(!l || delta->CBMVersion[l - 1] != KDELIM)
- {
- afputc('\n', out);
- } /* if */
- } /* if */
- #else
- a1014 1
- #endif /* _AMIGA */
- @
-
-
- 5.11.1.5
- log
- @First version of Amiga keywords implemented. Ugly, but acceptable for now.
- @
- text
- @a38 3
- * Revision 5.11.1.4 1994/02/12 19:20:21 heinz
- * Support for the new keywords VER, AmigaREV, and AmigaProtection.
- *
- d168 1
- a168 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.4 1994/02/12 19:20:21 heinz Exp heinz $")
- a171 10
- #ifdef _AMIGA
- /* We need a flag for ci that tells us when to increment
- our special revision numbers. This flag is in the delta structure to be
- specific about what delta to "increment".
- There is also a global variable to pass
- the string we create fromexpandline to keyreplace. I don't want to patch
- into the functions declarations. */
-
- static char *AMIGA_specialstring;
- #endif /*_AMIGA */
- a951 1
- matchresult == CBMDate ||
- d955 2
- a956 1
- int incflag = delta->CBMRevIncFlag;
- d978 1
- d982 1
- a982 1
- strcat(CBMbuf, " 0.0 (xx.xx.xx) $");
- d1036 1
- a1036 1
- /* Skip over to ')' and skip it, too */
- d1047 6
- d1062 1
- a1062 1
- l = strftime(d, 11, "%d.%m.%y)", localtime(&t));
- d1073 1
- d1091 1
- a1091 1
- int rev, l;
- d1097 1
- a1097 1
- /* Copy up to a digit */
- a1132 81
- case CBMDate:
- if(!vp)
- {
- strcpy(CBMbuf, "00.00.00");
-
- vp = CBMbuf;
-
- /* Force expansion of the fragment */
- incflag = true;
- } /* if */
-
- if(incflag)
- {
- /* Ouch. Now it gets tricky.
- We don't use sscanf here to be sure of
- what we do. */
- const char *s;
- char *d;
- int l;
-
- s = vp;
- d = CBMbuf;
-
- /* Copy up to a digit */
- while(*s && !isdigit(*s))
- {
- *d++ = *s++;
- } /* while */
-
- /* Skip over day digits */
- while(*s && isdigit(*s))
- {
- s++;
- } /* while */
-
- if(*s == '.')
- {
- s++;
- } /* if */
-
- /* Skip over month digits */
- while(*s && isdigit(*s))
- {
- s++;
- } /* while */
-
- if(*s == '.')
- {
- s++;
- } /* if */
-
- /* Skip over year digits */
- while(*s && isdigit(*s))
- {
- s++;
- } /* while */
-
- {
- char datebuf[12];
- time_t t;
-
- time(&t);
-
- l = strftime(datebuf, 11, "%d.%m.%y", localtime(&t));
-
- memmove(d + l, s, strlen(s) + 1);
- memmove(d, datebuf, l);
- }
-
- /* Trim off trailing space */
- l = strlen(CBMbuf);
- while(l &&
- (CBMbuf[l - 1] == ' ' ||
- CBMbuf[l - 1] == '\t'))
- {
- CBMbuf[--l] = 0;
- } /* while */
-
- vp = CBMbuf;
- } /* if */
- break;
- d1134 1
- d1194 1
- a1194 1
- vp = NULL;
- d1198 7
- a1204 3
- /* Set the value in the delta.
- This is just for keyreplace below. */
- AMIGA_specialstring = (vp) ? vp : "";
- d1206 1
- d1308 1
- a1308 1
- /* The Amiga keywords use only one special variable set in expandline! */
- d1310 2
- d1313 2
- d1316 1
- a1316 2
- case CBMDate:
- aputs(AMIGA_specialstring, out);
- d1336 1
- a1336 1
- int l = strlen(AMIGA_specialstring);
- d1338 1
- a1338 1
- if(!l || AMIGA_specialstring[l - 1] != KDELIM)
- @
-
-
- 5.11.1.6
- log
- @Auto increment support for the new AMiga keywords should work better now.
- Somme comment clarifications.
- @
- text
- @a38 3
- * Revision 5.11.1.5 1994/02/14 19:29:45 heinz
- * First version of Amiga keywords implemented. Ugly, but acceptable for now.
- *
- d171 1
- a171 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.5 1994/02/14 19:29:45 heinz Exp heinz $")
- d177 3
- a179 4
- our special revision numbers in what delta. */
- struct hshentry *CBMRevIncDelta;
-
- /* There is also a global variable to pass
- d969 1
- a969 1
- int incflag = (delta == CBMRevIncDelta);
- d1778 1
- a1778 3
- /* AMIGA fix for delete before close! Unlinking an open file is not
- possible with any non Unix file system I know. So this problem affects
- the Amiga, too! */
- @
-
-
- 5.11.1.7
- log
- @Fixed NULL read enforcer hit when rcssuffix returns NULL.
- @
- text
- @a38 4
- * Revision 5.11.1.6 1994/03/14 09:19:05 heinz
- * Auto increment support for the new AMiga keywords should work better now.
- * Somme comment clarifications.
- *
- d174 1
- a174 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.6 1994/03/14 09:19:05 heinz Exp heinz $")
- a1568 16
- #ifdef _AMIGA
- /* rcssuffix may well return 0 and this is not caught without
- readlink being available. Actually this happened here because of the
- Amiga RCS RCS_link soft link emulation when the specified filename had
- no suitable suffix and its path was different from the current
- directories RCS directory choice via RCS_link. So rcssuffix did not find
- anything and returned NULL.
-
- So we need to do something about it. We choose the least destructive
- option.
- */
- if(!x)
- {
- x = "";
- } /* if */
- #endif /* _AMIGA */
- @
-
-
- 5.11.1.8
- log
- @Fixed handling of a newline terminated CBMVersion string.
- @
- text
- @a38 3
- * Revision 5.11.1.7 1994/03/31 18:38:48 heinz
- * Fixed NULL read enforcer hit when rcssuffix returns NULL.
- *
- d178 1
- a178 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.7 1994/03/31 18:38:48 heinz Exp heinz $")
- d1002 1
- a1002 3
- strcat(CBMbuf, " 0.0 (xx.xx.xx) ");
- CBMbuf[strlen(CBMbuf)] = KDELIM;
- CBMbuf[strlen(CBMbuf)] = 0;
- a1298 19
- #ifdef _AMIGA
- /* This is even more ugly. For the CBMVersion keyword we allow a trailing
- newline to end the keyword value, too. But we also need this newline for
- standard RCS processing. Otherwise the line count would be lost. So if
- for CBMVersion the keyword value is not delimited by KDELIM, it has
- been a newline end. We now need to start processing of this "left over"
- newline.
- */
- if(matchresult == CBMVersion)
- {
- int l = strlen(AMIGA_specialstring);
-
- if(!l || AMIGA_specialstring[l - 1] != KDELIM)
- {
- c = '\n';
- continue; /* last c handled properly */
- } /* if */
- } /* if */
- #endif /* _AMIGA */
- d1409 4
- a1412 2
- /* For CBMVersion, we don't need to add anything as this is handled
- separately in expandline().
- d1418 9
- @
-
-
- 5.11.1.9
- log
- @Cleaned up handling of terminating char for CBMVersion.
- There was a bug in setting up a value for the first time.
- @
- text
- @a38 3
- * Revision 5.11.1.8 1994/08/01 20:53:56 heinz
- * Fixed handling of a newline terminated CBMVersion string.
- *
- d181 1
- a181 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.8 1994/08/01 20:53:56 heinz Exp heinz $")
- d191 2
- a192 2
- the string we create from expandline to keyreplace. I don't want to patch
- into the function declarations. */
- d844 2
- a845 5
- /* We need this buffer for a CBMVersion string increment. This might not be
- a very nice way to do all this. But it is easy for now. We also need a
- place to remember the terminating char for CBMVersion to count the
- newlines correctly!
- */
- a847 1
- int lastc;
- d955 1
- a955 4
- /* Save the actual delimiter for a later check! */
- lastc = c;
-
- /* Fake an OK! */
- a1003 2
- int l;
-
- d1006 2
- a1007 4
-
- l = strlen(CBMbuf);
- CBMbuf[l] = lastc;
- CBMbuf[l + 1] = 0;
- d1307 4
- a1310 2
- standard RCS processing. Otherwise the line count would be lost. We now
- might need to start processing this "left over" newline.
- d1314 3
- a1316 1
- if((c = lastc) == '\n')
- d1318 1
- @
-
-
- 5.11.1.10
- log
- @lastc wasn't always set correctly.
- @
- text
- @a38 4
- * Revision 5.11.1.9 1994/08/05 16:43:13 heinz
- * Cleaned up handling of terminating char for CBMVersion.
- * There was a bug in setting up a value for the first time.
- *
- d184 1
- a184 1
- libId(editId, "$Id: rcsedit.c,v 5.11.1.9 1994/08/05 16:43:13 heinz Exp heinz $")
- a921 6
- #ifdef _AMIGA
- /* Preinit lastc with the current c. We definitely need this for CBMVersion,
- and it does not hurt otherwise.
- */
- lastc = c;
- #endif /* _AMIGA */
- @
-