File: | cli/src/cli-cmd.c |
Location: | line 85, column 33 |
Description: | Dereference of null pointer (loaded from variable 'status') |
1 | /* | |||||
2 | Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com> | |||||
3 | This file is part of GlusterFS. | |||||
4 | ||||||
5 | This file is licensed to you under your choice of the GNU Lesser | |||||
6 | General Public License, version 3 or any later version (LGPLv3 or | |||||
7 | later), or the GNU General Public License, version 2 (GPLv2), in all | |||||
8 | cases as published by the Free Software Foundation. | |||||
9 | */ | |||||
10 | #include <stdio.h> | |||||
11 | #include <string.h> | |||||
12 | #include <stdlib.h> | |||||
13 | #include <stdint.h> | |||||
14 | #include <pthread.h> | |||||
15 | ||||||
16 | #ifndef _CONFIG_H | |||||
17 | #define _CONFIG_H | |||||
18 | #include "config.h" | |||||
19 | #endif | |||||
20 | ||||||
21 | #include "cli.h" | |||||
22 | #include "cli-cmd.h" | |||||
23 | #include "cli-mem-types.h" | |||||
24 | #include "protocol-common.h" | |||||
25 | ||||||
26 | #include <fnmatch.h> | |||||
27 | ||||||
28 | static int cmd_done; | |||||
29 | static int cmd_sent; | |||||
30 | static pthread_cond_t cond = PTHREAD_COND_INITIALIZER{ { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }; | |||||
31 | static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, { 0 } } }; | |||||
32 | static pthread_cond_t conn = PTHREAD_COND_INITIALIZER{ { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }; | |||||
33 | static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, { 0 } } }; | |||||
34 | ||||||
35 | int cli_op_ret = 0; | |||||
36 | int connected = 0; | |||||
37 | ||||||
38 | int cli_cmd_log_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, | |||||
39 | const char **words, int wordcount); | |||||
40 | ||||||
41 | static unsigned | |||||
42 | cli_cmd_needs_connection (struct cli_cmd_word *word) | |||||
43 | { | |||||
44 | if (!strcasecmp ("quit", word->word)) | |||||
45 | return 0; | |||||
46 | ||||||
47 | if (!strcasecmp ("help", word->word)) | |||||
48 | return 0; | |||||
49 | ||||||
50 | if (!strcasecmp ("getwd", word->word)) | |||||
51 | return 1; | |||||
52 | ||||||
53 | if (!strcasecmp ("exit", word->word)) | |||||
54 | return 0; | |||||
55 | ||||||
56 | return CLI_DEFAULT_CONN_TIMEOUT120; | |||||
57 | } | |||||
58 | ||||||
59 | int | |||||
60 | cli_cmd_status_reset (void) | |||||
61 | { | |||||
62 | int ret = 0; | |||||
63 | ||||||
64 | ret = cli_cmd_lock (); | |||||
65 | { | |||||
66 | if (ret == 0) { | |||||
67 | cmd_sent = 0; | |||||
68 | cmd_done = 0; | |||||
69 | } | |||||
70 | } | |||||
71 | ret = cli_cmd_unlock (); | |||||
72 | return ret; | |||||
73 | ||||||
74 | } | |||||
75 | ||||||
76 | int | |||||
77 | cli_cmd_sent_status_get (int *status) | |||||
78 | { | |||||
79 | int ret = 0; | |||||
80 | GF_ASSERT (status)do { if (!(status)) { do { do { if (0) printf ("Assertion failed: " "status"); } while (0); _gf_log_callingfn ("", "cli-cmd.c", __FUNCTION__ , 80, GF_LOG_ERROR, "Assertion failed: " "status"); } while ( 0); } } while (0); | |||||
| ||||||
81 | ||||||
82 | ret = cli_cmd_lock (); | |||||
83 | { | |||||
84 | if (ret == 0) | |||||
85 | *status = cmd_sent; | |||||
| ||||||
86 | } | |||||
87 | ret = cli_cmd_unlock (); | |||||
88 | return ret; | |||||
89 | } | |||||
90 | ||||||
91 | int | |||||
92 | cli_cmd_process (struct cli_state *state, int argc, char **argv) | |||||
93 | { | |||||
94 | int ret = 0; | |||||
95 | struct cli_cmd_word *word = NULL((void*)0); | |||||
96 | struct cli_cmd_word *next = NULL((void*)0); | |||||
97 | int i = 0; | |||||
98 | ||||||
99 | word = &state->tree.root; | |||||
100 | ||||||
101 | if (!argc) | |||||
102 | return 0; | |||||
103 | ||||||
104 | for (i = 0; i < argc; i++) { | |||||
105 | next = cli_cmd_nextword (word, argv[i]); | |||||
106 | ||||||
107 | word = next; | |||||
108 | if (!word) | |||||
109 | break; | |||||
110 | ||||||
111 | if (word->cbkfn) | |||||
112 | break; | |||||
113 | } | |||||
114 | ||||||
115 | if (!word) { | |||||
116 | cli_out ("unrecognized word: %s (position %d)",do { do { if (0) printf ("unrecognized word: %s (position %d)" , argv[i], i); } while (0); _cli_out("unrecognized word: %s (position %d)" , argv[i], i); } while (0) | |||||
117 | argv[i], i)do { do { if (0) printf ("unrecognized word: %s (position %d)" , argv[i], i); } while (0); _cli_out("unrecognized word: %s (position %d)" , argv[i], i); } while (0); | |||||
118 | return -1; | |||||
119 | } | |||||
120 | ||||||
121 | if (!word->cbkfn) { | |||||
122 | cli_out ("unrecognized command")do { do { if (0) printf ("unrecognized command"); } while (0) ; _cli_out("unrecognized command"); } while (0); | |||||
123 | return -1; | |||||
124 | } | |||||
125 | ||||||
126 | if ( strcmp (word->word,"help")==0 ) | |||||
127 | goto callback; | |||||
128 | ||||||
129 | state->await_connected = cli_cmd_needs_connection (word); | |||||
130 | ||||||
131 | ret = cli_cmd_await_connected (state->await_connected); | |||||
132 | if (ret) { | |||||
133 | cli_out ("Connection failed. Please check if gluster "do { do { if (0) printf ("Connection failed. Please check if gluster " "daemon is operational."); } while (0); _cli_out("Connection failed. Please check if gluster " "daemon is operational."); } while (0) | |||||
134 | "daemon is operational.")do { do { if (0) printf ("Connection failed. Please check if gluster " "daemon is operational."); } while (0); _cli_out("Connection failed. Please check if gluster " "daemon is operational."); } while (0); | |||||
135 | gf_log ("", GF_LOG_INFO, "Exiting with: %d", ret)do { do { if (0) printf ("Exiting with: %d", ret); } while (0 ); _gf_log ("", "cli-cmd.c", __FUNCTION__, 135, GF_LOG_INFO, "Exiting with: %d" , ret); } while (0); | |||||
136 | exit (ret); | |||||
137 | } | |||||
138 | ||||||
139 | callback: | |||||
140 | ret = word->cbkfn (state, word, (const char **)argv, argc); | |||||
141 | (void) cli_cmd_status_reset (); | |||||
142 | return ret; | |||||
143 | } | |||||
144 | ||||||
145 | int | |||||
146 | cli_cmd_input_token_count (const char *text) | |||||
147 | { | |||||
148 | int count = 0; | |||||
149 | const char *trav = NULL((void*)0); | |||||
150 | int is_spc = 1; | |||||
151 | ||||||
152 | for (trav = text; *trav; trav++) { | |||||
153 | if (*trav == ' ') { | |||||
154 | is_spc = 1; | |||||
155 | } else { | |||||
156 | if (is_spc) { | |||||
157 | count++; | |||||
158 | is_spc = 0; | |||||
159 | } | |||||
160 | } | |||||
161 | } | |||||
162 | ||||||
163 | return count; | |||||
164 | } | |||||
165 | ||||||
166 | ||||||
167 | int | |||||
168 | cli_cmd_process_line (struct cli_state *state, const char *text) | |||||
169 | { | |||||
170 | int count = 0; | |||||
171 | char **tokens = NULL((void*)0); | |||||
172 | char **tokenp = NULL((void*)0); | |||||
173 | char *token = NULL((void*)0); | |||||
174 | char *copy = NULL((void*)0); | |||||
175 | char *saveptr = NULL((void*)0); | |||||
176 | int i = 0; | |||||
177 | int ret = -1; | |||||
178 | ||||||
179 | count = cli_cmd_input_token_count (text); | |||||
180 | ||||||
181 | tokens = calloc (count + 1, sizeof (*tokens)); | |||||
182 | if (!tokens) | |||||
183 | return -1; | |||||
184 | ||||||
185 | copy = strdup (text); | |||||
186 | if (!copy) | |||||
187 | goto out; | |||||
188 | ||||||
189 | tokenp = tokens; | |||||
190 | ||||||
191 | for (token = strtok_r (copy, " \t\r\n", &saveptr); token; | |||||
192 | token = strtok_r (NULL((void*)0), " \t\r\n", &saveptr)) { | |||||
193 | *tokenp = strdup (token); | |||||
194 | ||||||
195 | if (!*tokenp) | |||||
196 | goto out; | |||||
197 | tokenp++; | |||||
198 | i++; | |||||
199 | ||||||
200 | } | |||||
201 | ||||||
202 | ret = cli_cmd_process (state, count, tokens); | |||||
203 | out: | |||||
204 | free (copy); | |||||
205 | ||||||
206 | if (tokens) | |||||
207 | cli_cmd_tokens_destroy (tokens); | |||||
208 | ||||||
209 | return ret; | |||||
210 | } | |||||
211 | ||||||
212 | ||||||
213 | int | |||||
214 | cli_cmds_register (struct cli_state *state) | |||||
215 | { | |||||
216 | int ret = 0; | |||||
217 | ||||||
218 | ret = cli_cmd_volume_register (state); | |||||
219 | if (ret) | |||||
220 | goto out; | |||||
221 | ||||||
222 | ret = cli_cmd_probe_register (state); | |||||
223 | if (ret) | |||||
224 | goto out; | |||||
225 | ||||||
226 | ret = cli_cmd_system_register (state); | |||||
227 | if (ret) | |||||
228 | goto out; | |||||
229 | ||||||
230 | ret = cli_cmd_misc_register (state); | |||||
231 | if (ret) | |||||
232 | goto out; | |||||
233 | ||||||
234 | #ifdef HAVE_BD_XLATOR | |||||
235 | ret = cli_cmd_bd_register (state); | |||||
236 | if (ret) | |||||
237 | goto out; | |||||
238 | #endif | |||||
239 | out: | |||||
240 | return ret; | |||||
241 | } | |||||
242 | ||||||
243 | int | |||||
244 | cli_cmd_cond_init () | |||||
245 | { | |||||
246 | ||||||
247 | pthread_mutex_init (&cond_mutex, NULL((void*)0)); | |||||
248 | pthread_cond_init (&cond, NULL((void*)0)); | |||||
249 | ||||||
250 | pthread_mutex_init (&conn_mutex, NULL((void*)0)); | |||||
251 | pthread_cond_init (&conn, NULL((void*)0)); | |||||
252 | ||||||
253 | return 0; | |||||
254 | } | |||||
255 | ||||||
256 | int | |||||
257 | cli_cmd_lock () | |||||
258 | { | |||||
259 | pthread_mutex_lock (&cond_mutex); | |||||
260 | return 0; | |||||
261 | } | |||||
262 | ||||||
263 | int | |||||
264 | cli_cmd_unlock () | |||||
265 | { | |||||
266 | pthread_mutex_unlock (&cond_mutex); | |||||
267 | return 0; | |||||
268 | } | |||||
269 | ||||||
270 | static void | |||||
271 | seconds_from_now (unsigned secs, struct timespec *ts) | |||||
272 | { | |||||
273 | struct timeval tv = {0,}; | |||||
274 | ||||||
275 | gettimeofday (&tv, NULL((void*)0)); | |||||
276 | ||||||
277 | ts->tv_sec = tv.tv_sec + secs; | |||||
278 | ts->tv_nsec = tv.tv_usec * 1000; | |||||
279 | } | |||||
280 | ||||||
281 | int | |||||
282 | cli_cmd_await_response (unsigned time) | |||||
283 | { | |||||
284 | struct timespec ts = {0,}; | |||||
285 | int ret = 0; | |||||
286 | ||||||
287 | cli_op_ret = -1; | |||||
288 | ||||||
289 | seconds_from_now (time, &ts); | |||||
290 | while (!cmd_done && !ret) { | |||||
291 | ret = pthread_cond_timedwait (&cond, &cond_mutex, | |||||
292 | &ts); | |||||
293 | } | |||||
294 | ||||||
295 | cmd_done = 0; | |||||
296 | ||||||
297 | if (ret) | |||||
298 | return ret; | |||||
299 | ||||||
300 | return cli_op_ret; | |||||
301 | } | |||||
302 | ||||||
303 | int | |||||
304 | cli_cmd_broadcast_response (int32_t status) | |||||
305 | { | |||||
306 | ||||||
307 | pthread_mutex_lock (&cond_mutex); | |||||
308 | { | |||||
309 | if (!cmd_sent) | |||||
310 | goto out; | |||||
311 | cmd_done = 1; | |||||
312 | cli_op_ret = status; | |||||
313 | pthread_cond_broadcast (&cond); | |||||
314 | } | |||||
315 | ||||||
316 | ||||||
317 | out: | |||||
318 | pthread_mutex_unlock (&cond_mutex); | |||||
319 | return 0; | |||||
320 | } | |||||
321 | ||||||
322 | int32_t | |||||
323 | cli_cmd_await_connected (unsigned conn_timo) | |||||
324 | { | |||||
325 | int32_t ret = 0; | |||||
326 | struct timespec ts = {0,}; | |||||
327 | ||||||
328 | if (!conn_timo) | |||||
329 | return 0; | |||||
330 | ||||||
331 | pthread_mutex_lock (&conn_mutex); | |||||
332 | { | |||||
333 | seconds_from_now (conn_timo, &ts); | |||||
334 | while (!connected && !ret) { | |||||
335 | ret = pthread_cond_timedwait (&conn, &conn_mutex, | |||||
336 | &ts); | |||||
337 | } | |||||
338 | } | |||||
339 | pthread_mutex_unlock (&conn_mutex); | |||||
340 | ||||||
341 | ||||||
342 | return ret; | |||||
343 | } | |||||
344 | ||||||
345 | int32_t | |||||
346 | cli_cmd_broadcast_connected () | |||||
347 | { | |||||
348 | pthread_mutex_lock (&conn_mutex); | |||||
349 | { | |||||
350 | connected = 1; | |||||
351 | pthread_cond_broadcast (&conn); | |||||
352 | } | |||||
353 | ||||||
354 | pthread_mutex_unlock (&conn_mutex); | |||||
355 | ||||||
356 | return 0; | |||||
357 | } | |||||
358 | ||||||
359 | int | |||||
360 | cli_cmd_submit (void *req, call_frame_t *frame, | |||||
361 | rpc_clnt_prog_t *prog, | |||||
362 | int procnum, struct iobref *iobref, | |||||
363 | xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc) | |||||
364 | { | |||||
365 | int ret = -1; | |||||
366 | unsigned timeout = 0; | |||||
367 | ||||||
368 | timeout = (GLUSTER_CLI_PROFILE_VOLUME == procnum) ? | |||||
369 | CLI_TOP_CMD_TIMEOUT600 : CLI_DEFAULT_CMD_TIMEOUT120; | |||||
370 | ||||||
371 | cli_cmd_lock (); | |||||
372 | cmd_sent = 0; | |||||
373 | ret = cli_submit_request (req, frame, prog, | |||||
374 | procnum, NULL((void*)0), this, cbkfn, xdrproc); | |||||
375 | ||||||
376 | if (!ret) { | |||||
377 | cmd_sent = 1; | |||||
378 | ret = cli_cmd_await_response (timeout); | |||||
379 | } | |||||
380 | ||||||
381 | cli_cmd_unlock (); | |||||
382 | ||||||
383 | gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret)do { do { if (0) printf ("Returning %d", ret); } while (0); _gf_log ("cli", "cli-cmd.c", __FUNCTION__, 383, GF_LOG_DEBUG, "Returning %d" , ret); } while (0); | |||||
384 | return ret; | |||||
385 | } |