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