|
|
1.1 ! root 1: /* ! 2: * RCS utilities ! 3: */ ! 4: #ifndef lint ! 5: static char rcsid[]= "$Id: rcsutil.c,v 4.3 87/10/18 10:40:22 narten Exp $ Purdue CS"; ! 6: #endif ! 7: /***************************************************************************** ! 8: ***************************************************************************** ! 9: * ! 10: * Copyright (C) 1982 by Walter F. Tichy ! 11: * Purdue University ! 12: * Computer Science Department ! 13: * West Lafayette, IN 47907 ! 14: * ! 15: * All rights reserved. No part of this software may be sold or distributed ! 16: * in any form or by any means without the prior written permission of the ! 17: * author. ! 18: * Report problems and direct all inquiries to Tichy@purdue (ARPA net). ! 19: */ ! 20: ! 21: ! 22: ! 23: /* $Log: rcsutil.c,v $ ! 24: * Revision 4.3 87/10/18 10:40:22 narten ! 25: * Updating version numbers. Changes relative to 1.1 actually ! 26: * relative to 4.1 ! 27: * ! 28: * Revision 1.3 87/09/24 14:01:01 narten ! 29: * Sources now pass through lint (if you ignore printf/sprintf/fprintf ! 30: * warnings) ! 31: * ! 32: * Revision 1.2 87/03/27 14:22:43 jenkins ! 33: * Port to suns ! 34: * ! 35: * Revision 1.1 84/01/23 14:50:43 kcs ! 36: * Initial revision ! 37: * ! 38: * Revision 4.1 83/05/10 15:53:13 wft ! 39: * Added getcaller() and findlock(). ! 40: * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal ! 41: * (needed for background jobs in older shells). Added restoreints(). ! 42: * Removed printing of full RCS path from logcommand(). ! 43: * ! 44: * Revision 3.8 83/02/15 15:41:49 wft ! 45: * Added routine fastcopy() to copy remainder of a file in blocks. ! 46: * ! 47: * Revision 3.7 82/12/24 15:25:19 wft ! 48: * added catchints(), ignoreints() for catching and ingnoring interrupts; ! 49: * fixed catchsig(). ! 50: * ! 51: * Revision 3.6 82/12/08 21:52:05 wft ! 52: * Using DATEFORM to format dates. ! 53: * ! 54: * Revision 3.5 82/12/04 18:20:49 wft ! 55: * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update ! 56: * lockedby-field. ! 57: * ! 58: * Revision 3.4 82/12/03 17:17:43 wft ! 59: * Added check to addlock() ensuring only one lock per person. ! 60: * Addlock also returns a pointer to the lock created. Deleted fancydate(). ! 61: * ! 62: * Revision 3.3 82/11/27 12:24:37 wft ! 63: * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c. ! 64: * Introduced macro SNOOP so that snoop can be placed in directory other than ! 65: * TARGETDIR. Changed %02d to %.2d for compatibility reasons. ! 66: * ! 67: * Revision 3.2 82/10/18 21:15:11 wft ! 68: * added function getfullRCSname(). ! 69: * ! 70: * Revision 3.1 82/10/13 16:17:37 wft ! 71: * Cleanup message is now suppressed in quiet mode. ! 72: */ ! 73: ! 74: ! 75: ! 76: ! 77: #include <sys/types.h> ! 78: #include <sys/stat.h> ! 79: #include <signal.h> ! 80: #include "rcsbase.h" ! 81: #include <pwd.h> ! 82: ! 83: extern char * malloc(); ! 84: extern char * bindex(); ! 85: extern FILE * finptr; ! 86: extern char * RCSfilename; ! 87: extern char * getlogin(); ! 88: extern struct passwd *getpwuid(); ! 89: ! 90: int (*oldSIGINT)(); /* saves the original value for SIGINT */ ! 91: ! 92: ! 93: ! 94: char * getcaller() ! 95: /* Function: gets the callers login from his uid. ! 96: * If the uid is root, tries to get the true login with getlogin(). ! 97: */ ! 98: { char * name; ! 99: int uid; ! 100: uid=getuid(); ! 101: if (uid==0) { ! 102: /* super user; try getlogin() to distinguish */ ! 103: name = getlogin(); ! 104: if (name!=nil && *name!='\0') ! 105: return name; ! 106: } ! 107: return(getpwuid(uid)->pw_name); ! 108: } ! 109: ! 110: ! 111: ! 112: struct hshentry * findlock(who,delete) ! 113: char * who; int delete; ! 114: /* Finds the first lock held by who and returns a pointer ! 115: * to the locked delta; also removes the lock if delete==true. ! 116: * Returns nil if there is no lock held by who. ! 117: */ ! 118: { ! 119: register struct lock * next, * trail; ! 120: struct lock dummy; ! 121: ! 122: dummy.nextlock=next=Locks; ! 123: trail = &dummy; ! 124: while (next!=nil) { ! 125: if(strcmp(who,next->login)==0) break; /*found a lock*/ ! 126: trail=next; ! 127: next=next->nextlock; ! 128: } ! 129: if (next!=nil) { ! 130: /* found one */ ! 131: if (delete) { ! 132: /* delete it */ ! 133: trail->nextlock=next->nextlock; ! 134: Locks=dummy.nextlock; ! 135: next->delta->lockedby=nil; /* reset locked-by */ ! 136: } ! 137: return next->delta; ! 138: } else return nil; ! 139: } ! 140: ! 141: ! 142: ! 143: ! 144: ! 145: ! 146: ! 147: struct lock * addlock(delta,who) ! 148: struct hshentry * delta; char * who; ! 149: /* Given a delta, addlock checks whether ! 150: * the delta is locked by somebody other than who. ! 151: * If so, an error message is printed, and false returned. ! 152: * If the delta is not reserved at all, a lock for it is added, ! 153: * and a pointer for the lock returned. ! 154: */ ! 155: { ! 156: struct lock * next; ! 157: ! 158: next=Locks; ! 159: while (next!=nil) { ! 160: if (cmpnum(delta->num,next->delta->num)==0) { ! 161: if (strcmp(who,next->login)==0) ! 162: return next; ! 163: /* lock exists already */ ! 164: else { ! 165: error("revision %s already locked by %s", ! 166: delta->num, next->login); ! 167: return false; ! 168: } ! 169: } else { ! 170: if (strcmp(who,next->login)==0) { ! 171: error("you already locked %s; only one lock allowed per person.", ! 172: next->delta->num); ! 173: return false; ! 174: } else { ! 175: next=next->nextlock; ! 176: } ! 177: } ! 178: } ! 179: /* not found; set up new lockblock */ ! 180: next= (struct lock *) malloc(sizeof (struct lock)); ! 181: delta->lockedby=next->login=who; ! 182: next->delta= delta; ! 183: next->nextlock=Locks; ! 184: Locks=next; ! 185: return next; ! 186: } ! 187: ! 188: ! 189: ! 190: int addsymbol(delta,name,rebind) ! 191: struct hshentry * delta; char * name; int rebind; ! 192: /* Function: adds a new symbolic name and associates it with node delta. ! 193: * If name already exists and rebind is true, the name is associated ! 194: * with the new delta; otherwise, an error message is printed and ! 195: * false returned. Returns true it successful. ! 196: */ ! 197: { register struct assoc * next; ! 198: next=Symbols; ! 199: while (next!=nil) { ! 200: if (strcmp(name,next->symbol)==0) { ! 201: if (rebind) { ! 202: next->delta=delta; ! 203: return true; ! 204: } else { ! 205: error("symbolic name %s already bound to %s", ! 206: name,next->delta->num); ! 207: return false; ! 208: } ! 209: } else next = next->nextassoc; ! 210: } ! 211: /* not found; insert new pair. */ ! 212: next = (struct assoc *) malloc(sizeof(struct assoc)); ! 213: next->symbol=name; ! 214: next->delta=delta; ! 215: next->nextassoc=Symbols; ! 216: Symbols = next; ! 217: return true; ! 218: } ! 219: ! 220: ! 221: ! 222: ! 223: int checkaccesslist(who) ! 224: char * who; ! 225: /* function: Returns true if who is the superuser, the owner of the ! 226: * file, the access list is empty, or who is on the access list. ! 227: * Prints an error message and returns false otherwise. ! 228: */ ! 229: { ! 230: register struct access * next; ! 231: struct stat statbuf; ! 232: ! 233: if ((AccessList==nil) || (strcmp(who,"root")==0)) ! 234: return true; ! 235: ! 236: next=AccessList; ! 237: do { ! 238: if (strcmp(who,next->login)==0) ! 239: return true; ! 240: next=next->nextaccess; ! 241: } while (next!=nil); ! 242: ! 243: VOID fstat(fileno(finptr),&statbuf); /* get owner of file */ ! 244: if (getuid() == statbuf.st_uid) return true; ! 245: ! 246: error("User %s not on the access list",who); ! 247: return false; ! 248: } ! 249: ! 250: catchsig(sig) ! 251: { ! 252: VOID signal(sig, SIG_IGN); ! 253: diagnose("\nRCS: cleaning up\n"); ! 254: VOID cleanup(); ! 255: exit(1); ! 256: } ! 257: ! 258: ! 259: void catchints() ! 260: { ! 261: cksignal(SIGINT); cksignal(SIGHUP); ! 262: cksignal(SIGQUIT); cksignal(SIGPIPE); ! 263: cksignal(SIGTERM); ! 264: } ! 265: ! 266: ! 267: cksignal(sig) ! 268: int sig; ! 269: { ! 270: if (signal(sig,SIG_IGN) != SIG_IGN) ! 271: VOID signal(sig,catchsig); ! 272: } ! 273: ! 274: void ignoreints() ! 275: { ! 276: VOID signal(SIGINT,SIG_IGN); VOID signal(SIGHUP,SIG_IGN); ! 277: VOID signal(SIGQUIT,SIG_IGN); VOID signal(SIGPIPE,SIG_IGN); ! 278: VOID signal(SIGTERM,SIG_IGN); ! 279: } ! 280: ! 281: ! 282: void restoreints() ! 283: { ! 284: if (oldSIGINT!=SIG_IGN) ! 285: VOID signal(SIGINT,catchsig); ! 286: VOID signal(SIGHUP,catchsig); VOID signal(SIGQUIT,catchsig); ! 287: VOID signal(SIGPIPE,catchsig); VOID signal(SIGTERM,catchsig); ! 288: } ! 289: ! 290: ! 291: fastcopy(inf,outf) ! 292: FILE * inf, * outf; ! 293: /* Function: copies the remainder of file inf to outf. First copies the ! 294: * rest that is in the IO-buffer of inf character by character, and then ! 295: * copies the remainder in blocks. ! 296: */ ! 297: { char buf[BUFSIZ]; ! 298: register int rcount, wcount; ! 299: ! 300: /* write the rest of the buffer to outf */ ! 301: while ((--inf->_cnt)>=0) { ! 302: VOID putc(*inf->_ptr++&0377,outf); ! 303: } ! 304: if (fflush(outf) == EOF) { ! 305: faterror("write error"); ! 306: } ! 307: ! 308: /*now read the rest of the file in blocks*/ ! 309: while ((rcount=read(fileno(inf),buf,BUFSIZ))>0) { ! 310: wcount=write(fileno(outf),buf,rcount); ! 311: if (wcount!=rcount) { ! 312: faterror("write error"); ! 313: } ! 314: } ! 315: } ! 316: ! 317: ! 318: ! 319: ! 320: ! 321: ! 322: #ifdef SNOOPFILE ! 323: ! 324: #include "time.h" ! 325: extern struct tm* localtime(); ! 326: extern long time(); ! 327: ! 328: logcommand(commandname,delta, sequence,login) ! 329: char* commandname; struct hshentry * delta, * sequence[];char * login; ! 330: /* Function: start a process to write the file that ! 331: * logs the RCS command. ! 332: * Each line in the log file contains the following information: ! 333: * operation, revision(r), backward deltas applied(b), forward deltas applied(f), ! 334: * total deltas present(t), creation date of delta(d), date of operation(o), ! 335: * login of caller, RCS file name. ! 336: */ ! 337: { ! 338: char command[200]; ! 339: char curdate[datelength]; ! 340: register int i, backward, forward; ! 341: long clock; ! 342: struct tm * tm; ! 343: ! 344: clock=time((long *)0); ! 345: tm=localtime(&clock); ! 346: ! 347: VOID sprintf(curdate,DATEFORM, ! 348: tm->tm_year, tm->tm_mon+1, tm->tm_mday, ! 349: tm->tm_hour, tm->tm_min, tm->tm_sec); ! 350: ! 351: i= backward=forward=0; ! 352: while(sequence[i]!=nil) { /* count deltas to be applied*/ ! 353: if (countnumflds(sequence[i]->num) == 2) ! 354: backward++; /* reverse delta */ ! 355: else forward++; /* branch delta */ ! 356: i++; ! 357: } ! 358: VOID sprintf(command,"%s \"%s %10sr %3db %3df %3dt %sc %so %s %s\" &\n", ! 359: SNOOP, commandname,delta->num,backward,forward,TotalDeltas,delta->date, ! 360: curdate,login,bindex(RCSfilename,'/')); ! 361: VOID system(command); ! 362: } ! 363: #endif ! 364: ! 365: ! 366: ! 367: ! 368: ! 369: ! 370: ! 371: ! 372:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.