home *** CD-ROM | disk | FTP | other *** search
- /*
- * RCS file name handling
- */
- #ifndef lint
- static char
- rcsid[]= "$Id: rcsfnms.c,v 5.5 90/07/16 21:30:57 lfk Release $ Purdue CS";
- #endif
- /****************************************************************************
- * creation and deletion of semaphorefile,
- * creation of temporary filenames and cleanup()
- * pairing of RCS file names and working file names.
- * Testprogram: define PAIRTEST
- ****************************************************************************
- */
-
- /* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Distributed under license by the Free Software Foundation, Inc.
-
- This file is part of RCS.
-
- RCS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- RCS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with RCS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Report problems and direct all questions to:
-
- rcs-bugs@cs.purdue.edu
-
- */
-
-
-
-
- /* $Log: rcsfnms.c,v $
- * Revision 5.5 90/07/16 21:30:57 lfk
- * fixed a number of mistakes in the MKS/DOS filenaming stuff
- *
- * Revision 5.4 90/07/15 23:42:35 lfk
- * Fixed one last '\\' versus '/' problem
- *
- * Revision 5.3 90/07/15 20:25:06 lfk
- * Most major fixes added between rev 5.1 and rev 5.5:
- * signals fixed so they work on MS-DOS
- * Added MKS arguments code so argv can be large
- * added code to handle slashes a'la Unix
- * added more file extensions to system from MS-DOS
- *
- * Revision 5.2 90/07/15 11:33:42 ROOT_DOS
- * DOS version of RCS 4.0 checked in for MODS
- * by lfk@athena.mit.edu
- * Also update to MSC 6.0
- *
- * revision 5.2 koya 90/01/24 10:22:39
- * Change path-name handlars.
- * Especially, separator of path names.
- *
- * revision 5.1 koya 90/01/24 07:05:43
- * Initial revision
- *
- * Revision 4.8 89/05/01 15:09:41 narten
- * changed getwd to not stat empty directories.
- *
- * Revision 4.7 88/11/08 12:01:22 narten
- * changes from eggert@sm.unisys.com (Paul Eggert)
- *
- * 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 1.1 84/01/23 14:50:24 kcs
- * Initial revision
- *
- * 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"
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef MSDOS
- #include <direct.h>
- #else
- #include <sys/dir.h>
- #endif /* MSDOS */
-
- extern char * rindex();
- extern char * mktemp();
- extern FILE * fopen();
- extern char * getwd(); /* get working directory; forward decl */
- extern int stat(), fstat();
-
- extern FILE * finptr; /* RCS input file descriptor */
- extern FILE * frewrite; /* New RCS file descriptor */
- extern char * RCSfilename, * workfilename; /* filenames */
- struct stat RCSstat, workstat; /* file status for RCS file and working file */
- int haveRCSstat, haveworkstat; /* indicators if status availalble */
-
-
- char tempfilename [NCPFN+10]; /* used for derived file names */
- char sub1filename [NCPPN]; /* used for files path/file.sfx,v */
- char sub2filename [NCPPN]; /* used for files path/RCS/file.sfx,v */
- char semafilename [NCPPN]; /* name of semaphore file */
- int madesema; /* indicates whether a semaphore file has been set */
- char * tfnames[10]; /* temp. file names to be unlinked when finished */
- int freefilename; /* index of next free file name in tfnames[] */
-
-
- struct compair {
- char * suffix, * comlead;
- };
-
- struct compair 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. */
- /* According to your MSDOS-environment, you change these settlements. !! */
- /* If you can work on UN*X, it is worthwile to keep these. */
- /* It however, may casue lack of memory on MSDOS */
- /* $Author: lfk $ */
- "", "# ", /* default for empty suffix */
- "awk", "# ", /* AWK */
- "c", " * ", /* C */
- #ifdef ALL
- "c++" "// " /* C++ */
- "cc" "// " /* C++ */
- "CC" "// " /* C++ */
- "C" "// " /* C++ */
- "cl", ";;; ", /* common lisp */
- "csh", "# ", /* shell */
- "e", "# ", /* efl */
- "el", "; ", /* gnulisp */
- #endif
- "f", "c ", /* fortran */
- "h", " * ", /* C-header */
- "ksh", "# ", /* korn shell */
- "l", " * ", /* lex NOTE: conflict between lex and franzlisp*/
- "mac", "; ", /* macro vms or dec-20 or pdp-11 macro */
- "me", ".\\\" ", /* me-macros t/nroff*/
- #ifdef ALL
- "ml", "; ", /* mocklisp */
- #endif
- "mm", ".\\\" ", /* mm-macros t/nroff*/
- "ms", ".\\\" ", /* ms-macros t/nroff*/
- #ifdef ALL
- "p", " * ", /* pascal */
- "perl", "# ", /* L. Wall's Perl */
- "pl", "% ", /* prolog */
- "r", "# ", /* ratfor */
- "red", "% ", /* psl/rlisp */
- "sh", "# ", /* shell */
- "sl", "% ", /* psl */
- #endif
- "tex", "% ", /* tex */
- "y", " * ", /* yacc */
- #ifdef ALL
- "ye", " * ", /* yacc-efl */
- "yr", " * ", /* yacc-ratfor */
- #endif
- #ifdef sparc
- "s", "! ", /* assembler */
- #endif
- #ifdef mc68000
- "s", "| ", /* assembler */
- #endif
- #ifdef pdp11
- "s", "/ ", /* assembler */
- #endif
- #ifdef vax
- "s", "# ", /* assembler */
- #endif
- #ifdef MSDOS
- "asm", "; ", /* assembler */
- "bat", "REM ", /* MS-DOS command.com */
- "cxx", "// ", /* MS-DOS c++ */
- "fin", ".\\\" ", /* for *.fin files on MSDOS */
- "fma", ".\\\" ", /* for fma-macors fin on MSDOS */
- "for", "c ", /* MS Fortran */
- "pl", "# ", /* L. Wall's Perl for MS-DOS */
- #endif /* MSDOS */
- nil, "" /* default for unknown suffix; must always be last */
- };
-
-
- ffclose(fptr)
- FILE * fptr;
- /* Function: checks ferror(fptr) and aborts the program if there were
- * errors; otherwise closes fptr.
- */
- { if (ferror(fptr) || fclose(fptr)==EOF)
- faterror("File read or write error; file system full?");
- }
-
-
- int trysema(RCSname,makesema)
- char * RCSname; int makesema;
- /* Function: Checks whether a semaphore file exists for RCSname. If yes,
- * returns false. If not, creates one if makesema==true and returns true
- * if successful. If a semaphore file was created, madesema is set to true.
- * The name of the semaphore file is put into variable semafilename.
- */
- {
- #ifndef MSDOS
- register char * tp, *sp, *lp;
- int fdesc;
-
- sp=RCSname;
- lp = rindex(sp,'/');
- if (lp==0) {
- semafilename[0]='.'; semafilename[1]='/';
- tp= &semafilename[2];
- } else {
- /* copy path */
- tp=semafilename;
- do *tp++ = *sp++; while (sp<=lp);
- }
- /*now insert `,' and append file name */
- *tp++ = ',';
- lp = rindex(sp, RCSSEP);
- while (sp<lp) *tp++ = *sp++;
- *tp++ = ','; *tp++ = '\0'; /* will be the same length as RCSname*/
-
- madesema = false;
- if (access(semafilename, 0) == 0) {
- error("RCS file %s is in use",RCSname);
- return false;
- }
- if (makesema) {
- if ((fdesc=creat(semafilename, 000)) == -1) {
- error("Can't create semaphore file for RCS file %s",RCSname);
- return false;
- } else
- VOID close(fdesc);
- madesema=true;
- }
- return true;
- #else /* NOT MSDOS */
- makesema = true;
- return true;
- #endif /* NOT MSDOS */
- }
-
-
- rmsema()
- /* Function: delete the semaphore file if madeseam==true;
- * sets madesema to false.
- */
- {
- #ifdef MSDOS
- madesema = false ;
- #else
- if (madesema) {
- madesema=false;
- if (unlink(semafilename) == -1) {
- error("Can't find semaphore file %s",semafilename);
- }
- }
- #endif /* MSDOS */
- }
-
- InitCleanup()
- { freefilename = 0; /* initialize pointer */
- }
-
-
- cleanup()
- /* Function: closes input file and rewrite file.
- * Unlinks files in tfnames[], deletes semaphore file.
- */
- {
- register int i;
-
- if (finptr!=NULL) VOID fclose(finptr);
- if (frewrite!=NULL) VOID fclose(frewrite);
- for (i=0; i<freefilename; i++) {
- if (tfnames[i][0]!='\0') VOID unlink(tfnames[i]);
- }
- InitCleanup();
- rmsema();
- }
-
-
- char * mktempfile(fullpath,filename)
- register char * fullpath, * filename;
- /* Function: Creates a unique filename using the process id and stores it
- * into a free slot in tfnames. The filename consists of the path contained
- * in fullpath concatenated with filename. filename should end in "XXXXXX".
- * Because of storage in tfnames, cleanup() can unlink the file later.
- * freefilename indicates the lowest unoccupied slot in tfnames.
- * Returns a pointer to the filename created.
- * Example use: mktempfile("/tmp/", somefilename)
- */
- {
- register char * lastslash, *tp;
- if ((tp=tfnames[freefilename])==nil)
- tp=tfnames[freefilename] = talloc(NCPPN);
- #ifdef MSDOS
- # ifdef MKS
- if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
- # else
- if (fullpath!=nil && (lastslash=rindex(fullpath,'\\'))!=0) {
- # endif
- #else
- if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
- #endif /* MSDOS */
- /* copy path */
- while (fullpath<=lastslash) *tp++ = *fullpath++;
- }
- while (*tp++ = *filename++);
- return (mktemp(tfnames[freefilename++]));
- }
-
-
-
-
- char * bindex(sp,c)
- register char * sp, c;
- /* 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 * r;
- r = sp;
- while (*sp) {
- if (*sp++ == c) r=sp;
- }
- return r;
- }
-
-
-
-
-
- InitAdmin()
- /* function: initializes an admin node */
- { register char * Suffix;
- register int i;
-
- Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
- StrictLocks=STRICT_LOCKING;
-
- /* guess the comment leader from the suffix*/
- Suffix=bindex(workfilename, '.');
- #ifdef MSDOS
- Suffix = strlwr( Suffix );
- #endif /* MSDOS */
- if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
- for (i=0;;i++) {
- if (comtable[i].suffix==nil) {
- Comment=comtable[i].comlead; /*default*/
- break;
- } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
- Comment=comtable[i].comlead; /*default*/
- break;
- }
- }
- Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
- }
-
-
-
- char * findpairfile(argc, argv, fname)
- int argc; char * argv[], *fname;
- /* Function: Given a filename fname, findpairfile scans argv for a pathname
- * ending in fname. If found, returns a pointer to the pathname, and sets
- * the corresponding pointer in argv to nil. Otherwise returns fname.
- * argc indicates the number of entries in argv. Some of them may be nil.
- */
- {
- register char * * next, * match;
- register int count;
-
- for (next = argv, count = argc; count>0; next++,count--) {
- #ifdef MSDOS
- # ifdef MKS
- if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
- # else
- if ((*next != nil) && strcmp(bindex(*next,'\\'),fname)==0) {
- # endif
- #else
- if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
- #endif /* MSDOS */
- /* bindex finds the beginning of the file name stem */
- match= *next;
- *next=nil;
- return match;
- }
- }
- return fname;
- }
-
-
- int pairfilenames(argc, argv, mustread, tostdout)
- int argc; char ** argv; int mustread, tostdout;
- /* Function: Pairs the filenames pointed to by argv; argc indicates
- * how many there are.
- * Places a pointer to the RCS filename into RCSfilename,
- * and a pointer to the name of the working file into workfilename.
- * If both the workfilename and the RCS filename are given, and tostdout
- * is true, a warning is printed.
- *
- * If the working file exists, places its status into workstat and
- * sets haveworkstat to 0; otherwise, haveworkstat is set to -1;
- * Similarly for the RCS file and the variables RCSstat and haveRCSstat.
- *
- * If the RCS file exists, it is opened for reading, the file pointer
- * is placed into finptr, and the admin-node is read in; returns 1.
- * If the RCS file does not exist and mustread==true, an error is printed
- * and 0 returned.
- * If the RCS file does not exist and mustread==false, the admin node
- * is initialized to empty (Head, AccessList, Locks, Symbols, StrictLocks, Dbranch)
- * and -1 returned.
- *
- * 0 is returned on all errors. Files that are directories are errors.
- * Also calls InitCleanup();
- */
- {
- register char * sp, * tp;
- char * lastsep, * purefname, * pureRCSname;
- int opened, returncode;
- #ifdef MSDOS
- struct stat dirstat;
- #endif /* MSDOS */
- char * RCS1;
- char prefdir[NCPPN];
-
-
- if (*argv == nil) return 0; /* already paired filename */
- if (rindex(*argv,KDELIM)!=0) {
- /* KDELIM causes havoc in keyword expansion */
- error("RCS file name may not contain %c",KDELIM);
- return 0;
- }
- InitCleanup();
-
- /* first check suffix to see whether it is an RCS file or not */
- #ifdef MSDOS
- # ifdef MKS
- purefname=bindex(*argv, '/'); /* skip path */
- # else
- purefname=bindex(*argv, '\\'); /* skip path */
- # endif
- #else
- purefname=bindex(*argv, '/'); /* skip path */
- #endif /* MSDOS */
- #ifdef MSDOS
- # ifdef MKS
- if( ( pureRCSname = strstr( *argv, "rcs/" ) ) != NULL){
- #else
- if( ( pureRCSname = strstr( *argv, "RCS\\" ) ) != NULL){
- #endif
- /* RCS file name given*/
- RCS1 = (*argv);
- /* derive workfilename*/
- sp = purefname; tp=tempfilename;
- while( *sp != '\0' ) *tp++=*sp++; *tp= '\0';
- workfilename=findpairfile(argc-1,argv+1,tempfilename);
- if( strlen(pureRCSname) > NCPFN + 4 ) {
- /* To avoid, ambiguous file name. eg."RCS\RCS\foo.c" */
- if( strlen(pureRCSname + 4) != (int) NULL ){
- error("file name %s is ambiguous", RCS1);
- return 0;
- }
- error("RCS file name %s too long",RCS1);
- return 0;
- }
- } else {
- /* working file given; now try to find RCS file */
- workfilename=*argv;
- /* derive RCS file name*/
- # ifdef MKS
- strcpy( tempfilename, "rcs/" );
- # else
- strcpy( tempfilename, "RCS\\" );
- # endif
- strcat( tempfilename, purefname );
- RCS1=findpairfile(argc-1,argv+1,tempfilename);
- # ifdef MKS
- pureRCSname = strstr( RCS1, "rcs/" );
- # else
- pureRCSname = strstr( RCS1, "RCS\\" );
- # endif
- if (strlen(pureRCSname)>NCPFN+4) {
- error("working file name %s too long",workfilename);
- return 0;
- }
- }
- # ifdef MKS
- if( strchr( workfilename, '/' ) != NULL ){
- # else
- if( strchr( workfilename, '\\' ) != NULL ){
- # endif
- error("Sorry, file name %s confuse RCS", workfilename );
- return 0;
- }
- #else /* MSDOS */
- lastsep=rindex(purefname, RCSSEP);
- if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
- /* RCS file name given*/
- RCS1=(*argv); pureRCSname=purefname;
- /* derive workfilename*/
- sp = purefname; tp=tempfilename;
- while (sp<lastsep) *tp++ = *sp++; *tp='\0';
- /* try to find workfile name among arguments */
- workfilename=findpairfile(argc-1,argv+1,tempfilename);
- if (strlen(pureRCSname)>NCPFN) {
- error("RCS file name %s too long",RCS1);
- return 0;
- }
- } else {
- /* working file given; now try to find RCS file */
- workfilename= *argv;
- /* derive RCS file name*/
- sp=purefname; tp=tempfilename;
- while (*tp++ = *sp++);
- *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp++='\0';
- /* Try to find RCS file name among arguments*/
- RCS1=findpairfile(argc-1,argv+1,tempfilename);
- pureRCSname=bindex(RCS1, '/');
- if (strlen(pureRCSname)>NCPFN) {
- error("working file name %s too long",workfilename);
- return 0;
- }
- }
- #endif /* MSDOS */
- /* now we have a (tentative) RCS filename in RCS1 and workfilename */
- /* First, get status of workfilename */
- haveworkstat=stat(workfilename, &workstat);
- if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
- diagnose("Directory %s ignored",workfilename);
- return 0;
- }
- /* Second, try to find the right RCS file */
- #ifdef MSDOS
- RCSfilename=pureRCSname;
- if (pureRCSname != RCS1){
- error("Sorry, file name %s confuse RCS", RCS1);
- return 0;
- }else{
- opened = ( ( finptr=fopen(pureRCSname, "r" ) ) != NULL );
- if(opened){
- returncode = 1;
- }else{
- if (mustread) {
- error("Can't find %s",RCSfilename);
- return 0;
- }else{
- if( stat("RCS", &dirstat) == -1 ){
- error("Can't find RCS subdirectory");
- return 0;
- }else{
- if( !( dirstat.st_mode & S_IFDIR ) ){
- error("RCS is really directory?");
- return 0;
- }else returncode = -1;
- }
- }
- }
- }
- #else /* MSDOS */
- if (pureRCSname!=RCS1) {
- /* a path for RCSfile is given; single RCS file to look for */
- finptr=fopen(RCSfilename=RCS1, "r");
- if (finptr!=NULL) {
- returncode=1;
- } else { /* could not open */
- if (access(RCSfilename,0)==0) {
- error("Can't open existing %s", RCSfilename);
- return 0;
- }
- if (mustread) {
- error("Can't find %s", RCSfilename);
- return 0;
- } else {
- /* initialize if not mustread */
- returncode = -1;
- }
- }
- } else {
- /* no path for RCS file name. Prefix it with path of work */
- /* file if RCS file omitted. Make a second name including */
- /* RCSDIR and try to open that one first. */
- sub1filename[0]=sub2filename[0]= '\0';
- if (RCS1==tempfilename) {
- /* RCS file name not given; prepend work path */
- sp= *argv; tp= sub1filename;
- while (sp<purefname) *tp++ = *sp ++;
- *tp='\0';
- VOID strcpy(sub2filename,sub1filename); /* second one */
- }
- VOID strcat(sub1filename,RCSDIR);
- VOID strcpy(prefdir,sub1filename); /* preferred directory for RCS file*/
- VOID strcat(sub1filename,RCS1); VOID strcat(sub2filename,RCS1);
-
- opened=(
- ((finptr=fopen(RCSfilename=sub1filename, "r"))!=NULL) ||
- ((finptr=fopen(RCSfilename=sub2filename,"r"))!=NULL) );
-
- if (opened) {
- /* open succeeded */
- returncode=1;
- } else {
- /* open failed; may be read protected */
- if ((access(RCSfilename=sub1filename,0)==0) ||
- (access(RCSfilename=sub2filename,0)==0)) {
- error("Can't open existing %s",RCSfilename);
- return 0;
- }
- if (mustread) {
- error("Can't find %s nor %s",sub1filename,sub2filename);
- return 0;
- } else {
- /* initialize new file. Put into ./RCS if possible, strip off suffix*/
- RCSfilename= (access(prefdir,0)==0)?sub1filename:sub2filename;
- returncode= -1;
- }
- }
- }
- #endif /* MSDOS */
- if (returncode == 1) { /* RCS file open */
- haveRCSstat=fstat(fileno(finptr),&RCSstat);
- if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
- diagnose("Directory %s ignored",RCSfilename);
- return 0;
- }
- Lexinit(); getadmin();
- } else { /* returncode == -1; RCS file nonexisting */
- haveRCSstat = -1;
- InitAdmin();
- };
-
- if (tostdout&&
- !(RCS1==tempfilename||workfilename==tempfilename))
- /*The last term determines whether a pair of */
- /* file names was given in the argument list */
- warn("Option -p is set; ignoring output file %s",workfilename);
-
- return returncode;
- }
-
-
- char * getfullRCSname()
- /* Function: returns a pointer to the full path name of the RCS file.
- * Calls getwd(), but only once.
- * removes leading "../" and "./".
- */
- { static char pathbuf[NCPPN];
- static char namebuf[NCPPN];
- static int pathlength;
-
- register char * realname, * lastpathchar;
- register int dotdotcounter, realpathlength;
-
- #ifdef MSDOS
- /* Treat a full path name containing the drive name */
- /* Added by $Author: lfk $ */
- # ifdef MKS
- if (RCSfilename[1] == ':' && RCSfilename[2] == '/') {
- # else
- if (RCSfilename[1] == ':' && RCSfilename[2] == '\\') {
- # endif
- #else
- if (*RCSfilename=='/') {
- #endif /* MSDOS */
- return(RCSfilename);
- } else {
- if (pathlength==0) { /*call curdir for the first time*/
- if (getwd(pathbuf)==NULL)
- faterror("Can't build current directory path");
- pathlength=strlen(pathbuf);
- #ifdef MSDOS
- /* Generally, a MSDOS path name seems to be like "A:\" */
- /* Added by $Author: lfk $ */
- # ifdef MKS
- if (!((pathlength==3) && (pathbuf[2]=='/'))) {
- pathbuf[pathlength++]='/';
- # else
- if (!((pathlength==3) && (pathbuf[2]=='\\'))) {
- pathbuf[pathlength++]='\\';
- # endif
- /* Check needed because some getwd implementations */
- /* generate "/" for the root. */
- }
- #else
- if (!((pathlength==1) && (pathbuf[0]=='/'))) {
- pathbuf[pathlength++]='/';
- /* Check needed because some getwd implementations */
- /* generate "/" for the root. */
- }
- #endif /* MSDOS */
- }
- /*the following must be redone since RCSfilename may change*/
- /* find how many ../ to remvove from RCSfilename */
- dotdotcounter =0;
- realname = RCSfilename;
- #ifdef MSDOS /* Chaged '/' to '\\' : By $Author: lfk $ */
- while( realname[0]=='.' &&
- # ifdef MKS
- (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
- if (realname[1]=='/') {
- # else
- (realname[1]=='\\'||(realname[1]=='.'&&realname[2]=='\\'))){
- if (realname[1]=='\\') {
- # endif
- /* drop leading ./ */
- realname += 2;
- } else {
- /* drop leading ../ and remember */
- dotdotcounter++;
- realname += 3;
- }
- }
- #else
- while( realname[0]=='.' &&
- (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
- if (realname[1]=='/') {
- /* drop leading ./ */
- realname += 2;
- } else {
- /* drop leading ../ and remember */
- dotdotcounter++;
- realname += 3;
- }
- }
- #endif /* MSDOS */
- /* now remove dotdotcounter trailing directories from pathbuf*/
- lastpathchar=pathbuf + pathlength-1;
- while (dotdotcounter>0 && lastpathchar>pathbuf) {
- /* move pointer backwards over trailing directory */
- lastpathchar--;
- #ifdef MSDOS
- # ifdef MKS
- if (*lastpathchar=='/') {
- # else
- if (*lastpathchar=='\\') {
- # endif
- #else
- if (*lastpathchar=='/') {
- #endif /* MSDOS */
- dotdotcounter--;
- }
- }
- if (dotdotcounter>0) {
- error("Can't generate full path name for RCS file");
- return RCSfilename;
- } else {
- /* build full path name */
- realpathlength=lastpathchar-pathbuf+1;
- VOID strncpy(namebuf,pathbuf,realpathlength);
- VOID strcpy(&namebuf[realpathlength],realname);
- return(namebuf);
- }
- }
- }
-
- /* In MSDOS and (perhaps) OS/2, any directries are writable. */
- /* So, the below check is NON-SENSE !! : $Author: lfk $ */
- int trydiraccess(filename)
- char * filename;
- /* checks write permission in directory of filename and returns
- * true if writable, false otherwise
- */
- {
- char pathname[NCPPN];
- register char * tp, *sp, *lp;
-
- #ifdef MSDOS
- return true;
- #else
- lp = rindex(filename,'/');
- if (lp==0) {
- /* check current directory */
- if (access(".",2)==0)
- return true;
- else {
- error("Current directory not writable");
- return false;
- }
- }
- /* copy path */
- sp=filename;
- tp=pathname;
- do *tp++ = *sp++; while (sp<=lp);
- *tp='\0';
- if (access(pathname,2)==0)
- return true;
- else {
- error("Directory %s not writable", pathname);
- return false;
- }
- #endif /* MSDOS */
- }
-
-
-
- #ifndef V4_2BSD
- /* rename() and getwd() will be provided in bsd 4.2 */
-
- #ifndef MSDOS
- int rename(from, to)
- char * from, *to;
- /* Function: renames a file with the name given by from to the name given by to.
- * unlinks the to-file if it already exists. returns -1 on error, 0 otherwise.
- */
- { VOID unlink(to); /* no need to check return code; will be caught by link*/
- /* no harm done if file "to" does not exist */
- if (link(from,to)<0) return -1;
- return(unlink(from));
- }
-
- #define dot "."
- #define dotdot ".."
-
-
- char * getwd(name)
- char * name;
- /* Function: places full pathname of current working directory into name and
- * returns name on success, NULL on failure.
- * getwd is an adaptation of pwd. May not return to the current directory on
- * failure.
- */
- {
- FILE *file;
- struct stat d, dd;
- char buf[2]; /* to NUL-terminate dir.d_name */
- struct direct dir;
-
- int rdev, rino;
- int off;
- register i,j;
-
- name[off= 0] = '/';
- name[1] = '\0';
- buf[0] = '\0';
- if (stat("/", &d)<0) return NULL;
- rdev = d.st_dev;
- rino = d.st_ino;
- for (;;) {
- if (stat(dot, &d)<0) return NULL;
- if (d.st_ino==rino && d.st_dev==rdev) {
- if (name[off] == '/') name[off] = '\0';
- chdir(name); /*change back to current directory*/
- return name;
- }
- if ((file = fopen(dotdot,"r")) == NULL) return NULL;
- if (fstat(fileno(file), &dd)<0) goto fail;
- chdir(dotdot);
- if(d.st_dev == dd.st_dev) {
- if(d.st_ino == dd.st_ino) {
- if (name[off] == '/') name[off] = '\0';
- chdir(name); /*change back to current directory*/
- VOID fclose(file);
- return name;
- }
- do {
- if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
- goto fail;
- } while (dir.d_ino != d.st_ino);
- }
- else do {
- if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
- goto fail;
- }
- if (dir.d_ino == 0)
- dd.st_ino = d.st_ino + 1;
- else if (stat(dir.d_name, &dd) < 0)
- goto fail;
- } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
- VOID fclose(file);
-
- /* concatenate file name */
- i = -1;
- while (dir.d_name[++i] != 0);
- for(j=off+1; j>0; --j)
- name[j+i+1] = name[j];
- off=i+off+1;
- name[i+1] = '/';
- for(--i; i>=0; --i)
- name[i+1] = dir.d_name[i];
- } /* end for */
-
- fail: VOID fclose(file);
- return NULL;
- }
- #else /* MSDOS */
-
- char *getwd(name)
- char *name;
- {
- int a,i;
- (void)getcwd(name, NCPPN);
- #ifdef MKS
- strlwr(name);
- a = strlen(name);
- for ( i = 0; i <= a; i++)
- if(name[i] == '\\')
- name[i] = '/';
- #endif
- return name;
- }
- #endif /* MSODS */
- #endif
- #ifdef MSDOS
- char *gettmpdir()
- {
- char tp[NCPPN];
-
- strcpy( tp, (char *) getenv("TMP") );
- if( *tp == (char) NULL ) strcpy( tp, "." );
- if( tp[strlen(tp) - 1] != '\\' )
- strcat( tp, "\\" );
- return tp;
- }
-
- #endif /* MSDOS */
-
- #ifdef PAIRTEST
- /* test program for pairfilenames() and getfullRCSname() */
- char * workfilename, *RCSfilename;
- extern int quietflag;
-
- main(argc, argv)
- int argc; char *argv[];
- {
- int result;
- int initflag,tostdout;
- quietflag=tostdout=initflag=false;
- cmdid="pair";
-
- while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
- switch ((*argv)[1]) {
-
- case 'p': tostdout=true;
- break;
- case 'i': initflag=true;
- break;
- case 'q': quietflag=true;
- break;
- default: error("unknown option: %s", *argv);
- break;
- }
- }
-
- do {
- RCSfilename=workfilename=nil;
- result=pairfilenames(argc,argv,!initflag,tostdout);
- if (result!=0) {
- diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
- diagnose("Full RCS file name: %s", getfullRCSname());
- }
- switch (result) {
- case 0: continue; /* already paired file */
-
- case 1: if (initflag) {
- error("RCS file %s exists already",RCSfilename);
- } else {
- diagnose("RCS file %s exists",RCSfilename);
- }
- VOID fclose(finptr);
- break;
-
- case -1:diagnose("RCS file does not exist");
- break;
- }
-
- } while (++argv, --argc>=1);
-
- }
- #endif
-
-