Annotation of 43BSD/contrib/rcs/src/rcsfnms.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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