|
|
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 "/usr/spool/locks/L." ! 13: #define TMPLNAME "/usr/spool/locks/mlXXXXXX" ! 14: static char lockname[FILNAMSIZ+sizeof("/usr/spool/locks/")]; ! 15: static char tlockname[FILNAMSIZ+sizeof("/usr/spool/locks/")]; ! 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. Remove the lock if it too old. ! 196: */ ! 197: int ! 198: islocked(file) ! 199: char *file; ! 200: { ! 201: struct stat stbuf; ! 202: ! 203: setlname(tlockname, file); ! 204: if (stat(tlockname, &stbuf)<0) ! 205: return 0; ! 206: if(time(0) - stbuf.st_mtime > 15*60) { ! 207: lockbotch("old lock: breaking lock", tlockname); ! 208: unlink(tlockname); ! 209: return 0; ! 210: } ! 211: return 1; ! 212: } ! 213: ! 214: unlock() ! 215: { ! 216: if (*tmplname != '\0') { ! 217: if(unlink(tmplname)<0) ! 218: lockbotch("unlock of tmpfile failed", tmplname); ! 219: *tmplname = '\0'; ! 220: } ! 221: if (*lockname != '\0') { ! 222: if(unlink(lockname)<0) ! 223: lockbotch("unlock of lock file failed", tmplname); ! 224: *lockname = '\0'; ! 225: } ! 226: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.