|
|
1.1 ! root 1: /*#include <stdio.h> ! 2: #include <sys/types.h>*/ ! 3: #include "rcv.h" ! 4: ! 5: /* imports */ ! 6: extern char *mktemp(); ! 7: extern int sleep(); ! 8: extern long lseek(); ! 9: ! 10: #define FILNAMSIZ 14 ! 11: #define LOCKPREFIX "/tmp/L." ! 12: #define TMPLNAME "/tmp/mlXXXXXX" ! 13: static char lockname[FILNAMSIZ+sizeof("/tmp/")]; ! 14: static char tlockname[FILNAMSIZ+sizeof("/tmp/")]; ! 15: static char tmplname[sizeof(TMPLNAME)]; ! 16: ! 17: static void lockbotch(); ! 18: ! 19: /* ! 20: * open a file for appending. if the file doesn't exist, create it. ! 21: * return the file descriptor. ! 22: */ ! 23: appendopen(file) ! 24: char *file; ! 25: { ! 26: int out; ! 27: long lseek(); ! 28: ! 29: lock(file); ! 30: out = open(file, 2); ! 31: if (out < 0) ! 32: out = creat(file, 0666); ! 33: else ! 34: chmod(file, 0666); ! 35: lseek(out, 0L, 2); ! 36: return out; ! 37: } ! 38: ! 39: /* ! 40: * close an append only file ! 41: */ ! 42: appendclose(fd) ! 43: int fd; ! 44: { ! 45: close(fd); ! 46: unlock(); ! 47: } ! 48: ! 49: /* ! 50: * lock and open file. If the file doesn't exist and mode!=0, create it. ! 51: * return the file descriptor. ! 52: */ ! 53: ! 54: FILE * ! 55: lockopen(file, omode, pmode, uid, gid) ! 56: char *file; ! 57: char *omode; ! 58: int pmode; ! 59: { ! 60: FILE *fp; ! 61: struct stat sbuf; ! 62: int newfile; ! 63: ! 64: lock(file); ! 65: if(stat(file, &sbuf)<0) ! 66: newfile = 1; ! 67: else ! 68: newfile = 0; ! 69: fp = fopen(file, omode); ! 70: if(fp==NULL){ ! 71: unlock(); ! 72: return NULL; ! 73: } ! 74: if(newfile){ ! 75: chown(file, uid, gid); ! 76: chmod(file, pmode); ! 77: } ! 78: return fp; ! 79: } ! 80: ! 81: /* ! 82: * close and unlock a file. ! 83: */ ! 84: lockclose(fp) ! 85: FILE *fp; ! 86: { ! 87: fclose(fp); ! 88: unlock(); ! 89: } ! 90: ! 91: /* ! 92: * reopen a file without losing the lock. ! 93: */ ! 94: FILE * ! 95: lockreopen(file, omode, fp) ! 96: char *file; ! 97: char *omode; ! 98: FILE *fp; ! 99: { ! 100: return freopen(file, omode, fp); ! 101: } ! 102: ! 103: /* ! 104: * remove ALL locks ! 105: */ ! 106: cleanlocks() ! 107: { ! 108: unlock(); ! 109: } ! 110: ! 111: /* break an old lock */ ! 112: static void ! 113: lockbotch(err, file) ! 114: char *err; ! 115: char *file; ! 116: { ! 117: int fd; ! 118: char msg[128]; ! 119: char log[256]; ! 120: ! 121: sprintf(msg, "mail: problem with lock file\n"); ! 122: write(2, msg, strlen(msg)); ! 123: strcpy(log, MAILROOT); ! 124: strcat(log, "mail.log"); ! 125: if ((fd=open(log, 1)) >= 0) { ! 126: sprintf(msg, "error %s (tmp=%s lock=%s)\n", err, file, lockname); ! 127: lseek(fd, (long)0, 2); ! 128: write(fd, msg, strlen(msg)); ! 129: close(fd); ! 130: } ! 131: } ! 132: ! 133: /* Fill name with the lock name for file */ ! 134: setlname(name, file) ! 135: char *name, *file; ! 136: { ! 137: char *slashp, *strrchr(); ! 138: ! 139: (void)strcpy(name, LOCKPREFIX); ! 140: slashp = strrchr(file, '/'); ! 141: if (slashp==NULL) ! 142: strncat(name, file, sizeof(lockname)-strlen(name)-1); ! 143: else ! 144: strncat(name, slashp+1, sizeof(lockname)-strlen(name)-1); ! 145: lockname[sizeof(lockname)-1] = '\0'; ! 146: } ! 147: ! 148: /* Lock the given file */ ! 149: lock(file) ! 150: char *file; ! 151: { ! 152: int fd, i; ! 153: char pidbuf[20]; ! 154: ! 155: /* return if we are already in the middle of a lock */ ! 156: if (*lockname != '\0') { ! 157: lockbotch("double lock", tmplname); ! 158: return; ! 159: } ! 160: ! 161: /* create a temporary file */ ! 162: (void)strcpy(tmplname, TMPLNAME); ! 163: (void)mktemp(tmplname); ! 164: if ((fd=creat(tmplname, 0444))<0) { ! 165: lockbotch("tmp exists", tmplname); ! 166: return; ! 167: } ! 168: sprintf(pidbuf, "%d upas", getpid()); ! 169: write(fd, pidbuf, strlen(pidbuf)); ! 170: close(fd); ! 171: ! 172: /* Make a link to it with the lock file name. This will fail only ! 173: * if it already exists. ! 174: */ ! 175: setlname(lockname, file); ! 176: i = 0; ! 177: while (link(tmplname, lockname) < 0) { ! 178: /* File is already locked */ ! 179: sleep(2); ! 180: (void) islocked(file); /* might break a stale lock */ ! 181: if (++i > 300) { ! 182: lockbotch("breaking old lock", tmplname); ! 183: unlink(lockname); ! 184: link(tmplname, lockname); ! 185: break; ! 186: } ! 187: } ! 188: unlink(tmplname); ! 189: *tmplname = '\0'; ! 190: return; ! 191: } ! 192: ! 193: /* Return true if file has been locked by us or another program using the same ! 194: * lock name scheme. ! 195: * But remove the lock file if the locking process has gone away. ! 196: */ ! 197: int ! 198: islocked(file) ! 199: char *file; ! 200: { ! 201: struct stat stbuf; ! 202: int pid; ! 203: FILE *fp; ! 204: ! 205: setlname(tlockname, file); ! 206: if (stat(tlockname, &stbuf)==0) { ! 207: fp = fopen(tlockname, "r"); ! 208: if (fp == NULL || fscanf(fp, "%d", &pid)!=1) { ! 209: /* either we made the lock wrong, or it just went away (race) */ ! 210: lockbotch("can't read pid: breaking lock", tlockname); ! 211: fclose(fp); ! 212: unlink(tlockname); ! 213: return 0; ! 214: } ! 215: fclose(fp); ! 216: if (kill(pid, 0) == 0) ! 217: return 1; ! 218: /* locker has gone away */ ! 219: lockbotch("breaking stale lock", tlockname); ! 220: unlink(tlockname); ! 221: } ! 222: return 0; ! 223: } ! 224: ! 225: unlock() ! 226: { ! 227: if (*tmplname != '\0') { ! 228: if(unlink(tmplname)<0) ! 229: lockbotch("unlock of tmpfile failed", tmplname); ! 230: *tmplname = '\0'; ! 231: } ! 232: if (*lockname != '\0') { ! 233: if(unlink(lockname)<0) ! 234: lockbotch("unlock of lock file failed", tmplname); ! 235: *lockname = '\0'; ! 236: } ! 237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.