Initialize smart traffic control iptables package
[platform/core/connectivity/stc-iptables.git] / test / stc_ipt_menu.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <glib.h>
22 #include <asm/unistd.h>
23 #include <unistd.h>
24 #include <sys/syscall.h>
25
26 #include "stc_ipt_menu.h"
27
28 #define DEFAULT_MENU_MENU       "m"
29 #define DEFAULT_MENU_PREV       "p"
30 #define DEFAULT_MENU_QUIT       "q"
31 #define DEFAULT_MENU_NONE       "-"
32 #define TAB_SPACE     "  "
33
34 struct menu_manager {
35         GQueue *stack;
36         GQueue *title_stack;
37
38         struct menu_data *menu;
39
40         char *buf;
41
42         void *user_data;
43         GMainLoop *mainloop;
44 };
45
46
47 char key_buffer[MENU_DATA_SIZE];
48 int flag_pid_display = 1;
49
50
51 static void _show_prompt(void)
52 {
53         msgn("(%5d) >> ", get_tid());
54 }
55
56 static void _show_reserved_menu(void)
57 {
58         msg(LOG_DARKGRAY HR_SINGLE2 LOG_END);
59         msg(LOG_DARKGRAY " [ " LOG_END "%s" LOG_DARKGRAY
60                         " ] " LOG_END "Previous Menu " , DEFAULT_MENU_PREV);
61         msg(LOG_DARKGRAY " [ " LOG_END "%s" LOG_DARKGRAY
62                         " ] " LOG_END "Show Menu " , DEFAULT_MENU_MENU);
63         msg(LOG_DARKGRAY " [ " LOG_END "%s" LOG_DARKGRAY
64                         " ] " LOG_END "Quit " , DEFAULT_MENU_QUIT);
65 }
66
67 static void _show_input_ok(void)
68 {
69         msg("OK.");
70 }
71
72 static void _show_menu(MManager *m, struct menu_data menu[])
73 {
74         int i = 0;
75         int len = 0;
76         struct menu_data *item;
77         char title_buf[256] = { 0, };
78
79         if (!menu)
80                 return;
81
82         msg("");
83         msg(HR_DOUBLE);
84
85         len = g_queue_get_length(m->title_stack);
86         msgn(LOG_YELLOW " Main");
87         if (len > 0) {
88                 for (i = 0; i < len; i++) {
89                         msgn(LOG_END " >> " LOG_YELLOW "%s",
90                                         (char *)g_queue_peek_nth(m->title_stack, i));
91                 }
92         }
93         msg(LOG_END);
94         msg(HR_SINGLE);
95
96         hide_pid();
97         i = 0;
98
99         while (1) {
100                 item = menu + i;
101                 if (item->key == NULL)
102                         break;
103
104                 if (!g_strcmp0(item->key, "-")) {
105                         msgn("       ");
106                 } else if (!g_strcmp0(item->key, "_")) {
107                         msg(LOG_DARKGRAY HR_SINGLE2 LOG_END);
108
109                         if (item->callback)
110                                 item->callback(m, item);
111
112                         i++;
113
114                         continue;
115                 } else if (!g_strcmp0(item->key, "*")) {
116                         msg(" %s", item->title);
117                         if (item->callback)
118                                 item->callback(m, item);
119                 } else {
120                         msgn(LOG_DARKGRAY " [" LOG_END "%3s"
121                                         LOG_DARKGRAY "] " LOG_END,      item->key);
122                 }
123
124                 memset(title_buf, 0, 256);
125                 if (item->title) {
126                         snprintf(title_buf, MAX_TITLE, "%s", item->title);
127
128                         if (strlen(item->title) >= MAX_TITLE) {
129                                 title_buf[MAX_TITLE - 2] = '.';
130                                 title_buf[MAX_TITLE - 1] = '.';
131                         }
132                 }
133
134                 if (item->data) {
135                         msg("%s " LOG_LIGHTBLUE "(%s)" LOG_END,
136                                         title_buf, item->data);
137                 } else if (!g_strcmp0(item->key, "*")) {
138                         /* none */
139                 } else {
140                         msg("%s", title_buf);
141                 }
142
143                 if (item->sub_menu)
144                         msg("\e[1A\e[%dC >", (int)POS_MORE);
145
146                 i++;
147         }
148
149         show_pid();
150
151         _show_reserved_menu();
152
153         msg(HR_DOUBLE);
154
155         _show_prompt();
156 }
157
158 static void _show_item_data_input_msg(struct menu_data *item)
159 {
160         msg("");
161         msg(HR_DOUBLE);
162         msg(" Input [%s] data ", item->title);
163         msg(HR_SINGLE);
164         msg(" current = [%s]", item->data);
165         msgn(" new >> ");
166 }
167
168 static void _move_menu(MManager *mm, struct menu_data menu[], char *key)
169 {
170         struct menu_data *item;
171         int i = 0;
172
173         if (!mm->menu)
174                 return;
175
176         if (!g_strcmp0(DEFAULT_MENU_PREV, key)) {
177                 if (g_queue_get_length(mm->stack) > 0) {
178                         mm->menu = g_queue_pop_tail(mm->stack);
179                         g_queue_pop_tail(mm->title_stack);
180                 }
181
182                 _show_menu(mm, mm->menu);
183                 mm->buf = key_buffer;
184
185                 return;
186         } else if (!g_strcmp0(DEFAULT_MENU_MENU, key)) {
187                 _show_menu(mm, mm->menu);
188                 return;
189         } else if (!g_strcmp0(DEFAULT_MENU_QUIT, key)) {
190                 g_main_loop_quit(mm->mainloop);
191                 return;
192         } else if (!g_strcmp0(DEFAULT_MENU_NONE, key)) {
193                 _show_prompt();
194                 return;
195         }
196
197         while (1) {
198                 int ret = RET_SUCCESS;
199                 item = menu + i;
200                 if (item->key == NULL)
201                         break;
202
203                 if (!g_strcmp0(item->key, key)) {
204                         if (item->callback) {
205                                 ret = item->callback(mm, item);
206                                 _show_prompt();
207                         }
208
209                         if (RET_SUCCESS == ret) {
210                                 if (item->sub_menu) {
211                                         g_queue_push_tail(mm->stack, mm->menu);
212                                         g_queue_push_tail(mm->title_stack, (gpointer *)item->title);
213
214                                         mm->menu = item->sub_menu;
215                                         _show_menu(mm, mm->menu);
216                                         mm->buf = key_buffer;
217                                 }
218
219                                 if (item->data) {
220                                         _show_item_data_input_msg(item);
221                                         mm->buf = item->data;
222                                 }
223                         }
224
225                         return;
226                 }
227
228                 i++;
229         }
230
231         _show_prompt();
232 }
233
234 MManager *menu_manager_new(struct menu_data items[], GMainLoop *mainloop)
235 {
236         MManager *mm;
237
238         mm = calloc(sizeof(struct menu_manager), 1);
239         if (!mm)
240                 return NULL;
241
242         mm->stack = g_queue_new();
243         mm->title_stack = g_queue_new();
244         mm->menu = items;
245         mm->mainloop = mainloop;
246
247         return mm;
248 }
249
250 int menu_manager_run(MManager *mm)
251 {
252         _show_menu(mm, mm->menu);
253
254         mm->buf = key_buffer;
255
256         return 0;
257 }
258
259 int menu_manager_set_user_data(MManager *mm, void *user_data)
260 {
261         if (!mm)
262                 return -1;
263
264         mm->user_data = user_data;
265
266         return 0;
267 }
268
269 void *menu_manager_ref_user_data(MManager *mm)
270 {
271         if (!mm)
272                 return NULL;
273
274         return mm->user_data;
275 }
276
277 gboolean on_menu_manager_keyboard(GIOChannel *src, GIOCondition con,
278                 gpointer data)
279 {
280         MManager *mm = data;
281         char local_buf[MENU_DATA_SIZE + 1] = { 0, };
282
283         if (fgets(local_buf, MENU_DATA_SIZE, stdin) == NULL)
284                 return TRUE;
285
286         if (strlen(local_buf) > 0) {
287                 if (local_buf[strlen(local_buf) - 1] == '\n')
288                         local_buf[strlen(local_buf) - 1] = '\0';
289         }
290
291         if (mm->buf == key_buffer) {
292                 if (strlen(local_buf) < 1) {
293                         _show_prompt();
294                         return TRUE;
295                 }
296
297                 _move_menu(mm, mm->menu, local_buf);
298         } else {
299                 if (mm->buf) {
300                         memset(mm->buf, 0, MENU_DATA_SIZE);
301                         memcpy(mm->buf, local_buf, MENU_DATA_SIZE);
302                         _show_input_ok();
303                 }
304                 mm->buf = key_buffer;
305                 _move_menu(mm, mm->menu, (char *)DEFAULT_MENU_MENU);
306         }
307
308         return TRUE;
309 }
310
311 pid_t get_tid()
312 {
313         return syscall(__NR_gettid);
314 }
315
316 void hide_pid()
317 {
318         flag_pid_display = 0;
319 }
320
321 void show_pid()
322 {
323         flag_pid_display = 1;
324 }
325
326 int is_pid_show()
327 {
328         return flag_pid_display;
329 }
330
331 static void _hex_dump(const char *pad, int size, const void *data)
332 {
333         char buf[255] = {0, };
334         char hex[4] = {0, };
335         int i;
336         unsigned char *p;
337
338         if (size <= 0) {
339                 msg("%sno data", pad);
340                 return;
341         }
342         p = (unsigned char *)data;
343
344         snprintf(buf, 255, "%s%04X: ", pad, 0);
345         for (i = 0; i < size; i++) {
346                 snprintf(hex, 4, "%02X ", p[i]);
347                 strncat(buf, hex, 255 - strlen(buf) - 1);
348
349                 if ((i + 1) % 8 == 0) {
350                         if ((i + 1) % 16 == 0) {
351                                 msg("%s", buf);
352                                 memset(buf, 0, 255);
353                                 snprintf(buf, 255, "%s%04X: ", pad, i + 1);
354                         } else {
355                                 strncat(buf, TAB_SPACE, 255 - strlen(buf) - 1);
356                         }
357                 }
358         }
359
360         msg("%s", buf);
361 }
362
363 void menu_print_dump(int data_len, void *data)
364 {
365         if (!data)
366                 return;
367
368         msg("");
369         msg("  \tlen=%d", data_len);
370         _hex_dump("        ", data_len, data);
371
372         msg("");
373 }
374