|
|
1.1 root 1: /*
2: * lock.c
3: *
4: * Provide a locking mechanism for UUCP
5: */
6:
7: #include <stdio.h>
8: #include <access.h>
9: #include <sys/stat.h>
10:
11: char *gen_res_name();
12:
13: #ifdef UUCP
14: #include "dcp.h"
15: #else
16: #define SPOOLDIR "/usr/spool/uucp"
17: #define LOCKSIG 9 /* Significant Chars of Lockable Resources. */
18: #define LOKFLEN 64 /* Max Length of UUCP Lock File Name. */
19: #endif /* UUCP */
20:
21: #define LOCKDIR SPOOLDIR
22: #define LOCKPRE "LCK.."
23: #define PIDLEN 6 /* Maximum length of string representing a PID. */
24:
25: /* There is a special version of DEVMASK for the PE multiport driver
26: * because of the peculiar way it uses the minor device number. For
27: * all other drivers, the lower 5 bits describe the physical port--
28: * the upper 3 bits give attributes for the port.
29: */
30:
31: #define PE_DRIVER 21 /* Major device number for the PE driver. */
32: #define PE_DEVMASK 0x3f /* PE driver minor device mask. */
33: #define DEVMASK 0x1f /* Minor device mask. */
34:
35:
36: /*
37: * lockit(resource) char *resource;
38: *
39: * Lock the given resource.
40: * Returns (-1) if already locked or error in locking.
41: * ( 0) if all ok, resource locked.
42: */
43:
44: lockit(resource)
45: char *resource;
46: {
47:
48: int lockfd;
49: char lockfn[LOKFLEN];
50: char pidstring[PIDLEN];
51:
52: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
53: if ( (access(lockfn, AEXISTS) == 0) ||
54: ((lockfd=creat(lockfn, 0644)) == -1) ) {
55: #ifdef UUCP
56: printmsg(M_DEBUG, "Can't lock: %s", lockfn);
57: #endif /* UUCP */
58: return( -1 );
59: }
60: #ifdef UUCP
61: printmsg(M_DEBUG, "Just created lock: %s", lockfn);
62: #endif /* UUCP */
63: sprintf(pidstring, "%d", getpid());
64: if(-1 == write(lockfd, pidstring, strlen(pidstring))){
65: close(lockfd);
66: unlink(lockfn);
67: return(-1);
68: }
69:
70: close(lockfd);
71: return( 0 );
72: }
73:
74: /*
75: * lockrm(resource) char *resource;
76: *
77: * Simply remove the lock on the given resource.
78: * Returns (-1) if not locked or error in unlocking.
79: * ( 0) if all ok, resource lock removed.
80: *
81: *
82: * Open the lock file for read operations to try to read the PID
83: * stored in the file. If the open fails, abort. If the read fails,
84: * abort. If the read PID does not match our PID, abort. We will only
85: * remove the lock if our PID matches the PID written to the file.
86: */
87:
88: lockrm(resource)
89: char *resource;
90: {
91: return(locknrm(resource, getpid()));
92: }
93:
94:
95: /*
96: * locknrm(resource, pid) char *resource;
97: *
98: * Remove the lock on the given resource, using pid as the process id to
99: * look for.
100: *
101: * Returns (-1) if not locked or error in unlocking.
102: * ( 0) if all ok, resource lock removed.
103: *
104: * Open the lock file for read operations to try to read the PID
105: * stored in the file. If the open fails, abort. If the read fails,
106: * abort. If the read PID does not match our PID, abort. We will only
107: * remove the lock if the passed matches the PID written to the file,
108: * or if the pid we are passed was 0.
109: *
110: */
111:
112: locknrm(resource, pid)
113: char *resource;
114: int pid;
115: {
116: int lockfd; /* pointer to file to read */
117: int chars_read; /* Number of characters read(). */
118:
119: char gotpid[PIDLEN + 1]; /* String value of the PID that should be stored
120: * in the lock file pointed to by *lockfp.
121: */
122: char lockfn[LOKFLEN];
123:
124: if ( resource == NULL ) {
125: #ifdef UUCP
126: plog(M_CALL, "Unlocking NULL resource.");
127: #endif /* UUCP */
128: return( 0 );
129: }
130:
131: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
132:
133: /* open the lock file for read, abort on failure */
134: if(-1 == (lockfd = (open(lockfn, 0)))){
135: #ifdef UUCP
136: printmsg(M_DEBUG, "Error opening lock file for PID verify");
137: plog(M_CALL, "Error opening lock file for PID verify");
138: #endif /* UUCP */
139: close(lockfd);
140: return(-1);
141: }
142:
143: /* read the contents of the file. Abort if empty */
144: if ( -1 == (chars_read = read(lockfd, gotpid, PIDLEN))) {
145: #ifdef UUCP
146: printmsg(M_DEBUG, "Lockrm: Error reading lock file for PID verify");
147: plog(M_CALL, "Lockrm: Error reading lock file for PID verify");
148: #endif /* UUCP */
149: close(lockfd);
150: return(-1);
151: }
152:
153: gotpid[chars_read] = '\0'; /* NUL terminate the string. */
154: if ( (0 != pid) && (atoi(gotpid) != pid) ){
155: #ifdef UUCP
156: printmsg(M_DEBUG, "Lockrm: PID verify failed. PID read was %s.",
157: gotpid);
158: plog(M_CALL, "Lockrm: PID verify failed. PID read was %s", gotpid);
159: #endif /* UUCP */
160: close(lockfd);
161: return(-1);
162: } else {
163: #ifdef UUCP
164: printmsg(M_DEBUG, "Lockrm: PID verify successful, removing lock.");
165: plog(M_CALL, "Lockrm: PID verify successful, removing lock.");
166: #endif /* UUCP */
167:
168: if ( unlink(lockfn) < 0 ) {
169: #ifdef UUCP
170: printmsg(M_DEBUG, "Lockrm: Error unlocking: %s", lockfn);
171: plog(M_CALL, "Lockrm: Error unlocking: %s", lockfn);
172: #endif /* UUCP */
173: close(lockfd);
174: return( -1 );
175: }
176: #ifdef UUCP
177: printmsg(M_DEBUG, "Just unlocked: %s", lockfn);
178: #endif /* UUCP */
179: close(lockfd);
180: return( 0 );
181: }
182: #ifdef UUCP
183: plog(M_CALL, "Unreachable code in locknrm().");
184: #endif /* UUCP */
185: }
186:
187: /*
188: * lockexist(resource) char *resource;
189: *
190: * Test for existance of a lock on the given resource.
191: *
192: * Returns: (1) Resource is locked.
193: * (0) Resource is not locked.
194: */
195:
196: lockexist(resource)
197: char *resource;
198: {
199: char lockfn[LOKFLEN];
200:
201: if ( resource == NULL )
202: return(0);
203: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
204:
205: return (!access(lockfn, AEXISTS));
206: }
207:
208:
209: /*
210: * Attempt to lock a tty device. Takes the name of the tty itself,
211: * otherwise behaves like lockit().
212: */
213: locktty(ttyname)
214: {
215: char resource[LOKFLEN];
216: char filename[LOKFLEN];
217:
218: sprintf(filename, "/dev/%s", ttyname);
219: if (NULL == gen_res_name(filename, resource)){
220: return(-1);
221: }
222: return(lockit(resource));
223:
224: } /* locktty() */
225:
226: /*
227: * Unlock a tty device. Takes the name of the tty itself,
228: * otherwise behaves like lockrm().
229: */
230: unlocktty(ttyname)
231: char *ttyname;
232: {
233: return(unlockntty(ttyname, getpid()));
234: } /* unlocktty() */
235:
236: /*
237: * Unlock a tty device. Takes the name of the tty itself,
238: * otherwise behaves like locknrm().
239: */
240: unlockntty(ttyname, pid)
241: char *ttyname;
242: int pid;
243: {
244: char resource[LOKFLEN];
245: char filename[LOKFLEN];
246:
247: sprintf(filename, "/dev/%s", ttyname);
248: if (NULL == gen_res_name(filename, resource)){
249: #ifdef UUCP
250: plog(M_CALL, "Can't generate resource for %s.", ttyname);
251: #endif /* UUCP */
252: return(-1);
253: }
254: return(locknrm(resource, pid));
255: } /* unlockntty() */
256:
257: /*
258: * Attempt to lock a tty device. Takes the name of the tty itself,
259: * otherwise behaves like lockit().
260: */
261: lockttyexist(ttyname)
262: {
263: char resource[LOKFLEN];
264: char filename[LOKFLEN];
265:
266: sprintf(filename, "/dev/%s", ttyname);
267: if (NULL == gen_res_name(filename, resource)){
268: return(0); /* Non-existent tty can not be locked :-) */
269: }
270:
271: return(lockexist(resource));
272: } /* lockttyexist() */
273:
274: /*
275: * Generates a resource name for locking, based on the major number
276: * and the lower 4 bits of the minor number of the tty device.
277: *
278: * Builds the name in buff as two "." separated decimal numbers.
279: * Returns NULL on failure, buff on success.
280: */
281: char *
282: gen_res_name(path, buff)
283: char *path;
284: char *buff;
285: {
286: struct stat sbuf;
287: int status;
288:
289: if (0 != (status = stat(path, &sbuf))) {
290: /* Can't stat the file. */
291: return (NULL);
292: }
293:
294: if (PE_DRIVER == major(sbuf.st_rdev)) {
295: sprintf(buff, "%d.%d", major(sbuf.st_rdev),
296: PE_DEVMASK & minor(sbuf.st_rdev));
297: } else {
298: sprintf(buff, "%d.%d", major(sbuf.st_rdev),
299: DEVMASK & minor(sbuf.st_rdev));
300: }
301:
302: return(buff);
303: } /* gen_res_name */
304:
305: #ifdef TEST
306: #include <stdio.h>
307:
308: #define LOCKSIG 9 /* Significant Chars of Lockable Resources. */
309:
310: main(argc, argv)
311: int argc;
312: char *argv[];
313: {
314: char buffer[LOCKSIG + 1];
315: char path[LOKFLEN];
316:
317: if (argc != 2) {
318: fprintf(stderr, "Usage: %s ttyname\n", argv[0]);
319: exit(1);
320: }
321:
322: sprintf(path, "/dev/%s", argv[1]);
323:
324: if (NULL == gen_res_name(path, buffer)) {
325: fprintf(stderr, "%s: Can't stat %s.\n", argv[0], argv[1]);
326: exit(1);
327: }
328:
329: printf("Resource to lock: %s\n", buffer);
330:
331: if (-1 == locktty(argv[1])) {
332: fprintf(stderr, "%s: Can't lock %s.\n", argv[0], argv[1]);
333: exit(1);
334: }
335:
336: printf("I think I've locked %s.\n", argv[1]);
337:
338: if (lockttyexist(argv[1])) {
339: printf("Yep, %s is locked.\n", argv[1]);
340: } else {
341: fprintf(stderr, "%s: Failed to lock %s.\n", argv[0], argv[1]);
342: exit(1);
343: }
344:
345:
346: sprintf(path, "cat /usr/spool/uucp/LCK..%s", buffer);
347: printf("Contents of lock file: ");
348: fflush(stdout);
349: system(path);
350: printf("\n");
351:
352: if (-1 == unlocktty(argv[1])) {
353: fprintf(stderr, "%s: Problem removing lock on %s.\n", argv[0], argv[1]);
354: exit(1);
355: }
356:
357: printf("I think I've unlocked %s.\n", argv[1]);
358:
359: if (lockttyexist(argv[1])) {
360: fprintf(stderr, "%s: Failed to unlock %s.\n", argv[0], argv[1]);
361: exit(1);
362: } else {
363: printf("Successfully unlocked %s.\n", argv[1]);
364: }
365:
366:
367: exit(0);
368: }
369: #endif /* TEST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.