/* dispose of local addresses */ int cat_mail(dest *dp, message *mp) { Biobuf *fp; char *rcvr, *cp; Mlock *l; String *tmp, *s; int i, n; s = unescapespecial(s_clone(dp->repl1)); if (nflg) { if(!xflg) print("cat >> %s\n", s_to_c(s)); else print("%s\n", s_to_c(dp->addr)); s_free(s); return 0; } for(i = 0;; i++){ l = syslock(s_to_c(s)); if(l == 0) return refuse(dp, mp, "can't lock mail file", 0, 0); fp = sysopen(s_to_c(s), "al", MBOXMODE); if(fp) break; tmp = s_append(0, s_to_c(s)); s_append(tmp, ".tmp"); fp = sysopen(s_to_c(tmp), "al", MBOXMODE); if(fp){ syslog(0, "mail", "error: used %s", s_to_c(tmp)); s_free(tmp); break; } s_free(tmp); sysunlock(l); if(i >= 5) return refuse(dp, mp, "mail file cannot be opened", 0, 0); sleep(1000); } s_free(s); n = m_print(mp, fp, (char *)0, 1); if (Bprint(fp, "\n") < 0 || Bflush(fp) < 0 || n < 0){ sysclose(fp); sysunlock(l); return refuse(dp, mp, "error writing mail file", 0, 0); } sysclose(fp); sysunlock(l); rcvr = s_to_c(dp->addr); if(cp = strrchr(rcvr, '!')) rcvr = cp+1; logdelivery(dp, rcvr, mp); return 0; }
void main(int argc, char **argv) { int bytes, fd, i; char now[30]; char *deliveredto; Addr *a; Mlock *l; ARGBEGIN{ }ARGEND; if(argc != 3) usage(); deliveredto = strrchr(argv[0], '!'); if(deliveredto == nil) deliveredto = argv[0]; else deliveredto++; a = readaddrs(argv[1], nil); if(a == nil) sysfatal("missing from address"); l = syslock(argv[2]); /* append to mbox */ i = 0; retry: fd = open(argv[2], OWRITE); if(fd < 0){ rerrstr(now, sizeof(now)); if(strstr(now, "exclusive lock") && i++ < 20){ sleep(500); /* wait for lock to go away */ goto retry; } sysfatal("opening mailbox: %r"); } seek(fd, 0, 2); strncpy(now, ctime(time(0)), sizeof(now)); now[28] = 0; if(fprint(fd, "From %s %s\n", a->val, now) < 0) sysfatal("writing mailbox: %r"); /* copy message handles escapes and any needed new lines */ bytes = appendfiletombox(0, fd); if(bytes < 0) sysfatal("writing mailbox: %r"); close(fd); sysunlock(l); /* log it */ syslog(0, "mail", "delivered %s From %s %s (%s) %d", deliveredto, a->val, now, argv[0], bytes); exits(0); }
char* plan9syncmbox(Mailbox *mb, int doplumb) { Mlock *lk; char *rv; lk = nil; if(mb->dolock){ lk = syslock(mb->path); if(lk == nil) return "can't lock mailbox"; } rv = _readmbox(mb, doplumb, lk); /* interpolate */ if(purgedeleted(mb) > 0) _writembox(mb, lk); if(lk != nil) sysunlock(lk); return rv; }
/* * load balancing */ void doload(int start) { int fd; char buf[32]; int i, n; Mlock *l; Dir *d; if(load <= 0) return; if(chdir(root) < 0){ load = 0; return; } l = syslock(loadfile); fd = open(loadfile, ORDWR); if(fd < 0){ fd = create(loadfile, 0666, ORDWR); if(fd < 0){ load = 0; sysunlock(l); return; } } /* get current load */ i = 0; n = read(fd, buf, sizeof(buf)-1); if(n >= 0){ buf[n] = 0; i = atoi(buf); } if(i < 0) i = 0; /* ignore load if file hasn't been changed in 30 minutes */ d = dirfstat(fd); if(d != nil){ if(d->mtime + 30*60 < time(0)) i = 0; free(d); } /* if load already too high, give up */ if(start && i >= load){ sysunlock(l); exits(0); } /* increment/decrement load */ if(start) i++; else i--; seek(fd, 0, 0); fprint(fd, "%d\n", i); sysunlock(l); close(fd); }
/* * try a message */ void dofile(Dir *dp) { Dir *d; int dfd, ac, dtime, efd, pid, i, etime; char *buf, *cp, **av; Waitmsg *wm; Biobuf *b; Mlock *l = nil; if(debug) fprint(2, "dofile %s\n", dp->name); /* * if no data file or empty control or data file, just clean up * the empty control file must be 15 minutes old, to minimize the * chance of a race. */ d = dirstat(file(dp->name, 'D')); if(d == nil){ syslog(0, runqlog, "no data file for %s", dp->name); remmatch(dp->name); return; } if(dp->length == 0){ if(time(0)-dp->mtime > 15*60){ syslog(0, runqlog, "empty ctl file for %s", dp->name); remmatch(dp->name); } return; } dtime = d->mtime; free(d); /* * retry times depend on the age of the errors file */ if(!Eflag && (d = dirstat(file(dp->name, 'E'))) != nil){ etime = d->mtime; free(d); if(etime - dtime < 15*60){ /* up to the first 15 minutes, every 30 seconds */ if(time(0) - etime < 30) return; } else if(etime - dtime < 60*60){ /* up to the first hour, try every 15 minutes */ if(time(0) - etime < 15*60) return; } else { /* after the first hour, try once an hour */ if(time(0) - etime < 60*60) return; } } /* * open control and data */ b = sysopen(file(dp->name, 'C'), "rl", 0660); if(b == 0) { if(debug) fprint(2, "can't open %s: %r\n", file(dp->name, 'C')); return; } dfd = open(file(dp->name, 'D'), OREAD); if(dfd < 0){ if(debug) fprint(2, "can't open %s: %r\n", file(dp->name, 'D')); Bterm(b); sysunlockfile(Bfildes(b)); return; } /* * make arg list * - read args into (malloc'd) buffer * - malloc a vector and copy pointers to args into it */ buf = malloc(dp->length+1); if(buf == 0){ warning("buffer allocation", 0); Bterm(b); sysunlockfile(Bfildes(b)); close(dfd); return; } if(Bread(b, buf, dp->length) != dp->length){ warning("reading control file %s\n", dp->name); Bterm(b); sysunlockfile(Bfildes(b)); close(dfd); free(buf); return; } buf[dp->length] = 0; av = malloc(2*sizeof(char*)); if(av == 0){ warning("argv allocation", 0); close(dfd); free(buf); Bterm(b); sysunlockfile(Bfildes(b)); return; } for(ac = 1, cp = buf; *cp; ac++){ while(isspace(*cp)) *cp++ = 0; if(*cp == 0) break; av = realloc(av, (ac+2)*sizeof(char*)); if(av == 0){ warning("argv allocation", 0); close(dfd); free(buf); Bterm(b); sysunlockfile(Bfildes(b)); return; } av[ac] = cp; while(*cp && !isspace(*cp)){ if(*cp++ == '"'){ while(*cp && *cp != '"') cp++; if(*cp) cp++; } } } av[0] = cmd; av[ac] = 0; if(!Eflag &&time(0) - dtime > giveup){ if(returnmail(av, dp->name, "Giveup") != 0) logit("returnmail failed", dp->name, av); remmatch(dp->name); goto done; } for(i = 0; i < nbad; i++){ if(strcmp(av[3], badsys[i]) == 0) goto done; } /* * Ken's fs, for example, gives us 5 minutes of inactivity before * the lock goes stale, so we have to keep reading it. */ l = keeplockalive(file(dp->name, 'C'), Bfildes(b)); /* * transfer */ pid = fork(); switch(pid){ case -1: sysunlock(l); sysunlockfile(Bfildes(b)); syslog(0, runqlog, "out of procs"); exits(0); case 0: if(debug) { fprint(2, "Starting %s", cmd); for(ac = 0; av[ac]; ac++) fprint(2, " %s", av[ac]); fprint(2, "\n"); } logit("execing", dp->name, av); close(0); dup(dfd, 0); close(dfd); close(2); efd = open(file(dp->name, 'E'), OWRITE); if(efd < 0){ if(debug) syslog(0, "runq", "open %s as %s: %r", file(dp->name,'E'), getuser()); efd = create(file(dp->name, 'E'), OWRITE, 0666); if(efd < 0){ if(debug) syslog(0, "runq", "create %s as %s: %r", file(dp->name, 'E'), getuser()); exits("could not open error file - Retry"); } } seek(efd, 0, 2); exec(cmd, av); error("can't exec %s", cmd); break; default: for(;;){ wm = wait(); if(wm == nil) error("wait failed: %r", ""); if(wm->pid == pid) break; free(wm); } if(debug) fprint(2, "wm->pid %d wm->msg == %s\n", wm->pid, wm->msg); if(wm->msg[0]){ if(debug) fprint(2, "[%d] wm->msg == %s\n", getpid(), wm->msg); syslog(0, runqlog, "message: %s\n", wm->msg); if(strstr(wm->msg, "Ignore") != nil){ /* fix for fish/chips, leave message alone */ logit("ignoring", dp->name, av); }else if(!Rflag && strstr(wm->msg, "Retry")==0){ /* return the message and remove it */ if(returnmail(av, dp->name, wm->msg) != 0) logit("returnmail failed", dp->name, av); remmatch(dp->name); } else { /* add sys to bad list and try again later */ nbad++; badsys = realloc(badsys, nbad*sizeof(char*)); badsys[nbad-1] = strdup(av[3]); } } else { /* it worked remove the message */ remmatch(dp->name); } free(wm); } done: if (l) sysunlock(l); Bterm(b); sysunlockfile(Bfildes(b)); free(buf); free(av); close(dfd); }
static void unlockSyscall(int* args) { sysunlock((Lock*)args[0]); }