File:  [ELWIX - Embedded LightWeight unIX -] / libaitcli / example / t.c
Revision 1.1.2.1: download - view: text, annotated - select for diffs - revision graph
Wed Jun 2 17:17:56 2010 UTC (14 years, 1 month ago) by misho
Branches: cli1_0
Diff to: branchpoint 1.1: preferred, unified
experimental & development code

    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/param.h>
    9: #include <sys/stat.h>
   10: #include <sys/queue.h>
   11: #include "keys.h"
   12: 
   13: 
   14: int freeLineCLI(linebuffer_t * __restrict buffer);
   15: 
   16: 
   17: static int
   18: catCh2Buf(int idx, void * __restrict buffer)
   19: {
   20: 	linebuffer_t *buf = buffer;
   21: 	char *ptr;
   22: 
   23: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
   24: 		return RETCODE_ERR;
   25: 
   26: 	ptr = realloc(buf->line_buf, buf->line_len + buf->line_keys[idx].key_len);
   27: 	if (!ptr)
   28: 		return RETCODE_ERR;
   29: 	else
   30: 		buf->line_len += buf->line_keys[idx].key_len;
   31: 
   32: 	memcpy(ptr + buf->line_eol, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   33: 	ptr[buf->line_len - 1] = 0;
   34: 
   35: 	/* show */
   36: 	write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   37: 
   38: 	buf->line_eol += buf->line_keys[idx].key_len;
   39: 	buf->line_buf = ptr;
   40: 	return RETCODE_OK;
   41: }
   42: 
   43: static int
   44: bufEOL(int idx, void * __restrict buffer)
   45: {
   46: 	linebuffer_t *buf = buffer;
   47: 
   48: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
   49: 		return RETCODE_ERR;
   50: 
   51: 	/* show */
   52: 	write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   53: 
   54: 	return RETCODE_EOL;
   55: }
   56: 
   57: static int
   58: bufEOF(int idx, void * __restrict buffer)
   59: {
   60: 	linebuffer_t *buf = buffer;
   61: 
   62: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
   63: 		return RETCODE_ERR;
   64: 
   65: 	/* show */
   66: 	write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   67: 
   68: 	return RETCODE_EOF;
   69: }
   70: 
   71: static int
   72: bufTab(int idx, void * __restrict buffer)
   73: {
   74: 	linebuffer_t *buf = buffer;
   75: 
   76: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
   77: 		return RETCODE_ERR;
   78: 
   79: 	/* show */
   80: 	write(buf->line_out, "shmink", 6);
   81: 
   82: 	return RETCODE_OK;
   83: }
   84: 
   85: static int
   86: bufUP(int idx, void * __restrict buffer)
   87: {
   88: 	linebuffer_t *buf = buffer;
   89: 	char *ptr;
   90: 	register int i;
   91: 
   92: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
   93: 		return RETCODE_ERR;
   94: 
   95: 	if (!buf->line_h)
   96: 		buf->line_h = TAILQ_FIRST(&buf->line_history);
   97: 	else
   98: 		buf->line_h = TAILQ_NEXT(buf->line_h, hist_next);
   99: 	if (!buf->line_h)
  100: 		return RETCODE_OK;
  101: 
  102: 	/* clear line */
  103: 	write(buf->line_out, K_CR, 1);
  104: 	for (i = 0; i < buf->line_len; i++)
  105: 		write(buf->line_out, K_SPACE, 1);
  106: 
  107: 	freeLineCLI(buffer);
  108: 	ptr = realloc(buf->line_buf, buf->line_len + buf->line_h->hist_len);
  109: 	if (!ptr)
  110: 		return RETCODE_ERR;
  111: 	else
  112: 		buf->line_len += buf->line_h->hist_len;
  113: 
  114: 	memcpy(ptr + buf->line_eol, buf->line_h->hist_line, buf->line_h->hist_len);
  115: 	ptr[buf->line_len - 1] = 0;
  116: 
  117: 	buf->line_eol += buf->line_h->hist_len;
  118: 	buf->line_buf = ptr;
  119: 
  120: 	/* show */
  121: 	write(buf->line_out, K_CR, 1);
  122: 	write(buf->line_out, buf->line_buf, buf->line_len);
  123: 
  124: 	return RETCODE_OK;
  125: }
  126: 
  127: static int
  128: bufDOWN(int idx, void * __restrict buffer)
  129: {
  130: 	linebuffer_t *buf = buffer;
  131: 	char *ptr;
  132: 	register int i;
  133: 
  134: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  135: 		return RETCODE_ERR;
  136: 
  137: 	if (!buf->line_h)
  138: 		buf->line_h = TAILQ_LAST(&buf->line_history, tqHistoryHead);
  139: 	else
  140: 		buf->line_h = TAILQ_PREV(buf->line_h, tqHistoryHead, hist_next);
  141: 	if (!buf->line_h)
  142: 		return RETCODE_OK;
  143: 
  144: 	/* clear line */
  145: 	write(buf->line_out, K_CR, 1);
  146: 	for (i = 0; i < buf->line_len; i++)
  147: 		write(buf->line_out, K_SPACE, 1);
  148: 
  149: 	freeLineCLI(buffer);
  150: 	ptr = realloc(buf->line_buf, buf->line_len + buf->line_h->hist_len);
  151: 	if (!ptr)
  152: 		return RETCODE_ERR;
  153: 	else
  154: 		buf->line_len += buf->line_h->hist_len;
  155: 
  156: 	memcpy(ptr + buf->line_eol, buf->line_h->hist_line, buf->line_h->hist_len);
  157: 	ptr[buf->line_len - 1] = 0;
  158: 
  159: 	buf->line_eol += buf->line_h->hist_len;
  160: 	buf->line_buf = ptr;
  161: 
  162: 	/* show */
  163: 	write(buf->line_out, K_CR, 1);
  164: 	write(buf->line_out, buf->line_buf, buf->line_len);
  165: 
  166: 	return RETCODE_OK;
  167: }
  168: 
  169: static int
  170: bufClr(int idx, void * __restrict buffer)
  171: {
  172: 	linebuffer_t *buf = buffer;
  173: 	register int i;
  174: 
  175: 	if (!buffer || idx < 0 || idx > MAX_BINDKEY)
  176: 		return RETCODE_ERR;
  177: 
  178: 	/* clear line */
  179: 	write(buf->line_out, K_CR, 1);
  180: 	for (i = 0; i < buf->line_len; i++)
  181: 		write(buf->line_out, K_SPACE, 1);
  182: 
  183: 	freeLineCLI(buffer);
  184: 
  185: 	write(buf->line_out, K_CR, 1);
  186: 	return RETCODE_OK;
  187: }
  188: 
  189: // ---------------------------------------------------------------
  190: 
  191: int
  192: bindKeyCLI(bindkey_t * __restrict key, linebuffer_t * __restrict buffer)
  193: {
  194: 	register int i;
  195: 
  196: 	if (!key || !buffer)
  197: 		return RETCODE_ERR;
  198: 
  199: 	for (i = 0; i < MAX_BINDKEY; i++)
  200: 		if (key->key_len == buffer->line_keys[i].key_len && 
  201: 				!memcmp(key->key_ch, buffer->line_keys[i].key_ch, key->key_len)) {
  202: 			buffer->line_keys[i].key_func = key->key_func;
  203: 			return i;
  204: 		}
  205: 	return RETCODE_OK;
  206: }
  207: 
  208: linebuffer_t *
  209: initCLI(int fin, int fout)
  210: {
  211: 	linebuffer_t *buffer;
  212: 	bindkey_t *keys;
  213: 	register int i;
  214: 	struct termios t;
  215: 
  216: 	memset(&t, 0, sizeof t);
  217: 	/* init buffer */
  218: 	buffer = malloc(sizeof (linebuffer_t));
  219: 	if (!buffer)
  220: 		return NULL;
  221: 	else {
  222: 		memset(buffer, 0, sizeof(linebuffer_t));
  223: 
  224: 		buffer->line_in = fin;
  225: 		buffer->line_out = fout;
  226: 
  227: 		TAILQ_INIT(&buffer->line_history);
  228: 	}
  229: 	buffer->line_buf = malloc(1);
  230: 	if (!buffer->line_buf) {
  231: 		free(buffer);
  232: 		return NULL;
  233: 	} else {
  234: 		*buffer->line_buf = 0;
  235: 		buffer->line_len = 1;
  236: 	}
  237: 	keys = calloc(MAX_BINDKEY + 1, sizeof(bindkey_t));
  238: 	if (!keys) {
  239: 		free(buffer->line_buf);
  240: 		free(buffer);
  241: 		return NULL;
  242: 	} else
  243: 		memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1));
  244: 
  245: 	/* fill key bindings */
  246: 	// ascii chars & ctrl+chars
  247: 	for (i = 0; i < 256; i++) {
  248: 		*keys[i].key_ch = (unsigned char) i;
  249: 		keys[i].key_len = 1;
  250: 
  251: 		if (!i || i == *K_CTRL_D)
  252: 			keys[i].key_func = bufEOF;
  253: 		if (i == *K_CTRL_M || i == *K_CTRL_J)
  254: 			keys[i].key_func = bufEOL;
  255: 		if (i == *K_CTRL_C)
  256: 			keys[i].key_func = bufClr;
  257: 		if (i >= *K_SPACE && i < *K_BACKSPACE)
  258: 			keys[i].key_func = catCh2Buf;
  259: 		if (i > *K_BACKSPACE && i < 0xff)
  260: 			keys[i].key_func = catCh2Buf;
  261: 	}
  262: 	// alt+chars
  263: 	for (i = 256; i < 512; i++) {
  264: 		keys[i].key_ch[0] = 0x1b;
  265: 		keys[i].key_ch[1] = (unsigned char) i - 256;
  266: 		keys[i].key_len = 2;
  267: 	}
  268: 
  269: 	// 3 bytes
  270: 	keys[i].key_len = sizeof K_F1 - 1;
  271: 	memcpy(keys[i].key_ch, K_F1, keys[i++].key_len);
  272: 	keys[i].key_len = sizeof K_F2 - 1;
  273: 	memcpy(keys[i].key_ch, K_F2, keys[i++].key_len);
  274: 	keys[i].key_len = sizeof K_F3 - 1;
  275: 	memcpy(keys[i].key_ch, K_F3, keys[i++].key_len);
  276: 	keys[i].key_len = sizeof K_F4 - 1;
  277: 	memcpy(keys[i].key_ch, K_F4, keys[i++].key_len);
  278: 	keys[i].key_len = sizeof K_CTRL_SH_F1 - 1;
  279: 	memcpy(keys[i].key_ch, K_CTRL_SH_F1, keys[i++].key_len);
  280: 	keys[i].key_len = sizeof K_CTRL_SH_F2 - 1;
  281: 	memcpy(keys[i].key_ch, K_CTRL_SH_F2, keys[i++].key_len);
  282: 	keys[i].key_len = sizeof K_CTRL_SH_F3 - 1;
  283: 	memcpy(keys[i].key_ch, K_CTRL_SH_F3, keys[i++].key_len);
  284: 	keys[i].key_len = sizeof K_CTRL_SH_F4 - 1;
  285: 	memcpy(keys[i].key_ch, K_CTRL_SH_F4, keys[i++].key_len);
  286: 	keys[i].key_len = sizeof K_CTRL_SH_F5 - 1;
  287: 	memcpy(keys[i].key_ch, K_CTRL_SH_F5, keys[i++].key_len);
  288: 	keys[i].key_len = sizeof K_CTRL_SH_F6 - 1;
  289: 	memcpy(keys[i].key_ch, K_CTRL_SH_F6, keys[i++].key_len);
  290: 	keys[i].key_len = sizeof K_CTRL_SH_F7 - 1;
  291: 	memcpy(keys[i].key_ch, K_CTRL_SH_F7, keys[i++].key_len);
  292: 	keys[i].key_len = sizeof K_CTRL_SH_F8 - 1;
  293: 	memcpy(keys[i].key_ch, K_CTRL_SH_F8, keys[i++].key_len);
  294: 	keys[i].key_len = sizeof K_CTRL_SH_F9 - 1;
  295: 	memcpy(keys[i].key_ch, K_CTRL_SH_F9, keys[i++].key_len);
  296: 	keys[i].key_len = sizeof K_CTRL_SH_F10 - 1;
  297: 	memcpy(keys[i].key_ch, K_CTRL_SH_F10, keys[i++].key_len);
  298: 	keys[i].key_len = sizeof K_CTRL_SH_F11 - 1;
  299: 	memcpy(keys[i].key_ch, K_CTRL_SH_F11, keys[i++].key_len);
  300: 	keys[i].key_len = sizeof K_CTRL_SH_F12 - 1;
  301: 	memcpy(keys[i].key_ch, K_CTRL_SH_F12, keys[i++].key_len);
  302: 	keys[i].key_len = sizeof K_CTRL_F1 - 1;
  303: 	memcpy(keys[i].key_ch, K_CTRL_F1, keys[i++].key_len);
  304: 	keys[i].key_len = sizeof K_CTRL_F2 - 1;
  305: 	memcpy(keys[i].key_ch, K_CTRL_F2, keys[i++].key_len);
  306: 	keys[i].key_len = sizeof K_CTRL_F3 - 1;
  307: 	memcpy(keys[i].key_ch, K_CTRL_F3, keys[i++].key_len);
  308: 	keys[i].key_len = sizeof K_CTRL_F4 - 1;
  309: 	memcpy(keys[i].key_ch, K_CTRL_F4, keys[i++].key_len);
  310: 	keys[i].key_len = sizeof K_CTRL_F5 - 1;
  311: 	memcpy(keys[i].key_ch, K_CTRL_F5, keys[i++].key_len);
  312: 	keys[i].key_len = sizeof K_CTRL_F6 - 1;
  313: 	memcpy(keys[i].key_ch, K_CTRL_F6, keys[i++].key_len);
  314: 	keys[i].key_len = sizeof K_CTRL_F7 - 1;
  315: 	memcpy(keys[i].key_ch, K_CTRL_F7, keys[i++].key_len);
  316: 	keys[i].key_len = sizeof K_CTRL_F8 - 1;
  317: 	memcpy(keys[i].key_ch, K_CTRL_F8, keys[i++].key_len);
  318: 	keys[i].key_len = sizeof K_CTRL_F9 - 1;
  319: 	memcpy(keys[i].key_ch, K_CTRL_F9, keys[i++].key_len);
  320: 	keys[i].key_len = sizeof K_CTRL_F10 - 1;
  321: 	memcpy(keys[i].key_ch, K_CTRL_F10, keys[i++].key_len);
  322: 	keys[i].key_len = sizeof K_CTRL_F11 - 1;
  323: 	memcpy(keys[i].key_ch, K_CTRL_F11, keys[i++].key_len);
  324: 	keys[i].key_len = sizeof K_CTRL_F12 - 1;
  325: 	memcpy(keys[i].key_ch, K_CTRL_F12, keys[i++].key_len);
  326: 	keys[i].key_len = sizeof K_HOME - 1;
  327: 	memcpy(keys[i].key_ch, K_HOME, keys[i++].key_len);
  328: 	keys[i].key_len = sizeof K_END - 1;
  329: 	memcpy(keys[i].key_ch, K_END, keys[i++].key_len);
  330: 	keys[i].key_len = sizeof K_UP - 1;
  331: 	keys[i].key_func = bufUP;
  332: 	memcpy(keys[i].key_ch, K_UP, keys[i++].key_len);
  333: 	keys[i].key_len = sizeof K_DOWN - 1;
  334: 	keys[i].key_func = bufDOWN;
  335: 	memcpy(keys[i].key_ch, K_DOWN, keys[i++].key_len);
  336: 	keys[i].key_len = sizeof K_RIGHT - 1;
  337: 	memcpy(keys[i].key_ch, K_RIGHT, keys[i++].key_len);
  338: 	keys[i].key_len = sizeof K_LEFT - 1;
  339: 	memcpy(keys[i].key_ch, K_LEFT, keys[i++].key_len);
  340: 	keys[i].key_len = sizeof K_BTAB - 1;
  341: 	memcpy(keys[i].key_ch, K_BTAB, keys[i++].key_len);
  342: 	// 4 bytes
  343: 	keys[i].key_len = sizeof K_INS - 1;
  344: 	memcpy(keys[i].key_ch, K_INS, keys[i++].key_len);
  345: 	keys[i].key_len = sizeof K_DEL - 1;
  346: 	memcpy(keys[i].key_ch, K_DEL, keys[i++].key_len);
  347: 	keys[i].key_len = sizeof K_PGUP - 1;
  348: 	memcpy(keys[i].key_ch, K_PGUP, keys[i++].key_len);
  349: 	keys[i].key_len = sizeof K_PGDN - 1;
  350: 	memcpy(keys[i].key_ch, K_PGDN, keys[i++].key_len);
  351: 	// 5 bytes
  352: 	keys[i].key_len = sizeof K_F5 - 1;
  353: 	memcpy(keys[i].key_ch, K_F5, keys[i++].key_len);
  354: 	keys[i].key_len = sizeof K_F6 - 1;
  355: 	memcpy(keys[i].key_ch, K_F6, keys[i++].key_len);
  356: 	keys[i].key_len = sizeof K_F7 - 1;
  357: 	memcpy(keys[i].key_ch, K_F7, keys[i++].key_len);
  358: 	keys[i].key_len = sizeof K_F8 - 1;
  359: 	memcpy(keys[i].key_ch, K_F8, keys[i++].key_len);
  360: 	keys[i].key_len = sizeof K_F9 - 1;
  361: 	memcpy(keys[i].key_ch, K_F9, keys[i++].key_len);
  362: 	keys[i].key_len = sizeof K_F10 - 1;
  363: 	memcpy(keys[i].key_ch, K_F10, keys[i++].key_len);
  364: 	keys[i].key_len = sizeof K_F11 - 1;
  365: 	memcpy(keys[i].key_ch, K_F11, keys[i++].key_len);
  366: 	keys[i].key_len = sizeof K_F12 - 1;
  367: 	memcpy(keys[i].key_ch, K_F12, keys[i++].key_len);
  368: 
  369: 	tcgetattr(buffer->line_in, &t);
  370: 	t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
  371: 	t.c_iflag |= IGNBRK;
  372: 	t.c_cc[VMIN] = 1;
  373: 	t.c_cc[VTIME] = 0;
  374: 	tcsetattr(buffer->line_in, TCSANOW, &t);
  375: 
  376: 	buffer->line_keys = keys;
  377: 	return buffer;
  378: }
  379: 
  380: void
  381: endCLI(linebuffer_t * __restrict buffer)
  382: {
  383: 	struct tagHistory *h;
  384: 
  385: 	if (buffer) {
  386: 		while ((h = TAILQ_FIRST(&buffer->line_history))) {
  387: 			TAILQ_REMOVE(&buffer->line_history, h, hist_next);
  388: 			free(h);
  389: 		}
  390: 
  391: 		if (buffer->line_keys)
  392: 			free(buffer->line_keys);
  393: 		if (buffer->line_buf)
  394: 			free(buffer->line_buf);
  395: 
  396: 		free(buffer);
  397: 		buffer = NULL;
  398: 	}
  399: }
  400: 
  401: int
  402: freeLineCLI(linebuffer_t * __restrict buffer)
  403: {
  404: 	int code = RETCODE_ERR;
  405: 
  406: 	if (buffer) {
  407: 		if (buffer->line_buf)
  408: 			free(buffer->line_buf);
  409: 
  410: 		buffer->line_buf = malloc(1);
  411: 		if (buffer->line_buf) {
  412: 			*buffer->line_buf = 0;
  413: 			buffer->line_eol = 0;
  414: 			buffer->line_len = 1;
  415: 
  416: 			code = RETCODE_OK;
  417: 		}
  418: 	}
  419: 
  420: 	return code;
  421: }
  422: 
  423: int
  424: readLineCLI(linebuffer_t * __restrict buffer)
  425: {
  426: 	int code, readLen;
  427: 	register int i;
  428: 	char buf[BUFSIZ];
  429: 	struct pollfd fds;
  430: 
  431: 	if (!buffer)
  432: 		return RETCODE_ERR;
  433: 
  434: 	memset(&fds, 0, sizeof fds);
  435: 	fds.fd = buffer->line_in;
  436: 	fds.events = POLLIN;
  437: 
  438: 	while (42) {
  439: 		if (poll(&fds, 1, -1) < 1)
  440: 			return RETCODE_ERR;
  441: 
  442: 		memset(buf, 0, sizeof buf);
  443: 		readLen = read(buffer->line_in, buf, BUFSIZ);
  444: 		if (readLen == -1)
  445: 			return RETCODE_ERR;
  446: 		if (!readLen)
  447: 			return RETCODE_EOF;
  448: 
  449: recheck:
  450: //		for (i = 0; i < readLen; i++)
  451: //			printf("i=%d readLen=%d buf=%x\n", i, readLen, (u_char) buf[i]);
  452: 		for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
  453: 			if (readLen >= buffer->line_keys[i].key_len && 
  454: 					!memcmp(buffer->line_keys[i].key_ch, buf, buffer->line_keys[i].key_len)) {
  455: 				readLen -= buffer->line_keys[i].key_len;
  456: 				if (readLen)
  457: 					memmove(buf, buf + buffer->line_keys[i].key_len, readLen);
  458: 				else
  459: 					memset(buf, 0, buffer->line_keys[i].key_len);
  460: 
  461: 				if (buffer->line_keys[i].key_func)
  462: 					if ((code = buffer->line_keys[i].key_func(i, buffer)))
  463: 						readLen = 0;
  464: 
  465: 				if (readLen)
  466: 					goto recheck;
  467: 				else
  468: 					break;
  469: 			}
  470: 
  471: 		if (code)
  472: 			break;
  473: 	}
  474: 
  475: 	return code;
  476: }
  477: 
  478: int
  479: addHistoryCLI(linebuffer_t * __restrict buffer, const char * __restrict str)
  480: {
  481: 	struct tagHistory *h;
  482: 
  483: 	if (!buffer)
  484: 		return RETCODE_ERR;
  485: 
  486: 	if (!(h = malloc(sizeof(struct tagHistory)))) {
  487: 		return RETCODE_ERR;
  488: 	} else
  489: 		memset(h, 0, sizeof(struct tagHistory));
  490: 
  491: 	if (str) {
  492: 		if (!*str) {
  493: 			free(h);
  494: 			return RETCODE_OK;
  495: 		}
  496: 
  497: 		h->hist_len = strlcpy(h->hist_line, str, BUFSIZ);
  498: 	} else {
  499: 		if (!*buffer->line_buf || buffer->line_len < 2) {
  500: 			free(h);
  501: 			return RETCODE_OK;
  502: 		}
  503: 
  504: 		memcpy(h->hist_line, buffer->line_buf, (h->hist_len = buffer->line_len));
  505: 		io_TrimStr((unsigned char*) h->hist_line);
  506: 		h->hist_len = strlen(h->hist_line);
  507: 	}
  508: 
  509: 	TAILQ_INSERT_HEAD(&buffer->line_history, h, hist_next);
  510: 	return h->hist_len;
  511: }
  512: 
  513: int
  514: saveHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile)
  515: {
  516: 	FILE *f;
  517: 	mode_t mode;
  518: 	char szFName[MAXPATHLEN];
  519: 	struct tagHistory *h;
  520: 
  521: 	if (!buffer)
  522: 		return RETCODE_ERR;
  523: 	if (!histfile)
  524: 		strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
  525: 	else
  526: 		strlcpy(szFName, histfile, MAXPATHLEN);
  527: 
  528: 	mode = umask(0177);
  529: 	f = fopen(szFName, "w");
  530: 	if (!f)
  531: 		return RETCODE_ERR;
  532: 	TAILQ_FOREACH(h, &buffer->line_history, hist_next)
  533: 		fprintf(f, "%s\n", h->hist_line);
  534: 	fclose(f);
  535: 	umask(mode);
  536: 
  537: 	return RETCODE_OK;
  538: }
  539: 
  540: int
  541: loadHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile)
  542: {
  543: 	FILE *f;
  544: 	char szFName[MAXPATHLEN], buf[BUFSIZ];
  545: 	struct tagHistory *h;
  546: 
  547: 	if (!buffer)
  548: 		return RETCODE_ERR;
  549: 	if (!histfile)
  550: 		strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
  551: 	else
  552: 		strlcpy(szFName, histfile, MAXPATHLEN);
  553: 
  554: 	f = fopen(szFName, "r");
  555: 	if (!f)
  556: 		return RETCODE_ERR;
  557: 	while (fgets(buf, BUFSIZ, f)) {
  558: 		if (!*buf || *buf == '#')
  559: 			continue;
  560: 		else
  561: 			io_TrimStr((unsigned char*) buf);
  562: 
  563: 		if (!(h = malloc(sizeof(struct tagHistory)))) {
  564: 			fclose(f);
  565: 			return RETCODE_ERR;
  566: 		} else
  567: 			memset(h, 0, sizeof(struct tagHistory));
  568: 
  569: 		h->hist_len = strlcpy(h->hist_line, buf, BUFSIZ);
  570: 		TAILQ_INSERT_TAIL(&buffer->line_history, h, hist_next);
  571: 	}
  572: 	fclose(f);
  573: 
  574: 	return RETCODE_OK;
  575: }
  576: 
  577: inline void
  578: resetHistoryCLI(linebuffer_t * __restrict buffer)
  579: {
  580: 	buffer->line_h = NULL;
  581: }
  582: 
  583: 
  584: int
  585: main()
  586: {
  587: 	int ret;
  588: 	bindkey_t key = { sizeof K_TAB - 1, K_TAB, bufTab };
  589: 	linebuffer_t *buffer = initCLI(STDIN_FILENO, STDOUT_FILENO);
  590: 
  591: 	bindKeyCLI(&key, buffer);
  592: 
  593: 	loadHistoryCLI(buffer, NULL);
  594: 
  595: 	while (42) {
  596: 		ret = readLineCLI(buffer);
  597: 		addHistoryCLI(buffer, NULL);
  598: 
  599: 		printf("LINE=%s (%d)/%d CODE=%d\n", buffer->line_buf, buffer->line_len, buffer->line_eol, ret);
  600: 
  601: 		freeLineCLI(buffer);
  602: 		resetHistoryCLI(buffer);
  603: 
  604: 		if (ret == RETCODE_EOF)
  605: 			break;
  606: 	}
  607: 
  608: 	saveHistoryCLI(buffer, NULL);
  609: 
  610: 	endCLI(buffer);
  611: 	return 0;
  612: }

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