File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / aitio.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 23 22:54:52 2010 UTC (14 years, 3 months ago) by misho
Branches: MAIN
CVS tags: HEAD
Initial revision

/*************************************************************************
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
*  by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: aitio.c,v 1.1 2010/02/23 22:54:52 misho Exp $
*
*************************************************************************/
#include "global.h"


#pragma GCC visibility push(hidden)

int io_Errno;
char io_Error[STRSIZ];

#pragma GCC visibility pop


// io_GetErrno() Get error code of last operation
inline int io_GetErrno()
{
	return io_Errno;
}

// io_GetError() Get error text of last operation
inline const char *io_GetError()
{
	return io_Error;
}

// io_SetErr() Set error to variables for internal use!!!
inline void io_SetErr(int eno, char *estr, ...)
{
	va_list lst;

	io_Errno = eno;
	memset(io_Error, 0, STRSIZ);
	va_start(lst, estr);
	vsnprintf(io_Error, STRSIZ, estr, lst);
	va_end(lst);
}


/*
 * ioPromptRead() Read data from input h[0] with prompt to output h[1]
 * @h = file handles h[0] = input, h[1] = output, if NULL use stdin, stdout
 * @csPrompt = Prompt before input, may be NULL
 * @psData = Readed data
 * @dataLen = Length of data
 * return: 0 EOF; -1 error:: can`t read; >0 count of readed chars
*/
int ioPromptRead(int *h, const char *csPrompt, char * __restrict psData, int dataLen)
{
	int ok = 0;
	FILE *inp, *out;
	char szLine[BUFSIZ], *pos;

	if (!psData || !dataLen)
		return -1;

	inp = fdopen(!h ? 0 : h[0], "r");
	if (!inp) {
		LOGERR;
		return -1;
	}
	out = fdopen(!h ? 1 : h[1], "w");
	if (!out) {
		LOGERR;
		return -1;
	}

	while (!ok) {
		if (csPrompt) {
			fprintf(out, "%s", csPrompt);
			fflush(out);
		}

		memset(szLine, 0, BUFSIZ);
		if (!fgets(szLine, BUFSIZ, inp)) {
			clearerr(inp);
			fpurge(out);
			fflush(out);
			return 0;
		}

		if ((pos = strchr(szLine, '\n')))
			*pos = 0;

		strlcpy(psData, szLine, dataLen);
		ok = 1;
	}

	return pos - szLine;
}

/*
 * ioPromptPassword() Read password from input h[0] with prompt to output h[1]
 * @h = file handles h[0] = input, h[1] = output, if NULL use stdin, stdout
 * @csPrompt = Prompt before input, may be NULL
 * @psPass = Readed password
 * @passLen = Length of password
 * @confirm = Confirm password, 0 - get password, !=0 Ask for confirmation
 * return: 0 EOF; -1 error:: can`t read; >0 count of readed chars
*/
int ioPromptPassword(int *h, const char *csPrompt, char * __restrict psPass, int passLen, int confirm)
{
	int ret, ok = 0;
	FILE *inp, *out;
	char szLine[2][STRSIZ];
	struct sgttyb tty_state;

	if (!psPass || !passLen)
		return -1;

	inp = fdopen(!h ? 0 : h[0], "r");
	if (!inp) {
		LOGERR;
		return -1;
	}
	out = fdopen(!h ? 1 : h[1], "w");
	if (!out) {
		LOGERR;
		return -1;
	}

	if (ioctl(fileno(inp), TIOCGETP, &tty_state) == -1) {
		LOGERR;
		return -1;
	} else {
		tty_state.sg_flags &= ~ECHO;
		if (ioctl(fileno(inp), TIOCSETP, &tty_state) == -1) {
			LOGERR;
			return -1;
		}
	}

	while (!ok) {
		switch ((ret = ioPromptRead(h, (!csPrompt || !*csPrompt) ? "Password:" : csPrompt, 
						szLine[0], STRSIZ))) {
			case -1:
				LOGERR;
				ok = -1;
			case 0:
				goto next;
		}
		if (confirm) {
			fprintf(out, "\n");
			fflush(out);

			switch (ioPromptRead(h, "Password confirm:", szLine[1], STRSIZ)) {
				case -1:
					LOGERR;
					ok = -1;
					goto next;
				case 0:
				default:
					if (strcmp(szLine[0], szLine[1])) {
						fprintf(out, "\n\07\07Mismatch - Try again!\n");
						fflush(out);
						continue;
					}
			}
		}

		strlcpy(psPass, szLine[0], passLen);
		ok = ret;
		fprintf(out, "\n");
		fflush(out);
	}

next:
	tty_state.sg_flags |= ECHO;
	if (ioctl(fileno(inp), TIOCSETP, &tty_state) == -1) {
		LOGERR;
		return -1;
	}

	return ok;
}

