Annotation of libaitcli/src/aitcli.c, revision 1.1.1.1.2.4
1.1 misho 1: /*************************************************************************
2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.1.1.1.2.4! misho 6: * $Id: aitcli.c,v 1.1.1.1.2.3 2010/04/19 23:02:47 misho Exp $
1.1 misho 7: *
8: *************************************************************************/
9: #include "global.h"
10:
11:
12: #pragma GCC visibility push(hidden)
13:
14: cliCommands_t cli_stdCmds[] = {
15: { "test", cli_Cmd_Unsupported, "Test - Don`t use default command structure!", "test <cr>", cli_Comp_Filename },
16: { "-------", NULL, "---------------------", NULL, NULL },
17: { "help", cli_Cmd_Help, "Help screen", "help [command] <cr>", NULL },
18: { "exit", cli_Cmd_Exit, "Exit from console", "exit <cr>", NULL },
19: { NULL, NULL, NULL, NULL }
20: };
21:
22: // ------------------------------------------------
23:
24: int cli_Errno;
25: char cli_Error[STRSIZ];
26:
27: #pragma GCC visibility pop
28:
29:
1.1.1.1.2.4! misho 30: static void cli_Null_Prep_Term(int meta)
! 31: {
! 32: }
! 33:
! 34: static void cli_Null_Deprep_Term()
! 35: {
! 36: }
! 37:
! 38: static int cli_Pre_Input_Change_Mode()
! 39: {
! 40: return 0;
! 41: }
! 42:
! 43: static int cli_GetC(FILE *dummy)
! 44: {
! 45: int ch = rl_getc(stdin);
! 46:
! 47: /*
! 48: if (is_special_char(ch)) {
! 49: pending_special_char = ch;
! 50: return '\r';
! 51: }
! 52: */
! 53:
! 54: return ch;
! 55: }
! 56:
! 57:
1.1 misho 58: // cli_GetErrno() Get error code of last operation
59: inline int cli_GetErrno()
60: {
61: return cli_Errno;
62: }
63:
64: // io_GetError() Get error text of last operation
65: inline const char *cli_GetError()
66: {
67: return cli_Error;
68: }
69:
70: // cli_SetErr() Set error to variables for internal use!!!
71: inline void cli_SetErr(int eno, char *estr, ...)
72: {
73: va_list lst;
74:
75: cli_Errno = eno;
76: memset(cli_Error, 0, STRSIZ);
77: va_start(lst, estr);
78: vsnprintf(cli_Error, STRSIZ, estr, lst);
79: va_end(lst);
80: }
81:
82: // ------------------------------------------------------------
83:
84: /*
85: * cli_Printf() Printf CLI features
86: * @out = Output stream
87: * @csFormat = Printf format string
1.1.1.1.2.4! misho 88: * return: -1 error, != -1 printed chars
1.1 misho 89: */
90: inline int cli_Printf(FILE *out, const char *csFormat, ...)
91: {
92: va_list lst;
93: int ret;
94:
95: va_start(lst, csFormat);
96:
97: ret = vfprintf(out, csFormat, lst);
98: if (-1 == ret)
99: LOGERR;
100:
101: va_end(lst);
102: return ret;
103: }
104:
105:
106: /*
107: * cliComp() Initialize completion CLI features
108: * @cmdComplete = Completion function
109: * @cmdEntry = Compentry function
110: * return: none
111: */
112: inline void cliComp(cli_Completion_t *cmdComplete, cli_CompEntry_t *cmdEntry)
113: {
114: // command completon
115: rl_attempted_completion_function = cmdComplete;
116: rl_completion_entry_function = cmdEntry;
117: }
118:
119: /*
1.1.1.1.2.1 misho 120: * cliTTY() Initialize I/O TTY CLI features
1.1.1.1.2.3 misho 121: * @term = terminal name
1.1.1.1.2.1 misho 122: * @inp = input handle
123: * @out = output handle
1.1.1.1.2.4! misho 124: * @win = window size
! 125: * return: -1 error, != -1 ok
! 126: */
! 127: inline int cliTTY(const char *term, FILE *inp, FILE *out, struct winsize *win)
! 128: {
! 129: if (term)
! 130: rl_terminal_name = term;
! 131:
! 132: if (inp)
! 133: rl_instream = inp;
! 134: if (out)
! 135: rl_outstream = out;
! 136:
! 137: if (win)
! 138: if (ioctl(!rl_outstream ? STDOUT_FILENO : fileno(rl_outstream), TIOCSWINSZ, win) == -1) {
! 139: LOGERR;
! 140: return -1;
! 141: }
! 142:
! 143: return 0;
! 144: }
! 145:
! 146: /*
! 147: * cliInit() Initialize Readline
! 148: * @csProg = program name
1.1.1.1.2.1 misho 149: * return: none
150: */
1.1.1.1.2.4! misho 151: inline void cliInit(const char *csProg)
1.1.1.1.2.1 misho 152: {
1.1.1.1.2.4! misho 153: rl_readline_name = csProg;
! 154:
! 155: rl_variable_bind("editing-mode", "emacs");
! 156: }
! 157:
! 158: /*
! 159: * cliNetInit() Initialize Readline if CLI bind to socket
! 160: * @csProg = program name
! 161: * @pty = Master pty
! 162: * @term = stdin termios
! 163: * return: none
! 164: */
! 165: void cliNetInit(const char *csProg, int pty, struct termios *term)
! 166: {
! 167: struct termios t;
! 168:
! 169: if (term) {
! 170: t = *term;
! 171: t.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
! 172: t.c_iflag &= ~ICRNL;
! 173: t.c_iflag |= IGNBRK;
! 174: t.c_cc[VMIN] = 1;
! 175: t.c_cc[VTIME] = 0;
! 176: tcsetattr(pty, TCSANOW, &t);
! 177: }
! 178:
! 179: cliInit(csProg);
! 180:
! 181: rl_instream = fdopen(pty, "r");
! 182:
! 183: rl_prep_term_function = cli_Null_Prep_Term;
! 184: rl_deprep_term_function = cli_Null_Deprep_Term;
! 185: rl_pre_input_hook = cli_Pre_Input_Change_Mode;
! 186:
! 187: rl_getc_function = cli_GetC;
! 188:
1.1.1.1.2.1 misho 189: }
190:
191: /*
1.1 misho 192: * cliExec() Execute CLI main loop
193: * @cmdList = Commands list
194: * @csPrompt = Prompt text
195: * return: -1 error, 0 = exit w/^+D, 1 done.
196: */
1.1.1.1.2.2 misho 197: int cliExec(cliCommands_t *cmdList, const char *csPrompt)
1.1 misho 198: {
199: char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];
200: int ret = 0;
201: register int i;
202: cliCommands_t *cmd = NULL;
1.1.1.1.2.2 misho 203: FILE *out;
1.1 misho 204:
205: inline int inline_help()
206: {
207: cli_Cmd_Help(cmdList ? cmdList : cli_stdCmds, -1, out, NULL);
208: rl_on_new_line();
209: return 0;
210: }
211:
212: char **cli_stdCompletion(const char *text, int start, int end)
213: {
214: register int i;
215: char **matches = NULL;
216:
217: char *cmdCompGet(const char *text, int state)
218: {
219: int len = strlen(text);
220:
221: for (i = state; cmdList[i].cmd_name; i++) {
222: if (strncmp(cmdList[i].cmd_name, "---", 3) &&
223: !strncmp(cmdList[i].cmd_name, text, len))
224: return strdup(cmdList[i].cmd_name);
225: }
226:
227: return NULL;
228: }
229:
230: if (!start)
231: matches = rl_completion_matches(text, cmdCompGet);
232: else
233: for (i = 0; cmdList[i].cmd_name; i++) {
234: if (!cmdList[i].cmd_comp)
235: continue;
236: if (!strncmp(rl_line_buffer, cmdList[i].cmd_name, strlen(cmdList[i].cmd_name)))
237: matches = rl_completion_matches(text, cmdList[i].cmd_comp);
238: }
239:
240: return matches;
241: }
242: char *cli_stdCompEntry(const char *ignore, int invoking_key)
243: {
244: return NULL;
245: }
246:
247: /* --- main body of CLI --- */
248:
1.1.1.1.2.2 misho 249: out = rl_outstream;
250: if (!out)
251: out = stdout;
252:
1.1 misho 253: rl_bind_key('?', inline_help);
254: if (!rl_attempted_completion_function)
255: cliComp(cli_stdCompletion, cli_stdCompEntry);
256:
257: do {
258: line = readline(csPrompt);
259: if (!line) { // ^+d
260: cli_Printf(out, "\n");
261: break;
262: }
263: // clear whitespaces
264: for (s = line; isspace(*s); s++);
265: if (*s) {
266: for (t = s + strlen(s) - 1; t > s && isspace(*t); t--);
267: *++t = 0;
268: }
269:
270: if (*s) {
271: add_history(s);
272:
273: memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);
274: for (app = items; app < items + MAX_PROMPT_ITEMS - 1 && (*app = strsep(&s, " \t"));
275: *app ? app++ : app);
276:
277: /*
278: for (i = 0; i < MAX_PROMPT_ITEMS; i++)
279: cli_Printf(out, "i=%d %s\n", i, items[i]);
280: */
281:
282: // exec_cmd ...
283: for (cmd = NULL, i = 0; cmdList[i].cmd_name; i++)
284: if (*items[0] && !strncmp(cmdList[i].cmd_name, items[0], strlen(items[0]))) {
285: cmd = &cmdList[i];
286: break;
287: }
288: if (!cmd) {
289: cli_Printf(out, "Command '%s' not found!\n", items[0]);
290: ret = -1;
291: } else
292: ret = cmd->cmd_func(cmdList, i, out, items);
293: }
294:
295: free(line);
296: } while (ret < 1);
297:
298: return ret;
299: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>