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