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

unix.superglobalmegacorp.com

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