1: /* lock.c - universal locking routines */ 2: 3: #ifndef MMDFONLY 4: #include "../h/strings.h" 5: #else MMDFONLY 6: #include "strings.h" 7: #include "mmdfonly.h" 8: #endif MMDFONLY 9: #include <stdio.h> 10: #include "mts.h" 11: #include <sys/types.h> 12: #include <sys/stat.h> 13: 14: 15: #define NOTOK (-1) 16: #define OK 0 17: 18: #define NULLCP ((char *) 0) 19: 20: #ifdef SYS5 21: #define index strchr 22: #define rindex strrchr 23: #endif SYS5 24: 25: 26: extern int errno; 27: 28: /* */ 29: 30: int lkopen (file, access) 31: register char *file; 32: register int access; 33: { 34: mts_init ("mts"); 35: switch (lockstyle) { 36: case LOK_UNIX: 37: #ifdef BSD42 38: return f_lkopen (file, access); 39: #endif BSD42 40: 41: default: 42: return b_lkopen (file, access); 43: } 44: } 45: 46: /* */ 47: 48: static int b_lkopen (file, access) 49: register char *file; 50: register int access; 51: { 52: register int i, 53: j; 54: long curtime; 55: char curlock[BUFSIZ], 56: tmplock[BUFSIZ]; 57: struct stat st; 58: 59: if (stat (file, &st) == NOTOK) 60: return NOTOK; 61: lockname (curlock, tmplock, file, (int) st.st_dev, (int) st.st_ino); 62: 63: for (i = 0;;) 64: switch (lockit (tmplock, curlock)) { 65: case OK: 66: if ((i = open (file, access)) == NOTOK) { 67: j = errno; 68: (void) unlink (curlock); 69: errno = j; 70: } 71: timerON (curlock, i); 72: return i; 73: 74: case NOTOK: 75: if (stat (curlock, &st) == NOTOK) { 76: if (i++ > 5) 77: return NOTOK; 78: sleep (5); 79: break; 80: } 81: 82: i = 0; 83: (void) time (&curtime); 84: if (curtime < st.st_ctime + 60L) 85: sleep (5); 86: else 87: (void) unlink (curlock); 88: break; 89: } 90: } 91: 92: 93: static int lockit (tmp, file) 94: register char *tmp, 95: *file; 96: { 97: register int fd; 98: 99: if ((fd = creat (tmp, 0400)) == NOTOK) 100: return NOTOK; 101: (void) close (fd); 102: 103: fd = link (tmp, file); 104: (void) unlink (tmp); 105: 106: return (fd != NOTOK ? OK : NOTOK); 107: } 108: 109: /* */ 110: 111: static lockname (curlock, tmplock, file, dev, ino) 112: register char *curlock, 113: *tmplock, 114: *file; 115: register int dev, 116: ino; 117: { 118: register char *bp, 119: *cp; 120: 121: bp = curlock; 122: if ((cp = rindex (file, '/')) == NULL || *++cp == NULL) 123: cp = file; 124: if (lockldir == NULL || *lockldir == NULL) { 125: if (cp != file) { 126: (void) sprintf (bp, "%.*s", cp - file, file); 127: bp += strlen (bp); 128: } 129: } 130: else { 131: (void) sprintf (bp, "%s/", lockldir); 132: bp += strlen (bp); 133: } 134: 135: switch (lockstyle) { 136: case LOK_BELL: 137: default: 138: (void) sprintf (bp, "%s.lock", cp); 139: break; 140: 141: case LOK_MMDF: 142: (void) sprintf (bp, "LCK%05d.%05d", dev, ino); 143: break; 144: } 145: 146: if (tmplock) { 147: if ((cp = rindex (curlock, '/')) == NULL || *++cp == NULL) 148: (void) strcpy (tmplock, ",LCK.XXXXXX"); 149: else 150: (void) sprintf (tmplock, "%.*s,LCK.XXXXXX", 151: cp - curlock, curlock); 152: (void) unlink (mktemp (tmplock)); 153: } 154: } 155: 156: /* */ 157: 158: #ifdef BSD42 159: 160: #include <sys/file.h> 161: 162: static int f_lkopen (file, access) 163: register char *file; 164: register int access; 165: { 166: register int fd, 167: i, 168: j; 169: 170: for (i = 0; i < 5; i++) { 171: if ((fd = open (file, access | O_NDELAY)) == NOTOK) 172: return NOTOK; 173: if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK) 174: return fd; 175: j = errno; 176: (void) close (fd); 177: 178: sleep (5); 179: } 180: 181: (void) close (fd); 182: errno = j; 183: return NOTOK; 184: } 185: #endif BSD42 186: 187: /* */ 188: 189: /* ARGSUSED */ 190: 191: int lkclose (fd, file) 192: register int fd; 193: register char *file; 194: { 195: char curlock[BUFSIZ]; 196: struct stat st; 197: 198: if (fd == NOTOK) 199: return OK; 200: switch (lockstyle) { 201: case LOK_UNIX: 202: #ifdef BSD42 203: break; 204: #endif BSD42 205: 206: default: 207: if (fstat (fd, &st) != NOTOK) { 208: lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino); 209: (void) unlink (curlock); 210: timerOFF (fd); 211: } 212: } 213: 214: return (close (fd)); 215: } 216: 217: 218: /* */ 219: 220: FILE *lkfopen (file, mode) 221: register char *file, 222: *mode; 223: { 224: register int fd; 225: register FILE *fp; 226: 227: if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK) 228: return NULL; 229: 230: if ((fp = fdopen (fd, mode)) == NULL) { 231: (void) close (fd); 232: return NULL; 233: } 234: 235: return fp; 236: } 237: 238: 239: /* ARGSUSED */ 240: 241: int lkfclose (fp, file) 242: register FILE *fp; 243: register char *file; 244: { 245: char curlock[BUFSIZ]; 246: struct stat st; 247: 248: if (fp == NULL) 249: return OK; 250: 251: switch (lockstyle) { 252: case LOK_UNIX: 253: #ifdef BSD42 254: break; 255: #endif BSD42 256: 257: default: 258: if (fstat (fileno (fp), &st) != NOTOK) { 259: lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino); 260: (void) unlink (curlock); 261: } 262: } 263: 264: return (fclose (fp)); 265: } 266: 267: /* */ 268: 269: #include <signal.h> 270: 271: #define NSECS ((unsigned) 20) 272: 273: 274: struct lock { 275: int l_fd; 276: char *l_lock; 277: struct lock *l_next; 278: }; 279: #define NULLP ((struct lock *) 0) 280: 281: static struct lock *l_top = NULLP; 282: 283: 284: /* ARGSUSED */ 285: 286: static alrmser (sig) 287: int sig; 288: { 289: register int j; 290: register char *cp; 291: register struct lock *lp; 292: 293: #ifndef BSD42 294: (void) signal (SIGALRM, alrmser); 295: #endif BSD42 296: 297: for (lp = l_top; lp; lp = lp -> l_next) 298: if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK) 299: (void) close (j); 300: 301: (void) alarm (NSECS); 302: } 303: 304: /* */ 305: 306: static timerON (lock, fd) 307: char *lock; 308: int fd; 309: { 310: register struct lock *lp; 311: 312: if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP) 313: return; /* XXX */ 314: 315: lp -> l_fd = fd; 316: if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) { 317: free ((char *) lp); 318: return; /* XXX */ 319: } 320: (void) strcpy (lp -> l_lock, lock); 321: lp -> l_next = NULLP; 322: 323: if (l_top) 324: lp -> l_next = l_top -> l_next; 325: else { 326: (void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */ 327: (void) alarm (NSECS); 328: } 329: l_top = lp; 330: } 331: 332: 333: static timerOFF (fd) 334: int fd; 335: { 336: register struct lock *pp, 337: *lp; 338: 339: (void) alarm (0); 340: 341: if (l_top) { 342: for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next) 343: if (lp -> l_fd == fd) 344: break; 345: if (lp) { 346: if (lp == l_top) 347: l_top = lp -> l_next; 348: else 349: pp -> l_next = lp -> l_next; 350: 351: free (lp -> l_lock); 352: free ((char *) lp); 353: } 354: } 355: 356: if (l_top) 357: (void) alarm (NSECS); 358: }