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