1: /*
   2:  *                     RCS utilities
   3:  */
   4: #if !defined(lint) && defined(DOSCCS)
   5: static char rcsid[]= "$Id: rcsutil.c,v 4.3.1 97/10/2 10:40:22 sms Exp $";
   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.1 97/10/2 sms
  25:  * Use unistd.h instead of declaring system functions locally
  26:  *
  27:  * Revision 4.3  87/10/18  10:40:22  narten
  28:  * Updating version numbers. Changes relative to 1.1 actually
  29:  * relative to 4.1
  30:  *
  31:  * Revision 1.3  87/09/24  14:01:01  narten
  32:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
  33:  * warnings)
  34:  *
  35:  * Revision 1.2  87/03/27  14:22:43  jenkins
  36:  * Port to suns
  37:  *
  38:  * Revision 1.1  84/01/23  14:50:43  kcs
  39:  * Initial revision
  40:  *
  41:  * Revision 4.1  83/05/10  15:53:13  wft
  42:  * Added getcaller() and findlock().
  43:  * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
  44:  * (needed for background jobs in older shells). Added restoreints().
  45:  * Removed printing of full RCS path from logcommand().
  46:  *
  47:  * Revision 3.8  83/02/15  15:41:49  wft
  48:  * Added routine fastcopy() to copy remainder of a file in blocks.
  49:  *
  50:  * Revision 3.7  82/12/24  15:25:19  wft
  51:  * added catchints(), ignoreints() for catching and ingnoring interrupts;
  52:  * fixed catchsig().
  53:  *
  54:  * Revision 3.6  82/12/08  21:52:05  wft
  55:  * Using DATEFORM to format dates.
  56:  *
  57:  * Revision 3.5  82/12/04  18:20:49  wft
  58:  * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
  59:  * lockedby-field.
  60:  *
  61:  * Revision 3.4  82/12/03  17:17:43  wft
  62:  * Added check to addlock() ensuring only one lock per person.
  63:  * Addlock also returns a pointer to the lock created. Deleted fancydate().
  64:  *
  65:  * Revision 3.3  82/11/27  12:24:37  wft
  66:  * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
  67:  * Introduced macro SNOOP so that snoop can be placed in directory other than
  68:  * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
  69:  *
  70:  * Revision 3.2  82/10/18  21:15:11  wft
  71:  * added function getfullRCSname().
  72:  *
  73:  * Revision 3.1  82/10/13  16:17:37  wft
  74:  * Cleanup message is now suppressed in quiet mode.
  75:  */
  76: 
  77: 
  78: 
  79: 
  80: #include <sys/types.h>
  81: #include <sys/stat.h>
  82: #include <signal.h>
  83: #include "rcsbase.h"
  84: #include <pwd.h>
  85: #include <unistd.h>
  86: 
  87: extern char * malloc();
  88: extern char * bindex();
  89: extern FILE * finptr;
  90: extern char * RCSfilename;
  91: 
  92: sig_t    oldSIGINT;         /* saves the original value for SIGINT */
  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

Defined functions

addsymbol defined in line 190; used 2 times
catchsig defined in line 250; used 6 times
cksignal defined in line 267; used 5 times
logcommand defined in line 328; used 2 times

Defined variables

rcsid defined in line 5; never used
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3451
Valid CSS Valid XHTML 1.0 Strict