dcerpc: remove use-after-free (found by clang).
[metze/wireshark/wip.git] / epan / stat_tap_ui.c
1 /* stat_tap_ui.c
2  * Routines to register UI information for stats
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26
27 #include <string.h>
28
29 #include <glib.h>
30
31 #include <epan/stat_tap_ui.h>
32
33 /* structure to keep track of what stats have registered command-line
34    arguments.
35  */
36 typedef struct _stat_cmd_arg {
37     stat_tap_ui *ui;
38     const char *cmd;
39     void (*func)(const char *arg, void* userdata);
40     void* userdata;
41 } stat_cmd_arg;
42
43 static wmem_list_t *stat_cmd_arg_list=NULL;
44
45 /* structure to keep track of what stats have been specified on the
46    command line.
47  */
48 typedef struct {
49     stat_cmd_arg *sca;
50     char *arg;
51 } stat_requested;
52 static GSList *stats_requested = NULL;
53
54 /* **********************************************************************
55  * Function called from stat to register the stat's command-line argument
56  * and initialization routine
57  * ********************************************************************** */
58 static gint
59 search_duplicate(gconstpointer a, gconstpointer b)
60 {
61     return strcmp(((const stat_cmd_arg *)a)->cmd, (const char *)b);
62 }
63
64 static gint
65 sort_by_name(gconstpointer a, gconstpointer b)
66 {
67     return strcmp(((const stat_cmd_arg *)a)->cmd, ((const stat_cmd_arg *)b)->cmd);
68 }
69
70 void
71 register_stat_tap_ui(stat_tap_ui *ui, void *userdata)
72 {
73     stat_cmd_arg *newsca;
74
75     if (stat_cmd_arg_list == NULL)
76         stat_cmd_arg_list = wmem_list_new(wmem_epan_scope());
77
78     /* Key is already present */
79     if (wmem_list_find_custom(stat_cmd_arg_list, ui->cli_string, search_duplicate))
80         return;
81
82     newsca = wmem_new(wmem_epan_scope(), stat_cmd_arg);
83     newsca->cmd= wmem_strdup(wmem_epan_scope(), ui->cli_string);
84     newsca->func=ui->tap_init_cb;
85     newsca->userdata=userdata;
86
87     wmem_list_insert_sorted(stat_cmd_arg_list, newsca, sort_by_name);
88 }
89
90 /* **********************************************************************
91  * Function called for a stat command-line argument
92  * ********************************************************************** */
93 gboolean
94 process_stat_cmd_arg(char *optstr)
95 {
96     wmem_list_frame_t *entry;
97     stat_cmd_arg *sca;
98     stat_requested *tr;
99
100     /* The strings "ipx" or "ipv6" must be tested before "ip" to select the
101       right tap so the sorting does matter.  And it's also why the list is
102       walked backwards */
103     for (entry = wmem_list_tail(stat_cmd_arg_list); entry; entry = wmem_list_frame_prev(entry)) {
104         sca = (stat_cmd_arg*)wmem_list_frame_data(entry);
105         if(!strncmp(sca->cmd, optstr, strlen(sca->cmd))) {
106             tr=(stat_requested *)g_malloc(sizeof (stat_requested));
107             tr->sca = sca;
108             tr->arg=g_strdup(optstr);
109             stats_requested = g_slist_append(stats_requested, tr);
110             return TRUE;
111         }
112     }
113     return FALSE;
114 }
115
116 /* **********************************************************************
117  * Function to list all possible tap command-line arguments
118  * ********************************************************************** */
119 static void
120 list_stat_cmd_args_func(gpointer data, gpointer userdata _U_)
121 {
122     fprintf(stderr,"     %s\n", ((stat_cmd_arg*)data)->cmd);
123 }
124
125 void
126 list_stat_cmd_args(void)
127 {
128     wmem_list_foreach(stat_cmd_arg_list, list_stat_cmd_args_func, NULL);
129 }
130
131 /* **********************************************************************
132  * Function to process stats requested with command-line arguments
133  * ********************************************************************** */
134 void
135 start_requested_stats(void)
136 {
137     stat_requested *sr;
138
139     while(stats_requested){
140         sr=(stat_requested *)stats_requested->data;
141         (*sr->sca->func)(sr->arg,sr->sca->userdata);
142         stats_requested=g_slist_remove(stats_requested, sr);
143         g_free(sr->arg);
144         g_free(sr);
145     }
146 }
147
148 static wmem_tree_t *registered_stat_tables = NULL;
149
150 void register_stat_tap_table_ui(stat_tap_table_ui *ui)
151 {
152     if (registered_stat_tables == NULL)
153         registered_stat_tables = wmem_tree_new(wmem_epan_scope());
154
155     wmem_tree_insert_string(registered_stat_tables, ui->cli_string, ui, 0);
156 }
157
158 stat_tap_table_ui *new_stat_tap_by_name(const char *name)
159 {
160     return (stat_tap_table_ui *) wmem_tree_lookup_string(registered_stat_tables, name, 0);
161 }
162
163 void new_stat_tap_iterate_tables(wmem_foreach_func func, gpointer user_data)
164 {
165     wmem_tree_foreach(registered_stat_tables, func, user_data);
166 }
167
168 void new_stat_tap_get_filter(stat_tap_table_ui* new_stat, const char *opt_arg, const char **filter, char** err)
169 {
170     guint len = (guint) strlen(new_stat->cli_string);
171     *filter=NULL;
172     *err=NULL;
173
174     if (!strncmp(opt_arg, new_stat->cli_string, len))
175     {
176         if (opt_arg[len] == ',')
177         {
178            *filter = opt_arg + len+1;
179         }
180     }
181
182     if (new_stat->stat_filter_check_cb)
183         new_stat->stat_filter_check_cb(opt_arg, filter, err);
184 }
185
186 stat_tap_table* new_stat_tap_init_table(const char *name, int num_fields, int num_elements,
187                 const char *filter_string, new_stat_tap_gui_init_cb gui_callback, void* gui_data)
188 {
189     stat_tap_table* new_table = g_new0(stat_tap_table, 1);
190
191     new_table->title = name;
192     new_table->num_elements = num_elements;
193     new_table->num_fields = num_fields;
194     new_table->filter_string = filter_string;
195     new_table->elements = g_new0(stat_tap_table_item_type*, num_elements);
196
197     if (gui_callback)
198         gui_callback(new_table, gui_data);
199
200     return new_table;
201 }
202
203 void new_stat_tap_add_table(stat_tap_table_ui* new_stat, stat_tap_table* table)
204 {
205     if (new_stat->tables == NULL)
206         new_stat->tables = g_array_new(FALSE, TRUE, sizeof(stat_tap_table*));
207
208     g_array_insert_val(new_stat->tables, new_stat->tables->len, table);
209 }
210
211 void new_stat_tap_init_table_row(stat_tap_table *stat_table, guint table_index, guint num_fields, const stat_tap_table_item_type* fields)
212 {
213     /* we have discovered a new procedure. Extend the table accordingly */
214     if(table_index>=stat_table->num_elements){
215         guint old_num_elements=stat_table->num_elements;
216         guint i;
217
218         stat_table->num_elements=table_index+1;
219         stat_table->elements = (stat_tap_table_item_type**)g_realloc(stat_table->elements, sizeof(stat_tap_table_item_type*)*(stat_table->num_elements));
220         for(i=old_num_elements;i<stat_table->num_elements;i++){
221             stat_table->elements[i] = g_new0(stat_tap_table_item_type, stat_table->num_fields);
222         }
223     }
224     memcpy(stat_table->elements[table_index], fields, num_fields*sizeof(stat_tap_table_item_type));
225
226 }
227
228 stat_tap_table_item_type* new_stat_tap_get_field_data(const stat_tap_table *stat_table, guint table_index, guint field_index)
229 {
230     stat_tap_table_item_type* field_value;
231     g_assert(table_index < stat_table->num_elements);
232
233     field_value = stat_table->elements[table_index];
234
235     g_assert(field_index < stat_table->num_fields);
236
237     return &field_value[field_index];
238 }
239
240 void new_stat_tap_set_field_data(stat_tap_table *stat_table, guint table_index, guint field_index, stat_tap_table_item_type* field_data)
241 {
242     stat_tap_table_item_type* field_value;
243     g_assert(table_index < stat_table->num_elements);
244
245     field_value = stat_table->elements[table_index];
246
247     g_assert(field_index < stat_table->num_fields);
248
249     field_value[field_index] = *field_data;
250 }
251
252 void reset_stat_table(stat_tap_table_ui* new_stat, new_stat_tap_gui_reset_cb gui_callback, void *callback_data)
253 {
254     guint i = 0;
255     stat_tap_table *stat_table;
256
257     for (i = 0; i < new_stat->tables->len; i++)
258     {
259         stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
260
261         /* Give GUI the first crack at it before we clean up */
262         if (gui_callback)
263             gui_callback(stat_table, callback_data);
264
265         if (new_stat->stat_tap_reset_table_cb)
266             new_stat->stat_tap_reset_table_cb(stat_table);
267     }
268 }
269
270 void free_stat_tables(stat_tap_table_ui* new_stat, new_stat_tap_gui_free_cb gui_callback, void *callback_data)
271 {
272     guint i = 0, element, field_index;
273     stat_tap_table *stat_table;
274     stat_tap_table_item_type* field_data;
275
276     for (i = 0; i < new_stat->tables->len; i++)
277     {
278         stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
279
280         /* Give GUI the first crack at it before we clean up */
281         if (gui_callback)
282             gui_callback(stat_table, callback_data);
283
284         for (element = 0; element < stat_table->num_elements; element++)
285         {
286             for (field_index = 0; field_index < stat_table->num_fields; field_index++)
287             {
288                 field_data = new_stat_tap_get_field_data(stat_table, element, field_index);
289                 /* Give dissector a crack at it */
290                 /* XXX Should this be per-row instead? */
291                 if (new_stat->stat_tap_free_table_item_cb)
292                     new_stat->stat_tap_free_table_item_cb(stat_table, element, field_index, field_data);
293             }
294             g_free(stat_table->elements[element]);
295         }
296         g_free(stat_table->elements);
297         g_free(stat_table);
298     }
299     g_array_set_size(new_stat->tables, 0);
300 }
301
302
303 /*
304  * Editor modelines
305  *
306  * Local Variables:
307  * c-basic-offset: 4
308  * tab-width: 8
309  * indent-tabs-mode: nil
310  * End:
311  *
312  * ex: set shiftwidth=4 tabstop=8 expandtab:
313  * :indentSize=4:tabSize=8:noTabs=true:
314  */