File:  [ELWIX - Embedded LightWeight unIX -] / libaitcli / example / t.c
Revision 1.1.2.3: download - view: text, annotated - select for diffs - revision graph
Fri Jun 4 09:16:59 2010 UTC (14 years, 1 month ago) by misho
Branches: cli1_0
Diff to: branchpoint 1.1: preferred, unified
final cli engine

    1: #include <stdio.h>
    2: #include <stdlib.h>
    3: #include <unistd.h>
    4: #include <string.h>
    5: #include <termios.h>
    6: #include <poll.h>
    7: #include <aitio.h>
    8: #include <sys/types.h>
    9: #include <sys/param.h>
   10: #include <sys/stat.h>
   11: #include <sys/queue.h>
   12: #include "keys.h"
   13: 
   14: 
   15: int freeLineCLI(linebuffer_t * __restrict buffer);
   16: 
   17: 
   18: static inline void
   19: clrscrEOL(linebuffer_t * __restrict buf)
   20: {
   21: 	register int i;
   22: 
   23: 	if (buf) {
   24: 		write(buf->line_out, K_CR, 1);
   25: 
   26: 		for (i = 0; i < buf->line_len; i++)
   27: 			write(buf->line_out, K_SPACE, 1);
   28: 	}
   29: }
   30: 
   31: static inline void
   32: printfEOL(linebuffer_t * __restrict buf, int len, int prompt)
   33: {
   34: 	if (buf) {
   35: 		write(buf->line_out, K_CR, 1);
   36: 
   37: 		if (prompt && buf->line_prompt)
   38: 			write(buf->line_out, buf->line_prompt, buf->line_bol);
   39: 
   40: 		write(buf->line_out, buf->line_buf, len == -1 ? buf->line_eol - buf->line_bol: len);
   41: 	}
   42: }
   43: 
   44: static inline void
   45: printfCR(linebuffer_t * __restrict buf, int prompt)
   46: {
   47: 	if (buf) {
   48: 		write(buf->line_out, K_CR, 1);
   49: 
   50: 		if (prompt)
   51: 			if (prompt && buf->line_prompt)
   52: 				write(buf->line_out, buf->line_prompt, buf->line_bol);
   53: 	}
   54: }
   55: 
   56: static inline void
   57: printfCLI(linebuffer_t * __restrict buf, const unsigned char *text, int textlen, int prompt)
   58: {
   59: 	if (buf && text && textlen) {
   60: 		if (prompt && buf->line_prompt)
   61: 			write(buf->line_out, buf->line_prompt, buf->line_bol);
   62: 
   63: 		write(buf->line_out, text, textlen);
   64: 	}
   65: }
   66: 
   67: 
   68: static int
   69: catCh2Buf(int idx, void * __restrict buffer)
   70: {
   71: 	linebuffer_t *buf = buffer;
   72: 	int pos;
   73: 	unsigned char b[BUFSIZ];
   74: 
   75: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
   76: 		return RETCODE_ERR;
   77: 
   78: 	pos = buf->line_eol - buf->line_bol;
   79: 
   80: 	if (buf->line_mode == LINEMODE_INS)
   81: 		memmove(buf->line_buf + pos + buf->line_keys[idx].key_len, buf->line_buf + pos, 
   82: 				buf->line_len - buf->line_eol);
   83: 	if (buf->line_mode == LINEMODE_INS || buf->line_eol == buf->line_len - 1)
   84: 		buf->line_len += buf->line_keys[idx].key_len;
   85: 	buf->line_eol += buf->line_keys[idx].key_len;
   86: 
   87: 	memcpy(buf->line_buf + pos, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   88: 	buf->line_buf[buf->line_len - 1] = 0;
   89: 
   90: 	write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   91: 
   92: 	if (buf->line_mode == LINEMODE_INS) {
   93: 		printfCLI(buf, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, 
   94: 				buf->line_len - buf->line_eol, 0);
   95: 		printfEOL(buf, -1, 1);
   96: 	}
   97: 	return RETCODE_OK;
   98: }
   99: 
  100: static int
  101: bufEOL(int idx, void * __restrict buffer)
  102: {
  103: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  104: 		return RETCODE_ERR;
  105: 
  106: 	printfCR(buffer, 1);
  107: 	return RETCODE_EOL;
  108: }
  109: 
  110: static int
  111: bufEOF(int idx, void * __restrict buffer)
  112: {
  113: 	linebuffer_t *buf = buffer;
  114: 
  115: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  116: 		return RETCODE_ERR;
  117: 
  118: 	write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
  119: 	return RETCODE_EOF;
  120: }
  121: 
  122: static int
  123: bufTab(int idx, void * __restrict buffer)
  124: {
  125: 	linebuffer_t *buf = buffer;
  126: 
  127: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  128: 		return RETCODE_ERR;
  129: 
  130: 	/* show */
  131: 	write(buf->line_out, "shmink", 6);
  132: 
  133: 	return RETCODE_OK;
  134: }
  135: 
  136: static int
  137: bufUP(int idx, void * __restrict buffer)
  138: {
  139: 	linebuffer_t *buf = buffer;
  140: 	int pos;
  141: 
  142: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  143: 		return RETCODE_ERR;
  144: 
  145: 	if (!buf->line_h)
  146: 		buf->line_h = TAILQ_FIRST(&buf->line_history);
  147: 	else
  148: 		buf->line_h = TAILQ_NEXT(buf->line_h, hist_next);
  149: 	if (!buf->line_h)
  150: 		return RETCODE_OK;
  151: 
  152: 	clrscrEOL(buf);
  153: 	freeLineCLI(buf);
  154: 
  155: 	pos = buf->line_eol - buf->line_bol;
  156: 
  157: 	buf->line_len += buf->line_h->hist_len;
  158: 	buf->line_eol += buf->line_h->hist_len;
  159: 
  160: 	memcpy(buf->line_buf + pos, buf->line_h->hist_line, buf->line_h->hist_len);
  161: 	buf->line_buf[buf->line_len - 1] = 0;
  162: 
  163: 	printfEOL(buf, -1, 1);
  164: 	return RETCODE_OK;
  165: }
  166: 
  167: static int
  168: bufDOWN(int idx, void * __restrict buffer)
  169: {
  170: 	linebuffer_t *buf = buffer;
  171: 	int pos;
  172: 
  173: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  174: 		return RETCODE_ERR;
  175: 
  176: 	if (!buf->line_h)
  177: 		buf->line_h = TAILQ_LAST(&buf->line_history, tqHistoryHead);
  178: 	else
  179: 		buf->line_h = TAILQ_PREV(buf->line_h, tqHistoryHead, hist_next);
  180: 	if (!buf->line_h)
  181: 		return RETCODE_OK;
  182: 
  183: 	clrscrEOL(buf);
  184: 	freeLineCLI(buf);
  185: 
  186: 	pos = buf->line_eol - buf->line_bol;
  187: 
  188: 	buf->line_len += buf->line_h->hist_len;
  189: 	buf->line_eol += buf->line_h->hist_len;
  190: 
  191: 	memcpy(buf->line_buf + pos, buf->line_h->hist_line, buf->line_h->hist_len);
  192: 	buf->line_buf[buf->line_len - 1] = 0;
  193: 
  194: 	printfEOL(buf, -1, 1);
  195: 	return RETCODE_OK;
  196: }
  197: 
  198: static int
  199: bufClr(int idx, void * __restrict buffer)
  200: {
  201: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  202: 		return RETCODE_ERR;
  203: 
  204: 	clrscrEOL(buffer);
  205: 	freeLineCLI(buffer);
  206: 
  207: 	printfCR(buffer, 1);
  208: 	return RETCODE_OK;
  209: }
  210: 
  211: static int
  212: bufBS(int idx, void * __restrict buffer)
  213: {
  214: 	linebuffer_t *buf = buffer;
  215: 
  216: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  217: 		return RETCODE_ERR;
  218: 
  219: 	if (buf->line_bol < buf->line_eol) {
  220: 		clrscrEOL(buf);
  221: 
  222: 		buf->line_eol--;
  223: 		buf->line_len--;
  224: 		memmove(buf->line_buf + buf->line_eol, buf->line_buf + buf->line_eol + 1, 
  225: 				buf->line_len - buf->line_eol);
  226: 		buf->line_buf[buf->line_len - 1] = 0;
  227: 
  228: 		printfEOL(buf, buf->line_len - 1, 1);
  229: 		printfEOL(buf, -1, 1);
  230: 	}
  231: 
  232: 	return RETCODE_OK;
  233: }
  234: 
  235: static int
  236: bufBTAB(int idx, void * __restrict buffer)
  237: {
  238: 	linebuffer_t *buf = buffer;
  239: 
  240: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  241: 		return RETCODE_ERR;
  242: 
  243: 	if (buf->line_bol < buf->line_eol) {
  244: 		clrscrEOL(buf);
  245: 
  246: 		buf->line_eol--;
  247: 		buf->line_len--;
  248: 		buf->line_buf[buf->line_eol - buf->line_bol] = 0;
  249: 
  250: 		printfEOL(buf, -1, 1);
  251: 	}
  252: 
  253: 	return RETCODE_OK;
  254: }
  255: 
  256: static int
  257: bufMode(int idx, void * __restrict buffer)
  258: {
  259: 	linebuffer_t *buf = buffer;
  260: 
  261: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  262: 		return RETCODE_ERR;
  263: 
  264: 	buf->line_mode = !buf->line_mode ? LINEMODE_OVER : LINEMODE_INS;
  265: 	return RETCODE_OK;
  266: }
  267: 
  268: static int
  269: bufBegin(int idx, void * __restrict buffer)
  270: {
  271: 	linebuffer_t *buf = buffer;
  272: 
  273: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  274: 		return RETCODE_ERR;
  275: 
  276: 	buf->line_eol = buf->line_bol;
  277: 
  278: 	printfCR(buf, 1);
  279: 	return RETCODE_OK;
  280: }
  281: 
  282: static int
  283: bufEnd(int idx, void * __restrict buffer)
  284: {
  285: 	linebuffer_t *buf = buffer;
  286: 
  287: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  288: 		return RETCODE_ERR;
  289: 
  290: 	buf->line_eol = buf->line_len - 1;
  291: 
  292: 	printfEOL(buf, -1, 1);
  293: 	return RETCODE_OK;
  294: }
  295: 
  296: static int
  297: bufLEFT(int idx, void * __restrict buffer)
  298: {
  299: 	linebuffer_t *buf = buffer;
  300: 
  301: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  302: 		return RETCODE_ERR;
  303: 
  304: 	if (buf->line_bol < buf->line_eol)
  305: 		printfEOL(buf, --buf->line_eol - buf->line_bol, 1);
  306: 
  307: 	return RETCODE_OK;
  308: }
  309: 
  310: static int
  311: bufRIGHT(int idx, void * __restrict buffer)
  312: {
  313: 	linebuffer_t *buf = buffer;
  314: 
  315: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  316: 		return RETCODE_ERR;
  317: 
  318: 	if (buf->line_eol < buf->line_len - 1)
  319: 		printfEOL(buf, ++buf->line_eol - buf->line_bol, 1);
  320: 
  321: 	return RETCODE_OK;
  322: }
  323: 
  324: static int
  325: bufDel(int idx, void * __restrict buffer)
  326: {
  327: 	linebuffer_t *buf = buffer;
  328: 
  329: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  330: 		return RETCODE_ERR;
  331: 
  332: 	clrscrEOL(buf);
  333: 
  334: 	buf->line_len--;
  335: 	memmove(buf->line_buf + buf->line_eol, buf->line_buf + buf->line_eol + 1, 
  336: 			buf->line_len - buf->line_eol);
  337: 	buf->line_buf[buf->line_len - 1] = 0;
  338: 
  339: 	printfEOL(buf, buf->line_len - 1, 1);
  340: 	printfEOL(buf, -1, 1);
  341: 
  342: 	return RETCODE_OK;
  343: }
  344: 
  345: // ---------------------------------------------------------------
  346: 
  347: int
  348: bindKeyCLI(bindkey_t * __restrict key, linebuffer_t * __restrict buffer)
  349: {
  350: 	register int i;
  351: 
  352: 	if (!key || !buffer)
  353: 		return RETCODE_ERR;
  354: 
  355: 	for (i = 0; i < MAX_BINDKEY; i++)
  356: 		if (key->key_len == buffer->line_keys[i].key_len && 
  357: 				!memcmp(key->key_ch, buffer->line_keys[i].key_ch, key->key_len)) {
  358: 			buffer->line_keys[i].key_func = key->key_func;
  359: 			return i;
  360: 		}
  361: 	return RETCODE_OK;
  362: }
  363: 
  364: linebuffer_t *
  365: initCLI(int fin, int fout, const char *prompt)
  366: {
  367: 	linebuffer_t *buffer;
  368: 	bindkey_t *keys;
  369: 	register int i;
  370: 	struct termios t;
  371: 
  372: 	memset(&t, 0, sizeof t);
  373: 	/* init buffer */
  374: 	buffer = malloc(sizeof (linebuffer_t));
  375: 	if (!buffer)
  376: 		return NULL;
  377: 	else {
  378: 		memset(buffer, 0, sizeof(linebuffer_t));
  379: 
  380: 		buffer->line_in = fin;
  381: 		buffer->line_out = fout;
  382: 
  383: 		TAILQ_INIT(&buffer->line_history);
  384: 
  385: 		if (prompt) {
  386: 			buffer->line_prompt = strdup(prompt);
  387: 			if (!buffer->line_prompt) {
  388: 				free(buffer);
  389: 				return NULL;
  390: 			} else {
  391: 				buffer->line_bol = strlen(buffer->line_prompt);
  392: 				buffer->line_eol = buffer->line_bol;
  393: 			}
  394: 		}
  395: 	}
  396: 	buffer->line_buf = malloc(BUFSIZ);
  397: 	if (!buffer->line_buf) {
  398: 		if (buffer->line_prompt)
  399: 			free(buffer->line_prompt);
  400: 		free(buffer);
  401: 		return NULL;
  402: 	} else {
  403: 		memset(buffer->line_buf, 0, BUFSIZ);
  404: 		buffer->line_len = 1 + buffer->line_eol;
  405: 	}
  406: 	keys = calloc(MAX_BINDKEY + 1, sizeof(bindkey_t));
  407: 	if (!keys) {
  408: 		if (buffer->line_prompt)
  409: 			free(buffer->line_prompt);
  410: 		free(buffer->line_buf);
  411: 		free(buffer);
  412: 		return NULL;
  413: 	} else
  414: 		memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1));
  415: 
  416: 	/* fill key bindings */
  417: 	// ascii chars & ctrl+chars
  418: 	for (i = 0; i < 256; i++) {
  419: 		*keys[i].key_ch = (unsigned char) i;
  420: 		keys[i].key_len = 1;
  421: 
  422: 		if (!i || i == *K_CTRL_D)
  423: 			keys[i].key_func = bufEOF;
  424: 		if (i == *K_CTRL_M || i == *K_CTRL_J)
  425: 			keys[i].key_func = bufEOL;
  426: 		if (i == *K_CTRL_H || i == *K_BACKSPACE)
  427: 			keys[i].key_func = bufBS;
  428: 		if (i == *K_CTRL_C)
  429: 			keys[i].key_func = bufClr;
  430: 		if (i == *K_CTRL_A)
  431: 			keys[i].key_func = bufBegin;
  432: 		if (i == *K_CTRL_E)
  433: 			keys[i].key_func = bufEnd;
  434: 		if (i >= *K_SPACE && i < *K_BACKSPACE)
  435: 			keys[i].key_func = catCh2Buf;
  436: 		if (i > *K_BACKSPACE && i < 0xff)
  437: 			keys[i].key_func = catCh2Buf;
  438: 	}
  439: 	// alt+chars
  440: 	for (i = 256; i < 512; i++) {
  441: 		keys[i].key_ch[0] = 0x1b;
  442: 		keys[i].key_ch[1] = (unsigned char) i - 256;
  443: 		keys[i].key_len = 2;
  444: 	}
  445: 
  446: 	// 3 bytes
  447: 	keys[i].key_len = sizeof K_F1 - 1;
  448: 	memcpy(keys[i].key_ch, K_F1, keys[i++].key_len);
  449: 	keys[i].key_len = sizeof K_F2 - 1;
  450: 	memcpy(keys[i].key_ch, K_F2, keys[i++].key_len);
  451: 	keys[i].key_len = sizeof K_F3 - 1;
  452: 	memcpy(keys[i].key_ch, K_F3, keys[i++].key_len);
  453: 	keys[i].key_len = sizeof K_F4 - 1;
  454: 	memcpy(keys[i].key_ch, K_F4, keys[i++].key_len);
  455: 	keys[i].key_len = sizeof K_CTRL_SH_F1 - 1;
  456: 	memcpy(keys[i].key_ch, K_CTRL_SH_F1, keys[i++].key_len);
  457: 	keys[i].key_len = sizeof K_CTRL_SH_F2 - 1;
  458: 	memcpy(keys[i].key_ch, K_CTRL_SH_F2, keys[i++].key_len);
  459: 	keys[i].key_len = sizeof K_CTRL_SH_F3 - 1;
  460: 	memcpy(keys[i].key_ch, K_CTRL_SH_F3, keys[i++].key_len);
  461: 	keys[i].key_len = sizeof K_CTRL_SH_F4 - 1;
  462: 	memcpy(keys[i].key_ch, K_CTRL_SH_F4, keys[i++].key_len);
  463: 	keys[i].key_len = sizeof K_CTRL_SH_F5 - 1;
  464: 	memcpy(keys[i].key_ch, K_CTRL_SH_F5, keys[i++].key_len);
  465: 	keys[i].key_len = sizeof K_CTRL_SH_F6 - 1;
  466: 	memcpy(keys[i].key_ch, K_CTRL_SH_F6, keys[i++].key_len);
  467: 	keys[i].key_len = sizeof K_CTRL_SH_F7 - 1;
  468: 	memcpy(keys[i].key_ch, K_CTRL_SH_F7, keys[i++].key_len);
  469: 	keys[i].key_len = sizeof K_CTRL_SH_F8 - 1;
  470: 	memcpy(keys[i].key_ch, K_CTRL_SH_F8, keys[i++].key_len);
  471: 	keys[i].key_len = sizeof K_CTRL_SH_F9 - 1;
  472: 	memcpy(keys[i].key_ch, K_CTRL_SH_F9, keys[i++].key_len);
  473: 	keys[i].key_len = sizeof K_CTRL_SH_F10 - 1;
  474: 	memcpy(keys[i].key_ch, K_CTRL_SH_F10, keys[i++].key_len);
  475: 	keys[i].key_len = sizeof K_CTRL_SH_F11 - 1;
  476: 	memcpy(keys[i].key_ch, K_CTRL_SH_F11, keys[i++].key_len);
  477: 	keys[i].key_len = sizeof K_CTRL_SH_F12 - 1;
  478: 	memcpy(keys[i].key_ch, K_CTRL_SH_F12, keys[i++].key_len);
  479: 	keys[i].key_len = sizeof K_CTRL_F1 - 1;
  480: 	memcpy(keys[i].key_ch, K_CTRL_F1, keys[i++].key_len);
  481: 	keys[i].key_len = sizeof K_CTRL_F2 - 1;
  482: 	memcpy(keys[i].key_ch, K_CTRL_F2, keys[i++].key_len);
  483: 	keys[i].key_len = sizeof K_CTRL_F3 - 1;
  484: 	memcpy(keys[i].key_ch, K_CTRL_F3, keys[i++].key_len);
  485: 	keys[i].key_len = sizeof K_CTRL_F4 - 1;
  486: 	memcpy(keys[i].key_ch, K_CTRL_F4, keys[i++].key_len);
  487: 	keys[i].key_len = sizeof K_CTRL_F5 - 1;
  488: 	memcpy(keys[i].key_ch, K_CTRL_F5, keys[i++].key_len);
  489: 	keys[i].key_len = sizeof K_CTRL_F6 - 1;
  490: 	memcpy(keys[i].key_ch, K_CTRL_F6, keys[i++].key_len);
  491: 	keys[i].key_len = sizeof K_CTRL_F7 - 1;
  492: 	memcpy(keys[i].key_ch, K_CTRL_F7, keys[i++].key_len);
  493: 	keys[i].key_len = sizeof K_CTRL_F8 - 1;
  494: 	memcpy(keys[i].key_ch, K_CTRL_F8, keys[i++].key_len);
  495: 	keys[i].key_len = sizeof K_CTRL_F9 - 1;
  496: 	memcpy(keys[i].key_ch, K_CTRL_F9, keys[i++].key_len);
  497: 	keys[i].key_len = sizeof K_CTRL_F10 - 1;
  498: 	memcpy(keys[i].key_ch, K_CTRL_F10, keys[i++].key_len);
  499: 	keys[i].key_len = sizeof K_CTRL_F11 - 1;
  500: 	memcpy(keys[i].key_ch, K_CTRL_F11, keys[i++].key_len);
  501: 	keys[i].key_len = sizeof K_CTRL_F12 - 1;
  502: 	memcpy(keys[i].key_ch, K_CTRL_F12, keys[i++].key_len);
  503: 	keys[i].key_len = sizeof K_HOME - 1;
  504: 	keys[i].key_func = bufBegin;
  505: 	memcpy(keys[i].key_ch, K_HOME, keys[i++].key_len);
  506: 	keys[i].key_len = sizeof K_END - 1;
  507: 	keys[i].key_func = bufEnd;
  508: 	memcpy(keys[i].key_ch, K_END, keys[i++].key_len);
  509: 	keys[i].key_len = sizeof K_UP - 1;
  510: 	keys[i].key_func = bufUP;
  511: 	memcpy(keys[i].key_ch, K_UP, keys[i++].key_len);
  512: 	keys[i].key_len = sizeof K_DOWN - 1;
  513: 	keys[i].key_func = bufDOWN;
  514: 	memcpy(keys[i].key_ch, K_DOWN, keys[i++].key_len);
  515: 	keys[i].key_len = sizeof K_RIGHT - 1;
  516: 	keys[i].key_func = bufRIGHT;
  517: 	memcpy(keys[i].key_ch, K_RIGHT, keys[i++].key_len);
  518: 	keys[i].key_len = sizeof K_LEFT - 1;
  519: 	keys[i].key_func = bufLEFT;
  520: 	memcpy(keys[i].key_ch, K_LEFT, keys[i++].key_len);
  521: 	keys[i].key_len = sizeof K_BTAB - 1;
  522: 	keys[i].key_func = bufBTAB;
  523: 	memcpy(keys[i].key_ch, K_BTAB, keys[i++].key_len);
  524: 	// 4 bytes
  525: 	keys[i].key_len = sizeof K_INS - 1;
  526: 	keys[i].key_func = bufMode;
  527: 	memcpy(keys[i].key_ch, K_INS, keys[i++].key_len);
  528: 	keys[i].key_len = sizeof K_DEL - 1;
  529: 	keys[i].key_func = bufDel;
  530: 	memcpy(keys[i].key_ch, K_DEL, keys[i++].key_len);
  531: 	keys[i].key_len = sizeof K_PGUP - 1;
  532: 	memcpy(keys[i].key_ch, K_PGUP, keys[i++].key_len);
  533: 	keys[i].key_len = sizeof K_PGDN - 1;
  534: 	memcpy(keys[i].key_ch, K_PGDN, keys[i++].key_len);
  535: 	// 5 bytes
  536: 	keys[i].key_len = sizeof K_F5 - 1;
  537: 	memcpy(keys[i].key_ch, K_F5, keys[i++].key_len);
  538: 	keys[i].key_len = sizeof K_F6 - 1;
  539: 	memcpy(keys[i].key_ch, K_F6, keys[i++].key_len);
  540: 	keys[i].key_len = sizeof K_F7 - 1;
  541: 	memcpy(keys[i].key_ch, K_F7, keys[i++].key_len);
  542: 	keys[i].key_len = sizeof K_F8 - 1;
  543: 	memcpy(keys[i].key_ch, K_F8, keys[i++].key_len);
  544: 	keys[i].key_len = sizeof K_F9 - 1;
  545: 	memcpy(keys[i].key_ch, K_F9, keys[i++].key_len);
  546: 	keys[i].key_len = sizeof K_F10 - 1;
  547: 	memcpy(keys[i].key_ch, K_F10, keys[i++].key_len);
  548: 	keys[i].key_len = sizeof K_F11 - 1;
  549: 	memcpy(keys[i].key_ch, K_F11, keys[i++].key_len);
  550: 	keys[i].key_len = sizeof K_F12 - 1;
  551: 	memcpy(keys[i].key_ch, K_F12, keys[i++].key_len);
  552: 
  553: 	tcgetattr(buffer->line_in, &t);
  554: 	t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
  555: 	t.c_iflag |= IGNBRK;
  556: 	t.c_cc[VMIN] = 1;
  557: 	t.c_cc[VTIME] = 0;
  558: 	tcsetattr(buffer->line_in, TCSANOW, &t);
  559: 
  560: 	buffer->line_keys = keys;
  561: 	return buffer;
  562: }
  563: 
  564: void
  565: endCLI(linebuffer_t * __restrict buffer)
  566: {
  567: 	struct tagHistory *h;
  568: 
  569: 	if (buffer) {
  570: 		while ((h = TAILQ_FIRST(&buffer->line_history))) {
  571: 			TAILQ_REMOVE(&buffer->line_history, h, hist_next);
  572: 			free(h);
  573: 		}
  574: 
  575: 		if (buffer->line_prompt)
  576: 			free(buffer->line_prompt);
  577: 
  578: 		if (buffer->line_keys)
  579: 			free(buffer->line_keys);
  580: 		if (buffer->line_buf)
  581: 			free(buffer->line_buf);
  582: 
  583: 		free(buffer);
  584: 		buffer = NULL;
  585: 	}
  586: }
  587: 
  588: void
  589: setPromptCLI(linebuffer_t * __restrict buffer, const char *prompt)
  590: {
  591: 	if (buffer) {
  592: 		if (buffer->line_prompt) {
  593: 			free(buffer->line_prompt);
  594: 			buffer->line_prompt = NULL;
  595: 			buffer->line_bol = 0;
  596: 		}
  597: 
  598: 		if (prompt) {
  599: 			buffer->line_prompt = strdup(prompt);
  600: 			if (buffer->line_prompt) {
  601: 				buffer->line_bol = strlen(buffer->line_prompt);
  602: 				buffer->line_eol = buffer->line_bol;
  603: 				buffer->line_len = 1 + buffer->line_eol;
  604: 			}
  605: 		}
  606: 	}
  607: }
  608: 
  609: int
  610: freeLineCLI(linebuffer_t * __restrict buffer)
  611: {
  612: 	int code = RETCODE_ERR;
  613: 
  614: 	if (buffer) {
  615: 		if (buffer->line_buf)
  616: 			free(buffer->line_buf);
  617: 
  618: 		buffer->line_buf = malloc(BUFSIZ);
  619: 		if (buffer->line_buf) {
  620: 			memset(buffer->line_buf, 0, BUFSIZ);
  621: 			buffer->line_eol = buffer->line_bol;
  622: 			buffer->line_len = 1 + buffer->line_eol;
  623: 
  624: 			code = RETCODE_OK;
  625: 		}
  626: 	}
  627: 
  628: 	return code;
  629: }
  630: 
  631: int
  632: readLineCLI(linebuffer_t * __restrict buffer)
  633: {
  634: 	int code, readLen;
  635: 	register int i;
  636: 	char buf[BUFSIZ];
  637: 	struct pollfd fds;
  638: 
  639: 	if (!buffer)
  640: 		return RETCODE_ERR;
  641: 
  642: 	memset(&fds, 0, sizeof fds);
  643: 	fds.fd = buffer->line_in;
  644: 	fds.events = POLLIN;
  645: 
  646: 	printfCR(buffer, 1);
  647: 	while (42) {
  648: 		if (poll(&fds, 1, -1) < 1)
  649: 			return RETCODE_ERR;
  650: 
  651: 		memset(buf, 0, sizeof buf);
  652: 		readLen = read(buffer->line_in, buf, BUFSIZ);
  653: 		if (readLen == -1)
  654: 			return RETCODE_ERR;
  655: 		if (!readLen)
  656: 			return RETCODE_EOF;
  657: 
  658: recheck:
  659: //		for (i = 0; i < readLen; i++)
  660: //			printf("i=%d readLen=%d buf=%x\n", i, readLen, (u_char) buf[i]);
  661: 		for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
  662: 			if (readLen >= buffer->line_keys[i].key_len && 
  663: 					!memcmp(buffer->line_keys[i].key_ch, buf, buffer->line_keys[i].key_len)) {
  664: 				readLen -= buffer->line_keys[i].key_len;
  665: 				if (readLen)
  666: 					memmove(buf, buf + buffer->line_keys[i].key_len, readLen);
  667: 				else
  668: 					memset(buf, 0, buffer->line_keys[i].key_len);
  669: 
  670: 				if (buffer->line_keys[i].key_func)
  671: 					if ((code = buffer->line_keys[i].key_func(i, buffer)))
  672: 						readLen = 0;
  673: 
  674: 				if (readLen)
  675: 					goto recheck;
  676: 				else
  677: 					break;
  678: 			}
  679: 
  680: 		if (code)
  681: 			break;
  682: 	}
  683: 
  684: 	return code;
  685: }
  686: 
  687: int
  688: addHistoryCLI(linebuffer_t * __restrict buffer, const char * __restrict str)
  689: {
  690: 	struct tagHistory *h;
  691: 
  692: 	if (!buffer)
  693: 		return RETCODE_ERR;
  694: 
  695: 	if (!(h = malloc(sizeof(struct tagHistory)))) {
  696: 		return RETCODE_ERR;
  697: 	} else
  698: 		memset(h, 0, sizeof(struct tagHistory));
  699: 
  700: 	if (str) {
  701: 		if (!*str) {
  702: 			free(h);
  703: 			return RETCODE_OK;
  704: 		}
  705: 
  706: 		h->hist_len = strlcpy(h->hist_line, str, BUFSIZ);
  707: 	} else {
  708: 		if (!*buffer->line_buf || buffer->line_len < 2) {
  709: 			free(h);
  710: 			return RETCODE_OK;
  711: 		}
  712: 
  713: 		memcpy(h->hist_line, buffer->line_buf, (h->hist_len = buffer->line_len));
  714: 		io_TrimStr((unsigned char*) h->hist_line);
  715: 		h->hist_len = strlen(h->hist_line);
  716: 	}
  717: 
  718: 	TAILQ_INSERT_HEAD(&buffer->line_history, h, hist_next);
  719: 	return h->hist_len;
  720: }
  721: 
  722: int
  723: saveHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile, int lines)
  724: {
  725: 	FILE *f;
  726: 	mode_t mode;
  727: 	char szFName[MAXPATHLEN];
  728: 	struct tagHistory *h;
  729: 
  730: 	if (!buffer)
  731: 		return RETCODE_ERR;
  732: 	if (!histfile)
  733: 		strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
  734: 	else
  735: 		strlcpy(szFName, histfile, MAXPATHLEN);
  736: 
  737: 	mode = umask(0177);
  738: 	f = fopen(szFName, "w");
  739: 	if (!f)
  740: 		return RETCODE_ERR;
  741: 	TAILQ_FOREACH(h, &buffer->line_history, hist_next) {
  742: 		fprintf(f, "%s\n", h->hist_line);
  743: 
  744: 		if (lines)
  745: 			lines--;
  746: 		else
  747: 			break;
  748: 	}
  749: 	fclose(f);
  750: 	umask(mode);
  751: 
  752: 	return RETCODE_OK;
  753: }
  754: 
  755: int
  756: loadHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile)
  757: {
  758: 	FILE *f;
  759: 	char szFName[MAXPATHLEN], buf[BUFSIZ];
  760: 	struct tagHistory *h;
  761: 
  762: 	if (!buffer)
  763: 		return RETCODE_ERR;
  764: 	if (!histfile)
  765: 		strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
  766: 	else
  767: 		strlcpy(szFName, histfile, MAXPATHLEN);
  768: 
  769: 	f = fopen(szFName, "r");
  770: 	if (!f)
  771: 		return RETCODE_ERR;
  772: 	while (fgets(buf, BUFSIZ, f)) {
  773: 		if (!*buf || *buf == '#')
  774: 			continue;
  775: 		else
  776: 			io_TrimStr((unsigned char*) buf);
  777: 
  778: 		if (!(h = malloc(sizeof(struct tagHistory)))) {
  779: 			fclose(f);
  780: 			return RETCODE_ERR;
  781: 		} else
  782: 			memset(h, 0, sizeof(struct tagHistory));
  783: 
  784: 		h->hist_len = strlcpy(h->hist_line, buf, BUFSIZ);
  785: 		TAILQ_INSERT_TAIL(&buffer->line_history, h, hist_next);
  786: 	}
  787: 	fclose(f);
  788: 
  789: 	return RETCODE_OK;
  790: }
  791: 
  792: inline void
  793: resetHistoryCLI(linebuffer_t * __restrict buffer)
  794: {
  795: 	buffer->line_h = NULL;
  796: }
  797: 
  798: // ------------------------------------------------------------
  799: 
  800: int
  801: main()
  802: {
  803: 	int ret;
  804: 	bindkey_t key = { sizeof K_TAB - 1, K_TAB, bufTab };
  805: 	linebuffer_t *buffer = initCLI(STDIN_FILENO, STDOUT_FILENO, /*CLI_PROMPT*/ NULL);
  806: 
  807: 	bindKeyCLI(&key, buffer);
  808: 
  809: 	loadHistoryCLI(buffer, NULL);
  810: 
  811: 	while (42) {
  812: 		ret = readLineCLI(buffer);
  813: 		addHistoryCLI(buffer, NULL);
  814: 
  815: 		printf("LINE=%s (%d)/%d/%d CODE=%d\n", buffer->line_buf, buffer->line_len, buffer->line_eol, buffer->line_bol, ret);
  816: 
  817: 		freeLineCLI(buffer);
  818: 		resetHistoryCLI(buffer);
  819: 
  820: 		if (ret == RETCODE_EOF)
  821: 			break;
  822: 	}
  823: 
  824: 	saveHistoryCLI(buffer, NULL, HISTORY_LINES);
  825: 
  826: 	endCLI(buffer);
  827: 	return 0;
  828: }

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