void initfontpaths(void) { Biobufhdr *bp; char buf[128]; char *s; int i; /* we don't care if getenv(2) fails */ s = getenv("home"); snprint(buf, sizeof(buf)-1, "%s/lib/abaco.fonts", s); free(s); if((bp=Bopen(buf, OREAD)) == nil) goto Default; for(i=0; i<NumFnt; i++) if((fontpaths[i]=Brdstr(bp, '\n', 1)) == nil) goto Error; Bterm(bp); return; Error: fprint(2, "abaco: not enough fontpaths in '%s'\n", buf); Bterm(bp); for(i--; i>=0; i--) free(fontpaths[i]); Default: for(i=0; i<NumFnt; i++) fontpaths[i] = deffontpaths[i]; }
static void loadThumbprints(char *file, Thumbprint *table, Thumbprint *crltab) { Thumbprint *entry; Biobuf *bin; char *line, *field[50]; uchar sum[SHA1dlen]; int i; bin = Bopen(file, OREAD); if(bin == nil) return; for(; (line = Brdstr(bin, '\n', 1)) != 0; free(line)){ if(tokenize(line, field, nelem(field)) < 2) continue; if(strcmp(field[0], "#include") == 0){ loadThumbprints(field[1], table, crltab); continue; } if(strcmp(field[0], "x509") != 0 || strncmp(field[1], "sha1=", strlen("sha1=")) != 0) continue; field[1] += strlen("sha1="); dec16(sum, sizeof(sum), field[1], strlen(field[1])); if(crltab && okThumbprint(sum, crltab)) continue; entry = (Thumbprint*)emalloc(sizeof(*entry)); memcpy(entry->sha1, sum, SHA1dlen); i = ((sum[0]<<8) + sum[1]) & (ThumbTab-1); entry->next = table[i].next; table[i].next = entry; } Bterm(bin); }
static char* pop3resp(Pop *pop) { char *s; char *p; alarm(60*1000); if((s = Brdstr(&pop->bin, '\n', 0)) == nil){ close(pop->fd); pop->fd = -1; alarm(0); return "unexpected eof"; } alarm(0); p = s+strlen(s)-1; while(p >= s && (*p == '\r' || *p == '\n')) *p-- = '\0'; if(pop->debug) fprint(2, "-> %s\n", s); free(pop->lastline); pop->lastline = s; return s; }
static int looksize(char *file, int64_t size, int *pixels, int *lines, int *chunk) { Biobuf *bp; uint64_t l, p, c; char *s, *a[12]; /* * This may not always work, there could be an alias between file * sizes of different standards stored in 8bits and 10 bits. */ if((bp = Bopen(file, OREAD)) == nil) return -1; while((s = Brdstr(bp, '\n', 1)) != nil){ if(tokenize(s, a, nelem(a)) < 3) continue; if(a[0][0] == '#') continue; p = atoll(a[3]); l = atoll(a[5]); l += atoll(a[7]); c = 128 * ceil(p/48); if(l*c == size){ *pixels = p; *lines = l; *chunk = c; break; } } Bterm(bp); if(s == nil) return -1; return 0; }
static int retrcmd(char *arg) { int n; Biobuf *b; char buf[40], *p; if(*arg == 0) return senderr("RETR requires a message number"); n = atoi(arg)-1; if(n < 0 || n >= nmsg || msg[n].deleted) return senderr("no such message"); snprint(buf, sizeof buf, "%d/raw", msg[n].upasnum); if((b = Bopen(buf, OREAD)) == nil) return senderr("message disappeared"); sendok(""); while((p = Brdstr(b, '\n', 1)) != nil){ if(p[0]=='.') Bwrite(&out, ".", 1); Bwrite(&out, p, strlen(p)); Bwrite(&out, "\r\n", 2); free(p); } Bterm(b); sendcrnl("."); return 0; }
int tline(Biobuf *bp, char **str, char **args, int max) { char *s, *p; int q, dq, rc; do{ s = Brdstr(bp, '\n', 10); if(s == nil) return -1; q = dq = 0; for(p = s; *p != 0; p++) if(*p == '\'') dq = !dq; else{ if(dq){ q = !q; dq = 0; } if(*p == '#' && !q){ *p = 0; break; } } rc = tokenize(s, args, max); }while(rc == 0 && (free(s), 1)); *str = s; return rc; }
int smtpread(Biobuf *b, int code) { char *p, *q; int n; while((p = Brdstr(b, '\n', 1)) != nil) { n = strtol(p, &q, 10); if(n == 0 || q != p+3) { error: vtlogprint(errlog, "sending mail: %s\n", p); free(p); return -1; } if(*q == ' ') { if(n == code) { free(p); return 0; } goto error; } if(*q != '-') { goto error; } } return -1; }
RSApub* readpublickey(Biobuf *b, char **sp) { char *s; RSApub *key; key = rsapuballoc(); if(key == nil) return nil; for(;;){ if((s = Brdstr(b, '\n', 1)) == nil){ rsapubfree(key); return nil; } if(s[0]=='#'){ free(s); continue; } if(parsepubkey(s, key, sp, 10)==0 || parsepubkey(s, key, sp, 16)==0) return key; fprint(2, "warning: skipping line '%s'; cannot parse\n", s); free(s); } }
static int topcmd(char *arg) { int done, i, lines, n; char buf[40], *p; Biobuf *b; if(*arg == 0) return senderr("TOP requires a message number"); n = atoi(arg)-1; if(n < 0 || n >= nmsg || msg[n].deleted) return senderr("no such message"); arg = nextarg(arg); if(*arg == 0) return senderr("TOP requires a line count"); lines = atoi(arg); if(lines < 0) return senderr("bad args to TOP"); snprint(buf, sizeof buf, "%d/raw", msg[n].upasnum); if((b = Bopen(buf, OREAD)) == nil) return senderr("message disappeared"); sendok(""); while(p = Brdstr(b, '\n', 1)){ if(p[0]=='.') Bputc(&out, '.'); Bwrite(&out, p, strlen(p)); Bwrite(&out, "\r\n", 2); done = p[0]=='\0'; free(p); if(done) break; } for(i=0; i<lines; i++){ p = Brdstr(b, '\n', 1); if(p == nil) break; if(p[0]=='.') Bwrite(&out, ".", 1); Bwrite(&out, p, strlen(p)); Bwrite(&out, "\r\n", 2); free(p); } sendcrnl("."); Bterm(b); return 0; }
void xwrite(int argc, char **argv) { char buf[4096]; int n, did; CFid *fid; Biobuf *b; char *p; int byline; byline = 0; ARGBEGIN{ case 'l': byline = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); did = 0; fid = xopen(argv[0], OWRITE|OTRUNC); if(byline){ n = 0; b = malloc(sizeof *b); if(b == nil) sysfatal("out of memory"); Binit(b, 0, OREAD); while((p = Brdstr(b, '\n', 0)) != nil){ n = strlen(p); did = 1; if(fswrite(fid, p, n) != n) fprint(2, "write: %r\n"); } free(b); }else{ while((n = read(0, buf, sizeof buf)) > 0){ did = 1; if(fswrite(fid, buf, n) != n) sysfatal("write error: %r"); } } if(n == 0 && !did){ if(fswrite(fid, buf, 0) != 0) sysfatal("write error: %r"); } if(n < 0) sysfatal("read error: %r"); fsclose(fid); threadexitsall(0); }
/* * 18. Insertions from the standard input */ void r_rd(int argc, Rune **argv) { char buf[100]; char *s; Rune *p; Fmt fmt; static int didstdin; static Biobuf bstdin; /* * print prompt, then read until double newline, * then run the text just read as though it were * a macro body, using the remaining arguments. */ if(fd2path(0, buf, sizeof buf) >= 0 && strstr(buf, "/dev/cons")){ if(argc > 1) fprint(2, "%S", argv[1]); else fprint(2, "%c", 7/*BEL*/); } if(!didstdin){ Binit(&bstdin, 0, OREAD); didstdin = 1; } runefmtstrinit(&fmt); while((s = Brdstr(&bstdin, '\n', 0)) != nil){ if(s[0] == '\n'){ free(s); break; } fmtprint(&fmt, "%s", s); free(s); } p = runefmtstrflush(&fmt); if(p == nil) warn("out of memory in %Crd", dot); ds(L(".rd"), p); argc--; argv++; argv[0] = L(".rd"); runmacro('.', argc, argv); ds(L(".rd"), nil); }
static void _backtrace(int pid, char *btarg) { char *proc, *spid, *gdbcmd; int fd[3], p[2]; int status, cmdfd; gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX"); if(pipe(p) < 0) goto done; closeexec(p[0]); cmdfd = mkstemp(gdbcmd); if(cmdfd < 0) goto done; fprint(cmdfd, "bt %s\n", btarg); fprint(cmdfd, "detach\n"); close(cmdfd); fd[0] = open("/dev/null", O_RDONLY); fd[1] = p[1]; fd[2] = dup(2); proc = sxprint("/proc/%d/" PROGTXT, pid); spid = sxprint("%d", pid); if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) { unlink(gdbcmd); goto done; } Biobuf bp; char *s; Binit(&bp, p[0], OREAD); while((s = Brdstr(&bp, '\n', 1))) { Dprint(DStack, "%s\n", s); free(s); } unlink(gdbcmd); done: free(gdbcmd); kill(pid, SIGKILL); waitpid(pid, &status, 0); }
Db* opendb(char *file) { char *f[10], *s, *t; int i, fd, nf; Biobuf b; Db *db; Entry e; if(file == nil) fd = -1; else if((fd = open(file, ORDWR)) < 0) sysfatal("opendb %s: %r", file); db = emalloc(sizeof(Db)); db->avl = mkavltree(entrycmp); db->fd = fd; if(fd < 0) return db; Binit(&b, fd, OREAD); i = 0; for(; s=Brdstr(&b, '\n', 1); free(s)){ t = estrdup(s); nf = tokenize(s, f, nelem(f)); if(nf != 7) sysfatal("bad database entry '%s'", t); free(t); if(strcmp(f[2], "REMOVED") == 0) _removedb(db, f[0]); else{ memset(&e, 0, sizeof e); e.name = atom(f[0]); e.d.name = atom(f[1]); if(strcmp(e.d.name, "-")==0) e.d.name = e.name; e.d.mode = strtoul(f[2], 0, 8); e.d.uid = atom(f[3]); e.d.gid = atom(f[4]); e.d.mtime = strtoul(f[5], 0, 10); e.d.length = strtoll(f[6], 0, 10); _insertdb(db, &e); i++; } } return db; }
void fmt(void) { char *s; int i, nw; Word **w; nw = 0; w = nil; while((s = Brdstr(&bin, '\n', 1)) != nil){ w = parseline(s, w, &nw); free(s); } printwords(w, nw); for(i=0; i<nw; i++) free(w[i]); free(w); }
char* readhttphdr(Biobuf *netbio, vlong *size) { char *s, *stat; stat = nil; while((s = Brdstr(netbio, '\n', 1)) != nil && s[0] != '\r' && s[0] != '\0'){ if(stat == nil) stat = estrdup9p(s); if(strncmp(s, "Content-Length: ", 16) == 0 && size != nil) *size = atoll(s + 16); free(s); } if(stat) nocr(stat); return stat; }
void main(int argc, char* argv[]) { if(argc > 2) { fprint(2, "usage: %s [file]\n", argv[0]); exits("usage"); } // Run script from file given as parameter instead of stdin if necesary if(argc == 2) redirect_stdin(argv[1]); // Allocate buffer for standard input Biobuf bin; if(Binit(&bin, 0, OREAD)) sysfatal("%s: standard input: %r", argv0); tHeredoc heredoc; heredoc.mode = 0; // Main loop char* line; while((line = Brdstr(&bin, '\n', 0))) { // Process heredoc line = heredoc_process(&heredoc, line); if(line) { // Process script script_process(line); // Free procesed line free(line); } } // Free stdin buffer Bterm(&bin); // Exit sucesfully exits(nil); }
void loadexcludefile(char *file) { Biobuf *b; char *p, *q; int n, inc; Reprog *re; if((b = Bopen(file, OREAD)) == nil) sysfatal("open %s: %r", file); for(n=1; (p=Brdstr(b, '\n', 1)) != nil; free(p), n++){ q = p+strlen(p); while(q > p && isspace((uint8_t)*(q-1))) *--q = 0; switch(p[0]){ case '\0': case '#': continue; } inc = 0; if(strncmp(p, "include ", 8) == 0){ inc = 1; }else if(strncmp(p, "exclude ", 8) == 0){ inc = 0; }else sysfatal("%s:%d: line does not begin with include or exclude", file, n); if(strchr(p+8, ' ')) fprint(2, "%s:%d: warning: space in pattern\n", file, n); if((re = glob2regexp(p+8)) == nil) sysfatal("%s:%d: bad glob pattern", file, n); pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]); pattern[npattern].re = re; pattern[npattern].include = inc; npattern++; } Bterm(b); }
RSApub* readpublickey(Biobuf *b, char **sp) { char *s; RSApub *key; key = emalloc9p(sizeof(RSApub)); if(key == nil) return nil; for (; (s = Brdstr(b, '\n', 1)) != nil; free(s)) if(s[0] != '#'){ if(parsepubkey(s, key, sp, 10) == 0 || parsepubkey(s, key, sp, 16) == 0) return key; fprint(2, "warning: skipping line '%s'; cannot parse\n", s); } free(key); return nil; }
/* * Are we actually allowed to look in here? * * Rules: * 1) If neither allowed nor denied files exist, access is granted. * 2) If allowed exists and denied does not, dir *must* be in allowed * for access to be granted, otherwise, access is denied. * 3) If denied exists and allowed does not, dir *must not* be in * denied for access to be granted, otherwise, access is enied. * 4) If both exist, okay if either (a) file is not in denied, or * (b) in denied and in allowed. Otherwise, access is denied. */ static Reprog * getre(Biobuf *buf) { Reprog *re; char *p, *t; char *bbuf; int n; if (buf == nil) return(nil); for ( ; ; free(p)) { p = Brdstr(buf, '\n', 0); if (p == nil) return(nil); t = strchr(p, '#'); if (t != nil) *t = '\0'; t = p + strlen(p); while (--t > p && isspace(*t)) *t = '\0'; n = strlen(p); if (n == 0) continue; /* root the regular expresssion */ bbuf = malloc(n+2); if(bbuf == nil) sysfatal("out of memory"); bbuf[0] = '^'; strcpy(bbuf+1, p); re = regcomp(bbuf); free(bbuf); if (re == nil) continue; free(p); return(re); } }
static int looksize(char *file, vlong size, int *pixels, int *lines, int *bits) { Biobuf *bp; uvlong l, p; char *s, *a[12]; /* * This may not always work, there could be an alias between file * sizes of different standards stored in 8bits and 10 bits. */ if ((bp = Bopen(file, OREAD)) == nil) return -1; while((s = Brdstr(bp, '\n', 1)) != nil) { if (tokenize(s, a, nelem(a)) < 3) continue; if (a[0][0] == '#') continue; p = atoll(a[3]); l = atoll(a[5]); l += atoll(a[7]); if (l*p*2 == size) { *pixels = p; *lines = l; *bits = 8; break; } if ((l*p*20)/8 == size) { *pixels = p; *lines = l; *bits = 10; break; } } Bterm(bp); if (s == nil) return -1; return 0; }
RSApriv* getkey(int argc, char **argv, int needprivate, Attr **pa) { char *file, *s, *p; int sz; RSApriv *key; Biobuf *b; int regen; Attr *a; if(argc == 0) file = "#d/0"; else file = argv[0]; key = mallocz(sizeof(RSApriv), 1); if(key == nil) return nil; if((b = Bopen(file, OREAD)) == nil) { werrstr("open %s: %r", file); return nil; } s = Brdstr(b, '\n', 1); if(s == nil) { werrstr("read %s: %r", file); return nil; } if(strncmp(s, "key ", 4) != 0) { werrstr("bad key format"); return nil; } regen = 0; a = _parseattr(s+4); if(a == nil) { werrstr("empty key"); return nil; } if((p = _strfindattr(a, "proto")) == nil) { werrstr("no proto"); return nil; } if(strcmp(p, "rsa") != 0) { werrstr("proto not rsa"); return nil; } if((p = _strfindattr(a, "ek")) == nil) { werrstr("no ek"); return nil; } if((key->pub.ek = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad ek"); return nil; } if((p = _strfindattr(a, "n")) == nil) { werrstr("no n"); return nil; } if((key->pub.n = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad n"); return nil; } if((p = _strfindattr(a, "size")) == nil) fprint(2, "warning: missing size; will add\n"); else if((sz = strtol(p, &p, 10)) == 0 || *p != 0) fprint(2, "warning: bad size; will correct\n"); else if(sz != mpsignif(key->pub.n)) fprint(2, "warning: wrong size (got %d, expected %d); will correct\n", sz, mpsignif(key->pub.n)); if(!needprivate) goto call; if((p = _strfindattr(a, "!dk")) == nil) { werrstr("no !dk"); return nil; } if((key->dk = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !dk"); return nil; } if((p = _strfindattr(a, "!p")) == nil) { werrstr("no !p"); return nil; } if((key->p = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !p"); return nil; } if((p = _strfindattr(a, "!q")) == nil) { werrstr("no !q"); return nil; } if((key->q = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !q"); return nil; } if((p = _strfindattr(a, "!kp")) == nil) { fprint(2, "warning: no !kp\n"); regen = 1; goto regen; } if((key->kp = strtomp(p, &p, 16, nil)) == nil || *p != 0) { fprint(2, "warning: bad !kp\n"); regen = 1; goto regen; } if((p = _strfindattr(a, "!kq")) == nil) { fprint(2, "warning: no !kq\n"); regen = 1; goto regen; } if((key->kq = strtomp(p, &p, 16, nil)) == nil || *p != 0) { fprint(2, "warning: bad !kq\n"); regen = 1; goto regen; } if((p = _strfindattr(a, "!c2")) == nil) { fprint(2, "warning: no !c2\n"); regen = 1; goto regen; } if((key->c2 = strtomp(p, &p, 16, nil)) == nil || *p != 0) { fprint(2, "warning: bad !c2\n"); regen = 1; goto regen; } regen: if(regen) { RSApriv *k2; k2 = rsafill(key->pub.n, key->pub.ek, key->dk, key->p, key->q); if(k2 == nil) { werrstr("regenerating chinese-remainder parts failed: %r"); return nil; } key = k2; } call: a = _delattr(a, "ek"); a = _delattr(a, "n"); a = _delattr(a, "size"); a = _delattr(a, "!dk"); a = _delattr(a, "!p"); a = _delattr(a, "!q"); a = _delattr(a, "!c2"); a = _delattr(a, "!kp"); a = _delattr(a, "!kq"); if(pa) *pa = a; return key; }
void main(int argc, char **argv) { int p[2], pid, i, j, n, off, npad, prefix; char **av, *q, *r, *tofree, *name; char nambuf[100]; Biobuf *bin, *bout; Type *t; Field *f; quotefmtinstall(); oargc = argc; oargv = argv; av = emalloc((30+argc)*sizeof av[0]); atexit(waitforgcc); n = 0; av[n++] = "gcc"; av[n++] = "-c"; av[n++] = "-fdollars-in-identifiers"; av[n++] = "-S"; // write assembly av[n++] = "-gstabs"; // include stabs info av[n++] = "-o-"; // to stdout av[n++] = "-xc"; // read C ARGBEGIN{ case 'g': lang = &go; pkg = EARGF(usage()); break; case 'c': av[0] = EARGF(usage()); break; case 'f': av[n++] = EARGF(usage()); break; default: usage(); }ARGEND if(argc == 0) av[n++] = "-"; else av[n++] = argv[0]; av[n] = nil; // Run gcc writing assembly and stabs debugging to p[1]. if(pipe(p) < 0) sysfatal("pipe: %r"); pid = fork(); if(pid < 0) sysfatal("fork: %r"); if(pid == 0) { close(p[0]); dup(p[1], 1); if(argc == 0) { exec(av[0], av); fprint(2, "exec gcc: %r\n"); exit(1); } // Some versions of gcc do not accept -S with multiple files. // Run gcc once for each file. close(0); open("/dev/null", OREAD); for(i=0; i<argc; i++) { pid = fork(); if(pid < 0) sysfatal("fork: %r"); if(pid == 0) { av[n-1] = argv[i]; exec(av[0], av); fprint(2, "exec gcc: %r\n"); exit(1); } waitpid(); } exit(0); } close(p[1]); // Read assembly, pulling out .stabs lines. bin = Bfdopen(p[0], OREAD); while((q = Brdstr(bin, '\n', 1)) != nil) { // .stabs "float:t(0,12)=r(0,1);4;0;",128,0,0,0 tofree = q; while(*q == ' ' || *q == '\t') q++; if(strncmp(q, ".stabs", 6) != 0) goto Continue; q += 6; while(*q == ' ' || *q == '\t') q++; if(*q++ != '\"') { Bad: sysfatal("cannot parse .stabs line:\n%s", tofree); } r = strchr(q, '\"'); if(r == nil) goto Bad; *r++ = '\0'; if(*r++ != ',') goto Bad; if(*r < '0' || *r > '9') goto Bad; if(atoi(r) != 128) // stabs kind = local symbol goto Continue; parsestabtype(q); Continue: free(tofree); } Bterm(bin); waitpid(); // Write defs to standard output. bout = Bfdopen(1, OWRITE); fmtinstall('T', lang->typefmt); // Echo original command line in header. Bprint(bout, "//"); for(i=0; i<oargc; i++) Bprint(bout, " %q", oargv[i]); Bprint(bout, "\n"); Bprint(bout, "\n"); Bprint(bout, "// MACHINE GENERATED - DO NOT EDIT.\n"); Bprint(bout, "\n"); if(pkg) Bprint(bout, "package %s\n\n", pkg); // Constants. Bprint(bout, "// Constants\n"); if(ncon > 0) { Bprint(bout, lang->constbegin); for(i=0; i<ncon; i++) Bprint(bout, lang->constfmt, con[i].name, con[i].value); Bprint(bout, lang->constend); } Bprint(bout, "\n"); // Types // push our names down for(i=0; i<ntyp; i++) { t = typ[i]; name = t->name; while(t && t->kind == Typedef) t = t->type; if(t) t->name = name; } Bprint(bout, "// Types\n"); // Have to turn off structure padding in Plan 9 compiler, // mainly because it is more aggressive than gcc tends to be. if(lang == &c) Bprint(bout, "#pragma pack on\n"); for(i=0; i<ntyp; i++) { Bprint(bout, "\n"); t = typ[i]; name = t->name; while(t && t->kind == Typedef) { if(name == nil && t->name != nil) { name = t->name; if(t->printed) break; } t = t->type; } if(name == nil && t->name != nil) { name = t->name; if(t->printed) continue; t->printed = 1; } if(name == nil) { fprint(2, "unknown name for %T", typ[i]); continue; } if(name[0] == '$') name++; npad = 0; off = 0; switch(t->kind) { case 0: fprint(2, "unknown type definition for %s\n", name); break; default: // numeric, array, or pointer case Array: case Ptr: Bprint(bout, "%s %lT\n", lang->typdef, name, t); break; case Union: // In Go, print union as struct with only first element, // padded the rest of the way. Bprint(bout, lang->unionbegin, name, name, name); goto StructBody; case Struct: Bprint(bout, lang->structbegin, name, name, name); StructBody: prefix = 0; if(lang == &go) prefix = prefixlen(t); for(j=0; j<t->nf; j++) { f = &t->f[j]; // padding if(t->kind == Struct || lang == &go) { if(f->offset%8 != 0 || f->size%8 != 0) { fprint(2, "ignoring bitfield %s.%s\n", t->name, f->name); continue; } if(f->offset < off) sysfatal("%s: struct fields went backward", t->name); if(off < f->offset) { Bprint(bout, lang->structpadfmt, npad++, (f->offset - off) / 8); off = f->offset; } off += f->size; } name = f->name; if(cutprefix(name)) name += prefix; if(strcmp(name, "") == 0) { snprint(nambuf, sizeof nambuf, "Pad%d", npad++); name = nambuf; } Bprint(bout, "\t%#lT;\n", name, f->type); if(t->kind == Union && lang == &go) break; } // final padding if(t->kind == Struct || lang == &go) { if(off/8 < t->size) Bprint(bout, lang->structpadfmt, npad++, t->size - off/8); } Bprint(bout, lang->structend); } } if(lang == &c) Bprint(bout, "#pragma pack off\n"); Bterm(bout); exit(0); }
DSApriv* getdsakey(int argc, char **argv, int needprivate, Attr **pa) { char *file, *s, *p; DSApriv *key; Biobuf *b; Attr *a; if(argc == 0) file = "#d/0"; else file = argv[0]; key = mallocz(sizeof(RSApriv), 1); if(key == nil) return nil; if((b = Bopen(file, OREAD)) == nil) { werrstr("open %s: %r", file); return nil; } s = Brdstr(b, '\n', 1); if(s == nil) { werrstr("read %s: %r", file); return nil; } if(strncmp(s, "key ", 4) != 0) { werrstr("bad key format"); return nil; } a = _parseattr(s+4); if(a == nil) { werrstr("empty key"); return nil; } if((p = _strfindattr(a, "proto")) == nil) { werrstr("no proto"); return nil; } if(strcmp(p, "dsa") != 0) { werrstr("proto not dsa"); return nil; } if((p = _strfindattr(a, "p")) == nil) { werrstr("no p"); return nil; } if((key->pub.p = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad p"); return nil; } if((p = _strfindattr(a, "q")) == nil) { werrstr("no q"); return nil; } if((key->pub.q = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad q"); return nil; } if((p = _strfindattr(a, "alpha")) == nil) { werrstr("no alpha"); return nil; } if((key->pub.alpha = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad alpha"); return nil; } if((p = _strfindattr(a, "key")) == nil) { werrstr("no key="); return nil; } if((key->pub.key = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad key="); return nil; } if(!needprivate) goto call; if((p = _strfindattr(a, "!secret")) == nil) { werrstr("no !secret"); return nil; } if((key->secret = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !secret"); return nil; } call: a = _delattr(a, "p"); a = _delattr(a, "q"); a = _delattr(a, "alpha"); a = _delattr(a, "key"); a = _delattr(a, "!secret"); if(pa) *pa = a; return key; }
void main(int argc, char **argv) { char *f[10], *local, *name, *remote, *s, *t, verb; int fd, havedb, havelocal, i, k, n, nf, resolve1, skip; int checkedmatch1, checkedmatch2, checkedmatch3, checkedmatch4; ulong now; Biobuf bin; Dir dbd, ld, nd, rd; Avlwalk *w; Entry *e; membogus(argv); quotefmtinstall(); ARGBEGIN{ case 's': case 'c': i = ARGC(); addresolve(i, EARGF(usage())); break; case 'n': donothing = 1; verbose = 1; break; case 'S': safeinstall = 0; break; case 'T': timefile = EARGF(usage()); break; case 't': tempspool = 0; break; case 'u': douid = 1; break; case 'v': verbose++; break; default: usage(); }ARGEND if(argc < 3) usage(); if(timefile) readtimefile(); lroot = argv[1]; if(!isdir(lroot)) sysfatal("bad local root directory"); rroot = argv[2]; if(!isdir(rroot)) sysfatal("bad remote root directory"); match = argv+3; nmatch = argc-3; for(i=0; i<nmatch; i++) if(match[i][0] == '/') match[i]++; if((clientdb = opendb(argv[0])) == nil) sysfatal("opendb %q: %r", argv[2]); copyerr = opendb(nil); skip = 0; Binit(&bin, 0, OREAD); for(; s=Brdstr(&bin, '\n', 1); free(s)){ t = estrdup(s); nf = tokenize(s, f, nelem(f)); if(nf != 10 || strlen(f[2]) != 1){ skip = 1; fprint(2, "warning: skipping bad log entry <%s>\n", t); free(t); continue; } free(t); now = strtoul(f[0], 0, 0); n = atoi(f[1]); verb = f[2][0]; name = f[3]; if(now < maxnow || (now==maxnow && n <= maxn)) continue; local = mkname(localbuf, sizeof localbuf, lroot, name); if(strcmp(f[4], "-") == 0) f[4] = f[3]; remote = mkname(remotebuf, sizeof remotebuf, rroot, f[4]); rd.name = f[4]; rd.mode = strtoul(f[5], 0, 8); rd.uid = f[6]; rd.gid = f[7]; rd.mtime = strtoul(f[8], 0, 10); rd.length = strtoll(f[9], 0, 10); havedb = finddb(clientdb, name, &dbd)>=0; havelocal = localdirstat(local, &ld)>=0; resolve1 = resolve(name); /* * if(!ismatch(name)){ * skip = 1; * continue; * } * * This check used to be right here, but we want * the time to be able to move forward past entries * that don't match and have already been applied. * So now every path below must checked !ismatch(name) * before making any changes to the local file * system. The fake variable checkedmatch * tracks whether !ismatch(name) has been checked. * If the compiler doesn't produce any used/set * warnings, then all the paths should be okay. * Even so, we have the asserts to fall back on. */ switch(verb){ case 'd': /* delete file */ delce(local); if(!havelocal) /* doesn't exist; who cares? */ break; if(access(remote, AEXIST) >= 0) /* got recreated! */ break; if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch1); if(!havedb){ if(resolve1 == 's') goto DoRemove; else if(resolve1 == 'c') goto DoRemoveDb; conflict(name, "locally created; will not remove"); skip = 1; continue; } assert(havelocal && havedb); if(dbd.mtime > rd.mtime) /* we have a newer file than what was deleted */ break; if(samecontents(local, remote) > 0){ /* going to get recreated */ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); break; } if(!(dbd.mode&DMDIR) && (dbd.mtime != ld.mtime || dbd.length != ld.length)){ /* locally modified since we downloaded it */ if(resolve1 == 's') goto DoRemove; else if(resolve1 == 'c') break; conflict(name, "locally modified; will not remove"); skip = 1; continue; } DoRemove: USED(checkedmatch1); assert(ismatch(name)); chat("d %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; if(remove(local) < 0){ error("removing %q: %r", name); skip = 1; continue; } DoRemoveDb: USED(checkedmatch1); assert(ismatch(name)); removedb(clientdb, name); break; case 'a': /* add file */ if(!havedb){ if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch2); if(!havelocal) goto DoCreate; if((ld.mode&DMDIR) && (rd.mode&DMDIR)) break; if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCreateDb; } if(resolve1 == 's') goto DoCreate; else if(resolve1 == 'c') goto DoCreateDb; conflict(name, "locally created; will not overwrite"); skip = 1; continue; } assert(havedb); if(dbd.mtime >= rd.mtime) /* already created this file; ignore */ break; if(havelocal){ if((ld.mode&DMDIR) && (rd.mode&DMDIR)) break; if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch2); if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCreateDb; } if(dbd.mtime==ld.mtime && dbd.length==ld.length) goto DoCreate; if(resolve1=='s') goto DoCreate; else if(resolve1 == 'c') goto DoCreateDb; conflict(name, "locally modified; will not overwrite"); skip = 1; continue; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch2); DoCreate: USED(checkedmatch2); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break;; } chat("a %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; if(rd.mode&DMDIR){ fd = create(local, OREAD, DMDIR); if(fd < 0 && isdir(local)) fd = open(local, OREAD); if(fd < 0){ error("mkdir %q: %r", name); skip = 1; continue; } nulldir(&nd); nd.mode = rd.mode; if(dirfwstat(fd, &nd) < 0) fprint(2, "warning: cannot set mode on %q\n", local); nulldir(&nd); nd.gid = rd.gid; if(dirfwstat(fd, &nd) < 0) fprint(2, "warning: cannot set gid on %q\n", local); if(douid){ nulldir(&nd); nd.uid = rd.uid; if(dirfwstat(fd, &nd) < 0) fprint(2, "warning: cannot set uid on %q\n", local); } close(fd); rd.mtime = now; }else{ if(copyfile(local, remote, name, &rd, 1, &k) < 0){ if(k) addce(local); skip = 1; continue; } } DoCreateDb: USED(checkedmatch2); assert(ismatch(name)); insertdb(clientdb, name, &rd); break; case 'c': /* change contents */ if(!havedb){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch3); if(resolve1 == 's') goto DoCopy; else if(resolve1=='c') goto DoCopyDb; if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCopyDb; } if(havelocal) conflict(name, "locally created; will not update"); else conflict(name, "not replicated; will not update"); skip = 1; continue; } if(dbd.mtime >= rd.mtime) /* already have/had this version; ignore */ break; if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch3); if(!havelocal){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(resolve1 == 's') goto DoCopy; else if(resolve1 == 'c') break; conflict(name, "locally removed; will not update"); skip = 1; continue; } assert(havedb && havelocal); if(dbd.mtime != ld.mtime || dbd.length != ld.length){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCopyDb; } if(resolve1 == 's') goto DoCopy; else if(resolve1 == 'c') goto DoCopyDb; conflict(name, "locally modified; will not update [%llud %lud -> %llud %lud]", dbd.length, dbd.mtime, ld.length, ld.mtime); skip = 1; continue; } DoCopy: USED(checkedmatch3); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break; } chat("c %q\n", name); if(donothing) break; if(copyfile(local, remote, name, &rd, 0, &k) < 0){ if(k) addce(local); skip = 1; continue; } DoCopyDb: USED(checkedmatch3); assert(ismatch(name)); if(!havedb){ if(havelocal) dbd = ld; else dbd = rd; } dbd.mtime = rd.mtime; dbd.length = rd.length; insertdb(clientdb, name, &dbd); break; case 'm': /* change metadata */ if(!havedb){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's'){ USED(checkedmatch4); SET(checkedmatch2); goto DoCreate; } else if(resolve1 == 'c') goto DoMetaDb; if(havelocal) conflict(name, "locally created; will not update metadata"); else conflict(name, "not replicated; will not update metadata"); skip = 1; continue; } if(!(dbd.mode&DMDIR) && dbd.mtime > rd.mtime) /* have newer version; ignore */ break; if((dbd.mode&DMDIR) && dbd.mtime > now) break; if(havelocal && (!douid || strcmp(ld.uid, rd.uid)==0) && strcmp(ld.gid, rd.gid)==0 && ld.mode==rd.mode) break; if(!havelocal){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's'){ USED(checkedmatch4); SET(checkedmatch2); goto DoCreate; } else if(resolve1 == 'c') break; conflict(name, "locally removed; will not update metadata"); skip = 1; continue; } if(!(dbd.mode&DMDIR) && (dbd.mtime != ld.mtime || dbd.length != ld.length)){ /* this check might be overkill */ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's' || samecontents(local, remote) > 0) goto DoMeta; else if(resolve1 == 'c') break; conflict(name, "contents locally modified (%s); will not update metadata to %s %s %luo", dbd.mtime != ld.mtime ? "mtime" : dbd.length != ld.length ? "length" : "unknown", rd.uid, rd.gid, rd.mode); skip = 1; continue; } if((douid && strcmp(ld.uid, dbd.uid)!=0) || strcmp(ld.gid, dbd.gid)!=0 || ld.mode!=dbd.mode){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's') goto DoMeta; else if(resolve1 == 'c') break; conflict(name, "metadata locally changed; will not update metadata to %s %s %luo", rd.uid, rd.gid, rd.mode); skip = 1; continue; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); DoMeta: USED(checkedmatch4); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break; } chat("m %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; nulldir(&nd); nd.gid = rd.gid; nd.mode = rd.mode; if(douid) nd.uid = rd.uid; if(dirwstat(local, &nd) < 0){ error("dirwstat %q: %r", name); skip = 1; continue; } DoMetaDb: USED(checkedmatch4); assert(ismatch(name)); if(!havedb){ if(havelocal) dbd = ld; else dbd = rd; } if(dbd.mode&DMDIR) dbd.mtime = now; dbd.gid = rd.gid; dbd.mode = rd.mode; if(douid) dbd.uid = rd.uid; insertdb(clientdb, name, &dbd); break; } if(!skip && !donothing){ maxnow = now; maxn = n; } } w = avlwalk(copyerr->avl); while(e = (Entry*)avlnext(w)) error("copying %q: %s\n", e->name, e->d.name); if(timefile) writetimefile(); if(nconf) exits("conflicts"); if(errors) exits("errors"); exits(nil); }