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