bda4465b651ec45110e64f207f9565a86866aab3
[libcmdline.git] / src / lib / cmdline_rdline.h
1 /*-
2  * Copyright (c) <2010>, Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * - Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  *
17  * - Neither the name of Intel Corporation nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32  * OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 /*
36  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
37  * All rights reserved.
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions are met:
40  *
41  *     * Redistributions of source code must retain the above copyright
42  *       notice, this list of conditions and the following disclaimer.
43  *     * Redistributions in binary form must reproduce the above copyright
44  *       notice, this list of conditions and the following disclaimer in the
45  *       documentation and/or other materials provided with the distribution.
46  *     * Neither the name of the University of California, Berkeley nor the
47  *       names of its contributors may be used to endorse or promote products
48  *       derived from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
51  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
54  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
55  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
57  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60  */
61
62 #ifndef _RDLINE_H_
63 #define _RDLINE_H_
64
65 /**
66  * This file is a small equivalent to the GNU readline library, it was
67  * originally designed for very small systems (an 8-bits Atmel AVR
68  * microcontroller), but the library can now run on many emmbedded
69  * systems with or without OS.
70  *
71  * Obviously, it does not support as many things as the GNU readline,
72  * but at least it supports some interresting features like a kill
73  * buffer and a command history.
74  *
75  * It also have a feature that does not have the GNU readline (as far
76  * as I know): it is possible to have several instances of readline
77  * running at the same time, even on a monothread program, since it
78  * works with callbacks.
79  */
80
81 #include <cmdline_cirbuf.h>
82 #include <cmdline_vt100.h>
83
84 /* configuration */
85 #define RDLINE_BUF_SIZE 256
86 #define RDLINE_PROMPT_SIZE  32
87 #define RDLINE_VT100_BUF_SIZE  8
88 #define RDLINE_HISTORY_BUF_SIZE BUFSIZ
89 #define RDLINE_HISTORY_MAX_LINE 64
90 #define RDLINE_MAX_LINES 23
91
92 enum rdline_status {
93         RDLINE_INIT,
94         RDLINE_RUNNING,
95         RDLINE_EXITED
96 };
97
98 struct rdline;
99
100 /**
101  * callback given to rdline_help() to display the content of the
102  * help. The first argument is an opaque pointer. The other args
103  * are buffer and size.
104  */
105 typedef ssize_t (rdline_write_t)(struct rdline *, void *, size_t);
106
107
108 typedef void (rdline_validate_t)(struct rdline *rdl,
109                                  const char *buf, unsigned int size);
110 typedef int (rdline_complete_t)(struct rdline *rdl, const char *buf,
111                                 char *dstbuf, unsigned int dstsize);
112 typedef int (rdline_help_t)(struct rdline *rdl, const char *buf,
113                             rdline_write_t *write, void *opaque);
114
115 typedef void (rdline_asyncpager_cb_t)(struct rdline *, void *);
116
117 struct rdline {
118         enum rdline_status status;
119         int fd_in;
120         int fd_out;
121
122         /* rdline bufs */
123         struct cirbuf left;
124         struct cirbuf right;
125         char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */
126         char right_buf[RDLINE_BUF_SIZE];
127
128         char prompt[RDLINE_PROMPT_SIZE];
129
130 #ifndef NO_RDLINE_KILL_BUF
131         char kill_buf[RDLINE_BUF_SIZE];
132         unsigned int kill_size;
133 #endif
134
135 #ifndef NO_RDLINE_HISTORY
136         /* history */
137         struct cirbuf history;
138         char history_buf[RDLINE_HISTORY_BUF_SIZE];
139         int history_cur_line;
140 #endif
141
142         /* callbacks and func pointers */
143         rdline_validate_t *validate;
144         rdline_complete_t *complete;
145         rdline_help_t *help;
146
147         /* vt100 parser */
148         struct cmdline_vt100 vt100;
149
150         /* opaque pointer */
151         void *opaque;
152
153 #ifndef NO_PAGER
154         char *pager_buf; /* buffer used to store paged data */
155         int pager_len; /* total len of buffer */
156         int pager_off; /* offset of next data */
157         int pager_lines; /* number of lines displayed */
158         rdline_asyncpager_cb_t *pager_cb; /* callback once paging is finished */
159         void *pager_arg; /* argument of callback */
160         int pager_ret; /* saved return value */
161 #endif
162 };
163
164 /**
165  * Init fields for a struct rdline.
166  *
167  * @param rdl A pointer to an uninitialized struct rdline
168  * @param fd_in
169  *   Input file descriptor
170  * @param fd_out
171  *   Output file descriptor
172  * @param validate
173  *   A pointer to the function to execute when the user validates the
174  *   buffer.
175  * @param complete
176  *   A pointer to the function to execute when the user completes the
177  *   buffer.
178  * @param help
179  *   A pointer to the function to execute when the user ask for
180  *   contextual help.
181  */
182 void rdline_init(struct rdline *rdl,
183                  int fd_in, int fd_out,
184                  rdline_validate_t *validate,
185                  rdline_complete_t *complete,
186                  rdline_help_t *help);
187
188
189 /**
190  * Init the current buffer, and display a prompt.
191  *
192  * Also set the rdline status to "running", overriding previous
193  * rdline_stop() or rdline_quit().
194  *
195  * @param rdl
196  *   A pointer to an initialized struct rdline
197  * @param prompt
198  *   A string containing the prompt
199  */
200 void rdline_newline(struct rdline *rdl, const char *prompt);
201
202 /**
203  * Ignore all subsequent received chars.
204  *
205  * @param rdl
206  *   A pointer to a struct rdline
207  */
208 void rdline_stop(struct rdline *rdl);
209
210 /**
211  * Exit from running rdline loop
212  *
213  * Same than rdline_stop() except that next calls to rdline_char_in()
214  * will return RDLINE_RES_EXITED. Hence, any running rdline() function is
215  * interrupted.
216  *
217  * @param rdl
218  *   A pointer to a struct rdline
219  */
220 void rdline_quit(struct rdline *rdl);
221
222 /**
223  * Restart after a call to rdline_stop() or rdline_quit()
224  *
225  * @param rdl
226  *   A pointer to a struct rdline
227  */
228 void rdline_restart(struct rdline *rdl);
229
230 /**
231  * Redisplay the current buffer
232  *
233  * @param rdl
234  *   A pointer to a struct rdline
235  */
236 void rdline_redisplay(struct rdline *rdl);
237
238
239 /* return status for rdline_char_in() */
240 #define RDLINE_RES_SUCCESS       0
241 #define RDLINE_RES_VALIDATED     1
242 #define RDLINE_RES_NOT_RUNNING  -1
243 #define RDLINE_RES_EOF          -2
244 #define RDLINE_RES_EXITED       -3
245
246 /**
247  * Append a char to the readline buffer.
248  *
249  * @param rdl
250  *   A pointer to a struct rdline
251  * @param c
252  *   The character to append
253  * @return
254  *   - RDLINE_RES_VALIDATED when the line has been validated.
255  *   - RDLINE_RES_NOT_RUNNING if it is not running.
256  *   - RDLINE_RES_EOF if EOF (ctrl-d on an empty line).
257  *   - RDLINE_RES_EXITED if user called rdline_quit()
258  *   - Else return RDLINE_RES_SUCCESS.
259  */
260 int rdline_char_in(struct rdline *rdl, char c);
261
262 /**
263  * Read (and edit) a line
264  *
265  * @param rdl
266  *   A pointer to a struct rdline
267  * @param prompt
268  *   The prompt string
269  * @return
270  *   - RDLINE_RES_VALIDATED when the line has been validated.
271  *   - RDLINE_RES_NOT_RUNNING if it is not running.
272  *   - RDLINE_RES_EOF if EOF (ctrl-d on an empty line).
273  *   - RDLINE_RES_EXITED if user called rdline_quit()
274  */
275 int rdline(struct rdline *rdl, const char *prompt);
276
277 /**
278  * write a buffer on rdline file descriptor
279  *
280  * @param rdl
281  *   The rdline descriptor
282  * @param buf
283  *   Pointer to the buffer
284  * @param count
285  *   Number of bytes to write
286  * @return
287  *   On success, the number of bytes written is returned (zero
288  *   indicates nothing was written). On error, -1 is returned, and
289  *   errno is set appropriately
290  */
291 ssize_t rdline_write(const struct rdline *rdl, void *buf, size_t count);
292
293 /**
294  * write on rdline file descriptor according to a format string
295  *
296  * @param rdl
297  *   The rdline descriptor
298  * @param fmt
299  *   The format strings
300  * @return
301  *   Upon successful return, these functions return the number of
302  *   characters printed (not including the trailing '\0' used to end
303  *   output to strings). On error, a negative value is returned.
304  */
305 int rdline_printf(const struct rdline *rdl, const char *fmt, ...);
306
307 /**
308  * write on rdline file descriptor according to a format string
309  *
310  * @param rdl
311  *   The rdline descriptor
312  * @param fmt
313  *   The format strings
314  * @param ap
315  *   Variable argument list
316  * @return
317  *   Upon successful return, these functions return the number of
318  *   characters printed (not including the trailing '\0' used to end
319  *   output to strings). On error, a negative value is returned.
320  */
321 int rdline_vprintf(const struct rdline *rdl, const char *fmt, va_list ap);
322
323 /**
324  * Return the current buffer, terminated by '\0'.
325  *
326  * @param rdl
327  *   A pointer to a struct rdline
328  * @return
329  *   The rdline buffer
330  */
331 const char *rdline_get_buffer(struct rdline *rdl);
332
333 /**
334  * Add the buffer to history.
335  *
336  * @param rdl
337  *   A pointer to a struct rdline
338  * @param buf
339  *   A buffer that is terminated by '\0'
340  * @return
341  *   - 0 on success
342  *   - negative on error
343  */
344 int rdline_add_history(struct rdline *rdl, const char *buf);
345
346 /**
347  * Clear current history
348  *
349  * @param rdl
350  *   A pointer to a struct rdline
351  */
352 void rdline_clear_history(struct rdline *rdl);
353
354 /**
355  * Get the i-th history item
356  *
357  * @param rdl
358  *   A pointer to a struct rdline
359  * @param i
360  *   The index of the history item
361  * @return
362  *   The i-th string of history, or NULL on error.
363  */
364 char *rdline_get_history_item(struct rdline *rdl, unsigned int i);
365
366 #ifndef NO_PAGER
367 /**
368  * Write data asynchronously (using pager if needed)
369  *
370  * If there is enough place to print data on the current page, it is
371  * printed synchronously. Else, a temporary buffer is allocated and
372  * the data is stored in it. When the main rdline is called again, the
373  * pager is flushed before parsing any other commands.
374  *
375  * @param rdl
376  *   The rdline descriptor
377  * @param buf
378  *   Buffer to be sent
379  * @param len
380  *   Length of buffer to be sent
381  * @return
382  *   On success, the number of bytes written is returned (zero
383  *   indicates nothing was written). On error, -1 is returned, and
384  *   errno is set appropriately
385  */
386 ssize_t rdline_asyncpager_write(struct rdline *rdl, void *buf, size_t len);
387
388 /**
389  * Print data asynchronously (using pager if needed)
390  *
391  * If there is enough place to print data on the current page, it is
392  * printed synchronously. Else, a temporary buffer is allocated and
393  * the data is stored in it. When the main rdline is called again, the
394  * pager is flushed before parsing any other commands.
395  *
396  * @param rdl
397  *   The rdline descriptor
398  * @param fmt
399  *   The format strings
400  * @return
401  *   Upon successful return, these functions return the number of
402  *   characters printed (not including the trailing '\0' used to end
403  *   output to strings). On error, a negative value is returned.
404  */
405 int rdline_asyncpager_printf(struct rdline *rdl, const char *fmt, ...);
406
407 /**
408  * Set the callback for the pager
409  *
410  * If there is some data in the pager to be printed, set a callback
411  * function that will be called when all the data will be printed. If
412  * the pager is empty, don't do anything and return -1.
413  * @param rdl
414  *   The rdline descriptor
415  * @return
416  *   - 0 if there is some data in the pager buffer and the callback
417  *     is loaded
418  *   - -1 if there is no data in pager buffer (in this case the callback
419  *     is not called)
420  */
421 int rdline_asyncpager_set_cb(struct rdline *rdl, rdline_asyncpager_cb_t *cb,
422                              void *arg);
423 #endif
424
425
426 #endif /* _RDLINE_H_ */