|
|
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.