Annotation of 43BSDReno/contrib/rcs/src/rcsutil.c, revision 1.1.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.