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