Annotation of 43BSDTahoe/new/rcs/src/rcsfnms.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *                     RCS file name handling
        !             3:  */
        !             4: #ifndef lint
        !             5:  static char
        !             6:  rcsid[]= "$Id: rcsfnms.c,v 3.10 88/02/18 11:57:27 bostic Exp $ Purdue CS";
        !             7: #endif
        !             8: /****************************************************************************
        !             9:  *                     creation and deletion of semaphorefile,
        !            10:  *                     creation of temporary filenames and cleanup()
        !            11:  *                     pairing of RCS file names and working file names.
        !            12:  *                     Testprogram: define PAIRTEST
        !            13:  ****************************************************************************
        !            14:  *
        !            15:  * Copyright (C) 1982 by Walter F. Tichy
        !            16:  *                       Purdue University
        !            17:  *                       Computer Science Department
        !            18:  *                       West Lafayette, IN 47907
        !            19:  *
        !            20:  * All rights reserved. No part of this software may be sold or distributed
        !            21:  * in any form or by any means without the prior written permission of the
        !            22:  * author.
        !            23:  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
        !            24:  */
        !            25: 
        !            26: 
        !            27: /* $Log:       rcsfnms.c,v $
        !            28:  * Revision 3.10  88/02/18  11:57:27  bostic
        !            29:  * replaced with version 4
        !            30:  * 
        !            31:  * Revision 4.6  87/12/18  11:40:23  narten
        !            32:  * additional file types added from 4.3 BSD version, and SPARC assembler
        !            33:  * comment character added. Also, more lint cleanups. (Guy Harris)
        !            34:  * 
        !            35:  * Revision 4.5  87/10/18  10:34:16  narten
        !            36:  * Updating version numbers. Changes relative to 1.1 actually relative
        !            37:  * to verion 4.3
        !            38:  * 
        !            39:  * Revision 1.3  87/03/27  14:22:21  jenkins
        !            40:  * Port to suns
        !            41:  * 
        !            42:  * Revision 1.2  85/06/26  07:34:28  svb
        !            43:  * Comment leader '% ' for '*.tex' files added.
        !            44:  * 
        !            45:  * Revision 1.1  84/01/23  14:50:24  kcs
        !            46:  * Initial revision
        !            47:  * 
        !            48:  * Revision 4.3  83/12/15  12:26:48  wft
        !            49:  * Added check for KDELIM in file names to pairfilenames().
        !            50:  * 
        !            51:  * Revision 4.2  83/12/02  22:47:45  wft
        !            52:  * Added csh, red, and sl file name suffixes.
        !            53:  * 
        !            54:  * Revision 4.1  83/05/11  16:23:39  wft
        !            55:  * Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
        !            56:  * 1. added copying of path from workfile to RCS file, if RCS file is omitted;
        !            57:  * 2. added getting the file status of RCS and working files;
        !            58:  * 3. added ignoring of directories.
        !            59:  * 
        !            60:  * Revision 3.7  83/05/11  15:01:58  wft
        !            61:  * Added comtable[] which pairs file name suffixes with comment leaders;
        !            62:  * updated InitAdmin() accordingly.
        !            63:  * 
        !            64:  * Revision 3.6  83/04/05  14:47:36  wft
        !            65:  * fixed Suffix in InitAdmin().
        !            66:  * 
        !            67:  * Revision 3.5  83/01/17  18:01:04  wft
        !            68:  * Added getwd() and rename(); these can be removed by defining
        !            69:  * V4_2BSD, since they are not needed in 4.2 bsd.
        !            70:  * Changed sys/param.h to sys/types.h.
        !            71:  *
        !            72:  * Revision 3.4  82/12/08  21:55:20  wft
        !            73:  * removed unused variable.
        !            74:  *
        !            75:  * Revision 3.3  82/11/28  20:31:37  wft
        !            76:  * Changed mktempfile() to store the generated file names.
        !            77:  * Changed getfullRCSname() to store the file and pathname, and to
        !            78:  * delete leading "../" and "./".
        !            79:  *
        !            80:  * Revision 3.2  82/11/12  14:29:40  wft
        !            81:  * changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(),
        !            82:  * checksuffix(), checkfullpath(). Semaphore name generation updated.
        !            83:  * mktempfile() now checks for nil path; lastfilename initialized properly.
        !            84:  * Added Suffix .h to InitAdmin. Added testprogram PAIRTEST.
        !            85:  * Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here.
        !            86:  *
        !            87:  * Revision 3.1  82/10/18  14:51:28  wft
        !            88:  * InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h).
        !            89:  * renamed checkpath() to checkfullpath().
        !            90:  */
        !            91: 
        !            92: 
        !            93: #include "rcsbase.h"
        !            94: #include <sys/types.h>
        !            95: #include <sys/stat.h>
        !            96: #include <sys/dir.h>
        !            97: 
        !            98: extern char * rindex();
        !            99: extern char * mktemp();
        !           100: extern char * malloc();
        !           101: extern FILE * fopen();
        !           102: extern char * getwd();         /* get working directory; forward decl       */
        !           103: extern int    stat(), fstat();
        !           104: 
        !           105: extern FILE * finptr;          /* RCS input file descriptor                 */
        !           106: extern FILE * frewrite;        /* New RCS file descriptor                   */
        !           107: extern char * RCSfilename, * workfilename; /* filenames                     */
        !           108: struct stat RCSstat, workstat; /* file status for RCS file and working file */
        !           109: int    haveRCSstat,  haveworkstat; /* indicators if status availalble       */
        !           110: 
        !           111: 
        !           112: char tempfilename [NCPFN+10];  /* used for derived file names               */
        !           113: char sub1filename [NCPPN];     /* used for files path/file.sfx,v            */
        !           114: char sub2filename [NCPPN];     /* used for files path/RCS/file.sfx,v        */
        !           115: char semafilename [NCPPN];     /* name of semaphore file                    */
        !           116: int  madesema;                 /* indicates whether a semaphore file has been set */
        !           117: char * tfnames[10] =           /* temp. file names to be unlinked when finished   */
        !           118:        {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil};
        !           119: int  lastfilename         = -1;/* index of last file name in tfnames[]      */
        !           120: 
        !           121: 
        !           122: struct compair {
        !           123:         char * suffix, * comlead;
        !           124: };
        !           125: 
        !           126: struct compair comtable[] = {
        !           127: /* comtable pairs each filename suffix with a comment leader. The comment   */
        !           128: /* leader is placed before each line generated by the $Log keyword. This    */
        !           129: /* table is used to guess the proper comment leader from the working file's */
        !           130: /* suffix during initial ci (see InitAdmin()). Comment leaders are needed   */
        !           131: /* for languages without multiline comments; for others they are optional.  */
        !           132:         "c",   " * ",   /* C           */
        !           133:        "csh", "# ",    /* shell       */
        !           134:         "e",   "# ",    /* efl         */
        !           135:         "f",   "c ",    /* fortran     */
        !           136:         "h",   " * ",   /* C-header    */
        !           137:         "l",   " * ",   /* lex         NOTE: conflict between lex and franzlisp*/
        !           138:         "mac", "; ",    /* macro       vms or dec-20 or pdp-11 macro */
        !           139:         "me",  "\\\" ", /* me-macros   t/nroff*/
        !           140:        "mm",  "\\\" ", /* mm-macros   t/nroff*/
        !           141:         "ms",  "\\\" ", /* ms-macros   t/nroff*/
        !           142:         "p",   " * ",   /* pascal      */
        !           143:         "r",   "# ",    /* ratfor      */
        !           144:         "red", "% ",    /* psl/rlisp   */
        !           145: 
        !           146: #ifdef sparc
        !           147:         "s",   "! ",    /* assembler   */
        !           148: #endif
        !           149: #ifdef mc68000
        !           150:         "s",   "| ",    /* assembler   */
        !           151: #endif
        !           152: #ifdef pdp11
        !           153:         "s",   "/ ",    /* assembler   */
        !           154: #endif
        !           155: #ifdef vax
        !           156:         "s",   "# ",    /* assembler   */
        !           157: #endif
        !           158: 
        !           159:         "sh",  "# ",    /* shell       */
        !           160:         "sl",  "% ",    /* psl         */
        !           161:         "red", "% ",    /* psl/rlisp   */
        !           162:         "cl",  ";;; ",  /* common lisp   */
        !           163:         "ml",  "; ",    /* mocklisp    */
        !           164:         "el",  "; ",    /* gnulisp     */
        !           165:        "tex", "% ",    /* tex         */
        !           166:         "y",   " * ",   /* yacc        */
        !           167:         "ye",  " * ",   /* yacc-efl    */
        !           168:         "yr",  " * ",   /* yacc-ratfor */
        !           169:         "",    "# ",    /* default for empty suffix */
        !           170:         nil,   ""       /* default for unknown suffix; must always be last */
        !           171: };
        !           172: 
        !           173: 
        !           174: ffclose(fptr)
        !           175: FILE * fptr;
        !           176: /* Function: checks ferror(fptr) and aborts the program if there were
        !           177:  * errors; otherwise closes fptr.
        !           178:  */
        !           179: {       if (ferror(fptr) || fclose(fptr)==EOF)
        !           180:                 faterror("File read or write error; file system full?");
        !           181: }
        !           182: 
        !           183: 
        !           184: 
        !           185: int trysema(RCSfilename,makesema)
        !           186: char * RCSfilename; int makesema;
        !           187: /* Function: Checks whether a semaphore file exists for RCSfilename. If yes,
        !           188:  * returns false. If not, creates one if makesema==true and returns true
        !           189:  * if successful. If a semaphore file was created, madesema is set to true.
        !           190:  * The name of the semaphore file is put into variable semafilename.
        !           191:  */
        !           192: {
        !           193:         register char * tp, *sp, *lp;
        !           194:         int fdesc;
        !           195: 
        !           196:         sp=RCSfilename;
        !           197:         lp = rindex(sp,'/');
        !           198:         if (lp==0) {
        !           199:                 semafilename[0]='.'; semafilename[1]='/';
        !           200:                 tp= &semafilename[2];
        !           201:         } else {
        !           202:                 /* copy path */
        !           203:                 tp=semafilename;
        !           204:                 do *tp++ = *sp++; while (sp<=lp);
        !           205:         }
        !           206:         /*now insert `,' and append file name */
        !           207:         *tp++ = ',';
        !           208:         lp = rindex(sp, RCSSEP);
        !           209:         while (sp<lp) *tp++ = *sp++;
        !           210:         *tp++ = ','; *tp++ = '\0'; /* will be the same length as RCSfilename*/
        !           211: 
        !           212:         madesema = false;
        !           213:         if (access(semafilename, 0) == 0) {
        !           214:                 error("RCS file %s is in use",RCSfilename);
        !           215:                 return false;
        !           216:         }
        !           217:         if (makesema) {
        !           218:                 if ((fdesc=creat(semafilename, 000)) == -1) {
        !           219:                      error("Can't create semaphore file for RCS file %s",RCSfilename);
        !           220:                      return false;
        !           221:                 } else
        !           222:                      VOID close(fdesc);
        !           223:                      madesema=true;
        !           224:         }
        !           225:         return true;
        !           226: }
        !           227: 
        !           228: 
        !           229: int rmsema()
        !           230: /* Function: delete the semaphore file if madeseam==true;
        !           231:  * sets madesema to false.
        !           232:  */
        !           233: {
        !           234:         if (madesema) {
        !           235:                 madesema=false;
        !           236:                 if (unlink(semafilename) == -1) {
        !           237:                         error("Can't find semaphore file %s",semafilename);
        !           238:                         return false;
        !           239:                 }
        !           240:         }
        !           241:         return true;
        !           242: }
        !           243: 
        !           244: 
        !           245: 
        !           246: InitCleanup()
        !           247: {       lastfilename =  -1;  /* initialize pointer */
        !           248: }
        !           249: 
        !           250: 
        !           251: cleanup()
        !           252: /* Function: closes input file and rewrite file.
        !           253:  * Unlinks files in tfnames[], deletes semaphore file.
        !           254:  */
        !           255: {
        !           256:         register int i;
        !           257: 
        !           258:         if (finptr!=NULL)   VOID fclose(finptr);
        !           259:         if (frewrite!=NULL) VOID fclose(frewrite);
        !           260:         for (i=0; i<=lastfilename; i++) {
        !           261:             if (tfnames[i][0]!='\0')  VOID unlink(tfnames[i]);
        !           262:         }
        !           263:         InitCleanup();
        !           264:         return (rmsema());
        !           265: }
        !           266: 
        !           267: 
        !           268: char * mktempfile(fullpath,filename)
        !           269: register char * fullpath, * filename;
        !           270: /* Function: Creates a unique filename using the process id and stores it
        !           271:  * into a free slot in tfnames. The filename consists of the path contained
        !           272:  * in fullpath concatenated with filename. filename should end in "XXXXXX".
        !           273:  * Because of storage in tfnames, cleanup() can unlink the file later.
        !           274:  * lastfilename indicates the highest occupied slot in tfnames.
        !           275:  * Returns a pointer to the filename created.
        !           276:  * Example use: mktempfile("/tmp/", somefilename)
        !           277:  */
        !           278: {
        !           279:         register char * lastslash, *tp;
        !           280:         lastfilename++;
        !           281:         if ((tp=tfnames[lastfilename])==nil)
        !           282:               tp=tfnames[lastfilename] = malloc(NCPPN);
        !           283:         if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
        !           284:                 /* copy path */
        !           285:                 while (fullpath<=lastslash) *tp++ = *fullpath++;
        !           286:         }
        !           287:         while (*tp++ = *filename++);
        !           288:         return (mktemp(tfnames[lastfilename]));
        !           289: }
        !           290: 
        !           291: 
        !           292: 
        !           293: 
        !           294: char * bindex(sp,c)
        !           295: register char * sp, c;
        !           296: /* Function: Finds the last occurrence of character c in string sp
        !           297:  * and returns a pointer to the character just beyond it. If the
        !           298:  * character doesn't occur in the string, sp is returned.
        !           299:  */
        !           300: {       register char * r;
        !           301:         r = sp;
        !           302:         while (*sp) {
        !           303:                 if (*sp++ == c) r=sp;
        !           304:         }
        !           305:         return r;
        !           306: }
        !           307: 
        !           308: 
        !           309: 
        !           310: 
        !           311: 
        !           312: InitAdmin()
        !           313: /* function: initializes an admin node */
        !           314: {       register char * Suffix;
        !           315:         register int i;
        !           316: 
        !           317:         Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
        !           318:         StrictLocks=STRICT_LOCKING;
        !           319: 
        !           320:         /* guess the comment leader from the suffix*/
        !           321:         Suffix=bindex(workfilename, '.');
        !           322:         if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
        !           323:         for (i=0;;i++) {
        !           324:                 if (comtable[i].suffix==nil) {
        !           325:                         Comment=comtable[i].comlead; /*default*/
        !           326:                         break;
        !           327:                 } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
        !           328:                         Comment=comtable[i].comlead; /*default*/
        !           329:                         break;
        !           330:                 }
        !           331:         }
        !           332:         Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
        !           333: }
        !           334: 
        !           335: 
        !           336: 
        !           337: char * findpairfile(argc, argv, fname)
        !           338: int argc; char * argv[], *fname;
        !           339: /* Function: Given a filename fname, findpairfile scans argv for a pathname
        !           340:  * ending in fname. If found, returns a pointer to the pathname, and sets
        !           341:  * the corresponding pointer in argv to nil. Otherwise returns fname.
        !           342:  * argc indicates the number of entries in argv. Some of them may be nil.
        !           343:  */
        !           344: {
        !           345:         register char * * next, * match;
        !           346:         register int count;
        !           347: 
        !           348:         for (next = argv, count = argc; count>0; next++,count--) {
        !           349:                 if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
        !           350:                         /* bindex finds the beginning of the file name stem */
        !           351:                         match= *next;
        !           352:                         *next=nil;
        !           353:                         return match;
        !           354:                 }
        !           355:         }
        !           356:         return fname;
        !           357: }
        !           358: 
        !           359: 
        !           360: int pairfilenames(argc, argv, mustread, tostdout)
        !           361: int argc; char ** argv; int mustread, tostdout;
        !           362: /* Function: Pairs the filenames pointed to by argv; argc indicates
        !           363:  * how many there are.
        !           364:  * Places a pointer to the RCS filename into RCSfilename,
        !           365:  * and a pointer to the name of the working file into workfilename.
        !           366:  * If both the workfilename and the RCS filename are given, and tostdout
        !           367:  * is true, a warning is printed.
        !           368:  *
        !           369:  * If the working file exists, places its status into workstat and
        !           370:  * sets haveworkstat to 0; otherwise, haveworkstat is set to -1;
        !           371:  * Similarly for the RCS file and the variables RCSstat and haveRCSstat.
        !           372:  *
        !           373:  * If the RCS file exists, it is opened for reading, the file pointer
        !           374:  * is placed into finptr, and the admin-node is read in; returns 1.
        !           375:  * If the RCS file does not exist and mustread==true, an error is printed
        !           376:  * and 0 returned.
        !           377:  * If the RCS file does not exist and mustread==false, the admin node
        !           378:  * is initialized to empty (Head, AccessList, Locks, Symbols, StrictLocks, Dbranch)
        !           379:  * and -1 returned.
        !           380:  *
        !           381:  * 0 is returned on all errors. Files that are directories are errors.
        !           382:  * Also calls InitCleanup();
        !           383:  */
        !           384: {
        !           385:         register char * sp, * tp;
        !           386:         char * lastsep, * purefname, * pureRCSname;
        !           387:         int opened, returncode;
        !           388:         char * RCS1;
        !           389:        char prefdir[NCPPN];
        !           390: 
        !           391:         if (*argv == nil) return 0; /* already paired filename */
        !           392:        if (rindex(*argv,KDELIM)!=0) {
        !           393:                /* KDELIM causes havoc in keyword expansion    */
        !           394:                error("RCS file name may not contain %c",KDELIM);
        !           395:                return 0;
        !           396:        }
        !           397:         InitCleanup();
        !           398: 
        !           399:         /* first check suffix to see whether it is an RCS file or not */
        !           400:         purefname=bindex(*argv, '/'); /* skip path */
        !           401:         lastsep=rindex(purefname, RCSSEP);
        !           402:         if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
        !           403:                 /* RCS file name given*/
        !           404:                 RCS1=(*argv); pureRCSname=purefname;
        !           405:                 /* derive workfilename*/
        !           406:                 sp = purefname; tp=tempfilename;
        !           407:                 while (sp<lastsep) *tp++ = *sp++; *tp='\0';
        !           408:                 /* try to find workfile name among arguments */
        !           409:                 workfilename=findpairfile(argc-1,argv+1,tempfilename);
        !           410:                 if (strlen(pureRCSname)>NCPFN) {
        !           411:                         error("RCS file name %s too long",RCS1);
        !           412:                         return 0;
        !           413:                 }
        !           414:         } else {
        !           415:                 /* working file given; now try to find RCS file */
        !           416:                 workfilename= *argv;
        !           417:                 /* derive RCS file name*/
        !           418:                 sp=purefname; tp=tempfilename;
        !           419:                 while (*tp++ = *sp++);
        !           420:                 *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp++='\0';
        !           421:                 /* Try to find RCS file name among arguments*/
        !           422:                 RCS1=findpairfile(argc-1,argv+1,tempfilename);
        !           423:                 pureRCSname=bindex(RCS1, '/');
        !           424:                 if (strlen(pureRCSname)>NCPFN) {
        !           425:                         error("working file name %s too long",workfilename);
        !           426:                         return 0;
        !           427:                 }
        !           428:         }
        !           429:         /* now we have a (tentative) RCS filename in RCS1 and workfilename  */
        !           430:         /* First, get status of workfilename */
        !           431:         haveworkstat=stat(workfilename, &workstat);
        !           432:         if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
        !           433:                 diagnose("Directory %s ignored",workfilename);
        !           434:                 return 0;
        !           435:         }
        !           436:         /* Second, try to find the right RCS file */
        !           437:         if (pureRCSname!=RCS1) {
        !           438:                 /* a path for RCSfile is given; single RCS file to look for */
        !           439:                 finptr=fopen(RCSfilename=RCS1, "r");
        !           440:                 if (finptr!=NULL) {
        !           441:                     returncode=1;
        !           442:                 } else { /* could not open */
        !           443:                     if (access(RCSfilename,0)==0) {
        !           444:                         error("Can't open existing %s", RCSfilename);
        !           445:                         return 0;
        !           446:                     }
        !           447:                     if (mustread) {
        !           448:                         error("Can't find %s", RCSfilename);
        !           449:                         return 0;
        !           450:                     } else {
        !           451:                         /* initialize if not mustread */
        !           452:                         returncode = -1;
        !           453:                     }
        !           454:                 }
        !           455:         } else {
        !           456:                /* no path for RCS file name. Prefix it with path of work */
        !           457:                /* file if RCS file omitted. Make a second name including */
        !           458:                /* RCSDIR and try to open that one first.                 */
        !           459:                sub1filename[0]=sub2filename[0]= '\0';
        !           460:                if (RCS1==tempfilename) {
        !           461:                        /* RCS file name not given; prepend work path */
        !           462:                        sp= *argv; tp= sub1filename;
        !           463:                        while (sp<purefname) *tp++ = *sp ++;
        !           464:                        *tp='\0';
        !           465:                        VOID strcpy(sub2filename,sub1filename); /* second one */
        !           466:                }
        !           467:                VOID strcat(sub1filename,RCSDIR);
        !           468:                VOID strcpy(prefdir,sub1filename); /* preferred directory for RCS file*/
        !           469:                VOID strcat(sub1filename,RCS1); VOID strcat(sub2filename,RCS1);
        !           470: 
        !           471: 
        !           472:                 opened=(
        !           473:                ((finptr=fopen(RCSfilename=sub1filename, "r"))!=NULL) ||
        !           474:                ((finptr=fopen(RCSfilename=sub2filename,"r"))!=NULL) );
        !           475: 
        !           476:                 if (opened) {
        !           477:                         /* open succeeded */
        !           478:                         returncode=1;
        !           479:                 } else {
        !           480:                         /* open failed; may be read protected */
        !           481:                        if ((access(RCSfilename=sub1filename,0)==0) ||
        !           482:                            (access(RCSfilename=sub2filename,0)==0)) {
        !           483:                                 error("Can't open existing %s",RCSfilename);
        !           484:                                 return 0;
        !           485:                         }
        !           486:                         if (mustread) {
        !           487:                                error("Can't find %s nor %s",sub1filename,sub2filename);
        !           488:                                 return 0;
        !           489:                         } else {
        !           490:                                 /* initialize new file. Put into ./RCS if possible, strip off suffix*/
        !           491:                                RCSfilename= (access(prefdir,0)==0)?sub1filename:sub2filename;
        !           492:                                 returncode= -1;
        !           493:                         }
        !           494:                 }
        !           495:         }
        !           496: 
        !           497:         if (returncode == 1) { /* RCS file open */
        !           498:                 haveRCSstat=fstat(fileno(finptr),&RCSstat);
        !           499:                 if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
        !           500:                         diagnose("Directory %s ignored",RCSfilename);
        !           501:                         return 0;
        !           502:                 }
        !           503:                 Lexinit(); getadmin();
        !           504:         } else {  /* returncode == -1; RCS file nonexisting */
        !           505:                 haveRCSstat = -1;
        !           506:                 InitAdmin();
        !           507:         };
        !           508: 
        !           509:         if (tostdout&&
        !           510:             !(RCS1==tempfilename||workfilename==tempfilename))
        !           511:                 /*The last term determines whether a pair of        */
        !           512:                 /* file names was given in the argument list        */
        !           513:                 warn("Option -p is set; ignoring output file %s",workfilename);
        !           514: 
        !           515:         return returncode;
        !           516: }
        !           517: 
        !           518: 
        !           519: char * getfullRCSname()
        !           520: /* Function: returns a pointer to the full path name of the RCS file.
        !           521:  * Calls getwd(), but only once.
        !           522:  * removes leading "../" and "./".
        !           523:  */
        !           524: {       static char pathbuf[NCPPN];
        !           525:         static char namebuf[NCPPN];
        !           526:         static int  pathlength =0;
        !           527: 
        !           528:         register char * realname, * lastpathchar;
        !           529:         register int  dotdotcounter, realpathlength;
        !           530: 
        !           531:         if (*RCSfilename=='/') {
        !           532:                 return(RCSfilename);
        !           533:         } else {
        !           534:                 if (pathlength==0) { /*call curdir for the first time*/
        !           535:                     if (getwd(pathbuf)==NULL)
        !           536:                         faterror("Can't build current directory path");
        !           537:                     pathlength=strlen(pathbuf);
        !           538:                     if (!((pathlength==1) && (pathbuf[0]=='/'))) {
        !           539:                         pathbuf[pathlength++]='/';
        !           540:                         /* Check needed because some getwd implementations */
        !           541:                         /* generate "/" for the root.                      */
        !           542:                     }
        !           543:                 }
        !           544:                 /*the following must be redone since RCSfilename may change*/
        !           545:                 /* find how many ../ to remvove from RCSfilename */
        !           546:                 dotdotcounter =0;
        !           547:                 realname = RCSfilename;
        !           548:                 while( realname[0]=='.' &&
        !           549:                       (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
        !           550:                         if (realname[1]=='/') {
        !           551:                             /* drop leading ./ */
        !           552:                             realname += 2;
        !           553:                         } else {
        !           554:                             /* drop leading ../ and remember */
        !           555:                             dotdotcounter++;
        !           556:                             realname += 3;
        !           557:                         }
        !           558:                 }
        !           559:                 /* now remove dotdotcounter trailing directories from pathbuf*/
        !           560:                 lastpathchar=pathbuf + pathlength-1;
        !           561:                 while (dotdotcounter>0 && lastpathchar>pathbuf) {
        !           562:                     /* move pointer backwards over trailing directory */
        !           563:                     lastpathchar--;
        !           564:                     if (*lastpathchar=='/') {
        !           565:                         dotdotcounter--;
        !           566:                     }
        !           567:                 }
        !           568:                 if (dotdotcounter>0) {
        !           569:                     error("Can't generate full path name for RCS file");
        !           570:                     return RCSfilename;
        !           571:                 } else {
        !           572:                     /* build full path name */
        !           573:                     realpathlength=lastpathchar-pathbuf+1;
        !           574:                     VOID strncpy(namebuf,pathbuf,realpathlength);
        !           575:                     VOID strcpy(&namebuf[realpathlength],realname);
        !           576:                     return(namebuf);
        !           577:                 }
        !           578:         }
        !           579: }
        !           580: 
        !           581: 
        !           582: 
        !           583: int trydiraccess(filename)
        !           584: char * filename;
        !           585: /* checks write permission in directory of filename and returns
        !           586:  * true if writable, false otherwise
        !           587:  */
        !           588: {
        !           589:         char pathname[NCPPN];
        !           590:         register char * tp, *sp, *lp;
        !           591:         lp = rindex(filename,'/');
        !           592:         if (lp==0) {
        !           593:                 /* check current directory */
        !           594:                 if (access(".",2)==0)
        !           595:                         return true;
        !           596:                 else {
        !           597:                         error("Current directory not writable");
        !           598:                         return false;
        !           599:                 }
        !           600:         }
        !           601:         /* copy path */
        !           602:         sp=filename;
        !           603:         tp=pathname;
        !           604:         do *tp++ = *sp++; while (sp<=lp);
        !           605:         *tp='\0';
        !           606:         if (access(pathname,2)==0)
        !           607:                 return true;
        !           608:         else {
        !           609:                 error("Directory %s not writable", pathname);
        !           610:                 return false;
        !           611:         }
        !           612: }
        !           613: 
        !           614: 
        !           615: 
        !           616: #ifndef V4_2BSD
        !           617: /* rename() and getwd() will be provided in bsd 4.2 */
        !           618: 
        !           619: 
        !           620: int rename(from, to)
        !           621: char * from, *to;
        !           622: /* Function: renames a file with the name given by from to the name given by to.
        !           623:  * unlinks the to-file if it already exists. returns -1 on error, 0 otherwise.
        !           624:  */
        !           625: {       VOID unlink(to);      /* no need to check return code; will be caught by link*/
        !           626:                          /* no harm done if file "to" does not exist            */
        !           627:         if (link(from,to)<0) return -1;
        !           628:         return(unlink(from));
        !           629: }
        !           630: 
        !           631: 
        !           632: 
        !           633: #define dot     "."
        !           634: #define dotdot  ".."
        !           635: 
        !           636: 
        !           637: 
        !           638: char * getwd(name)
        !           639: char * name;
        !           640: /* Function: places full pathname of current working directory into name and
        !           641:  * returns name on success, NULL on failure.
        !           642:  * getwd is an adaptation of pwd. May not return to the current directory on
        !           643:  * failure.
        !           644:  */
        !           645: {
        !           646:         FILE    *file;
        !           647:         struct  stat    d, dd;
        !           648:         char buf[2];    /* to NUL-terminate dir.d_name */
        !           649:         struct  direct  dir;
        !           650: 
        !           651:         int rdev, rino;
        !           652:         int off;
        !           653:         register i,j;
        !           654: 
        !           655:         name[off= 0] = '/';
        !           656:         name[1] = '\0';
        !           657:         buf[0] = '\0';
        !           658:         stat("/", &d);
        !           659:         rdev = d.st_dev;
        !           660:         rino = d.st_ino;
        !           661:         for (;;) {
        !           662:                 if (stat(dot, &d)<0) return NULL;
        !           663:                 if (d.st_ino==rino && d.st_dev==rdev) {
        !           664:                         if (name[off] == '/') name[off] = '\0';
        !           665:                         chdir(name); /*change back to current directory*/
        !           666:                         return name;
        !           667:                 }
        !           668:                 if ((file = fopen(dotdot,"r")) == NULL) return NULL;
        !           669:                 if (fstat(fileno(file), &dd)<0) goto fail;
        !           670:                 chdir(dotdot);
        !           671:                 if(d.st_dev == dd.st_dev) {
        !           672:                         if(d.st_ino == dd.st_ino) {
        !           673:                             if (name[off] == '/') name[off] = '\0';
        !           674:                             chdir(name); /*change back to current directory*/
        !           675:                             VOID fclose(file);
        !           676:                             return name;
        !           677:                         }
        !           678:                         do {
        !           679:                             if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
        !           680:                                 goto fail;
        !           681:                         } while (dir.d_ino != d.st_ino);
        !           682:                 }
        !           683:                 else do {
        !           684:                         if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
        !           685:                             goto fail;
        !           686:                         }
        !           687:                         stat(dir.d_name, &dd);
        !           688:                 } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
        !           689:                 VOID fclose(file);
        !           690: 
        !           691:                 /* concatenate file name */
        !           692:                 i = -1;
        !           693:                 while (dir.d_name[++i] != 0);
        !           694:                 for(j=off+1; j>0; --j)
        !           695:                         name[j+i+1] = name[j];
        !           696:                 off=i+off+1;
        !           697:                 name[i+1] = '/';
        !           698:                 for(--i; i>=0; --i)
        !           699:                         name[i+1] = dir.d_name[i];
        !           700:         } /* end for */
        !           701: 
        !           702: fail:   VOID fclose(file);
        !           703:         return NULL;
        !           704: }
        !           705: 
        !           706: 
        !           707: #endif
        !           708: 
        !           709: 
        !           710: #ifdef PAIRTEST
        !           711: /* test program for pairfilenames() and getfullRCSname() */
        !           712: char * workfilename, *RCSfilename;
        !           713: extern int quietflag;
        !           714: 
        !           715: main(argc, argv)
        !           716: int argc; char *argv[];
        !           717: {
        !           718:         int result;
        !           719:         int initflag,tostdout;
        !           720:         quietflag=tostdout=initflag=false;
        !           721:         cmdid="pair";
        !           722: 
        !           723:         while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
        !           724:                 switch ((*argv)[1]) {
        !           725: 
        !           726:                 case 'p':       tostdout=true;
        !           727:                                 break;
        !           728:                 case 'i':       initflag=true;
        !           729:                                 break;
        !           730:                 case 'q':       quietflag=true;
        !           731:                                 break;
        !           732:                 default:        error("unknown option: %s", *argv);
        !           733:                                 break;
        !           734:                 }
        !           735:         }
        !           736: 
        !           737:         do {
        !           738:                 RCSfilename=workfilename=nil;
        !           739:                 result=pairfilenames(argc,argv,!initflag,tostdout);
        !           740:                 if (result!=0) {
        !           741:                      diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
        !           742:                      diagnose("Full RCS file name: %s", getfullRCSname());
        !           743:                 }
        !           744:                 switch (result) {
        !           745:                         case 0: continue; /* already paired file */
        !           746: 
        !           747:                         case 1: if (initflag) {
        !           748:                                     error("RCS file %s exists already",RCSfilename);
        !           749:                                 } else {
        !           750:                                     diagnose("RCS file %s exists",RCSfilename);
        !           751:                                 }
        !           752:                                 VOID fclose(finptr);
        !           753:                                 break;
        !           754: 
        !           755:                         case -1:diagnose("RCS file does not exist");
        !           756:                                 break;
        !           757:                 }
        !           758: 
        !           759:         } while (++argv, --argc>=1);
        !           760: 
        !           761: }
        !           762: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.