/*
 * This file is part of the UCB release of Plan 9. It is subject to the license
 * terms in the LICENSE file found in the top-level directory of this
 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
 * part of the UCB release of Plan 9, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms contained
 * in the LICENSE file.
 */
/* Portions of this file are Copyright (C) 2015-2018 Giacomo Tesio <giacomo@tesio.it>
 * See /doc/license/gpl-2.0.txt for details about the licensing.
 */
/* Portions of this file are Copyright (C) 9front's team.
 * See /doc/license/9front-mit for details about the licensing.
 * See http://code.9front.org/hg/plan9front/ for a list of authors.
 */
#include <u.h>
#include <lib9.h>
#include <mp.h>
#include <libsec.h>
#include "SConn.h"
#include "secstore.h"

void *
emalloc(uint32_t n)
{
	void *p = malloc(n);

	if(p == nil)
		sysfatal("emalloc");
	memset(p, 0, n);
	return p;
}

void *
erealloc(void *p, uint32_t n)
{
	if ((p = realloc(p, n)) == nil)
		sysfatal("erealloc");
	return p;
}

char *
estrdup(char *s)
{
	if ((s = strdup(s)) == nil)
		sysfatal("estrdup");
	return s;
}

char*
getpassm(char *prompt)
{
	char *p, line[4096];
	int n, nr;
	static int cons, consctl; /* closing & reopening fails in ssh environment */

	if(cons == 0){			/* first time? */
		cons = sys_open("/dev/cons", ORDWR);
		if(cons < 0)
			sysfatal("couldn't open cons");
		consctl = sys_open("/dev/consctl", OWRITE);
		if(consctl < 0)
			sysfatal("couldn't set raw mode via consctl");
	}
	fprint(consctl, "rawon");
	fprint(cons, "%s", prompt);
	nr = 0;
	p = line;
	for(;;){
		n = jehanne_read(cons, p, 1);
		if(n < 0){
			fprint(consctl, "rawoff");
			fprint(cons, "\n");
			return nil;
		}
		if(n == 0 || *p == '\n' || *p == '\r' || *p == 0x7f){
			*p = '\0';
			fprint(consctl, "rawoff");
			fprint(cons, "\n");
			p = strdup(line);
			memset(line, 0, nr);
			return p;
		}
		if(*p == '\b'){
			if(nr > 0){
				nr--;
				p--;
			}
		}else if(*p == ('u' & 037)){		/* cntrl-u */
			fprint(cons, "\n%s", prompt);
			nr = 0;
			p = line;
		}else{
			nr++;
			p++;
		}
		if(nr+1 == sizeof line){
			fprint(cons, "line too int32_t; try again\n%s", prompt);
			nr = 0;
			p = line;
		}
	}
}

static char *
illegal(char *f)
{
	syslog(0, LOG, "illegal name: %s", f);
	return nil;
}

char *
validatefile(char *f)
{
	char *p;

	if(f == nil || *f == '\0')
		return nil;
	if(strcmp(f, "..") == 0 || strlen(f) >= 250)
		return illegal(f);
	for(p = f; *p; p++)
		if(*p < 040 || *p == '/')
			return illegal(f);
	return f;
}
