Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include <ctype.h>
3 5cdb1798 2005-10-29 devnull
4 5cdb1798 2005-10-29 devnull void doalldirs(void);
5 5cdb1798 2005-10-29 devnull void dodir(char*);
6 5cdb1798 2005-10-29 devnull void dofile(Dir*);
7 5cdb1798 2005-10-29 devnull void rundir(char*);
8 5cdb1798 2005-10-29 devnull char* file(char*, char);
9 5cdb1798 2005-10-29 devnull void warning(char*, void*);
10 5cdb1798 2005-10-29 devnull void error(char*, void*);
11 5cdb1798 2005-10-29 devnull int returnmail(char**, char*, char*);
12 5cdb1798 2005-10-29 devnull void logit(char*, char*, char**);
13 5cdb1798 2005-10-29 devnull void doload(int);
14 5cdb1798 2005-10-29 devnull
15 5cdb1798 2005-10-29 devnull #define HUNK 32
16 5cdb1798 2005-10-29 devnull char *cmd;
17 5cdb1798 2005-10-29 devnull char *root;
18 5cdb1798 2005-10-29 devnull int debug;
19 5cdb1798 2005-10-29 devnull int giveup = 2*24*60*60;
20 5cdb1798 2005-10-29 devnull int load;
21 5cdb1798 2005-10-29 devnull int limit;
22 5cdb1798 2005-10-29 devnull
23 5cdb1798 2005-10-29 devnull /* the current directory */
24 5cdb1798 2005-10-29 devnull Dir *dirbuf;
25 5cdb1798 2005-10-29 devnull long ndirbuf = 0;
26 5cdb1798 2005-10-29 devnull int nfiles;
27 5cdb1798 2005-10-29 devnull char *curdir;
28 5cdb1798 2005-10-29 devnull
29 5cdb1798 2005-10-29 devnull char *runqlog = "runq";
30 5cdb1798 2005-10-29 devnull
31 5cdb1798 2005-10-29 devnull int *pidlist;
32 5cdb1798 2005-10-29 devnull char **badsys; /* array of recalcitrant systems */
33 5cdb1798 2005-10-29 devnull int nbad;
34 5cdb1798 2005-10-29 devnull int npid = 50;
35 5cdb1798 2005-10-29 devnull int sflag; /* single thread per directory */
36 5cdb1798 2005-10-29 devnull int aflag; /* all directories */
37 5cdb1798 2005-10-29 devnull int Eflag; /* ignore E.xxxxxx dates */
38 5cdb1798 2005-10-29 devnull int Rflag; /* no giving up, ever */
39 5cdb1798 2005-10-29 devnull
40 5cdb1798 2005-10-29 devnull void
41 5cdb1798 2005-10-29 devnull usage(void)
42 5cdb1798 2005-10-29 devnull {
43 5cdb1798 2005-10-29 devnull fprint(2, "usage: runq [-adsE] [-q dir] [-l load] [-t time] [-r nfiles] [-n nprocs] q-root cmd\n");
44 5cdb1798 2005-10-29 devnull exits("");
45 5cdb1798 2005-10-29 devnull }
46 5cdb1798 2005-10-29 devnull
47 5cdb1798 2005-10-29 devnull void
48 5cdb1798 2005-10-29 devnull main(int argc, char **argv)
49 5cdb1798 2005-10-29 devnull {
50 5cdb1798 2005-10-29 devnull char *qdir, *x;
51 5cdb1798 2005-10-29 devnull
52 5cdb1798 2005-10-29 devnull qdir = 0;
53 5cdb1798 2005-10-29 devnull
54 5cdb1798 2005-10-29 devnull ARGBEGIN{
55 5cdb1798 2005-10-29 devnull case 'l':
56 5cdb1798 2005-10-29 devnull x = ARGF();
57 5cdb1798 2005-10-29 devnull if(x == 0)
58 5cdb1798 2005-10-29 devnull usage();
59 5cdb1798 2005-10-29 devnull load = atoi(x);
60 5cdb1798 2005-10-29 devnull if(load < 0)
61 5cdb1798 2005-10-29 devnull load = 0;
62 5cdb1798 2005-10-29 devnull break;
63 5cdb1798 2005-10-29 devnull case 'E':
64 5cdb1798 2005-10-29 devnull Eflag++;
65 5cdb1798 2005-10-29 devnull break;
66 5cdb1798 2005-10-29 devnull case 'R': /* no giving up -- just leave stuff in the queue */
67 5cdb1798 2005-10-29 devnull Rflag++;
68 5cdb1798 2005-10-29 devnull break;
69 5cdb1798 2005-10-29 devnull case 'a':
70 5cdb1798 2005-10-29 devnull aflag++;
71 5cdb1798 2005-10-29 devnull break;
72 5cdb1798 2005-10-29 devnull case 'd':
73 5cdb1798 2005-10-29 devnull debug++;
74 5cdb1798 2005-10-29 devnull break;
75 5cdb1798 2005-10-29 devnull case 'r':
76 5cdb1798 2005-10-29 devnull limit = atoi(ARGF());
77 5cdb1798 2005-10-29 devnull break;
78 5cdb1798 2005-10-29 devnull case 's':
79 5cdb1798 2005-10-29 devnull sflag++;
80 5cdb1798 2005-10-29 devnull break;
81 5cdb1798 2005-10-29 devnull case 't':
82 5cdb1798 2005-10-29 devnull giveup = 60*60*atoi(ARGF());
83 5cdb1798 2005-10-29 devnull break;
84 5cdb1798 2005-10-29 devnull case 'q':
85 5cdb1798 2005-10-29 devnull qdir = ARGF();
86 5cdb1798 2005-10-29 devnull if(qdir == 0)
87 5cdb1798 2005-10-29 devnull usage();
88 5cdb1798 2005-10-29 devnull break;
89 5cdb1798 2005-10-29 devnull case 'n':
90 5cdb1798 2005-10-29 devnull npid = atoi(ARGF());
91 5cdb1798 2005-10-29 devnull if(npid == 0)
92 5cdb1798 2005-10-29 devnull usage();
93 5cdb1798 2005-10-29 devnull break;
94 5cdb1798 2005-10-29 devnull }ARGEND;
95 5cdb1798 2005-10-29 devnull
96 5cdb1798 2005-10-29 devnull if(argc != 2)
97 5cdb1798 2005-10-29 devnull usage();
98 5cdb1798 2005-10-29 devnull
99 5cdb1798 2005-10-29 devnull pidlist = malloc(npid*sizeof(*pidlist));
100 5cdb1798 2005-10-29 devnull if(pidlist == 0)
101 5cdb1798 2005-10-29 devnull error("can't malloc", 0);
102 5cdb1798 2005-10-29 devnull
103 5cdb1798 2005-10-29 devnull if(aflag == 0 && qdir == 0) {
104 5cdb1798 2005-10-29 devnull qdir = getuser();
105 5cdb1798 2005-10-29 devnull if(qdir == 0)
106 5cdb1798 2005-10-29 devnull error("unknown user", 0);
107 5cdb1798 2005-10-29 devnull }
108 5cdb1798 2005-10-29 devnull root = argv[0];
109 5cdb1798 2005-10-29 devnull cmd = argv[1];
110 5cdb1798 2005-10-29 devnull
111 5cdb1798 2005-10-29 devnull if(chdir(root) < 0)
112 5cdb1798 2005-10-29 devnull error("can't cd to %s", root);
113 5cdb1798 2005-10-29 devnull
114 5cdb1798 2005-10-29 devnull doload(1);
115 5cdb1798 2005-10-29 devnull if(aflag)
116 5cdb1798 2005-10-29 devnull doalldirs();
117 5cdb1798 2005-10-29 devnull else
118 5cdb1798 2005-10-29 devnull dodir(qdir);
119 5cdb1798 2005-10-29 devnull doload(0);
120 5cdb1798 2005-10-29 devnull exits(0);
121 5cdb1798 2005-10-29 devnull }
122 5cdb1798 2005-10-29 devnull
123 5cdb1798 2005-10-29 devnull int
124 5cdb1798 2005-10-29 devnull emptydir(char *name)
125 5cdb1798 2005-10-29 devnull {
126 5cdb1798 2005-10-29 devnull int fd;
127 5cdb1798 2005-10-29 devnull long n;
128 5cdb1798 2005-10-29 devnull char buf[2048];
129 5cdb1798 2005-10-29 devnull
130 5cdb1798 2005-10-29 devnull fd = open(name, OREAD);
131 5cdb1798 2005-10-29 devnull if(fd < 0)
132 5cdb1798 2005-10-29 devnull return 1;
133 5cdb1798 2005-10-29 devnull n = read(fd, buf, sizeof(buf));
134 5cdb1798 2005-10-29 devnull close(fd);
135 5cdb1798 2005-10-29 devnull if(n <= 0) {
136 5cdb1798 2005-10-29 devnull if(debug)
137 5cdb1798 2005-10-29 devnull fprint(2, "removing directory %s\n", name);
138 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "rmdir %s", name);
139 5cdb1798 2005-10-29 devnull sysremove(name);
140 5cdb1798 2005-10-29 devnull return 1;
141 5cdb1798 2005-10-29 devnull }
142 5cdb1798 2005-10-29 devnull return 0;
143 5cdb1798 2005-10-29 devnull }
144 5cdb1798 2005-10-29 devnull
145 5cdb1798 2005-10-29 devnull int
146 5cdb1798 2005-10-29 devnull forkltd(void)
147 5cdb1798 2005-10-29 devnull {
148 5cdb1798 2005-10-29 devnull int i;
149 5cdb1798 2005-10-29 devnull int pid;
150 5cdb1798 2005-10-29 devnull
151 5cdb1798 2005-10-29 devnull for(i = 0; i < npid; i++){
152 5cdb1798 2005-10-29 devnull if(pidlist[i] <= 0)
153 5cdb1798 2005-10-29 devnull break;
154 5cdb1798 2005-10-29 devnull }
155 5cdb1798 2005-10-29 devnull
156 5cdb1798 2005-10-29 devnull while(i >= npid){
157 5cdb1798 2005-10-29 devnull pid = waitpid();
158 5cdb1798 2005-10-29 devnull if(pid < 0){
159 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "forkltd confused");
160 5cdb1798 2005-10-29 devnull exits(0);
161 5cdb1798 2005-10-29 devnull }
162 5cdb1798 2005-10-29 devnull
163 5cdb1798 2005-10-29 devnull for(i = 0; i < npid; i++)
164 5cdb1798 2005-10-29 devnull if(pidlist[i] == pid)
165 5cdb1798 2005-10-29 devnull break;
166 5cdb1798 2005-10-29 devnull }
167 5cdb1798 2005-10-29 devnull pidlist[i] = fork();
168 5cdb1798 2005-10-29 devnull return pidlist[i];
169 5cdb1798 2005-10-29 devnull }
170 5cdb1798 2005-10-29 devnull
171 5cdb1798 2005-10-29 devnull /*
172 5cdb1798 2005-10-29 devnull * run all user directories, must be bootes (or root on unix) to do this
173 5cdb1798 2005-10-29 devnull */
174 5cdb1798 2005-10-29 devnull void
175 5cdb1798 2005-10-29 devnull doalldirs(void)
176 5cdb1798 2005-10-29 devnull {
177 5cdb1798 2005-10-29 devnull Dir *db;
178 5cdb1798 2005-10-29 devnull int fd;
179 5cdb1798 2005-10-29 devnull long i, n;
180 5cdb1798 2005-10-29 devnull
181 5cdb1798 2005-10-29 devnull
182 5cdb1798 2005-10-29 devnull fd = open(".", OREAD);
183 5cdb1798 2005-10-29 devnull if(fd == -1){
184 5cdb1798 2005-10-29 devnull warning("reading %s", root);
185 5cdb1798 2005-10-29 devnull return;
186 5cdb1798 2005-10-29 devnull }
187 5cdb1798 2005-10-29 devnull n = sysdirreadall(fd, &db);
188 5cdb1798 2005-10-29 devnull if(n > 0){
189 5cdb1798 2005-10-29 devnull for(i=0; i<n; i++){
190 5cdb1798 2005-10-29 devnull if(db[i].qid.type & QTDIR){
191 5cdb1798 2005-10-29 devnull if(emptydir(db[i].name))
192 5cdb1798 2005-10-29 devnull continue;
193 5cdb1798 2005-10-29 devnull switch(forkltd()){
194 5cdb1798 2005-10-29 devnull case -1:
195 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "out of procs");
196 5cdb1798 2005-10-29 devnull doload(0);
197 5cdb1798 2005-10-29 devnull exits(0);
198 5cdb1798 2005-10-29 devnull case 0:
199 5cdb1798 2005-10-29 devnull if(sysdetach() < 0)
200 5cdb1798 2005-10-29 devnull error("%r", 0);
201 5cdb1798 2005-10-29 devnull dodir(db[i].name);
202 5cdb1798 2005-10-29 devnull exits(0);
203 5cdb1798 2005-10-29 devnull default:
204 5cdb1798 2005-10-29 devnull break;
205 5cdb1798 2005-10-29 devnull }
206 5cdb1798 2005-10-29 devnull }
207 5cdb1798 2005-10-29 devnull }
208 5cdb1798 2005-10-29 devnull free(db);
209 5cdb1798 2005-10-29 devnull }
210 5cdb1798 2005-10-29 devnull close(fd);
211 5cdb1798 2005-10-29 devnull }
212 5cdb1798 2005-10-29 devnull
213 5cdb1798 2005-10-29 devnull /*
214 5cdb1798 2005-10-29 devnull * cd to a user directory and run it
215 5cdb1798 2005-10-29 devnull */
216 5cdb1798 2005-10-29 devnull void
217 5cdb1798 2005-10-29 devnull dodir(char *name)
218 5cdb1798 2005-10-29 devnull {
219 5cdb1798 2005-10-29 devnull curdir = name;
220 5cdb1798 2005-10-29 devnull
221 5cdb1798 2005-10-29 devnull if(chdir(name) < 0){
222 5cdb1798 2005-10-29 devnull warning("cd to %s", name);
223 5cdb1798 2005-10-29 devnull return;
224 5cdb1798 2005-10-29 devnull }
225 5cdb1798 2005-10-29 devnull if(debug)
226 5cdb1798 2005-10-29 devnull fprint(2, "running %s\n", name);
227 5cdb1798 2005-10-29 devnull rundir(name);
228 5cdb1798 2005-10-29 devnull chdir("..");
229 5cdb1798 2005-10-29 devnull }
230 5cdb1798 2005-10-29 devnull
231 5cdb1798 2005-10-29 devnull /*
232 5cdb1798 2005-10-29 devnull * run the current directory
233 5cdb1798 2005-10-29 devnull */
234 5cdb1798 2005-10-29 devnull void
235 5cdb1798 2005-10-29 devnull rundir(char *name)
236 5cdb1798 2005-10-29 devnull {
237 5cdb1798 2005-10-29 devnull int fd;
238 5cdb1798 2005-10-29 devnull long i;
239 5cdb1798 2005-10-29 devnull
240 5cdb1798 2005-10-29 devnull if(aflag && sflag)
241 5cdb1798 2005-10-29 devnull fd = sysopenlocked(".", OREAD);
242 5cdb1798 2005-10-29 devnull else
243 5cdb1798 2005-10-29 devnull fd = open(".", OREAD);
244 5cdb1798 2005-10-29 devnull if(fd == -1){
245 5cdb1798 2005-10-29 devnull warning("reading %s", name);
246 5cdb1798 2005-10-29 devnull return;
247 5cdb1798 2005-10-29 devnull }
248 5cdb1798 2005-10-29 devnull nfiles = sysdirreadall(fd, &dirbuf);
249 5cdb1798 2005-10-29 devnull if(nfiles > 0){
250 5cdb1798 2005-10-29 devnull for(i=0; i<nfiles; i++){
251 5cdb1798 2005-10-29 devnull if(dirbuf[i].name[0]!='C' || dirbuf[i].name[1]!='.')
252 5cdb1798 2005-10-29 devnull continue;
253 5cdb1798 2005-10-29 devnull dofile(&dirbuf[i]);
254 5cdb1798 2005-10-29 devnull }
255 5cdb1798 2005-10-29 devnull free(dirbuf);
256 5cdb1798 2005-10-29 devnull }
257 5cdb1798 2005-10-29 devnull if(aflag && sflag)
258 5cdb1798 2005-10-29 devnull sysunlockfile(fd);
259 5cdb1798 2005-10-29 devnull else
260 5cdb1798 2005-10-29 devnull close(fd);
261 5cdb1798 2005-10-29 devnull }
262 5cdb1798 2005-10-29 devnull
263 5cdb1798 2005-10-29 devnull /*
264 5cdb1798 2005-10-29 devnull * free files matching name in the current directory
265 5cdb1798 2005-10-29 devnull */
266 5cdb1798 2005-10-29 devnull void
267 5cdb1798 2005-10-29 devnull remmatch(char *name)
268 5cdb1798 2005-10-29 devnull {
269 5cdb1798 2005-10-29 devnull long i;
270 5cdb1798 2005-10-29 devnull
271 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "removing %s/%s", curdir, name);
272 5cdb1798 2005-10-29 devnull
273 5cdb1798 2005-10-29 devnull for(i=0; i<nfiles; i++){
274 5cdb1798 2005-10-29 devnull if(strcmp(&dirbuf[i].name[1], &name[1]) == 0)
275 5cdb1798 2005-10-29 devnull sysremove(dirbuf[i].name);
276 5cdb1798 2005-10-29 devnull }
277 5cdb1798 2005-10-29 devnull
278 5cdb1798 2005-10-29 devnull /* error file (may have) appeared after we read the directory */
279 5cdb1798 2005-10-29 devnull /* stomp on data file in case of phase error */
280 5cdb1798 2005-10-29 devnull sysremove(file(name, 'D'));
281 5cdb1798 2005-10-29 devnull sysremove(file(name, 'E'));
282 5cdb1798 2005-10-29 devnull }
283 5cdb1798 2005-10-29 devnull
284 5cdb1798 2005-10-29 devnull /*
285 5cdb1798 2005-10-29 devnull * like trylock, but we've already got the lock on fd,
286 5cdb1798 2005-10-29 devnull * and don't want an L. lock file.
287 5cdb1798 2005-10-29 devnull */
288 5cdb1798 2005-10-29 devnull static Mlock *
289 5cdb1798 2005-10-29 devnull keeplockalive(char *path, int fd)
290 5cdb1798 2005-10-29 devnull {
291 5cdb1798 2005-10-29 devnull char buf[1];
292 5cdb1798 2005-10-29 devnull Mlock *l;
293 5cdb1798 2005-10-29 devnull
294 5cdb1798 2005-10-29 devnull l = malloc(sizeof(Mlock));
295 5cdb1798 2005-10-29 devnull if(l == 0)
296 5cdb1798 2005-10-29 devnull return 0;
297 5cdb1798 2005-10-29 devnull l->fd = fd;
298 5cdb1798 2005-10-29 devnull l->name = s_new();
299 5cdb1798 2005-10-29 devnull s_append(l->name, path);
300 5cdb1798 2005-10-29 devnull
301 5cdb1798 2005-10-29 devnull /* fork process to keep lock alive until sysunlock(l) */
302 5cdb1798 2005-10-29 devnull switch(l->pid = rfork(RFPROC)){
303 5cdb1798 2005-10-29 devnull default:
304 5cdb1798 2005-10-29 devnull break;
305 5cdb1798 2005-10-29 devnull case 0:
306 5cdb1798 2005-10-29 devnull fd = l->fd;
307 5cdb1798 2005-10-29 devnull for(;;){
308 5cdb1798 2005-10-29 devnull sleep(1000*60);
309 5cdb1798 2005-10-29 devnull if(pread(fd, buf, 1, 0) < 0)
310 5cdb1798 2005-10-29 devnull break;
311 5cdb1798 2005-10-29 devnull }
312 5cdb1798 2005-10-29 devnull _exits(0);
313 5cdb1798 2005-10-29 devnull }
314 5cdb1798 2005-10-29 devnull return l;
315 5cdb1798 2005-10-29 devnull }
316 5cdb1798 2005-10-29 devnull
317 5cdb1798 2005-10-29 devnull /*
318 5cdb1798 2005-10-29 devnull * try a message
319 5cdb1798 2005-10-29 devnull */
320 5cdb1798 2005-10-29 devnull void
321 5cdb1798 2005-10-29 devnull dofile(Dir *dp)
322 5cdb1798 2005-10-29 devnull {
323 5cdb1798 2005-10-29 devnull Dir *d;
324 5cdb1798 2005-10-29 devnull int dfd, ac, dtime, efd, pid, i, etime;
325 5cdb1798 2005-10-29 devnull char *buf, *cp, **av;
326 5cdb1798 2005-10-29 devnull Waitmsg *wm;
327 5cdb1798 2005-10-29 devnull Biobuf *b;
328 5cdb1798 2005-10-29 devnull Mlock *l = nil;
329 5cdb1798 2005-10-29 devnull
330 5cdb1798 2005-10-29 devnull if(debug)
331 5cdb1798 2005-10-29 devnull fprint(2, "dofile %s\n", dp->name);
332 5cdb1798 2005-10-29 devnull /*
333 5cdb1798 2005-10-29 devnull * if no data file or empty control or data file, just clean up
334 5cdb1798 2005-10-29 devnull * the empty control file must be 15 minutes old, to minimize the
335 5cdb1798 2005-10-29 devnull * chance of a race.
336 5cdb1798 2005-10-29 devnull */
337 5cdb1798 2005-10-29 devnull d = dirstat(file(dp->name, 'D'));
338 5cdb1798 2005-10-29 devnull if(d == nil){
339 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "no data file for %s", dp->name);
340 5cdb1798 2005-10-29 devnull remmatch(dp->name);
341 5cdb1798 2005-10-29 devnull return;
342 5cdb1798 2005-10-29 devnull }
343 5cdb1798 2005-10-29 devnull if(dp->length == 0){
344 5cdb1798 2005-10-29 devnull if(time(0)-dp->mtime > 15*60){
345 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "empty ctl file for %s", dp->name);
346 5cdb1798 2005-10-29 devnull remmatch(dp->name);
347 5cdb1798 2005-10-29 devnull }
348 5cdb1798 2005-10-29 devnull return;
349 5cdb1798 2005-10-29 devnull }
350 5cdb1798 2005-10-29 devnull dtime = d->mtime;
351 5cdb1798 2005-10-29 devnull free(d);
352 5cdb1798 2005-10-29 devnull
353 5cdb1798 2005-10-29 devnull /*
354 5cdb1798 2005-10-29 devnull * retry times depend on the age of the errors file
355 5cdb1798 2005-10-29 devnull */
356 5cdb1798 2005-10-29 devnull if(!Eflag && (d = dirstat(file(dp->name, 'E'))) != nil){
357 5cdb1798 2005-10-29 devnull etime = d->mtime;
358 5cdb1798 2005-10-29 devnull free(d);
359 5cdb1798 2005-10-29 devnull if(etime - dtime < 60*60){
360 5cdb1798 2005-10-29 devnull /* up to the first hour, try every 15 minutes */
361 5cdb1798 2005-10-29 devnull if(time(0) - etime < 15*60)
362 5cdb1798 2005-10-29 devnull return;
363 5cdb1798 2005-10-29 devnull } else {
364 5cdb1798 2005-10-29 devnull /* after the first hour, try once an hour */
365 5cdb1798 2005-10-29 devnull if(time(0) - etime < 60*60)
366 5cdb1798 2005-10-29 devnull return;
367 5cdb1798 2005-10-29 devnull }
368 5cdb1798 2005-10-29 devnull
369 5cdb1798 2005-10-29 devnull }
370 5cdb1798 2005-10-29 devnull
371 5cdb1798 2005-10-29 devnull /*
372 5cdb1798 2005-10-29 devnull * open control and data
373 5cdb1798 2005-10-29 devnull */
374 5cdb1798 2005-10-29 devnull b = sysopen(file(dp->name, 'C'), "rl", 0660);
375 5cdb1798 2005-10-29 devnull if(b == 0) {
376 5cdb1798 2005-10-29 devnull if(debug)
377 5cdb1798 2005-10-29 devnull fprint(2, "can't open %s: %r\n", file(dp->name, 'C'));
378 5cdb1798 2005-10-29 devnull return;
379 5cdb1798 2005-10-29 devnull }
380 5cdb1798 2005-10-29 devnull dfd = open(file(dp->name, 'D'), OREAD);
381 5cdb1798 2005-10-29 devnull if(dfd < 0){
382 5cdb1798 2005-10-29 devnull if(debug)
383 5cdb1798 2005-10-29 devnull fprint(2, "can't open %s: %r\n", file(dp->name, 'D'));
384 5cdb1798 2005-10-29 devnull Bterm(b);
385 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
386 5cdb1798 2005-10-29 devnull return;
387 5cdb1798 2005-10-29 devnull }
388 5cdb1798 2005-10-29 devnull
389 5cdb1798 2005-10-29 devnull /*
390 5cdb1798 2005-10-29 devnull * make arg list
391 5cdb1798 2005-10-29 devnull * - read args into (malloc'd) buffer
392 5cdb1798 2005-10-29 devnull * - malloc a vector and copy pointers to args into it
393 5cdb1798 2005-10-29 devnull */
394 5cdb1798 2005-10-29 devnull buf = malloc(dp->length+1);
395 5cdb1798 2005-10-29 devnull if(buf == 0){
396 5cdb1798 2005-10-29 devnull warning("buffer allocation", 0);
397 5cdb1798 2005-10-29 devnull Bterm(b);
398 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
399 5cdb1798 2005-10-29 devnull close(dfd);
400 5cdb1798 2005-10-29 devnull return;
401 5cdb1798 2005-10-29 devnull }
402 5cdb1798 2005-10-29 devnull if(Bread(b, buf, dp->length) != dp->length){
403 5cdb1798 2005-10-29 devnull warning("reading control file %s\n", dp->name);
404 5cdb1798 2005-10-29 devnull Bterm(b);
405 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
406 5cdb1798 2005-10-29 devnull close(dfd);
407 5cdb1798 2005-10-29 devnull free(buf);
408 5cdb1798 2005-10-29 devnull return;
409 5cdb1798 2005-10-29 devnull }
410 5cdb1798 2005-10-29 devnull buf[dp->length] = 0;
411 5cdb1798 2005-10-29 devnull av = malloc(2*sizeof(char*));
412 5cdb1798 2005-10-29 devnull if(av == 0){
413 5cdb1798 2005-10-29 devnull warning("argv allocation", 0);
414 5cdb1798 2005-10-29 devnull close(dfd);
415 5cdb1798 2005-10-29 devnull free(buf);
416 5cdb1798 2005-10-29 devnull Bterm(b);
417 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
418 5cdb1798 2005-10-29 devnull return;
419 5cdb1798 2005-10-29 devnull }
420 5cdb1798 2005-10-29 devnull for(ac = 1, cp = buf; *cp; ac++){
421 5cdb1798 2005-10-29 devnull while(isspace(*cp))
422 5cdb1798 2005-10-29 devnull *cp++ = 0;
423 5cdb1798 2005-10-29 devnull if(*cp == 0)
424 5cdb1798 2005-10-29 devnull break;
425 5cdb1798 2005-10-29 devnull
426 5cdb1798 2005-10-29 devnull av = realloc(av, (ac+2)*sizeof(char*));
427 5cdb1798 2005-10-29 devnull if(av == 0){
428 5cdb1798 2005-10-29 devnull warning("argv allocation", 0);
429 5cdb1798 2005-10-29 devnull close(dfd);
430 5cdb1798 2005-10-29 devnull free(buf);
431 5cdb1798 2005-10-29 devnull Bterm(b);
432 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
433 5cdb1798 2005-10-29 devnull return;
434 5cdb1798 2005-10-29 devnull }
435 5cdb1798 2005-10-29 devnull av[ac] = cp;
436 5cdb1798 2005-10-29 devnull while(*cp && !isspace(*cp)){
437 5cdb1798 2005-10-29 devnull if(*cp++ == '"'){
438 5cdb1798 2005-10-29 devnull while(*cp && *cp != '"')
439 5cdb1798 2005-10-29 devnull cp++;
440 5cdb1798 2005-10-29 devnull if(*cp)
441 5cdb1798 2005-10-29 devnull cp++;
442 5cdb1798 2005-10-29 devnull }
443 5cdb1798 2005-10-29 devnull }
444 5cdb1798 2005-10-29 devnull }
445 5cdb1798 2005-10-29 devnull av[0] = cmd;
446 5cdb1798 2005-10-29 devnull av[ac] = 0;
447 5cdb1798 2005-10-29 devnull
448 5cdb1798 2005-10-29 devnull if(!Eflag &&time(0) - dtime > giveup){
449 5cdb1798 2005-10-29 devnull if(returnmail(av, dp->name, "Giveup") != 0)
450 5cdb1798 2005-10-29 devnull logit("returnmail failed", dp->name, av);
451 5cdb1798 2005-10-29 devnull remmatch(dp->name);
452 5cdb1798 2005-10-29 devnull goto done;
453 5cdb1798 2005-10-29 devnull }
454 5cdb1798 2005-10-29 devnull
455 5cdb1798 2005-10-29 devnull for(i = 0; i < nbad; i++){
456 5cdb1798 2005-10-29 devnull if(strcmp(av[3], badsys[i]) == 0)
457 5cdb1798 2005-10-29 devnull goto done;
458 5cdb1798 2005-10-29 devnull }
459 5cdb1798 2005-10-29 devnull
460 5cdb1798 2005-10-29 devnull /*
461 5cdb1798 2005-10-29 devnull * Ken's fs, for example, gives us 5 minutes of inactivity before
462 5cdb1798 2005-10-29 devnull * the lock goes stale, so we have to keep reading it.
463 5cdb1798 2005-10-29 devnull */
464 5cdb1798 2005-10-29 devnull l = keeplockalive(file(dp->name, 'C'), Bfildes(b));
465 5cdb1798 2005-10-29 devnull
466 5cdb1798 2005-10-29 devnull /*
467 5cdb1798 2005-10-29 devnull * transfer
468 5cdb1798 2005-10-29 devnull */
469 5cdb1798 2005-10-29 devnull pid = fork();
470 5cdb1798 2005-10-29 devnull switch(pid){
471 5cdb1798 2005-10-29 devnull case -1:
472 5cdb1798 2005-10-29 devnull sysunlock(l);
473 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
474 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "out of procs");
475 5cdb1798 2005-10-29 devnull exits(0);
476 5cdb1798 2005-10-29 devnull case 0:
477 5cdb1798 2005-10-29 devnull if(debug) {
478 5cdb1798 2005-10-29 devnull fprint(2, "Starting %s", cmd);
479 5cdb1798 2005-10-29 devnull for(ac = 0; av[ac]; ac++)
480 5cdb1798 2005-10-29 devnull fprint(2, " %s", av[ac]);
481 5cdb1798 2005-10-29 devnull fprint(2, "\n");
482 5cdb1798 2005-10-29 devnull }
483 5cdb1798 2005-10-29 devnull logit("execing", dp->name, av);
484 5cdb1798 2005-10-29 devnull close(0);
485 5cdb1798 2005-10-29 devnull dup(dfd, 0);
486 5cdb1798 2005-10-29 devnull close(dfd);
487 5cdb1798 2005-10-29 devnull close(2);
488 5cdb1798 2005-10-29 devnull efd = open(file(dp->name, 'E'), OWRITE);
489 5cdb1798 2005-10-29 devnull if(efd < 0){
490 5cdb1798 2005-10-29 devnull if(debug) syslog(0, "runq", "open %s as %s: %r", file(dp->name,'E'), getuser());
491 5cdb1798 2005-10-29 devnull efd = create(file(dp->name, 'E'), OWRITE, 0666);
492 5cdb1798 2005-10-29 devnull if(efd < 0){
493 5cdb1798 2005-10-29 devnull if(debug) syslog(0, "runq", "create %s as %s: %r", file(dp->name, 'E'), getuser());
494 5cdb1798 2005-10-29 devnull exits("could not open error file - Retry");
495 5cdb1798 2005-10-29 devnull }
496 5cdb1798 2005-10-29 devnull }
497 5cdb1798 2005-10-29 devnull seek(efd, 0, 2);
498 5cdb1798 2005-10-29 devnull exec(cmd, av);
499 5cdb1798 2005-10-29 devnull error("can't exec %s", cmd);
500 5cdb1798 2005-10-29 devnull break;
501 5cdb1798 2005-10-29 devnull default:
502 5cdb1798 2005-10-29 devnull for(;;){
503 5cdb1798 2005-10-29 devnull wm = wait();
504 5cdb1798 2005-10-29 devnull if(wm == nil)
505 5cdb1798 2005-10-29 devnull error("wait failed: %r", "");
506 5cdb1798 2005-10-29 devnull if(wm->pid == pid)
507 5cdb1798 2005-10-29 devnull break;
508 5cdb1798 2005-10-29 devnull free(wm);
509 5cdb1798 2005-10-29 devnull }
510 5cdb1798 2005-10-29 devnull if(debug)
511 5cdb1798 2005-10-29 devnull fprint(2, "wm->pid %d wm->msg == %s\n", wm->pid, wm->msg);
512 5cdb1798 2005-10-29 devnull
513 5cdb1798 2005-10-29 devnull if(wm->msg[0]){
514 5cdb1798 2005-10-29 devnull if(debug)
515 5cdb1798 2005-10-29 devnull fprint(2, "[%d] wm->msg == %s\n", getpid(), wm->msg);
516 5cc53af9 2006-02-12 devnull if(!Rflag && atoi(wm->msg) != RetryCode){
517 5cdb1798 2005-10-29 devnull /* return the message and remove it */
518 5cdb1798 2005-10-29 devnull if(returnmail(av, dp->name, wm->msg) != 0)
519 5cdb1798 2005-10-29 devnull logit("returnmail failed", dp->name, av);
520 5cdb1798 2005-10-29 devnull remmatch(dp->name);
521 5cdb1798 2005-10-29 devnull } else {
522 5cdb1798 2005-10-29 devnull /* add sys to bad list and try again later */
523 5cdb1798 2005-10-29 devnull nbad++;
524 5cdb1798 2005-10-29 devnull badsys = realloc(badsys, nbad*sizeof(char*));
525 5cdb1798 2005-10-29 devnull badsys[nbad-1] = strdup(av[3]);
526 5cdb1798 2005-10-29 devnull }
527 5cdb1798 2005-10-29 devnull } else {
528 5cdb1798 2005-10-29 devnull /* it worked remove the message */
529 5cdb1798 2005-10-29 devnull remmatch(dp->name);
530 5cdb1798 2005-10-29 devnull }
531 5cdb1798 2005-10-29 devnull free(wm);
532 5cdb1798 2005-10-29 devnull
533 5cdb1798 2005-10-29 devnull }
534 5cdb1798 2005-10-29 devnull done:
535 5cdb1798 2005-10-29 devnull if (l)
536 5cdb1798 2005-10-29 devnull sysunlock(l);
537 5cdb1798 2005-10-29 devnull Bterm(b);
538 5cdb1798 2005-10-29 devnull sysunlockfile(Bfildes(b));
539 5cdb1798 2005-10-29 devnull free(buf);
540 5cdb1798 2005-10-29 devnull free(av);
541 5cdb1798 2005-10-29 devnull close(dfd);
542 5cdb1798 2005-10-29 devnull }
543 5cdb1798 2005-10-29 devnull
544 5cdb1798 2005-10-29 devnull
545 5cdb1798 2005-10-29 devnull /*
546 5cdb1798 2005-10-29 devnull * return a name starting with the given character
547 5cdb1798 2005-10-29 devnull */
548 5cdb1798 2005-10-29 devnull char*
549 5cdb1798 2005-10-29 devnull file(char *name, char type)
550 5cdb1798 2005-10-29 devnull {
551 5cdb1798 2005-10-29 devnull static char nname[Elemlen+1];
552 5cdb1798 2005-10-29 devnull
553 5cdb1798 2005-10-29 devnull strncpy(nname, name, Elemlen);
554 5cdb1798 2005-10-29 devnull nname[Elemlen] = 0;
555 5cdb1798 2005-10-29 devnull nname[0] = type;
556 5cdb1798 2005-10-29 devnull return nname;
557 5cdb1798 2005-10-29 devnull }
558 5cdb1798 2005-10-29 devnull
559 5cdb1798 2005-10-29 devnull /*
560 5cdb1798 2005-10-29 devnull * send back the mail with an error message
561 5cdb1798 2005-10-29 devnull *
562 5cdb1798 2005-10-29 devnull * return 0 if successful
563 5cdb1798 2005-10-29 devnull */
564 5cdb1798 2005-10-29 devnull int
565 5cdb1798 2005-10-29 devnull returnmail(char **av, char *name, char *msg)
566 5cdb1798 2005-10-29 devnull {
567 5cdb1798 2005-10-29 devnull int pfd[2];
568 5cdb1798 2005-10-29 devnull Waitmsg *wm;
569 5cdb1798 2005-10-29 devnull int fd;
570 5cdb1798 2005-10-29 devnull char buf[256];
571 5cdb1798 2005-10-29 devnull char attachment[256];
572 5cdb1798 2005-10-29 devnull int i;
573 5cdb1798 2005-10-29 devnull long n;
574 5cdb1798 2005-10-29 devnull String *s;
575 5cdb1798 2005-10-29 devnull char *sender;
576 5cdb1798 2005-10-29 devnull
577 5cdb1798 2005-10-29 devnull if(av[1] == 0 || av[2] == 0){
578 5cdb1798 2005-10-29 devnull logit("runq - dumping bad file", name, av);
579 5cdb1798 2005-10-29 devnull return 0;
580 5cdb1798 2005-10-29 devnull }
581 5cdb1798 2005-10-29 devnull
582 5cdb1798 2005-10-29 devnull s = unescapespecial(s_copy(av[2]));
583 5cdb1798 2005-10-29 devnull sender = s_to_c(s);
584 5cdb1798 2005-10-29 devnull
585 5cdb1798 2005-10-29 devnull if(!returnable(sender) || strcmp(sender, "postmaster") == 0) {
586 5cdb1798 2005-10-29 devnull logit("runq - dumping p to p mail", name, av);
587 5cdb1798 2005-10-29 devnull return 0;
588 5cdb1798 2005-10-29 devnull }
589 5cdb1798 2005-10-29 devnull
590 5cdb1798 2005-10-29 devnull if(pipe(pfd) < 0){
591 5cdb1798 2005-10-29 devnull logit("runq - pipe failed", name, av);
592 5cdb1798 2005-10-29 devnull return -1;
593 5cdb1798 2005-10-29 devnull }
594 5cdb1798 2005-10-29 devnull
595 5cdb1798 2005-10-29 devnull switch(rfork(RFFDG|RFPROC|RFENVG)){
596 5cdb1798 2005-10-29 devnull case -1:
597 5cdb1798 2005-10-29 devnull logit("runq - fork failed", name, av);
598 5cdb1798 2005-10-29 devnull return -1;
599 5cdb1798 2005-10-29 devnull case 0:
600 5cdb1798 2005-10-29 devnull logit("returning", name, av);
601 5cdb1798 2005-10-29 devnull close(pfd[1]);
602 5cdb1798 2005-10-29 devnull close(0);
603 5cdb1798 2005-10-29 devnull dup(pfd[0], 0);
604 5cdb1798 2005-10-29 devnull close(pfd[0]);
605 5cdb1798 2005-10-29 devnull putenv("upasname", "/dev/null");
606 5cdb1798 2005-10-29 devnull snprint(buf, sizeof(buf), "%s/marshal", UPASBIN);
607 5cdb1798 2005-10-29 devnull snprint(attachment, sizeof(attachment), "%s", file(name, 'D'));
608 5cdb1798 2005-10-29 devnull execl(buf, "send", "-A", attachment, "-s", "permanent failure", sender, nil);
609 5cdb1798 2005-10-29 devnull error("can't exec", 0);
610 5cdb1798 2005-10-29 devnull break;
611 5cdb1798 2005-10-29 devnull default:
612 5cdb1798 2005-10-29 devnull break;
613 5cdb1798 2005-10-29 devnull }
614 5cdb1798 2005-10-29 devnull
615 5cdb1798 2005-10-29 devnull close(pfd[0]);
616 5cdb1798 2005-10-29 devnull fprint(pfd[1], "\n"); /* get out of headers */
617 5cdb1798 2005-10-29 devnull if(av[1]){
618 5cdb1798 2005-10-29 devnull fprint(pfd[1], "Your request ``%.20s ", av[1]);
619 5cdb1798 2005-10-29 devnull for(n = 3; av[n]; n++)
620 5cdb1798 2005-10-29 devnull fprint(pfd[1], "%s ", av[n]);
621 5cdb1798 2005-10-29 devnull }
622 5cdb1798 2005-10-29 devnull fprint(pfd[1], "'' failed (code %s).\nThe symptom was:\n\n", msg);
623 5cdb1798 2005-10-29 devnull fd = open(file(name, 'E'), OREAD);
624 5cdb1798 2005-10-29 devnull if(fd >= 0){
625 5cdb1798 2005-10-29 devnull for(;;){
626 5cdb1798 2005-10-29 devnull n = read(fd, buf, sizeof(buf));
627 5cdb1798 2005-10-29 devnull if(n <= 0)
628 5cdb1798 2005-10-29 devnull break;
629 5cdb1798 2005-10-29 devnull if(write(pfd[1], buf, n) != n){
630 5cdb1798 2005-10-29 devnull close(fd);
631 5cdb1798 2005-10-29 devnull goto out;
632 5cdb1798 2005-10-29 devnull }
633 5cdb1798 2005-10-29 devnull }
634 5cdb1798 2005-10-29 devnull close(fd);
635 5cdb1798 2005-10-29 devnull }
636 5cdb1798 2005-10-29 devnull close(pfd[1]);
637 5cdb1798 2005-10-29 devnull out:
638 5cdb1798 2005-10-29 devnull wm = wait();
639 5cdb1798 2005-10-29 devnull if(wm == nil){
640 5cdb1798 2005-10-29 devnull syslog(0, "runq", "wait: %r");
641 5cdb1798 2005-10-29 devnull logit("wait failed", name, av);
642 5cdb1798 2005-10-29 devnull return -1;
643 5cdb1798 2005-10-29 devnull }
644 5cdb1798 2005-10-29 devnull i = 0;
645 5cdb1798 2005-10-29 devnull if(wm->msg[0]){
646 5cdb1798 2005-10-29 devnull i = -1;
647 5cdb1798 2005-10-29 devnull syslog(0, "runq", "returnmail child: %s", wm->msg);
648 5cdb1798 2005-10-29 devnull logit("returnmail child failed", name, av);
649 5cdb1798 2005-10-29 devnull }
650 5cdb1798 2005-10-29 devnull free(wm);
651 5cdb1798 2005-10-29 devnull return i;
652 5cdb1798 2005-10-29 devnull }
653 5cdb1798 2005-10-29 devnull
654 5cdb1798 2005-10-29 devnull /*
655 5cdb1798 2005-10-29 devnull * print a warning and continue
656 5cdb1798 2005-10-29 devnull */
657 5cdb1798 2005-10-29 devnull void
658 5cdb1798 2005-10-29 devnull warning(char *f, void *a)
659 5cdb1798 2005-10-29 devnull {
660 5cdb1798 2005-10-29 devnull char err[65];
661 5cdb1798 2005-10-29 devnull char buf[256];
662 5cdb1798 2005-10-29 devnull
663 5cdb1798 2005-10-29 devnull rerrstr(err, sizeof(err));
664 5cdb1798 2005-10-29 devnull snprint(buf, sizeof(buf), f, a);
665 5cdb1798 2005-10-29 devnull fprint(2, "runq: %s: %s\n", buf, err);
666 5cdb1798 2005-10-29 devnull }
667 5cdb1798 2005-10-29 devnull
668 5cdb1798 2005-10-29 devnull /*
669 5cdb1798 2005-10-29 devnull * print an error and die
670 5cdb1798 2005-10-29 devnull */
671 5cdb1798 2005-10-29 devnull void
672 5cdb1798 2005-10-29 devnull error(char *f, void *a)
673 5cdb1798 2005-10-29 devnull {
674 5cdb1798 2005-10-29 devnull char err[Errlen];
675 5cdb1798 2005-10-29 devnull char buf[256];
676 5cdb1798 2005-10-29 devnull
677 5cdb1798 2005-10-29 devnull rerrstr(err, sizeof(err));
678 5cdb1798 2005-10-29 devnull snprint(buf, sizeof(buf), f, a);
679 5cdb1798 2005-10-29 devnull fprint(2, "runq: %s: %s\n", buf, err);
680 5cdb1798 2005-10-29 devnull exits(buf);
681 5cdb1798 2005-10-29 devnull }
682 5cdb1798 2005-10-29 devnull
683 5cdb1798 2005-10-29 devnull void
684 5cdb1798 2005-10-29 devnull logit(char *msg, char *file, char **av)
685 5cdb1798 2005-10-29 devnull {
686 5cdb1798 2005-10-29 devnull int n, m;
687 5cdb1798 2005-10-29 devnull char buf[256];
688 5cdb1798 2005-10-29 devnull
689 5cdb1798 2005-10-29 devnull n = snprint(buf, sizeof(buf), "%s/%s: %s", curdir, file, msg);
690 5cdb1798 2005-10-29 devnull for(; *av; av++){
691 5cdb1798 2005-10-29 devnull m = strlen(*av);
692 5cdb1798 2005-10-29 devnull if(n + m + 4 > sizeof(buf))
693 5cdb1798 2005-10-29 devnull break;
694 5cdb1798 2005-10-29 devnull sprint(buf + n, " '%s'", *av);
695 5cdb1798 2005-10-29 devnull n += m + 3;
696 5cdb1798 2005-10-29 devnull }
697 5cdb1798 2005-10-29 devnull syslog(0, runqlog, "%s", buf);
698 5cdb1798 2005-10-29 devnull }
699 5cdb1798 2005-10-29 devnull
700 5cdb1798 2005-10-29 devnull char *loadfile = ".runqload";
701 5cdb1798 2005-10-29 devnull
702 5cdb1798 2005-10-29 devnull /*
703 5cdb1798 2005-10-29 devnull * load balancing
704 5cdb1798 2005-10-29 devnull */
705 5cdb1798 2005-10-29 devnull void
706 5cdb1798 2005-10-29 devnull doload(int start)
707 5cdb1798 2005-10-29 devnull {
708 5cdb1798 2005-10-29 devnull int fd;
709 5cdb1798 2005-10-29 devnull char buf[32];
710 5cdb1798 2005-10-29 devnull int i, n;
711 5cdb1798 2005-10-29 devnull Mlock *l;
712 5cdb1798 2005-10-29 devnull Dir *d;
713 5cdb1798 2005-10-29 devnull
714 5cdb1798 2005-10-29 devnull if(load <= 0)
715 5cdb1798 2005-10-29 devnull return;
716 5cdb1798 2005-10-29 devnull
717 5cdb1798 2005-10-29 devnull if(chdir(root) < 0){
718 5cdb1798 2005-10-29 devnull load = 0;
719 5cdb1798 2005-10-29 devnull return;
720 5cdb1798 2005-10-29 devnull }
721 5cdb1798 2005-10-29 devnull
722 5cdb1798 2005-10-29 devnull l = syslock(loadfile);
723 5cdb1798 2005-10-29 devnull fd = open(loadfile, ORDWR);
724 5cdb1798 2005-10-29 devnull if(fd < 0){
725 5cdb1798 2005-10-29 devnull fd = create(loadfile, 0666, ORDWR);
726 5cdb1798 2005-10-29 devnull if(fd < 0){
727 5cdb1798 2005-10-29 devnull load = 0;
728 5cdb1798 2005-10-29 devnull sysunlock(l);
729 5cdb1798 2005-10-29 devnull return;
730 5cdb1798 2005-10-29 devnull }
731 5cdb1798 2005-10-29 devnull }
732 5cdb1798 2005-10-29 devnull
733 5cdb1798 2005-10-29 devnull /* get current load */
734 5cdb1798 2005-10-29 devnull i = 0;
735 5cdb1798 2005-10-29 devnull n = read(fd, buf, sizeof(buf)-1);
736 5cdb1798 2005-10-29 devnull if(n >= 0){
737 5cdb1798 2005-10-29 devnull buf[n] = 0;
738 5cdb1798 2005-10-29 devnull i = atoi(buf);
739 5cdb1798 2005-10-29 devnull }
740 5cdb1798 2005-10-29 devnull if(i < 0)
741 5cdb1798 2005-10-29 devnull i = 0;
742 5cdb1798 2005-10-29 devnull
743 5cdb1798 2005-10-29 devnull /* ignore load if file hasn't been changed in 30 minutes */
744 5cdb1798 2005-10-29 devnull d = dirfstat(fd);
745 5cdb1798 2005-10-29 devnull if(d != nil){
746 5cdb1798 2005-10-29 devnull if(d->mtime + 30*60 < time(0))
747 5cdb1798 2005-10-29 devnull i = 0;
748 5cdb1798 2005-10-29 devnull free(d);
749 5cdb1798 2005-10-29 devnull }
750 5cdb1798 2005-10-29 devnull
751 5cdb1798 2005-10-29 devnull /* if load already too high, give up */
752 5cdb1798 2005-10-29 devnull if(start && i >= load){
753 5cdb1798 2005-10-29 devnull sysunlock(l);
754 5cdb1798 2005-10-29 devnull exits(0);
755 5cdb1798 2005-10-29 devnull }
756 5cdb1798 2005-10-29 devnull
757 5cdb1798 2005-10-29 devnull /* increment/decrement load */
758 5cdb1798 2005-10-29 devnull if(start)
759 5cdb1798 2005-10-29 devnull i++;
760 5cdb1798 2005-10-29 devnull else
761 5cdb1798 2005-10-29 devnull i--;
762 5cdb1798 2005-10-29 devnull seek(fd, 0, 0);
763 5cdb1798 2005-10-29 devnull fprint(fd, "%d\n", i);
764 5cdb1798 2005-10-29 devnull sysunlock(l);
765 5cdb1798 2005-10-29 devnull close(fd);
766 5cdb1798 2005-10-29 devnull }