|
|
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: */
109:
110: locknrm(resource, pid)
111: char *resource;
112: int pid;
113: {
114: int lockfd; /* pointer to file to read */
115: int chars_read; /* Number of characters read(). */
116:
117: char gotpid[PIDLEN + 1]; /* String value of the PID that should be stored
118: * in the lock file pointed to by *lockfp.
119: */
120: char lockfn[LOKFLEN];
121:
122: if ( resource == NULL ) {
123: #ifdef UUCP
124: plog(M_CALL, "Unlocking NULL resource.");
125: #endif /* UUCP */
126: return( 0 );
127: }
128:
129: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
130:
131: /* open the lock file for read, abort on failure */
132: if(-1 == (lockfd = (open(lockfn, 0)))){
133: #ifdef UUCP
134: printmsg(M_DEBUG, "Error opening lock file for PID verify");
135: plog(M_CALL, "Error opening lock file for PID verify");
136: #endif /* UUCP */
137: close(lockfd);
138: return(-1);
139: }
140:
141: /* read the contents of the file. Abort if empty */
142: if ( -1 == (chars_read = read(lockfd, gotpid, PIDLEN))) {
143: #ifdef UUCP
144: printmsg(M_DEBUG, "Lockrm: Error reading lock file for PID verify");
145: plog(M_CALL, "Lockrm: Error reading lock file for PID verify");
146: #endif /* UUCP */
147: close(lockfd);
148: return(-1);
149: }
150:
151: gotpid[chars_read] = '\0'; /* NUL terminate the string. */
152: if (atoi(gotpid) != pid){
153: #ifdef UUCP
154: printmsg(M_DEBUG, "Lockrm: PID verify failed. PID read was %s.",
155: gotpid);
156: plog(M_CALL, "Lockrm: PID verify failed. PID read was %s", gotpid);
157: #endif /* UUCP */
158: close(lockfd);
159: return(-1);
160: }else{
161: #ifdef UUCP
162: printmsg(M_DEBUG, "Lockrm: PID verify successful, removing lock.");
163: plog(M_CALL, "Lockrm: PID verify successful, removing lock.");
164: #endif /* UUCP */
165:
166: if ( unlink(lockfn) < 0 ) {
167: #ifdef UUCP
168: printmsg(M_DEBUG, "Lockrm: Error unlocking: %s", lockfn);
169: plog(M_CALL, "Lockrm: Error unlocking: %s", lockfn);
170: #endif /* UUCP */
171: close(lockfd);
172: return( -1 );
173: }
174: #ifdef UUCP
175: printmsg(M_DEBUG, "Just unlocked: %s", lockfn);
176: #endif /* UUCP */
177: close(lockfd);
178: return( 0 );
179: }
180: #ifdef UUCP
181: plog(M_CALL, "Unreachable code in locknrm().");
182: #endif /* UUCP */
183: }
184:
185: /*
186: * lockexist(resource) char *resource;
187: *
188: * Test for existance of a lock on the given resource.
189: *
190: * Returns: (1) Resource is locked.
191: * (0) Resource is not locked.
192: */
193:
194: lockexist(resource)
195: char *resource;
196: {
197: char lockfn[LOKFLEN];
198:
199: if ( resource == NULL )
200: return(0);
201: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
202:
203: return (!access(lockfn, AEXISTS));
204: }
205:
206:
207: /*
208: * Attempt to lock a tty device. Takes the name of the tty itself,
209: * otherwise behaves like lockit().
210: */
211: locktty(ttyname)
212: {
213: char resource[LOKFLEN];
214: char filename[LOKFLEN];
215:
216: sprintf(filename, "/dev/%s", ttyname);
217: if (NULL == gen_res_name(filename, resource)){
218: return(-1);
219: }
220: return(lockit(resource));
221:
222: } /* locktty() */
223:
224: /*
225: * Unlock a tty device. Takes the name of the tty itself,
226: * otherwise behaves like lockrm().
227: */
228: unlocktty(ttyname)
229: char *ttyname;
230: {
231: return(unlockntty(ttyname, getpid()));
232: } /* unlocktty() */
233:
234: /*
235: * Unlock a tty device. Takes the name of the tty itself,
236: * otherwise behaves like locknrm().
237: */
238: unlockntty(ttyname, pid)
239: char *ttyname;
240: int pid;
241: {
242: char resource[LOKFLEN];
243: char filename[LOKFLEN];
244:
245: sprintf(filename, "/dev/%s", ttyname);
246: if (NULL == gen_res_name(filename, resource)){
247: #ifdef UUCP
248: plog(M_CALL, "Can't generate resource for %s.", ttyname);
249: #endif /* UUCP */
250: return(-1);
251: }
252: return(locknrm(resource, pid));
253: } /* unlockntty() */
254:
255: /*
256: * Attempt to lock a tty device. Takes the name of the tty itself,
257: * otherwise behaves like lockit().
258: */
259: lockttyexist(ttyname)
260: {
261: char resource[LOKFLEN];
262: char filename[LOKFLEN];
263:
264: sprintf(filename, "/dev/%s", ttyname);
265: if (NULL == gen_res_name(filename, resource)){
266: return(0); /* Non-existent tty can not be locked :-) */
267: }
268:
269: return(lockexist(resource));
270: } /* lockttyexist() */
271:
272: /*
273: * Generates a resource name for locking, based on the major number
274: * and the lower 4 bits of the minor number of the tty device.
275: *
276: * Builds the name in buff as two "." separated decimal numbers.
277: * Returns NULL on failure, buff on success.
278: */
279: char *
280: gen_res_name(path, buff)
281: char *path;
282: char *buff;
283: {
284: struct stat sbuf;
285: int status;
286:
287: if (0 != (status = stat(path, &sbuf))) {
288: /* Can't stat the file. */
289: return (NULL);
290: }
291:
292: if (PE_DRIVER == major(sbuf.st_rdev)) {
293: sprintf(buff, "%d.%d", major(sbuf.st_rdev),
294: PE_DEVMASK & minor(sbuf.st_rdev));
295: } else {
296: sprintf(buff, "%d.%d", major(sbuf.st_rdev),
297: DEVMASK & minor(sbuf.st_rdev));
298: }
299:
300: return(buff);
301: } /* gen_res_name */
302:
303: #ifdef TEST
304: #include <stdio.h>
305:
306: #define LOCKSIG 9 /* Significant Chars of Lockable Resources. */
307:
308: main(argc, argv)
309: int argc;
310: char *argv[];
311: {
312: char buffer[LOCKSIG + 1];
313: char path[LOKFLEN];
314:
315: if (argc != 2) {
316: fprintf(stderr, "Usage: %s ttyname\n", argv[0]);
317: exit(1);
318: }
319:
320: sprintf(path, "/dev/%s", argv[1]);
321:
322: if (NULL == gen_res_name(path, buffer)) {
323: fprintf(stderr, "%s: Can't stat %s.\n", argv[0], argv[1]);
324: exit(1);
325: }
326:
327: printf("Resource to lock: %s\n", buffer);
328:
329: if (-1 == locktty(argv[1])) {
330: fprintf(stderr, "%s: Can't lock %s.\n", argv[0], argv[1]);
331: exit(1);
332: }
333:
334: printf("I think I've locked %s.\n", argv[1]);
335:
336: if (lockttyexist(argv[1])) {
337: printf("Yep, %s is locked.\n", argv[1]);
338: } else {
339: fprintf(stderr, "%s: Failed to lock %s.\n", argv[0], argv[1]);
340: exit(1);
341: }
342:
343:
344: sprintf(path, "cat /usr/spool/uucp/LCK..%s", buffer);
345: printf("Contents of lock file: ");
346: fflush(stdout);
347: system(path);
348: printf("\n");
349:
350: if (-1 == unlocktty(argv[1])) {
351: fprintf(stderr, "%s: Problem removing lock on %s.\n", argv[0], argv[1]);
352: exit(1);
353: }
354:
355: printf("I think I've unlocked %s.\n", argv[1]);
356:
357: if (lockttyexist(argv[1])) {
358: fprintf(stderr, "%s: Failed to unlock %s.\n", argv[0], argv[1]);
359: exit(1);
360: } else {
361: printf("Successfully unlocked %s.\n", argv[1]);
362: }
363:
364:
365: exit(0);
366: }
367: #endif /* TEST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.