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