Annotation of 43BSDReno/contrib/rcs/src/rcsutil.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *                     RCS utilities
        !             3:  */
        !             4: #ifndef lint
        !             5: static char rcsid[]= "$Id: rcsutil.c,v 4.6 89/05/01 15:13:40 narten Exp $ Purdue CS";
        !             6: #endif
        !             7: 
        !             8: /* Copyright (C) 1982, 1988, 1989 Walter Tichy
        !             9:  * All rights reserved.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms are permitted
        !            12:  * provided that the above copyright notice and this paragraph are
        !            13:  * duplicated in all such forms and that any documentation,
        !            14:  * advertising materials, and other materials related to such
        !            15:  * distribution and use acknowledge that the software was developed
        !            16:  * by Walter Tichy.
        !            17:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            18:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            19:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            20:  *
        !            21:  * Report all problems and direct all questions to:
        !            22:  *   [email protected]
        !            23:  * 
        !            24: 
        !            25: 
        !            26: 
        !            27: 
        !            28: 
        !            29: 
        !            30: 
        !            31: */
        !            32: 
        !            33: 
        !            34: 
        !            35: 
        !            36: /* $Log:       rcsutil.c,v $
        !            37:  * Revision 4.6  89/05/01  15:13:40  narten
        !            38:  * changed copyright header to reflect current distribution rules
        !            39:  * 
        !            40:  * Revision 4.5  88/11/08  16:01:02  narten
        !            41:  * corrected use of varargs routines
        !            42:  * 
        !            43:  * Revision 4.4  88/11/08  12:00:28  narten
        !            44:  * changes from  [email protected] (Paul Eggert)
        !            45:  * 
        !            46:  * Revision 4.4  88/08/09  19:13:24  eggert
        !            47:  * Check for memory exhaustion.
        !            48:  * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
        !            49:  * Use execv(), not system(); yield exit status like diff(1)'s.
        !            50:  * 
        !            51:  * Revision 4.3  87/10/18  10:40:22  narten
        !            52:  * Updating version numbers. Changes relative to 1.1 actually
        !            53:  * relative to 4.1
        !            54:  * 
        !            55:  * Revision 1.3  87/09/24  14:01:01  narten
        !            56:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
        !            57:  * warnings)
        !            58:  * 
        !            59:  * Revision 1.2  87/03/27  14:22:43  jenkins
        !            60:  * Port to suns
        !            61:  * 
        !            62:  * Revision 1.1  84/01/23  14:50:43  kcs
        !            63:  * Initial revision
        !            64:  * 
        !            65:  * Revision 4.1  83/05/10  15:53:13  wft
        !            66:  * Added getcaller() and findlock().
        !            67:  * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
        !            68:  * (needed for background jobs in older shells). Added restoreints().
        !            69:  * Removed printing of full RCS path from logcommand().
        !            70:  * 
        !            71:  * Revision 3.8  83/02/15  15:41:49  wft
        !            72:  * Added routine fastcopy() to copy remainder of a file in blocks.
        !            73:  *
        !            74:  * Revision 3.7  82/12/24  15:25:19  wft
        !            75:  * added catchints(), ignoreints() for catching and ingnoring interrupts;
        !            76:  * fixed catchsig().
        !            77:  *
        !            78:  * Revision 3.6  82/12/08  21:52:05  wft
        !            79:  * Using DATEFORM to format dates.
        !            80:  *
        !            81:  * Revision 3.5  82/12/04  18:20:49  wft
        !            82:  * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
        !            83:  * lockedby-field.
        !            84:  *
        !            85:  * Revision 3.4  82/12/03  17:17:43  wft
        !            86:  * Added check to addlock() ensuring only one lock per person.
        !            87:  * Addlock also returns a pointer to the lock created. Deleted fancydate().
        !            88:  *
        !            89:  * Revision 3.3  82/11/27  12:24:37  wft
        !            90:  * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
        !            91:  * Introduced macro SNOOP so that snoop can be placed in directory other than
        !            92:  * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
        !            93:  *
        !            94:  * Revision 3.2  82/10/18  21:15:11  wft
        !            95:  * added function getfullRCSname().
        !            96:  *
        !            97:  * Revision 3.1  82/10/13  16:17:37  wft
        !            98:  * Cleanup message is now suppressed in quiet mode.
        !            99:  */
        !           100: 
        !           101: 
        !           102: 
        !           103: 
        !           104: #include <sys/types.h>
        !           105: #include <sys/stat.h>
        !           106: #include <signal.h>
        !           107: #include "rcsbase.h"
        !           108: #include <pwd.h>
        !           109: #include <varargs.h>
        !           110: 
        !           111: #if defined(USG) || defined(V4_2BSD)
        !           112: #include <fcntl.h>
        !           113: #endif
        !           114: 
        !           115: #ifndef V4_2BSD
        !           116: #define vfork fork
        !           117: #endif
        !           118: 
        !           119: extern char * bindex();
        !           120: extern FILE * finptr;
        !           121: extern char * RCSfilename;
        !           122: extern char * getlogin();
        !           123: extern struct passwd *getpwuid();
        !           124: extern char * malloc();
        !           125: 
        !           126: 
        !           127: char * talloc(size)
        !           128: unsigned size;
        !           129: {
        !           130:        char * p;
        !           131:        if (!(p = malloc(size))) {
        !           132:                faterror("out of memory");
        !           133:        }
        !           134:        return p;
        !           135: }
        !           136: 
        !           137: 
        !           138: 
        !           139: char * getcaller()
        !           140: /* Function: gets the callers login from his uid.
        !           141:  * If the uid is root, tries to get the true login with getlogin().
        !           142:  */
        !           143: {       char * name;
        !           144:        int uid;
        !           145:        uid=getuid();
        !           146:        if (uid==0) {
        !           147:                /* super user; try getlogin() to distinguish */
        !           148:                name = getlogin();
        !           149:                if (name!=nil && *name!='\0')
        !           150:                        return name;
        !           151:        }
        !           152:        return(getpwuid(uid)->pw_name);
        !           153: }
        !           154: 
        !           155: 
        !           156: 
        !           157: struct hshentry * findlock(who,delete)
        !           158: char * who; int delete;
        !           159: /* Finds the first lock held by who and returns a pointer
        !           160:  * to the locked delta; also removes the lock if delete==true.
        !           161:  * Returns nil if there is no lock held by who.
        !           162:  */
        !           163: {
        !           164:         register struct lock * next, * trail;
        !           165:         struct lock dummy;
        !           166: 
        !           167:         dummy.nextlock=next=Locks;
        !           168:         trail = &dummy;
        !           169:         while (next!=nil) {
        !           170:                 if(strcmp(who,next->login)==0) break; /*found a lock*/
        !           171:                 trail=next;
        !           172:                 next=next->nextlock;
        !           173:         }
        !           174:         if (next!=nil) {
        !           175:                /* found one */
        !           176:                if (delete) {
        !           177:                    /* delete it */
        !           178:                    trail->nextlock=next->nextlock;
        !           179:                    Locks=dummy.nextlock;
        !           180:                    next->delta->lockedby=nil; /* reset locked-by */
        !           181:                }
        !           182:                 return next->delta;
        !           183:         } else  return nil;
        !           184: }
        !           185: 
        !           186: 
        !           187: 
        !           188: 
        !           189: 
        !           190: 
        !           191: 
        !           192: struct lock * addlock(delta,who)
        !           193: struct hshentry * delta; char * who;
        !           194: /* Given a delta, addlock checks whether
        !           195:  * the delta is locked by somebody other than who.
        !           196:  * If so, an error message is printed, and false returned.
        !           197:  * If the delta is not reserved at all, a lock for it is added,
        !           198:  * and a pointer for the lock returned.
        !           199:  */
        !           200: {
        !           201:         struct lock * next;
        !           202: 
        !           203:         next=Locks;
        !           204:         while (next!=nil) {
        !           205:                 if (cmpnum(delta->num,next->delta->num)==0) {
        !           206:                         if (strcmp(who,next->login)==0)
        !           207:                                 return next;
        !           208:                                 /* lock exists already */
        !           209:                         else {
        !           210:                                 error("revision %s already locked by %s",
        !           211:                                       delta->num, next->login);
        !           212:                                 return false;
        !           213:                         }
        !           214:                 } else {
        !           215:                         if (strcmp(who,next->login)==0) {
        !           216:                                 error("you already locked %s; only one lock allowed per person.",
        !           217:                                        next->delta->num);
        !           218:                                 return false;
        !           219:                         } else {
        !           220:                                 next=next->nextlock;
        !           221:                         }
        !           222:                 }
        !           223:         }
        !           224:         /* not found; set up new lockblock */
        !           225:         next= (struct lock *) talloc(sizeof (struct lock));
        !           226:         delta->lockedby=next->login=who;
        !           227:         next->delta= delta;
        !           228:         next->nextlock=Locks;
        !           229:         Locks=next;
        !           230:         return next;
        !           231: }
        !           232: 
        !           233: 
        !           234: 
        !           235: int addsymbol(delta,name,rebind)
        !           236: struct hshentry * delta; char * name; int rebind;
        !           237: /* Function: adds a new symbolic name and associates it with node delta.
        !           238:  * If name already exists and rebind is true, the name is associated
        !           239:  * with the new delta; otherwise, an error message is printed and
        !           240:  * false returned. Returns true it successful.
        !           241:  */
        !           242: {       register struct assoc * next;
        !           243:         next=Symbols;
        !           244:         while (next!=nil) {
        !           245:                 if (strcmp(name,next->symbol)==0) {
        !           246:                         if (rebind) {
        !           247:                                 next->delta=delta;
        !           248:                                 return true;
        !           249:                         } else {
        !           250:                                 error("symbolic name %s already bound to %s",
        !           251:                                         name,next->delta->num);
        !           252:                                 return false;
        !           253:                         }
        !           254:                 } else  next = next->nextassoc;
        !           255:         }
        !           256:         /* not found; insert new pair. */
        !           257:         next = (struct assoc *) talloc(sizeof(struct assoc));
        !           258:         next->symbol=name;
        !           259:         next->delta=delta;
        !           260:         next->nextassoc=Symbols;
        !           261:         Symbols = next;
        !           262:         return true;
        !           263: }
        !           264: 
        !           265: 
        !           266: 
        !           267: 
        !           268: int checkaccesslist(who)
        !           269: char * who;
        !           270: /* function: Returns true if who is the superuser, the owner of the
        !           271:  * file, the access list is empty, or who is on the access list.
        !           272:  * Prints an error message and returns false otherwise.
        !           273:  */
        !           274: {
        !           275:         register struct access * next;
        !           276:         struct stat statbuf;
        !           277: 
        !           278:         if ((AccessList==nil) || (strcmp(who,"root")==0))
        !           279:                 return true;
        !           280: 
        !           281:         next=AccessList;
        !           282:         do {
        !           283:                 if (strcmp(who,next->login)==0)
        !           284:                         return true;
        !           285:                 next=next->nextaccess;
        !           286:         } while (next!=nil);
        !           287: 
        !           288:         VOID fstat(fileno(finptr),&statbuf);  /* get owner of file */
        !           289:         if (getuid() == statbuf.st_uid) return true;
        !           290: 
        !           291:         error("User %s not on the access list",who);
        !           292:         return false;
        !           293: }
        !           294: 
        !           295: 
        !           296: static SIGNAL_TYPE catchsig(s)
        !           297: {
        !           298:        ignoreints();
        !           299:         diagnose("\nRCS: cleaning up\n");
        !           300:         VOID cleanup();
        !           301:        exit(2);
        !           302: #ifdef lint
        !           303:        catchsig(s);
        !           304: #endif
        !           305: }
        !           306: 
        !           307: static sig[] = {SIGINT,SIGHUP,SIGQUIT,SIGPIPE,SIGTERM};
        !           308: #define SIGS (sizeof(sig)/sizeof(*sig))
        !           309: static SIGNAL_TYPE (*catcher[SIGS])();
        !           310:   
        !           311:   void catchints()
        !           312:   {
        !           313:        register i;
        !           314:        for (i=SIGS; 0<=--i; )
        !           315:            catcher[i]  =
        !           316:                signal(sig[i],SIG_IGN) == SIG_IGN  ?  SIG_IGN  :  catchsig;
        !           317:        restoreints();
        !           318:   }
        !           319: 
        !           320:   void ignoreints()
        !           321:   {
        !           322:        register i;
        !           323:        for (i=SIGS; 0<=--i; )
        !           324:                VOID signal(sig[i], SIG_IGN);
        !           325:   }
        !           326: 
        !           327: void restoreints()
        !           328: {
        !           329:        register i;
        !           330:        for (i=SIGS; 0<=--i; )
        !           331:                if (catcher[i] != SIG_IGN)
        !           332:                        VOID signal(sig[i], catcher[i]);
        !           333: }
        !           334: 
        !           335: fastcopy(inf,outf)
        !           336: FILE * inf, * outf;
        !           337: /* Function: copies the remainder of file inf to outf. First copies the
        !           338:  * rest that is in the IO-buffer of inf character by character, and then
        !           339:  * copies the remainder in blocks.
        !           340:  */
        !           341: {       char buf[BUFSIZ];
        !           342:         register int rcount, wcount;
        !           343: 
        !           344:         /* write the rest of the buffer to outf */
        !           345:         while ((--inf->_cnt)>=0) {
        !           346:                 VOID putc(*inf->_ptr++&0377,outf);
        !           347:         }
        !           348:         if (fflush(outf) == EOF) {
        !           349:                writeerror();
        !           350:        }
        !           351: 
        !           352:         /*now read the rest of the file in blocks*/
        !           353:         while ((rcount=read(fileno(inf),buf,BUFSIZ))>0) {
        !           354:                 wcount=write(fileno(outf),buf,rcount);
        !           355:                 if (wcount!=rcount) {
        !           356:                     writeerror();
        !           357:                 }
        !           358:         }
        !           359: }
        !           360: 
        !           361: 
        !           362: 
        !           363: 
        !           364: 
        !           365: 
        !           366: #ifdef SNOOPFILE
        !           367: 
        !           368: #include "time.h"
        !           369: extern struct tm* localtime();
        !           370: extern long time();
        !           371: 
        !           372: logcommand(commandname,delta, sequence,login)
        !           373: char* commandname; struct hshentry * delta, * sequence[];char * login;
        !           374: /* Function: start a process to write the file that
        !           375:  * logs the RCS command.
        !           376:  * Each line in the log file contains the following information:
        !           377:  * operation, revision(r), backward deltas applied(b), forward deltas applied(f),
        !           378:  * total deltas present(t), creation date of delta(d), date of operation(o),
        !           379:  * login of caller, RCS file name.
        !           380:  */
        !           381: {
        !           382:         char logline[200];
        !           383:         char curdate[datelength];
        !           384:        char *inoutargs[5];
        !           385:         register int i, backward, forward;
        !           386:         long clock;
        !           387:         struct tm * tm;
        !           388: 
        !           389:         clock=time((long *)0);
        !           390:         tm=localtime(&clock);
        !           391: 
        !           392:         VOID sprintf(curdate,DATEFORM,
        !           393:                 tm->tm_year, tm->tm_mon+1, tm->tm_mday,
        !           394:                 tm->tm_hour, tm->tm_min, tm->tm_sec);
        !           395: 
        !           396:         i= backward=forward=0;
        !           397:         while(sequence[i]!=nil) {  /* count deltas to be applied*/
        !           398:         if (countnumflds(sequence[i]->num) == 2)
        !           399:                 backward++;  /* reverse delta */
        !           400:         else    forward++;   /* branch delta  */
        !           401:         i++;
        !           402:         }
        !           403:        VOID sprintf(logline,"%s %10sr %3db %3df %3dt %sc %so %s %s",
        !           404:                commandname,delta->num,backward,forward,TotalDeltas,delta->date,
        !           405:                curdate,login,bindex(getfullRCSname(),'/'));
        !           406:        inoutargs[0] = nil;
        !           407:        inoutargs[1] = nil;
        !           408:        inoutargs[2] = SNOOP;
        !           409:        inoutargs[3] = logline;
        !           410:        inoutargs[4] = nil;
        !           411:        VOID run_back(inoutargs);
        !           412: }
        !           413: #endif
        !           414: 
        !           415: 
        !           416: static int fdreopen(fd, file, flags, mode)
        !           417:        char *file;
        !           418: {
        !           419:        int newfd;
        !           420:        VOID close(fd);
        !           421:        newfd = flags==-1 ? creat(file,mode) : open(file,flags,mode);
        !           422:        if (newfd < 0  ||  newfd == fd)
        !           423:                return newfd;
        !           424: #ifdef F_DUPFD
        !           425:        fd = fcntl(newfd, F_DUPFD, fd);
        !           426: #else
        !           427:        fd = dup2(newfd, fd);
        !           428: #endif
        !           429:        VOID close(newfd);
        !           430:        return fd;
        !           431: }
        !           432: 
        !           433: static void tryopen(fd,file,flags)
        !           434:        char *file;
        !           435: {
        !           436:        if (file  &&  fdreopen(fd,file,flags,0600) != fd) {
        !           437:                VOID write(fileno(stderr), file, strlen(file));
        !           438:                VOID write(fileno(stderr), ": cannot open\n", 14);
        !           439:                _exit(2);
        !           440:        }
        !           441: }
        !           442: 
        !           443: /*
        !           444: /* Run in the background a command specified by the strings in 'inoutargs'.
        !           445: /* inoutargs[0], if nonnil, is the name of the input file.
        !           446: /* inoutargs[1], if nonnil, is the name of the output file.
        !           447: /* inoutargs[2..] form the command to be run in the background.
        !           448: /*/
        !           449: static int run_back(inoutargs)
        !           450:        register char **inoutargs;
        !           451: {
        !           452:        int pid;
        !           453:        if (fflush(stdout) == EOF  ||  fflush(stderr) == EOF)
        !           454:                return -1;
        !           455:        if (!(pid = vfork())) {
        !           456:                tryopen(fileno(stdin), inoutargs[0], 0);
        !           457:                tryopen(fileno(stdout), inoutargs[1], -1);
        !           458:                VOID execv(inoutargs[2], &inoutargs[2]);
        !           459:                inoutargs[1] = "/bin/sh";
        !           460:                VOID execv(inoutargs[1], &inoutargs[1]);
        !           461:                VOID write(fileno(stderr), "/bin/sh: not found\n", 19);
        !           462:                _exit(2);
        !           463:        }
        !           464:        return pid;
        !           465: }
        !           466: 
        !           467: #define CARGSMAX 20
        !           468: /*
        !           469: /* Run a command.
        !           470: /* The first two arguments are the input and output files (if nonnil);
        !           471: /* the rest specify the command and its arguments.
        !           472: /*/
        !           473: int run(va_alist)
        !           474:        va_dcl
        !           475: {
        !           476:        va_list ap;
        !           477:        int pid, wstatus, w;
        !           478:        char *rgargs[CARGSMAX];
        !           479:        register i = 0;
        !           480:        va_start(ap);
        !           481:        rgargs[0] = va_arg(ap, char *);
        !           482:        rgargs[1] = va_arg(ap, char *);
        !           483:        for (i =2; i< CARGSMAX; i++) {
        !           484:            rgargs[i] = va_arg(ap, char *);
        !           485:            if (rgargs[i] == NULL)
        !           486:                break;
        !           487:        }
        !           488:        va_end(ap);
        !           489:        pid = run_back(rgargs);
        !           490:        if (pid < 0)
        !           491:                return pid;
        !           492:        for (;;)
        !           493:                if ((w = wait(&wstatus)) < 0)
        !           494:                        return w;
        !           495:                else if (w == pid)
        !           496:                        return wstatus;
        !           497: }

unix.superglobalmegacorp.com

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