#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/fcall.h>
#include <9pm/ns.h>

int
dup(int fd, int nfd)
{
	int nmchan, ret;
	Chan *c, *oc, **nchan;
	Proc *p;
	Fgrp *f;

	if(nfd < -1){
		werrstr("bad proposed fd in dup");
		return -1;
	}

	p = getproc();
	lock(&p->lk);
	f = p->fgrp;
	lock(&f->lk);
	unlock(&p->lk);
	if(fd < 0 || fd >= f->mchan || (c = f->chan[fd])==nil){
		werrstr("bad or closed fd in dup");
		unlock(&f->lk);
		return -1;
	}
	if(nfd == -1){
		incref(&c->ref);
		unlock(&f->lk);
		if((ret = newfd(c)) < 0)
			cclose(c);
		return ret;
	}
	if(nfd>=f->mchan){
		nmchan = (nfd+16)&~15;
		nchan = realloc(f->chan, nmchan*sizeof(f->chan[0]));
		if(nchan == nil){
			unlock(&f->lk);
			return -1;
		}
		f->chan = nchan;
		for(; f->mchan<nmchan; f->mchan++)
			f->chan[f->mchan] = nil;
	}
	oc = f->chan[nfd];
	f->chan[nfd] = c;
	incref(&c->ref);
	unlock(&f->lk);
	cclose(oc);
	return 0;
}
