#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 voidpexec(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);} intpipeexec(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];} voidprocwait(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;} inthget(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;} intalldigit(char *s){ if(*s == 0) return 0; for(; *s; s++) if(!isdigit(*s)) return 0; return 1;} intZfmt(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);} intPfmt(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))));} vlongjint(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;}
#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;
}