shithub: nvi

ref: d81d2b35559fea6684cee44a5d4f494fc585e38d
dir: nvi/util.c

View raw version
#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;
}