|
|
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.