ref: d81d2b35559fea6684cee44a5d4f494fc585e38d
dir: /util.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <ctype.h> #include <json.h> #include "nvi.h" enum { Us, Them, }; typedef struct Exec Exec; struct Exec { char *file; char **argv; int p[2]; Channel *pid; }; static void pexec(void *args) { Exec *e = args; int fd; if(e->p[0] >= 0){ dup(e->p[Them], 0); dup(e->p[Them], 1); close(e->p[0]); close(e->p[1]); }else{ close(0); close(1); } if(debug < 1){ dup(fd = open("/dev/null", OWRITE), 2); close(fd); } procexec(e->pid, e->file, e->argv); } int pipeexec(int *fd, char *file, char **argv) { int pid; Exec e; threadwaitchan(); e.file = file; e.argv = argv; e.pid = chancreate(sizeof(int), 0); e.p[0] = fd[0]; e.p[1] = fd[1]; procrfork(pexec, &e, 4096, RFFDG); recv(e.pid, &pid); chanfree(e.pid); close(e.p[Them]); if(pid < 0){ close(e.p[Us]); return -1; } return e.p[Us]; } void procwait(void) { free(recvp(threadwaitchan())); } char * readall(int f) { int bufsz, sz, n; char *s; bufsz = 1023; s = nil; for(sz = 0;; sz += n){ if(bufsz-sz < 1024){ bufsz *= 2; s = realloc(s, bufsz); } if((n = readn(f, s+sz, bufsz-sz-1)) < 1) break; } if(n < 0 || sz < 1){ free(s); return nil; } s[sz] = 0; return s; } int hget(char *url, int out) { char *argv[] = {"hget", url, nil}; int p[2]; if(debug) fprint(2, "GET %s\n", url); if(out >= 0){ p[0] = open("/dev/null", OREAD); p[1] = out; }else{ pipe(p); } return pipeexec(p, "/bin/hget", argv); } char * estrdup(char *s) { if((s = strdup(s == nil ? "" : s)) == nil) sysfatal("memory"); return s; } int alldigit(char *s) { if(*s == 0) return 0; for(; *s; s++) if(!isdigit(*s)) return 0; return 1; } int Zfmt(Fmt *f) { vlong z; z = va_arg(f->args, vlong); if(z > 1024*1024*1024) return fmtprint(f, "%.1fGb", (double)z / (1024.0*1024.0*1024.0)); if(z > 1024*1024) return fmtprint(f, "%.1fMb", (double)z / (1024.0*1024.0)); if(z > 1024) return fmtprint(f, "%lldKb", z / 1024); if(z == 0) return fmtprint(f, "----"); return fmtprint(f, "%lld", z); } int Pfmt(Fmt *f) { char *s, tmp[16]; u64int sec; s = tmp; sec = va_arg(f->args, uvlong); if(sec >= 3600){ s = seprint(s, tmp+sizeof(tmp), "%02lld:", sec/3600); sec %= 3600; } s = seprint(s, tmp+sizeof(tmp), "%02lld:", sec/60); sec %= 60; seprint(s, tmp+sizeof(tmp), "%02lld", sec); return fmtstrcpy(f, tmp); } JSON * jfield(JSON *j, int type, ...) { va_list a; char *s; va_start(a, type); while((s = va_arg(a, char*)) != nil){ if((j = jsonbyname(j, s)) == nil) break; } va_end(a); return (j == nil || (type >= 0 && j->t != type)) ? nil : j; } static char * strclean(char *s) { char *s₀, *o; s₀ = s; for(o = s; *s; s++){ if(*s != 0xd) *o++ = *s; } *o = 0; return s₀; } char * jstrdup(JSON *j, char *name) { return strclean(estrdup(jsonstr(jsonbyname(j, name)))); } vlong jint(JSON *j, char *name) { if((j = jfield(j, -1, name, nil)) != nil){ if(j->t == JSONNumber) return j->n; if(j->t == JSONString) return atoll(jsonstr(j)); } return 0; } char* strrpbrk(char *s, char *c) { char *r, *s0; if(*c == 0) return strchr(s, 0); for(r = nil, s0 = s; *c != 0; c++, s = s0){ while(s = strchr(s, *c)){ r = s++; s0 = s; } } return r; }