/*
 * ioRegexVerify() Function for verify data match in regex expression
 * @csRegex = Regulare expression pattern
 * @csData = Data for check and verify
 * @startPos = Return start positions
 * @endPos = Return end positions
 * return: NULL not match or error; !=NULL begin of matched data
*/
const char *ioRegexVerify(const char *csRegex, const char *csData, int *startPos, int *endPos)
{
	regex_t re;
	regmatch_t match;
	char szErr[STRSIZ];
	int ret, flg;
	const char *pos;

	if (!csRegex || !csData)
		return NULL;

	if ((ret = regcomp(&re, csRegex, REG_EXTENDED))) {
		regerror(ret, &re, szErr, STRSIZ);
		io_SetErr(ret, "Error:: %s\n", szErr);
		regfree(&re);
		return NULL;
	}

	for (ret = flg = 0, pos = csData; !(ret = regexec(&re, pos, 1, &match, flg)); 
			pos += match.rm_eo, flg = REG_NOTBOL) {
		if (startPos)
			*startPos = match.rm_so;
		if (endPos)
			*endPos = match.rm_eo;

		pos += match.rm_so;
		break;
	}

	if (ret) {
		regerror(ret, &re, szErr, STRSIZ);
		io_SetErr(ret, "Error:: %s\n", szErr);
		pos = NULL;
	}

	regfree(&re);
	return pos;
}

/*
 * ioRegexGet() Function for get data match in regex expression
 * @csRegex = Regulare expression pattern
 * @csData = Data from get
 * @psString = Returned string if match
 * @strLen = Length of string
 * return: 0 not match; >0 count of returned chars
*/
int ioRegexGet(const char *csRegex, const char *csData, char * __restrict psString, int strLen)
{
	int sp, ep, len;
	const char *str;

	if (!csRegex || !csData)
		return -1;

	str = ioRegexVerify(csRegex, csData, &sp, &ep);
	if (!str)
		return 0;

	len = ep - sp;
	if (psString && strLen) {
		memset(psString, 0, strLen);
		strncpy(psString, str, strLen <= len ? strLen - 1 : len);
	}

	return len;
}

/*
 * ioRegexReplace() Function for replace data match in regex expression with newdata
 * @csRegex = Regulare expression pattern
 * @csData = Source data
 * @csNew = Data for replace
 * return: NULL not match or error; !=NULL allocated new string, must be free after use!
*/
char *ioRegexReplace(const char *csRegex, const char *csData, const char *csNew)
{
	int sp, ep, len;
	char *str = NULL;

	if (!csRegex || !csData)
		return NULL;

	if (!ioRegexVerify(csRegex, csData, &sp, &ep))
		return NULL;

	// ___ before match
	len = sp + 1;
	str = malloc(len);
	if (!str) {
		LOGERR;
		return NULL;
	} else
		strlcpy(str, csData, len);
	// * replace match *
	if (csNew) {
		len += strlen(csNew);
		str = realloc(str, len);
		if (!str) {
			LOGERR;
			return NULL;
		} else
			strlcat(str, csNew, len);
	}
	// after match ___
	len += strlen(csData) - ep;
	str = realloc(str, len);
	if (!str) {
		LOGERR;
		return NULL;
	} else
		strlcat(str, csData + ep, len);

	return str;
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>