Annotation of 43BSD/contrib/rcs/src/rcsfnms.c, revision 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.