2 * Copyright (c) 2012, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifndef __MURPHY_CONSOLE_H__
31 #define __MURPHY_CONSOLE_H__
33 #include <murphy/common/list.h>
34 #include <murphy/common/msg.h>
35 #include <murphy/core/context.h>
37 #include <murphy/core/console-command.h>
44 * Console request correspond to top-down event propagation in the console
45 * communication stack. These requests are made by the core console to the
46 * underlying actual console implementation, typically either as a result
47 * of calls to the console abstraction layer, or in reponse to requests
48 * (ie. input) coming from the actual console implementation.
52 /** Deliver a buffer of data to the given console. */
53 ssize_t (*write)(mrp_console_t *c, void *buf, size_t size);
54 /** Console being closed, close the backend (do not release memory yet). */
55 void (*close)(mrp_console_t *c);
56 /** Console has been destroyed, release resources allocated by backend. */
57 void (*free)(void *data);
58 /** Set the prompt shown to the user at the console. */
59 void (*set_prompt)(mrp_console_t *c, const char *prompt);
66 * Console events correspond to bottom-up event propagation in the console
67 * communication stack. These callbacks are made by the console backend to
68 * the core console to inform about relevant console events, such as new
69 * console input or disconnect by the peer.
73 /** New input available from console. */
74 ssize_t (*input)(mrp_console_t *c, void *buf, size_t size);
75 /** Peer has disconnected from the console. */
76 void (*disconnected)(mrp_console_t *c, int error);
77 /** Generate possible completions for the given input. */
78 ssize_t (*complete)(mrp_console_t *c, void *input, size_t insize,
79 char **completions, size_t csize);
83 #define MRP_CONSOLE_PUBLIC_FIELDS \
85 mrp_console_req_t req; \
86 mrp_console_evt_t evt; \
87 int (*check_destroy)(mrp_console_t *c); \
93 int preserve : 1 /* the Kludge of Death, Sir Robin... */
95 struct mrp_console_s {
96 MRP_CONSOLE_PUBLIC_FIELDS;
101 * Macro to mark a console busy while running a block of code.
103 * The backend needs to make sure the console is not freed while any console
104 * request or event callback function is active. Similarly, the backend needs
105 * to check if the console has been marked for destruction whenever an event
106 * callback returns and trigger destruction if it is necessary and possible
107 * (ie. the above criterium of not being active is fullfilled).
109 * These are the easiest to accomplish using the provided MRP_CONSOLE_BUSY
110 * macro and the check_destroy callback member provided by mrp_console_t.
112 * 1) Use the provided MRP_CONSOLE_BUSY macro to enclose al blocks of
113 * code that invoke event callbacks. Do not do a return directly
114 * from within the enclosed call blocks, rather just set a flag
115 * within the block, check it after the block and do the return
116 * there if necessary.
118 * 2) Call mrp_console_t->check_destroy after any call to an console
119 * event callback. check_destroy will check for any pending destroy
120 * request and perform the actual destruction if it is both necessary
121 * and possible. If the console has been left intact, check_destroy
122 * returns FALSE. However, if the console has been destroyed and freed
123 * it returns TRUE, in which case the caller must not attempt to use
124 * or dereference the console any more.
127 #ifndef __MRP_CONSOLE_DISABLE_CODE_CHECK__
128 # define W mrp_log_error
129 # define __CONSOLE_CHK_BLOCK(...) do { \
130 static int __checked = FALSE, __warned = FALSE; \
132 if (MRP_UNLIKELY(!__checked)) { \
134 if (MRP_UNLIKELY(!__warned && \
135 strstr(#__VA_ARGS__, "return") != NULL)) { \
136 W("********************* WARNING *********************"); \
137 W("* You seem to directly do a return from a block *"); \
138 W("* of code protected by MRP_CONSOLE_BUSY. Are *"); \
139 W("* you absolutely sure you know what you are doing *"); \
140 W("* and that you are also doing it correctly ? *"); \
141 W("***************************************************"); \
142 W("The suspicious code block is located at: "); \
143 W(" %s@%s:%d", __FUNCTION__, __FILE__, __LINE__); \
144 W("and it looks like this:"); \
145 W("---------------------------------------------"); \
146 W("%s", #__VA_ARGS__); \
147 W("---------------------------------------------"); \
148 W("If you understand what MRP_CONSOLE_BUSY does"); \
149 W("and how, and you are sure about the correctness of"); \
150 W("your code you can disable this error message by"); \
151 W("#defining __MRP_CONSOLE_DISABLE_CODE_CHECK__"); \
152 W("when compiling %s.", __FILE__); \
158 # define __CONSOLE_CHK_BLOCK(...) do { } while (0)
161 #define MRP_CONSOLE_BUSY(c, ...) do { \
162 __CONSOLE_CHK_BLOCK(__VA_ARGS__); \
169 /** Create a new console instance. */
170 mrp_console_t *mrp_create_console(mrp_context_t *ctx, mrp_console_req_t *req,
173 /** Close and mark a console for destruction. */
174 void mrp_destroy_console(mrp_console_t *mc);
176 /** Send (printf-compatible) formatted output to a console. */
177 void mrp_console_printf(mrp_console_t *mc, const char *fmt, ...);
179 /** Send (vprintf-compatible) formatted output to a console. */
180 void mrp_console_vprintf(mrp_console_t *mc, const char *fmt, va_list ap);
182 /** Set the prompt of a console. */
183 void mrp_set_console_prompt(mrp_console_t *mc);
185 #endif /* __MURPHY_CONSOLE_H__ */