static void execproc(void *a) { int i, fd; Client *c; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "execproc%d", c->num); threadsetname(tmp); if(pipe(c->fd) < 0){ rerrstr(c->err, sizeof c->err); sendul(c->execpid, -1); return; } rfork(RFFDG); fd = c->fd[1]; close(c->fd[0]); dup(fd, 0); dup(fd, 1); for(i=3; i<100; i++) /* should do better */ close(i); strcpy(c->err, "exec failed"); procexecl(c->execpid, "/bin/rc", "rc", "-c", c->cmd, nil); }
char * rremove(Fid *f) { VacFile *vf, *vfp; char errbuf[80]; char *err = nil; if(!f->busy) return vtstrdup(Enotexist); vf = f->file; vfp = vacfilegetparent(vf); if(!permf(vfp, f->user, Pwrite)) { err = Eperm; goto Exit; } if(!vacfileremove(vf)) { rerrstr(errbuf, sizeof errbuf); err = errbuf; } Exit: vacfiledecref(vfp); rclunk(f); return vtstrdup(err); }
void writethread(void *v) { WriteReq wr; char err[ERRMAX]; USED(v); while(recv(writechan, &wr) == 1){ nrecv++; if(wr.p == nil) break; if(fastwrites && vtread(z, wr.score, wr.type, nil, 0) < 0){ rerrstr(err, sizeof err); if(strstr(err, "read too small")){ /* already exists */ nskip++; packetfree(wr.p); continue; } } if(vtwritepacket(z, wr.score, wr.type, wr.p) < 0) sysfatal("vtwritepacket: %r"); packetfree(wr.p); } }
char* rread(Fid *f) { char *buf; int64_t off; int cnt; VacFile *vf; char err[80]; int n; if(!f->busy) return vtstrdup(Enotexist); vf = f->file; thdr.count = 0; off = rhdr.offset; buf = thdr.data; cnt = rhdr.count; if(f->qid.type & QTDIR) n = vacdirread(f, buf, off, cnt); else if(vacfilegetmode(f->file)&ModeDevice) return vtstrdup("device"); else if(vacfilegetmode(f->file)&ModeLink) return vtstrdup("symbolic link"); else if(vacfilegetmode(f->file)&ModeNamedPipe) return vtstrdup("named pipe"); else n = vacfileread(vf, buf, cnt, off); if(n < 0) { rerrstr(err, sizeof err); return vtstrdup(err); } thdr.count = n; return 0; }
int plumbopen(char *name, int omode) { int fd; char buf[128], err[ERRMAX]; if(name[0] == '/') return open(name, omode); if(access("/mnt/plumb/send", AWRITE) < 0) return -1; snprint(buf, sizeof buf, "/mnt/plumb/%s", name); fd = open(buf, omode); if(fd >= 0) return fd; /* try creating port; used by non-standard plumb implementations */ rerrstr(err, sizeof err); fd = create(buf, omode, 0600); if(fd >= 0) return fd; errstr(err, sizeof err); return -1; }
VtSession * vtDial(char *host, int canfail) { VtSession *z; int fd; char *na; char e[ERRMAX]; if(host == nil) host = getenv("venti"); if(host == nil) host = "$venti"; if (host == nil) { if (!canfail) werrstr("no venti host set"); na = ""; fd = -1; } else { na = netmkaddr(host, 0, "venti"); fd = dial(na, 0, 0, 0); } if(fd < 0){ rerrstr(e, sizeof e); if(!canfail){ vtSetError("venti dialstring %s: %s", na, e); return nil; } } z = vtClientAlloc(); if(fd < 0) strcpy(z->fderror, e); vtSetFd(z, fd); return z; }
/* * this just proxies what the factotum tells it to. */ AuthInfo* fsfauth_proxy(CFid *fid, AuthRpc *rpc, AuthGetkey *getkey, char *params) { char *buf; int m, n, ret; AuthInfo *a; char oerr[ERRMAX]; rerrstr(oerr, sizeof oerr); werrstr("UNKNOWN AUTH ERROR"); if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){ werrstr("fauth_proxy start: %r"); return nil; } buf = malloc(AuthRpcMax); if(buf == nil) return nil; for(;;){ switch(dorpc(rpc, "read", nil, 0, getkey)){ case ARdone: free(buf); a = auth_getinfo(rpc); errstr(oerr, sizeof oerr); /* no error, restore whatever was there */ return a; case ARok: if(fswrite(fid, rpc->arg, rpc->narg) != rpc->narg){ werrstr("auth_proxy write fid: %r"); goto Error; } break; case ARphase: n = 0; memset(buf, 0, AuthRpcMax); while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){ if(atoi(rpc->arg) > AuthRpcMax) break; m = fsread(fid, buf+n, atoi(rpc->arg)-n); if(m <= 0){ if(m == 0) werrstr("auth_proxy short read: %s", buf); goto Error; } n += m; } if(ret != ARok){ werrstr("auth_proxy rpc write: %s: %r", buf); goto Error; } break; default: werrstr("auth_proxy rpc: %r"); goto Error; } } Error: free(buf); return nil; }
char* rattach(Fid *f) { /* no authentication for the momment */ VacFile *file; char err[80]; file = vacfsgetroot(fs); if(file == nil) { rerrstr(err, sizeof err); return vtstrdup(err); } f->busy = 1; f->file = file; f->qid.path = vacfilegetid(f->file); f->qid.vers = 0; f->qid.type = QTDIR; thdr.qid = f->qid; if(rhdr.uname[0]) f->user = vtstrdup(rhdr.uname); else f->user = "******"; return 0; }
char* geterrstr(void) { static char errbuf[ERRMAX]; rerrstr(errbuf, sizeof errbuf); return errbuf; }
void responderror(Req *r) { char errbuf[ERRMAX]; rerrstr(errbuf, sizeof errbuf); respond(r, errbuf); }
int errfmt(Fmt *f) { char buf[ERRMAX]; rerrstr(buf, sizeof buf); return _fmtcpy(f, buf, utflen(buf), strlen(buf)); }
static int wasintr(void) { char err[64]; rerrstr(err, sizeof err); return strstr(err, "interrupt") != 0; }
void responderrstr(Req *r) { char err[ERRMAX]; rerrstr(err, sizeof err); respond(r, err); }
/* Taken from imapdial, replaces tlsclient call with stunnel */ static int smtpdial(char *server) { int p[2]; int fd[3]; char *tmp; char *fpath; if(pipe(p) < 0) return -1; fd[0] = dup(p[0], -1); fd[1] = dup(p[0], -1); fd[2] = dup(2, -1); #ifdef PLAN9PORT tmp = smprint("%s:587", server); fpath = searchpath("stunnel3"); if (!fpath) { werrstr("stunnel not found. it is required for tls support."); return -1; } if(threadspawnl(fd, fpath, "stunnel", "-n", "smtp" , "-c", "-r", tmp, nil) < 0) { #else tmp = smprint("tcp!%s!587", server); if(threadspawnl(fd, "/bin/tlsclient", "tlsclient", tmp, nil) < 0){ #endif free(tmp); close(p[0]); close(p[1]); close(fd[0]); close(fd[1]); close(fd[2]); return -1; } free(tmp); close(p[0]); return p[1]; } int mxdial(char *addr, char *ddomain, char *gdomain) { int fd; DS ds; char err[Errlen]; addr = netmkaddr(addr, 0, "smtp"); dial_string_parse(addr, &ds); /* try connecting to destination or any of it's mail routers */ fd = callmx(&ds, addr, ddomain); /* try our mail gateway */ rerrstr(err, sizeof(err)); if(fd < 0 && gdomain && strstr(err, "can't translate") != 0) fd = dial(netmkaddr(gdomain, 0, "smtp"), 0, 0, 0); return fd; }
static void xioproc(void *a) { Channel *c; Ioproc *io; Iocall *r; c = a; if(io = mallocz(sizeof(*io), 1)){ char buf[128]; /* * open might fail, ignore it for programs like factotum * that don't use iointerrupt() anyway. */ snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); io->ctl = open(buf, OWRITE); if((io->creply = chancreate(sizeof(void*), 0)) == nil){ if(io->ctl >= 0) close(io->ctl); free(io); io = nil; } else io->c = c; } while(send(c, &io) < 0) ; if(io == nil) return; for(;;){ while(recv(io->c, &r) < 0) ; if(r == 0) break; if(io->intr){ r->ret = -1; strcpy(r->err, "interrupted"); } else if((r->ret = r->op(&r->arg)) < 0) rerrstr(r->err, sizeof r->err); qlock(io); if(io->intr){ io->intr = 0; if(io->ctl >= 0) write(io->ctl, "nointerrupt", 11); } while(send(io->creply, &r) < 0) ; qunlock(io); } if(io->ctl >= 0) close(io->ctl); chanfree(io->c); chanfree(io->creply); free(io); }
char* rcreate(Fid* fid) { VacFile *vf; uint32_t mode; if(fid->open) return vtstrdup(Eisopen); if(!fid->busy) return vtstrdup(Enotexist); if(fs->mode & ModeSnapshot) return vtstrdup(Erdonly); vf = fid->file; if(!vacfileisdir(vf)) return vtstrdup(Enotdir); if(!permf(vf, fid->user, Pwrite)) return vtstrdup(Eperm); mode = rhdr.perm & 0777; if(rhdr.perm & DMDIR){ if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND)) return vtstrdup(Emode); switch(rhdr.mode & OPERM){ default: return vtstrdup(Emode); case OEXEC: case OREAD: break; case OWRITE: case ORDWR: return vtstrdup(Eperm); } mode |= ModeDir; } vf = vacfilecreate(vf, rhdr.name, mode); if(vf == nil) { char err[80]; rerrstr(err, sizeof err); return vtstrdup(err); } vacfiledecref(fid->file); fid->file = vf; fid->qid.type = QTFILE; if(vacfileisdir(vf)) fid->qid.type = QTDIR; fid->qid.vers = vacfilegetmcount(vf); fid->qid.path = vacfilegetid(vf); thdr.qid = fid->qid; thdr.iounit = messagesize - IOHDRSZ; return 0; }
int xopenfd(Msg *m) { char errs[ERRMAX]; int n, p[2]; Conn *nc; if(pipe(p) < 0){ rerrstr(errs, sizeof errs); err(m, errs); /* XXX return here? */ } if(verbose) fprint(2, "%T xopen pipe %d %d...", p[0], p[1]); /* now we're committed. */ /* a new connection for this fid */ nc = emalloc(sizeof(Conn)); nc->internal = chancreate(sizeof(void*), 0); /* a ref for us */ nc->fdfid = m->fid; m->fid->ref++; nc->fdfid->openfd++; nc->fdmode = m->tx.mode; nc->fd = p[0]; /* a thread to tend the pipe */ threadcreate(openfdthread, nc, STACK); /* if mode is ORDWR, that openfdthread will write; start a reader */ if((m->tx.mode&3) == ORDWR){ nc = emalloc(sizeof(Conn)); nc->internal = chancreate(sizeof(void*), 0); nc->fdfid = m->fid; m->fid->ref++; nc->fdfid->openfd++; nc->fdmode = OREAD; nc->fd = dup(p[0], -1); threadcreate(openfdthread, nc, STACK); } /* steal fid from other connection */ if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0) fidput(m->fid); /* rewrite as Ropenfd */ m->rx.type = Ropenfd; n = GBIT32(m->rpkt); m->rpkt = erealloc(m->rpkt, n+4); PBIT32(m->rpkt+n, p[1]); n += 4; PBIT32(m->rpkt, n); m->rpkt[4] = Ropenfd; m->rx.unixfd = p[1]; 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); }
static void responderrstr(Req *r) { char e[ERRMAX]; *e = 0; rerrstr(e, sizeof e); respond(r, e); }
void errstr(char *buf, int n) { char tmp[IXP_ERRMAX]; strncpy(tmp, buf, sizeof tmp); rerrstr(buf, n); strncpy(thread->errbuf(), tmp, IXP_ERRMAX); errno = EPLAN9; }
/* * print a warning and continue */ void warning(char *f, void *a) { char err[65]; char buf[256]; rerrstr(err, sizeof(err)); snprint(buf, sizeof(buf), f, a); fprint(2, "runq: %s: %s\n", buf, err); }
void replyerror(Wsysmsg *m) { char err[256]; rerrstr(err, sizeof err); m->type = Rerror; m->error = err; replymsg(m); }
/* * print an error and die */ void error(char *f, void *a) { char err[Errlen]; char buf[256]; rerrstr(err, sizeof(err)); snprint(buf, sizeof(buf), f, a); fprint(2, "runq: %s: %s\n", buf, err); exits(buf); }
void ewrite(int fd, void *buf, int nbuf) { char e[ERRMAX], path[64]; if(write(fd, buf, nbuf) != nbuf){ rerrstr(e, sizeof e); strcpy(path, "unknown"); fd2path(fd, path, sizeof path); sysfatal("write %d to %s: %s", nbuf, path, e); } }
void mkdir(char *name, uint32_t mode, uint32_t mtime, char *uid, char *gid) { Dir *d, xd; int fd; char *p; char olderr[256]; fd = create(name, OREAD, mode); if(fd < 0){ rerrstr(olderr, sizeof(olderr)); if((d = dirstat(name)) == nil || !(d->mode & DMDIR)){ free(d); warn("can't make directory %q, mode %luo: %s", name, mode, olderr); return; } free(d); } close(fd); d = &xd; nulldir(d); p = utfrrune(name, L'/'); if(p) p++; else p = name; d->name = p; if(uflag){ d->uid = uid; d->gid = gid; } if(Tflag) d->mtime = mtime; d->mode = mode; if(dirwstat(name, d) < 0) warn("can't set modes for %q: %r", name); if(uflag||Tflag){ if((d = dirstat(name)) == nil){ warn("can't reread modes for %q: %r", name); return; } if(Tflag && d->mtime != mtime) warn("%q: time mismatch %lu %lu\n", name, mtime, d->mtime); if(uflag && strcmp(uid, d->uid)) warn("%q: uid mismatch %q %q", name, uid, d->uid); if(uflag && strcmp(gid, d->gid)) warn("%q: gid mismatch %q %q", name, gid, d->gid); } }
long robustread(int fd, void *buf, long sz) { long r; char err[32]; do { r = read(fd , buf, sz); if (r < 0) rerrstr(err, sizeof(err)); } while (r < 0 && robusthandler(nil, err)); return r; }
void addce(char *local) { char e[ERRMAX]; Dir d; memset(&d, 0, sizeof d); rerrstr(e, sizeof e); d.name = atom(e); d.uid = ""; d.gid = ""; insertdb(copyerr, atom(local), &d); }
/* override string error functions to do something reasonable */ void s_error(char *f, char *status) { char errbuf[Errlen]; errbuf[0] = 0; rerrstr(errbuf, sizeof(errbuf)); if(f && *f) reply("452 4.3.0 out of memory %s: %s\r\n", f, errbuf); else reply("452 4.3.0 out of memory %s\r\n", errbuf); syslog(0, "smtpd", "++Malloc failure %s [%s]", him, nci->rsys); exits(status); }
void main(int argc, char **argv) { int i, fd, n; char err[ERRMAX], *out; Biobuf *b, bout; out = nil; ARGBEGIN{ case 'o': out = EARGF(usage()); break; default: usage(); }ARGEND; if(argc==0 || argc%2) usage(); while(argc > 0){ if((b = Bopenlock(argv[0], OREAD)) == nil) sysfatal("open %s: %r", argv[0]); n = atoi(argv[1]); if(n == 0) sysfatal("0 scale given"); Breadhash(b, &hash, n); Bterm(b); argv += 2; argc -= 2; } fd = 1; if(out){ for(i=0; i<120; i++){ if((fd = create(out, OWRITE, 0666|DMEXCL)) >= 0) break; rerrstr(err, sizeof err); if(strstr(err, "file is locked")==nil && strstr(err, "exclusive lock")==nil) break; sleep(1000); } if(fd < 0) sysfatal("could not open %s: %r", out); } Binit(&bout, fd, OWRITE); Bwritehash(&bout, &hash); Bterm(&bout); exits(0); }
int notexists(char *path) { char buf[ERRMAX]; if(access(path, AEXIST) >= 0) return 0; rerrstr(buf, sizeof buf); if(strstr(buf, "entry not found") || strstr(buf, "not exist")) return 1; /* some other error, like network hangup */ return 0; }