static char * wraptls(void) { TLSconn *c; Thumbprint *goodcerts; char *h, *err; int fd; uchar hash[SHA1dlen]; goodcerts = nil; err = Giveup; c = mallocz(sizeof(*c), 1); if (c == nil) return err; fd = tlsClient(Bfildes(&bout), c); if (fd < 0) { syslog(0, "smtp", "tlsClient to %q: %r", ddomain); goto Out; } Bterm(&bout); Binit(&bout, fd, OWRITE); fd = dup(fd, Bfildes(&bin)); Bterm(&bin); Binit(&bin, fd, OREAD); goodcerts = initThumbprints(smtpthumbs, smtpexclthumbs); if (goodcerts == nil) { syslog(0, "smtp", "bad thumbprints in %s", smtpthumbs); goto Out; } /* compute sha1 hash of remote's certificate, see if we know it */ sha1(c->cert, c->certlen, hash, nil); if (!okThumbprint(hash, goodcerts)) { /* TODO? if not excluded, add hash to thumb list */ h = malloc(2*sizeof hash + 1); if (h == nil) goto Out; enc16(h, 2*sizeof hash + 1, hash, sizeof hash); syslog(0, "smtp", "remote cert. has bad thumbprint: x509 sha1=%s server=%q", h, ddomain); free(h); goto Out; } syslog(0, "smtp", "started TLS to %q", ddomain); err = nil; Out: if(goodcerts != nil) freeThumbprints(goodcerts); free(c->cert); free(c->sessionID); free(c); return err; }
/* * read a remote file */ int readfile1(Node *node) { Biobuf *bp; char buf[4*1024]; long off; int n; int tries; if(changedir(node->parent) < 0) return -1; for(tries = 0; tries < 4; tries++){ switch(data(OREAD, &bp, "RETR", s_to_c(node->remname))){ case Extra: break; case TempFail: continue; default: return seterr(nosuchfile); } off = 0; while((n = read(Bfildes(bp), buf, sizeof buf)) > 0){ if(filewrite(node, buf, off, n) != n){ off = -1; break; } off += n; } if(off < 0) return -1; /* make sure a file gets created even for a zero length file */ if(off == 0) filewrite(node, buf, 0, 0); close(Bfildes(bp)); switch(getreply(&ctlin, msg, sizeof(msg), 0)){ case Success: return off; case TempFail: continue; default: return seterr(nosuchfile); } } return seterr(nosuchfile); }
/* * send an x display location to the other side */ int xlocsub(Biobuf *bp, uchar *sub, int n) { char buf[64]; char *term; char *p = buf; if(n < 1) return 0; if(sub[0] == 1){ *p++ = Iac; *p++ = Sb; *p++ = opt[Xloc].code; *p++ = 0; term = getenv("XDISP"); if(term == 0 || *term == 0) term = "unknown"; strncpy(p, term, p - buf - 2); p += strlen(term); *p++ = Iac; *p++ = Se; return iwrite(Bfildes(bp), buf, p-buf); } return 0; }
/* * send terminal type to the other side */ int termsub(Biobuf *bp, uchar *sub, int n) { char buf[64]; char *term; char *p = buf; if(n < 1) return 0; if(sub[0] == 1){ *p++ = Iac; *p++ = Sb; *p++ = opt[Term].code; *p++ = 0; term = getenv("TERM"); if(term == 0 || *term == 0) term = "p9win"; strncpy(p, term, sizeof(buf) - (p - buf) - 2); buf[sizeof(buf)-2] = 0; p += strlen(p); *p++ = Iac; *p++ = Se; return iwrite(Bfildes(bp), buf, p-buf); } return 0; }
int menu(Biobuf *bp, int net) { char *cp; int done; comm->stopped = 1; rawoff(); fprint(2, ">>> "); for(done = 0; !done; ){ cp = Brdline(bp, '\n'); if(cp == 0){ comm->stopped = 0; return -1; } cp[Blinelen(bp)-1] = 0; switch(*cp){ case '!': system(Bfildes(bp), cp+1); done = 1; break; case '.': done = 1; break; case 'q': comm->stopped = 0; return -1; case 'o': switch(*(cp+1)){ case 'd': send3(net, Iac, Do, atoi(cp+2)); break; case 'w': send3(net, Iac, Will, atoi(cp+2)); break; } break; case 'r': comm->returns = !comm->returns; done = 1; break; case 'i': send2(net, Iac, Interrupt); break; case 'b': send2(net, Iac, Break); break; default: fprint(2, STDHELP); break; } if(!done) fprint(2, ">>> "); } rawon(); comm->stopped = 0; return 0; }
void contentinit(void) { static Biobuf *b = nil; static Qid qid; char *file, *s; Suffix *this; file = "/sys/lib/mimetype"; if(b == nil){ /* first time */ b = Bopen(file, OREAD); if(b == nil) sysfatal("can't read from %s", file); } if(updateQid(Bfildes(b), &qid) == 0) return; Bseek(b, 0, 0); while(suffixes!=nil){ this = suffixes; suffixes = suffixes->next; free(this->suffix); free(this->generic); free(this->specific); free(this->encoding); free(this); } while((s = Brdline(b, '\n')) != nil){ s[Blinelen(b) - 1] = 0; suffixes = parsesuffix(s, suffixes); } }
/* * Copy the file referenced by fd to the temp file */ void armove(Biobuf *b, Arfile *ap, Armember *bp) { char *cp; Dir *d; if ((d = dirfstat(Bfildes(b))) == nil) { fprint(2, "ar: cannot stat %s: %r\n", file); return; } trim(file, bp->hdr.name, sizeof(bp->hdr.name)); for (cp = strchr(bp->hdr.name, 0); /* blank pad on right */ cp < bp->hdr.name+sizeof(bp->hdr.name); cp++) *cp = ' '; sprint(bp->hdr.date, "%-12ld", d->mtime); sprint(bp->hdr.uid, "%-6d", 0); sprint(bp->hdr.gid, "%-6d", 0); sprint(bp->hdr.mode, "%-8lo", d->mode); sprint(bp->hdr.size, "%-10lld", (vlong)d->length); strncpy(bp->hdr.fmag, ARFMAG, 2); bp->size = d->length; bp->date = d->mtime; arread(b, bp, bp->size); if (d->length&0x01) d->length++; if (ap) { arinsert(ap, bp); ap->size += d->length+SAR_HDR; } free(d); }
/* * return true if any part of the database has changed */ int ndbchanged(struct ndb *db) { /* TODO: implement me (no one calls this yet) */ assert(0); return 0; #if 0 struct ndb *ndb; struct dir *d; /* FIX ME */ for(ndb = db; ndb != NULL; ndb = ndb->next){ d = dirfstat(Bfildes(&ndb->b)); if(d == NULL) continue; if(ndb->qid.path != d->qid.path || ndb->qid.vers != d->qid.vers){ free(d); return 1; } free(d); } return 0; #endif }
void redirectinit(void) { static Biobuf *b = nil; static Qid qid; char *file, *line, *s, *host, *field[3]; static char pfx[] = "http://"; file = "/sys/lib/httpd.rewrite"; if(b != nil){ if(updateQid(Bfildes(b), &qid) == 0) return; Bterm(b); } b = Bopen(file, OREAD); if(b == nil) sysfatal("can't read from %s", file); updateQid(Bfildes(b), &qid); cleartab(redirtab); cleartab(vhosttab); while((line = Brdline(b, '\n')) != nil){ line[Blinelen(b)-1] = 0; s = strchr(line, '#'); if(s != nil && (s == line || s[-1] == ' ' || s[-1] == '\t')) *s = '\0'; /* chop comment iff after whitespace */ if(tokenize(line, field, nelem(field)) == 2){ if(strncmp(field[0], pfx, STRLEN(pfx)) == 0 && strncmp(undecorated(field[1]), pfx, STRLEN(pfx)) != 0){ /* url -> filename */ host = field[0] + STRLEN(pfx); s = strrchr(host, '/'); if(s) *s = 0; /* chop trailing slash */ insert(vhosttab, estrdup(host), estrdup(field[1])); }else{ insert(redirtab, estrdup(field[0]), estrdup(field[1])); } } } syslog(0, HTTPLOG, "redirectinit pid=%d", getpid()); }
extern void stream_free(stream *sp) { int fd; close(sp->fd); fd = Bfildes(sp->fp); Bterm(sp->fp); close(fd); free((char *)sp); }
void starttls(void) { int certlen, fd; uchar *cert; TLSconn *conn; if (tlscert == nil) { reply("500 5.5.1 illegal command or bad syntax\r\n"); return; } conn = mallocz(sizeof *conn, 1); cert = readcert(tlscert, &certlen); if (conn == nil || cert == nil) { if (conn != nil) free(conn); reply("454 4.7.5 TLS not available\r\n"); return; } reply("220 2.0.0 Go ahead make my day\r\n"); conn->cert = cert; conn->certlen = certlen; fd = tlsServer(Bfildes(&bin), conn); if (fd < 0) { free(cert); free(conn); syslog(0, "smtpd", "TLS start-up failed with %s", him); /* force the client to hang up */ close(Bfildes(&bin)); /* probably fd 0 */ close(1); exits("tls failed"); } Bterm(&bin); Binit(&bin, fd, OREAD); if (dup(fd, 1) < 0) fprint(2, "dup of %d failed: %r\n", fd); passwordinclear = 1; syslog(0, "smtpd", "started TLS with %s", him); }
/* * close the database files */ void ndbclose(Ndb *db) { Ndb *nextdb; for(; db; db = nextdb){ nextdb = db->next; _ndbcacheflush(db); hffree(db); close(Bfildes(&db->b)); Bterm(&db->b); free(db); } }
int eof(void) { if(Bfildes(&(infile->Biobufhdr)) != 0) Bterm(&(infile->Biobufhdr)); if(filesp > files) infile = *--filesp; else if(*argv) infile = opn(*argv++); else exits(0); return(C); }
int Bage(Biobuf *b) { Dir *dir; int32_t mtime; dir = dirfstat(Bfildes(b)); if(dir != nil) mtime = dir->mtime; else mtime = 0; free(dir); return time(nil) - mtime; }
/* start a new process */ extern process * noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who) { process *pp; int i, n; if ((pp = (process *)malloc(sizeof(process))) == 0) { if (inp != 0) stream_free(inp); if (outp != 0) stream_free(outp); if (errp != 0) stream_free(errp); return 0; } pp->std[0] = inp; pp->std[1] = outp; pp->std[2] = errp; switch (pp->pid = fork()) { case -1: proc_free(pp); return 0; case 0: if(newpg) sysdetach(); for (i=0; i<3; i++) if (pp->std[i] != 0){ close(Bfildes(pp->std[i]->fp)); while(pp->std[i]->fd < 3) pp->std[i]->fd = dup(pp->std[i]->fd, -1); } for (i=0; i<3; i++) if (pp->std[i] != 0) dup(pp->std[i]->fd, i); for (n = sysfiles(); i < n; i++) close(i); if(who) become(av, who); exec(av[0], av); perror("proc_start"); exits("proc_start"); default: for (i=0; i<3; i++) if (pp->std[i] != 0) { close(pp->std[i]->fd); pp->std[i]->fd = -1; } return pp; } }
/* * process symbols in a file */ void dofile(Biobuf *bp) { int obj; obj = objtype(bp, 0); if (obj < 0) execsyms(Bfildes(bp)); else if (readobj(bp, obj)) { nsym = 0; objtraverse(psym, 0); printsyms(symptr, nsym); } }
/* * write back a file */ int createfile1(Node *node) { Biobuf *bp; char buf[4*1024]; long off; int n; if(changedir(node->parent) < 0) return -1; if(data(OWRITE, &bp, "STOR", s_to_c(node->remname)) != Extra) return -1; for(off = 0; ; off += n){ n = fileread(node, buf, off, sizeof(buf)); if(n <= 0) break; write(Bfildes(bp), buf, n); } close(Bfildes(bp)); if(getreply(&ctlin, msg, sizeof(msg), 0) != Success) return -1; return off; }
static String* Brdstring(Biobuf *b) { int32_t len; String *s; Dir *d; d = dirfstat(Bfildes(b)); if (d == nil) /* shouldn't happen, we just opened it */ len = 0; else len = d->length; free(d); s = s_newalloc(len); s_read(b, s, len); return s; }
/* * return true if any part of the database has changed */ int ndbchanged(Ndb *db) { Ndb *ndb; Dir *d; for(ndb = db; ndb != nil; ndb = ndb->next){ d = dirfstat(Bfildes(&ndb->b)); if(d == nil) continue; if(ndb->qid.path != d->qid.path || ndb->qid.vers != d->qid.vers){ free(d); return 1; } free(d); } return 0; }
/* * exchange names with remote host, attempt to * enable encryption and optionally authenticate. * not fatal if we can't. */ static char * dotls(char *me) { TLSconn *c; char *err; int fd; c = mallocz(sizeof(*c), 1); /* Note: not freed on success */ if (c == nil) return Giveup; dBprint("STARTTLS\r\n"); if (getreply() != 2) return Giveup; fd = tlsClient(Bfildes(&bout), c); if (fd < 0) { syslog(0, "smtp", "tlsClient to %q: %r", ddomain); return Giveup; } err = ckthumbs(c); if (err && !okunksecure) { free(c); close(fd); return err; /* how to recover? TLS is started */ } Bterm(&bin); Bterm(&bout); /* * set up bin & bout to use the TLS fd, i/o upon which generates * i/o on the original, underlying fd. */ Binit(&bin, fd, OREAD); fd = dup(fd, -1); Binit(&bout, fd, OWRITE); syslog(0, "smtp", "started TLS to %q", ddomain); return(hello(me, 1)); }
/* * return true if any part of the database has changed */ int ndbchanged(struct ndb *db) { return 1; #if 0 struct ndb *ndb; struct dir *d; /* FIX ME */ for(ndb = db; ndb != NULL; ndb = ndb->next){ d = dirfstat(Bfildes(&ndb->b)); if(d == NULL) continue; if(ndb->qid.path != d->qid.path || ndb->qid.vers != d->qid.vers){ free(d); return 1; } free(d); } return 0; #endif }
/* * extract the symbol references from an object file */ void scanobj(Biobuf *b, Arfile *ap, int size) { int obj; long offset; Dir *d; static int lastobj = -1; if (!allobj) /* non-object file encountered */ return; offset = Boffset(b); obj = objtype(b, 0); if (obj < 0) { /* not an object file */ allobj = 0; d = dirfstat(Bfildes(b)); if (d != nil && d->length == 0) fprint(2, "ar: zero length file %s\n", file); free(d); Bseek(b, offset, 0); return; } if (lastobj >= 0 && obj != lastobj) { fprint(2, "ar: inconsistent object file %s\n", file); allobj = 0; Bseek(b, offset, 0); return; } lastobj = obj; if (!readar(b, obj, offset+size, 0)) { fprint(2, "ar: invalid symbol reference in file %s\n", file); allobj = 0; Bseek(b, offset, 0); return; } Bseek(b, offset, 0); objtraverse(objsym, ap); }
/* * dump any cached information, forget the hash tables, and reopen a single file */ int ndbreopen(Ndb *db) { int fd; Dir *d; /* forget what we know about the open files */ if(db->mtime){ _ndbcacheflush(db); hffree(db); close(Bfildes(&db->b)); Bterm(&db->b); db->mtime = 0; } /* try the open again */ fd = open(db->file, OREAD); if(fd < 0) return -1; d = dirfstat(fd); if(d == nil){ close(fd); return -1; } /* no hashfile for /net/ndb (avoids deadlock in cs) */ if(d->type == 'I') db->nohash = 1; db->qid = d->qid; db->mtime = d->mtime; db->length = d->length; Binits(&db->b, fd, OREAD, db->buf, sizeof(db->buf)); free(d); return 0; }
/* * 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); }
void comline(void) { long c1, c2; while(C==' ' || c=='\t') ; comx: if((c1=c) == '\n') return; c2 = C; if(c1=='.' && c2!='.') inmacro = NO; if(msflag && c1 == '['){ refer(c2); return; } if(c2 == '\n') return; if(c1 == '\\' && c2 == '\"') SKIP; else if (filesp==files && c1=='E' && c2=='Q') eqn(); else if(filesp==files && c1=='T' && (c2=='S' || c2=='C' || c2=='&')) { if(msflag) stbl(); else tbl(); } else if(c1=='T' && c2=='E') intable = NO; else if (!inmacro && ((c1 == 'd' && c2 == 'e') || (c1 == 'i' && c2 == 'g') || (c1 == 'a' && c2 == 'm'))) macro(); else if(c1=='s' && c2=='o') { if(iflag) SKIP; else { getfname(); if(fname[0]) { if(infile = opn(fname)) *++filesp = infile; else infile = *filesp; } } } else if(c1=='n' && c2=='x') if(iflag) SKIP; else { getfname(); if(fname[0] == '\0') exits(0); if(Bfildes(&(infile->Biobufhdr)) != 0) Bterm(&(infile->Biobufhdr)); infile = *filesp = opn(fname); } else if(c1 == 't' && c2 == 'm') SKIP; else if(c1=='h' && c2=='w') SKIP; else if(msflag && c1 == 'T' && c2 == 'L') { SKIP_TO_COM; goto comx; } else if(msflag && c1=='N' && c2 == 'R') SKIP; else if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){ if(mac==MM)SKIP; else { SKIP_TO_COM; goto comx; } } else if(msflag && c1=='F' && c2=='S') { SKIP_TO_COM; goto comx; } else if(msflag && (c1=='S' || c1=='N') && c2=='H') { SKIP_TO_COM; goto comx; } else if(c1 == 'U' && c2 == 'X') { if(wordflag) Bprint(&(bout.Biobufhdr), "UNIX\n"); else Bprint(&(bout.Biobufhdr), "UNIX "); } else if(msflag && c1=='O' && c2=='K') { SKIP_TO_COM; goto comx; } else if(msflag && c1=='N' && c2=='D') SKIP; else if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U')) SKIP; else if(msflag && mac==MM && c2=='L') { if(disp || c1=='R') sdis('L', 'E'); else { SKIP; Bprint(&(bout.Biobufhdr), " ."); } } else if(!msflag && c1=='P' && c2=='S') { inpic(); } else if(msflag && (c1=='D' || c1=='N' || c1=='K'|| c1=='P') && c2=='S') { sdis(c1, 'E'); } else if(msflag && (c1 == 'K' && c2 == 'F')) { sdis(c1,'E'); } else if(msflag && c1=='n' && c2=='f') sdis('f','i'); else if(msflag && c1=='c' && c2=='e') sce(); else { if(c1=='.' && c2=='.') { if(msflag) { SKIP; return; } while(C == '.') ; } inmacro++; if(c1 <= 'Z' && msflag) regline(YES,ONE); else { if(wordflag) C; regline(YES,TWO); } inmacro--; } }
void main(int argc, char **argv) { Ndbtuple *t, *nt; int n; Dir *d; uint8_t buf[8]; char file[128]; int fd; uint32_t off; uint8_t *p; if(argc != 3){ fprint(2, "usage: mkhash file attribute\n"); exits("usage"); } db = ndbopen(argv[1]); if(db == 0){ fprint(2, "mkhash: can't open %s\n", argv[1]); exits(syserr()); } /* try a bigger than normal buffer */ Binits(&db->b, Bfildes(&db->b), OREAD, nbuf, sizeof(nbuf)); /* count entries to calculate hash size */ n = 0; while(nt = ndbparse(db)){ for(t = nt; t; t = t->entry){ if(strcmp(t->attr, argv[2]) == 0) n++; } ndbfree(nt); } /* allocate an array large enough for worst case */ hlen = 2*n+1; n = hlen*NDBPLEN + hlen*2*NDBPLEN; ht = mallocz(n, 1); if(ht == 0){ fprint(2, "mkhash: not enough memory\n"); exits(syserr()); } for(p = ht; p < &ht[n]; p += NDBPLEN) NDBPUTP(NDBNAP, p); nextchain = hlen*NDBPLEN; /* create the in core hash table */ Bseek(&db->b, 0, 0); off = 0; while(nt = ndbparse(db)){ for(t = nt; t; t = t->entry){ if(strcmp(t->attr, argv[2]) == 0) enter(t->val, off); } ndbfree(nt); off = Boffset(&db->b); } /* create the hash file */ snprint(file, sizeof(file), "%s.%s", argv[1], argv[2]); fd = create(file, ORDWR, 0664); if(fd < 0){ fprint(2, "mkhash: can't create %s\n", file); exits(syserr()); } NDBPUTUL(db->mtime, buf); NDBPUTUL(hlen, buf+NDBULLEN); if(write(fd, buf, NDBHLEN) != NDBHLEN){ fprint(2, "mkhash: writing %s\n", file); exits(syserr()); } if(write(fd, ht, nextchain) != nextchain){ fprint(2, "mkhash: writing %s\n", file); exits(syserr()); } close(fd); /* make sure file didn't change while we were making the hash */ d = dirstat(argv[1]); if(d == nil || d->qid.path != db->qid.path || d->qid.vers != db->qid.vers){ fprint(2, "mkhash: %s changed underfoot\n", argv[1]); remove(file); exits("changed"); } exits(0); }
/* * perform the 'r' and 'u' commands */ void arcmd(char *arname, int count, char **files) { int fd; int i; Arfile *ap; Armember *bp; Dir *d; Biobuf *bfile; fd = openar(arname, ORDWR, 1); if (fd >= 0) { Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); } astart = newtempfile(artemp); ap = astart; aend = 0; for(i = 0; fd >= 0; i++) { bp = getdir(&bar); if (!bp) break; if (bamatch(file, poname)) { /* check for pivot */ aend = newtempfile(tailtemp); ap = aend; } /* pitch symdef file */ if (i == 0 && strcmp(file, symdef) == 0) { skip(&bar, bp->size); continue; } if (count && !match(count, files)) { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); continue; } bfile = Bopen(file, OREAD); if (!bfile) { if (count != 0) fprint(2, "ar: cannot open %s\n", file); scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); continue; } d = dirfstat(Bfildes(bfile)); if (d == nil) fprint(2, "ar: cannot stat %s: %r\n", file); if (uflag && (d == nil || d->mtime <= bp->date)) { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); Bterm(bfile); free(d); continue; } mesg('r', file); skip(&bar, bp->size); scanobj(bfile, ap, d->length); free(d); armove(bfile, ap, bp); Bterm(bfile); } if(fd >= 0) close(fd); /* copy in remaining files named on command line */ for (i = 0; i < count; i++) { file = files[i]; if(file == 0) continue; files[i] = 0; bfile = Bopen(file, OREAD); if (!bfile) fprint(2, "ar: %s cannot open\n", file); else { mesg('a', file); d = dirfstat(Bfildes(bfile)); if (d == nil) fprint(2, "ar: can't stat %s: %r\n", file); else { scanobj(bfile, astart, d->length); armove(bfile, astart, newmember()); free(d); } Bterm(bfile); } } if(fd < 0 && !cflag) install(arname, astart, 0, aend, 1); /* issue 'creating' msg */ else install(arname, astart, 0, aend, 0); }
void extract(char *name, uint32_t mode, uint32_t mtime, char *uid, char *gid, uint64_t bytes) { Dir d, *nd; Biobuf *b; char buf[LEN]; char *p; uint32_t n; uint64_t tot; if(vflag) print("x %q %llu bytes\n", name, bytes); b = Bopen(name, OWRITE); if(!b){ warn("can't make file %q: %r", name); seekpast(bytes); return; } for(tot = 0; tot < bytes; tot += n){ n = sizeof buf; if(tot + n > bytes) n = bytes - tot; n = Bread(&bin, buf, n); if(n <= 0) error("premature eof reading %q", name); if(Bwrite(b, buf, n) != n) warn("error writing %q: %r", name); } nulldir(&d); p = utfrrune(name, '/'); 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; Bflush(b); if(dirfwstat(Bfildes(b), &d) < 0) warn("can't set modes for %q: %r", name); if(uflag||Tflag){ if((nd = dirfstat(Bfildes(b))) == nil) warn("can't reread modes for %q: %r", name); else{ if(Tflag && nd->mtime != mtime) warn("%q: time mismatch %lu %lu\n", name, mtime, nd->mtime); if(uflag && strcmp(uid, nd->uid)) warn("%q: uid mismatch %q %q", name, uid, nd->uid); if(uflag && strcmp(gid, nd->gid)) warn("%q: gid mismatch %q %q", name, gid, nd->gid); free(nd); } } Bterm(b); }
void mesgpost(Article *m) { Biobuf *b; char *p, *ep; int isfirst, ishdr, havegroup, havefrom; p = estrstrdup(dir, "post"); if((b = Bopen(p, OWRITE)) == nil){ fprint(2, "cannot open %s: %r\n", p); free(p); return; } free(p); winopenbody(m->w, OREAD); ishdr = 1; isfirst = 1; havegroup = havefrom = 0; while(p = Brdline(m->w->body, '\n')){ ep = p+Blinelen(m->w->body); if(ishdr && p+1==ep){ if(!havegroup) Bprint(b, "Newsgroups: %s\n", group); if(!havefrom) Bprint(b, "From: %s\n", from); ishdr = 0; } if(ishdr){ ep[-1] = '\0'; if(isfirst && strchr(p, ':')==0){ /* group list */ commas(p, ep); Bprint(b, "newsgroups: %s\n", p); havegroup = 1; isfirst = 0; continue; } if(cistrncmp(p, "newsgroup:", 10)==0){ commas(skip(p, "newsgroup:"), ep); Bprint(b, "newsgroups: %s\n", skip(p, "newsgroup:")); havegroup = 1; continue; } if(cistrncmp(p, "newsgroups:", 11)==0){ commas(skip(p, "newsgroups:"), ep); Bprint(b, "newsgroups: %s\n", skip(p, "newsgroups:")); havegroup = 1; continue; } if(cistrncmp(p, "from:", 5)==0) havefrom = 1; ep[-1] = '\n'; } Bwrite(b, p, ep-p); } winclosebody(m->w); Bflush(b); if(write(Bfildes(b), "", 0) == 0) winclean(m->w); else fprint(2, "post: %r\n"); Bterm(b); }
/* * read a remote directory */ int readdir(Node *node) { Biobuf *bp; char *line; Node *np; Dir *d; long n; int tries, x, files; static int uselist; int usenlist; String *remname; if(changedir(node) < 0) return -1; usenlist = 0; for(tries = 0; tries < 3; tries++){ if(usenlist || usenlst) x = data(OREAD, &bp, "NLST", nil); else if(os == Unix && !uselist) x = data(OREAD, &bp, "LIST -l", nil); else x = data(OREAD, &bp, "LIST", nil); switch(x){ case Extra: break; /* case TempFail: continue; */ default: if(os == Unix && uselist == 0){ uselist = 1; continue; } return seterr(nosuchfile); } files = 0; while(line = Brdline(bp, '\n')){ n = Blinelen(bp); if(debug) write(2, line, n); if(n > 1 && line[n-2] == '\r') n--; line[n - 1] = 0; d = crackdir(line, &remname); if(d == nil) continue; files++; np = extendpath(node, remname); d->qid.path = np->d->qid.path; d->qid.vers = np->d->qid.vers; d->type = np->d->type; d->dev = 1; /* mark node as valid */ if(os == MVS && node == remroot){ d->qid.type = QTDIR; d->mode |= DMDIR; } free(np->d); np->d = d; } close(Bfildes(bp)); switch(getreply(&ctlin, msg, sizeof(msg), 0)){ case Success: if(files == 0 && !usenlst && !usenlist){ usenlist = 1; continue; } if(files && usenlist) usenlst = 1; if(usenlst) node->chdirunknown = 1; return 0; case TempFail: break; default: return seterr(nosuchfile); } } return seterr(nosuchfile); }