|
|
1.1 ! root 1: /* ! 2: * RCS utilities ! 3: */ ! 4: static char rcsid[]= ! 5: "$Header: /usr/wft/RCS/SRC/RCS/rcsutil.c,v 3.8 83/02/15 15:41:49 wft Exp $ Purdue CS"; ! 6: /***************************************************************************** ! 7: ***************************************************************************** ! 8: * ! 9: * Copyright (C) 1982 by Walter F. Tichy ! 10: * Purdue University ! 11: * Computer Science Department ! 12: * West Lafayette, IN 47907 ! 13: * ! 14: * All rights reserved. No part of this software may be sold or distributed ! 15: * in any form or by any means without the prior written permission of the ! 16: * author. ! 17: * Report problems and direct all inquiries to Tichy@purdue (ARPA net). ! 18: */ ! 19: ! 20: ! 21: ! 22: /* $Log: rcsutil.c,v $ ! 23: * Revision 3.8 83/02/15 15:41:49 wft ! 24: * Added routine fastcopy() to copy remainder of a file in blocks. ! 25: * ! 26: * Revision 3.7 82/12/24 15:25:19 wft ! 27: * added catchints(), ignoreints() for catching and ingnoring interrupts; ! 28: * fixed catchsig(). ! 29: * ! 30: * Revision 3.6 82/12/08 21:52:05 wft ! 31: * Using DATEFORM to format dates. ! 32: * ! 33: * Revision 3.5 82/12/04 18:20:49 wft ! 34: * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update ! 35: * lockedby-field. ! 36: * ! 37: * Revision 3.4 82/12/03 17:17:43 wft ! 38: * Added check to addlock() ensuring only one lock per person. ! 39: * Addlock also returns a pointer to the lock created. Deleted fancydate(). ! 40: * ! 41: * Revision 3.3 82/11/27 12:24:37 wft ! 42: * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c. ! 43: * Introduced macro SNOOP so that snoop can be placed in directory other than ! 44: * TARGETDIR. Changed %02d to %.2d for compatibility reasons. ! 45: * ! 46: * Revision 3.2 82/10/18 21:15:11 wft ! 47: * added function getfullRCSname(). ! 48: * ! 49: * Revision 3.1 82/10/13 16:17:37 wft ! 50: * Cleanup message is now suppressed in quiet mode. ! 51: */ ! 52: ! 53: ! 54: ! 55: ! 56: #include <sys/types.h> ! 57: #include <sys/stat.h> ! 58: #include <signal.h> ! 59: #include "rcsbase.h" ! 60: ! 61: extern char * malloc(); ! 62: extern FILE * finptr; ! 63: extern char * getfullRCSname(); ! 64: ! 65: struct hshentry dummy; /* dummy delta for reservations */ ! 66: ! 67: ! 68: struct lock * addlock(delta,who) ! 69: struct hshentry * delta; char * who; ! 70: /* Given a delta, addlock checks whether ! 71: * the delta is locked by somebody other than who. ! 72: * If so, an error message is printed, and false returned. ! 73: * If the delta is not reserved at all, a lock for it is added, ! 74: * and a pointer for the lock returned. ! 75: */ ! 76: { ! 77: struct lock * next; ! 78: ! 79: next=Locks; ! 80: while (next!=nil) { ! 81: if (cmpnum(delta->num,next->delta->num)==0) { ! 82: if (strcmp(who,next->login)==0) ! 83: return next; ! 84: /* lock exists already */ ! 85: else { ! 86: error("revision %s already locked by %s", ! 87: delta->num, next->login); ! 88: return false; ! 89: } ! 90: } else { ! 91: if (strcmp(who,next->login)==0) { ! 92: error("you already locked %s; only one lock allowed per person.", ! 93: next->delta->num); ! 94: return false; ! 95: } else { ! 96: next=next->nextlock; ! 97: } ! 98: } ! 99: } ! 100: /* not found; set up new lockblock */ ! 101: next= (struct lock *) malloc(sizeof (struct lock)); ! 102: delta->lockedby=next->login=who; ! 103: next->delta= delta; ! 104: next->nextlock=Locks; ! 105: Locks=next; ! 106: return next; ! 107: } ! 108: ! 109: ! 110: ! 111: int addsymbol(delta,name,rebind) ! 112: struct hshentry * delta; char * name; int rebind; ! 113: /* Function: adds a new symbolic name and associates it with node delta. ! 114: * If name already exists and rebind is true, the name is associated ! 115: * with the new delta; otherwise, an error message is printed and ! 116: * false returned. Returns true it successful. ! 117: */ ! 118: { register struct assoc * next; ! 119: next=Symbols; ! 120: while (next!=nil) { ! 121: if (strcmp(name,next->symbol)==0) { ! 122: if (rebind) { ! 123: next->delta=delta; ! 124: return true; ! 125: } else { ! 126: error("symbolic name %s already bound to %s", ! 127: name,next->delta->num); ! 128: return false; ! 129: } ! 130: } else next = next->nextassoc; ! 131: } ! 132: /* not found; insert new pair. */ ! 133: next = (struct assoc *) malloc(sizeof(struct assoc)); ! 134: next->symbol=name; ! 135: next->delta=delta; ! 136: next->nextassoc=Symbols; ! 137: Symbols = next; ! 138: return true; ! 139: } ! 140: ! 141: ! 142: ! 143: ! 144: int checkaccesslist(who) ! 145: char * who; ! 146: /* function: Returns true if who is the superuser, the owner of the ! 147: * file, the access list is empty, or who is on the access list. ! 148: * Prints an error message and returns false otherwise. ! 149: */ ! 150: { ! 151: register struct access * next; ! 152: struct stat statbuf; ! 153: ! 154: if ((AccessList==nil) || (strcmp(who,"root")==0)) ! 155: return true; ! 156: ! 157: next=AccessList; ! 158: do { ! 159: if (strcmp(who,next->login)==0) ! 160: return true; ! 161: next=next->nextaccess; ! 162: } while (next!=nil); ! 163: ! 164: fstat(fileno(finptr),&statbuf); /* get owner of file */ ! 165: if (getuid() == statbuf.st_uid) return true; ! 166: ! 167: error("User %s not on the access list",who); ! 168: return false; ! 169: } ! 170: ! 171: void catchsig(sig) ! 172: { ! 173: signal(sig, SIG_IGN); ! 174: diagnose("\nRCS: cleaning up\n"); ! 175: cleanup(); ! 176: exit(1); ! 177: } ! 178: ! 179: void catchints() ! 180: { ! 181: signal(SIGINT,catchsig); signal(SIGHUP,catchsig); ! 182: signal(SIGQUIT,catchsig); signal(SIGPIPE,catchsig); ! 183: signal(SIGTERM,catchsig); ! 184: } ! 185: ! 186: void ignoreints() ! 187: { ! 188: signal(SIGINT,SIG_IGN); signal(SIGHUP,SIG_IGN); ! 189: signal(SIGQUIT,SIG_IGN); signal(SIGPIPE,SIG_IGN); ! 190: signal(SIGTERM,SIG_IGN); ! 191: } ! 192: ! 193: ! 194: fastcopy(inf,outf) ! 195: FILE * inf, * outf; ! 196: /* Function: copies the remainder of file inf to outf. First copies the ! 197: * rest that is in the IO-buffer of inf character by character, and then ! 198: * copies the remainder in blocks. ! 199: */ ! 200: { char buf[BUFSIZ]; ! 201: register int rcount, wcount; ! 202: ! 203: /* write the rest of the buffer to outf */ ! 204: while ((--inf->_cnt)>=0) { ! 205: putc(*inf->_ptr++&0377,outf); ! 206: } ! 207: fflush(outf); ! 208: ! 209: /*now read the rest of the file in blocks*/ ! 210: while ((rcount=read(fileno(inf),buf,BUFSIZ))>0) { ! 211: wcount=write(fileno(outf),buf,rcount); ! 212: if (wcount!=rcount) { ! 213: faterror("write error"); ! 214: } ! 215: } ! 216: } ! 217: ! 218: ! 219: ! 220: ! 221: ! 222: ! 223: #ifdef SNOOPFILE ! 224: ! 225: #include "time.h" ! 226: extern struct tm* localtime(); ! 227: extern long time(); ! 228: ! 229: logcommand(commandname,delta, sequence,login) ! 230: char* commandname; struct hshentry * delta, * sequence[];char * login; ! 231: /* Function: start a process to write the file that ! 232: * logs the RCS command. ! 233: * Each line in the log file contains the following information: ! 234: * operation, revision(r), backward deltas applied(b), forward deltas applied(f), ! 235: * total deltas present(t), creation date of delta(d), date of operation(o), ! 236: * login of caller, full path of RCS file ! 237: */ ! 238: { ! 239: char command[200]; ! 240: char curdate[datelength]; ! 241: register int i, backward, forward; ! 242: long clock; ! 243: struct tm * tm; ! 244: ! 245: clock=time(0); ! 246: tm=localtime(&clock); ! 247: ! 248: sprintf(curdate,DATEFORM, ! 249: tm->tm_year, tm->tm_mon+1, tm->tm_mday, ! 250: tm->tm_hour, tm->tm_min, tm->tm_sec); ! 251: ! 252: i= backward=forward=0; ! 253: while(sequence[i]!=nil) { /* count deltas to be applied*/ ! 254: if (countnumflds(sequence[i]->num) == 2) ! 255: backward++; /* reverse delta */ ! 256: else forward++; /* branch delta */ ! 257: i++; ! 258: } ! 259: sprintf(command,"%s \"%s %10sr %3db %3df %3dt %sc %so %s %s\" &\n", ! 260: SNOOP, commandname,delta->num,backward,forward,TotalDeltas,delta->date, ! 261: curdate,login,getfullRCSname()); ! 262: system(command); ! 263: } ! 264: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.