1    | #include "mysql_driver.h"
2    | #include "access_control.h"
3    | #include "thread.h"
4    | #include "constants.h"
5    | #include "properties.h"
6    | #include "protocol_config.h"
7    | #include "protocol_whois.h"
8    | #include "ta.h"
9    | #include "pc_commands.h"
10   | 
11   | #include "er_paths.h"
12   | #include "er_macro.h"
13   | 
14   | /* this is for purify - to display the memory allocation records */
15   | extern void purify_new_inuse(void);
16   | 
17   | 
18   | 
19   | /*++++++++++++++++++++++++++++++++++++++
20   |   
21   |   All functions in this file share the same interface: they take the
22   |   arguments to the command given by the user, pointer to a dynamic
23   |   GString to which the command output should be appended and the
24   |   connection data, so that some things can be displayed directly to it,
25   |   bypassing the GString.
26   |   
27   |   int <command_something>     return code. 0 indicates success.
28   |                               PC_RET_QUIT is a reserved code
29   |                               that indicates that the connection
30   | 			      should be closed. 
31   | 
32   |   char *input                 command arguments
33   | 
34   |   GString *output             (dynamic) output string
35   | 
36   |   sk_conn_st *condat          connection data
37   | 
38   |   ++++++++++++++++++++++++++++++++++++++*/
39   | 
40   | /*++++++++++++++++++++++++++++++++++++++
41   |       
42   |   Relay functions for composed commands (eg. "set counter").
43   | 
44   |   They run the second word as a command from a specific array
45   |   (show/set/stop/whatever). The hardcoded text is used only for help
46   |   messages, printed in case the command is wrong as 
47   | 
48   |  "<hardcoded> commands are: <list of possible commands>".
49   | 
50   |  ++++++++++++++++++++++++++++++++++++++*/
51   | int command_show(char *input, GString *output, sk_conn_st *condat) {
52   |   return command_execute(show, "show ", input, output, condat);
53   | }
54   | 
55   | int command_set( char *input, GString *output, sk_conn_st *condat) {
56   |   return command_execute(set,  "set ",  input, output, condat);
57   | }
58   | 
59   | int command_stop(char *input, GString *output, sk_conn_st *condat) {
60   |   return command_execute(stop, "stop ", input, output, condat);
61   | }
62   | 
63   | 
64   | /*++++++++++++++++++++++++++++++++++++++
65   |   
66   |   Display available commands.
67   |   
68   |   ++++++++++++++++++++++++++++++++++++++*/
69   | int command_help(char *input, GString *output, sk_conn_st *condat) 
70   | {
71   |   /* by the time it came here, the "help" bit is already taken away. */
72   |   return show_commands(command, "", output);
73   | 
74   | }
75   | 
76   | 
77   | /*++++++++++++++++++++++++++++++++++++++
78   |   
79   |   Quit the config session.
80   | 
81   |   ++++++++++++++++++++++++++++++++++++++*/
82   | int command_quit(char *input, GString *output, sk_conn_st *condat) {
83   |     /* Administrator wishes to quit. */
84   |   return PC_RET_QUIT;
85   | } /* command_quit() */
86   | 
87   | /*++++++++++++++++++++++++++++++++++++++
88   |   
89   |   Display the memory allocation records of purify(tm).
90   |   The #define must be changed to activate this.
91   |   The program will link only with purify.
92   | 
93   |   ++++++++++++++++++++++++++++++++++++++*/
94   | int command_purify(char *input, GString *output, sk_conn_st *condat)
95   | {
96   | #if 0
97   |   purify_new_inuse();
98   | #else 
99   |   g_string_append(output, "NOP");
100  | #endif
101  |   
102  |   return 0;
103  | }
104  | 
105  | 
106  | /*++++++++++++++++++++++++++++++++++++++
107  |   
108  |   Display a specific constant of the CO module.
109  | 
110  |   Argument: name of the constant.
111  | 
112  |   ++++++++++++++++++++++++++++++++++++++*/
113  | int show_const(char *input, GString *output, sk_conn_st *condat) {
114  |   /* Administrator wishes to show constants. */
115  |   char *result, *name, *cursor;
116  |   int res = 0;
117  |   
118  |   if( strlen(input) > 0 ) {
119  |     cursor = input;
120  |     name = (char *)strsep(&cursor, " ");
121  | 
122  |     if( (result = CO_const_to_string(name)) != NULL ) {
123  |       g_string_append(output, result);
124  |       wr_free(result);
125  |     }
126  |     else {
127  |       g_string_append(output,  "unknown constant");
128  |       res = PC_RET_ERR;
129  |     }
130  |   }
131  |   else {
132  |     g_string_append(output,  "name required");
133  |     res = PC_RET_ERR;
134  |   }
135  |  
136  |   return res;
137  | 
138  | } /* show_const() */
139  | 
140  | 
141  | /*++++++++++++++++++++++++++++++++++++++
142  |   
143  |   Display all the constants of the CO module.
144  | 
145  |   ++++++++++++++++++++++++++++++++++++++*/
146  | int show_consts(char *input, GString *output, sk_conn_st *condat) 
147  | {
148  |   /* Administrator wishes to show constants. */
149  |   char *s =  CO_to_string();
150  |   g_string_append(output, s);
151  |   free(s);
152  |   return 0;
153  | } /* show_consts() */
154  | 
155  | 
156  | /*++++++++++++++++++++++++++++++++++++++
157  |   
158  |   Display all the properties of the PR module.
159  | 
160  |   ++++++++++++++++++++++++++++++++++++++*/
161  | int show_props(char *input, GString *output, sk_conn_st *condat) 
162  | {
163  |   /* Administrator wishes to show properties. */
164  |   char *s =  PR_to_string();
165  |   g_string_append(output, s);
166  |   free(s);  
167  |   return 0;
168  | } /* show_props() */
169  | 
170  | 
171  | /*++++++++++++++++++++++++++++++++++++++
172  |   
173  |   Display all running threads registered with the TA module.
174  | 
175  |   ++++++++++++++++++++++++++++++++++++++*/
176  | int show_threads(char *input, GString *output, sk_conn_st *condat) 
177  | {
178  |   /* Administrator wishes to show thread information. */
179  |   char *s = TA_tostring();
180  |   g_string_append(output, s);
181  |   free(s);  
182  |   return 0;
183  | } /* show_thread() */
184  | 
185  | 
186  | /*++++++++++++++++++++++++++++++++++++++
187  |   
188  |   Switch the session to a whois session.
189  | 
190  |   ++++++++++++++++++++++++++++++++++++++*/
191  | int show_whois(char *input, GString *output, sk_conn_st *condat) 
192  | {
193  |   /*  Go to whois mode */
194  |   PW_interact(condat->sock);
195  |   return 0;
196  | } /* show_whois() */
197  | 
198  | 
199  | /*++++++++++++++++++++++++++++++++++++++
200  |   
201  |   Display the statistics about the server.
202  | 
203  |   ++++++++++++++++++++++++++++++++++++++*/
204  | int show_uptime(char *input, GString *output, sk_conn_st *condat) 
205  | {
206  |   char timestring[26];
207  |   extern time_t SV_starttime;
208  |   
209  |   ctime_r(&SV_starttime, timestring); 
210  |   SK_cd_printf( condat, 
211  | 	       "System running since %sUptime in seconds: %ld \n\n",
212  | 	       timestring,		  
213  | 	       time(NULL) - SV_starttime);
214  |   
215  |   return 0;
216  | } 
217  | 
218  | /*++++++++++++++++++++++++++++++++++++++
219  |   
220  |   Display the whois access statistics from the AC module.
221  | 
222  |   ++++++++++++++++++++++++++++++++++++++*/
223  | int show_access(char *input, GString *output, sk_conn_st *condat) 
224  | {  
225  |   int cnt = AC_print_access(output);
226  |   
227  |   g_string_sprintfa(output, "Found %d nodes\n", cnt);
228  | 
229  |   return 0;
230  | } /* show_access() */
231  | 
232  | 
233  | /*++++++++++++++++++++++++++++++++++++++
234  |   
235  |   Display the whois access control list from the AC module.
236  | 
237  |   ++++++++++++++++++++++++++++++++++++++*/
238  | int show_acl(char *input, GString *output, sk_conn_st *condat) 
239  | {
240  |   int cnt = AC_print_acl(output);
241  | 
242  |   g_string_sprintfa(output, "Found %d nodes\n", cnt);
243  | 
244  |   return 0;
245  | } /* show_acl() */
246  | 
247  | 
248  | /*++++++++++++++++++++++++++++++++++++++
249  |   
250  |   Modify the whois access control list in the AC module.
251  | 
252  |   Arguments: IP[/prefixlength] column=value,column=value...
253  | 
254  |   Column names as in acl display. Unset columns are inherited.
255  | 
256  |   ++++++++++++++++++++++++++++++++++++++*/
257  | int set_acl(char *input, GString *output, sk_conn_st *condat)
258  | {
259  |   int res = 0;
260  |   
261  |   /* first 8 characters ("set acl ") are already skipped */
262  |   if( ! NOERR( AC_asc_acl_command_set( input, "Manual"))) {
263  |     g_string_append(output, "Error!\n");
264  |     res = PC_RET_ERR;
265  |   }
266  |   return res;
267  | }
268  | 
269  | /*++++++++++++++++++++++++++++++++++++++
270  |   
271  |   Reset the deny counter in the access tree to 0 (after reenabling) 
272  |   (AC module).
273  | 
274  |   Argument: IP address.
275  | 
276  |   ++++++++++++++++++++++++++++++++++++++*/
277  | int set_nodeny(char *input, GString *output, sk_conn_st *condat) {
278  |   
279  |   /* first 11 characters ("set nodeny ")  are already skipped */
280  | 
281  |   if( ! NOERR( AC_asc_set_nodeny(input) )) {
282  |     g_string_append(output, "Error\n");
283  |     return PC_RET_ERR;
284  |   }
285  |   else {
286  |     return 0;
287  |   }
288  |   
289  | } /* set_nodeny() */
290  | 
291  | 
292  | /*++++++++++++++++++++++++++++++++++++++
293  |   
294  |   Pause/resume update capability of the UD module.
295  | 
296  |   Argument: the word "pause" or "resume".
297  | 
298  |   ++++++++++++++++++++++++++++++++++++++*/
299  | int set_updates(char *input, GString *output, sk_conn_st *condat) 
300  | {
301  |   char argstr[17];
302  |   int pause=0, resume=0;
303  |   int res = 0;
304  |  
305  |   if( sscanf(input, "%16s", argstr) == 1) {
306  |     pause = (strcmp(argstr,"pause") == 0);
307  |     resume = (strcmp(argstr,"resume") == 0);
308  |   }
309  |   
310  |   if( !pause && !resume ) {
311  |     g_string_append(output,  "syntax error.");
312  |     res = PC_RET_ERR;
313  |   }
314  |   else {
315  |     /* all params ok. just set the property */
316  |     char *value = pause ? "0" : "1";
317  |     
318  |     if (CO_set_const("UD.do_update", value) == 0) {
319  |       g_string_append(output, "Constant successfully set\n");
320  |     }
321  |     else {
322  |       g_string_append(output, "Could not set\n");
323  |       res = PC_RET_ERR;
324  |     }
325  |   }
326  |   return res;
327  | }
328  | 
329  | 
330  | /*++++++++++++++++++++++++++++++++++++++
331  |   
332  |   Reset the "session time" and "# of tasks" 
333  |   of a specific thread registered with the TA module.
334  | 
335  |   ++++++++++++++++++++++++++++++++++++++*/
336  | int set_counter(char *input, GString *output, sk_conn_st *condat) 
337  | {
338  |   unsigned thr_id;
339  |   
340  |   if( sscanf(input, "%d", &thr_id) == 1) {
341  |     TA_reset_counters(thr_id);
342  |   }
343  |   return 0;
344  | }
345  | 
346  | 
347  | 
348  | /*++++++++++++++++++++++++++++++++++++++
349  |   
350  |   Execute a command in the ER path processor of the ER module.
351  |   (first subject to macro expansion of the first word).
352  | 
353  |   Argument is passed entirely to ER_macro_spec().
354  | 
355  |   ++++++++++++++++++++++++++++++++++++++*/
356  | int set_err(char *input, GString *output, sk_conn_st *condat) 
357  | {
358  |   char *erret = NULL;
359  |   int res;
360  | 
361  |   res = ER_macro_spec(input, &erret);
362  |   g_string_append(output, erret);
363  |   free(erret);
364  | 
365  |   return res;
366  | }
367  | 
368  | 
369  | /*++++++++++++++++++++++++++++++++++++++
370  |   
371  |   Show the current setup of the ER path system of the ER module.
372  |   
373  |   ++++++++++++++++++++++++++++++++++++++*/
374  | int show_err(char *input, GString *output, sk_conn_st *condat) 
375  | {
376  |   char *erret = NULL;
377  | 
378  |   er_print_paths(&erret);
379  |   g_string_append(output, erret);
380  |   free(erret);
381  | 
382  |   return 0;
383  | }
384  | 
385  | 
386  | /*++++++++++++++++++++++++++++++++++++++
387  |   
388  |   Show the currently defined macros for the ER path system of the ER module.
389  | 
390  |   ++++++++++++++++++++++++++++++++++++++*/
391  | int show_macros(char *input, GString *output, sk_conn_st *condat)
392  | {
393  |   ER_macro_list(condat);
394  |   return 0;
395  | }
396  | 
397  | 
398  | 
399  | /*++++++++++++++++++++++++++++++++++++++
400  |   
401  |   (re)define a macro for the ER path processor.
402  | 
403  |   Arguments: The first word is treated as a macro name. 
404  |   The rest of the line is treated as a macro definition.
405  | 
406  |   ++++++++++++++++++++++++++++++++++++++*/
407  | int set_macro(char *input, GString *output, sk_conn_st *condat)
408  | {
409  |   char *name, *body;
410  |   
411  |   if( strlen(input) > 0 ) {
412  |     body = input;
413  |     name = (char *)strsep(&body, " "); 
414  |     
415  |     ER_make_macro( name, body );
416  |   }
417  | 
418  |   return 0;
419  | }
420  | 
421  | 
422  | 
423  | 
424  | /*++++++++++++++++++++++++++++++++++++++
425  |   
426  |   Trigger running of the socket watchdog actions for a specific thread
427  |   (typically resulting in shutting down of a query thread). 
428  |   
429  |   Arguments are "<socket_id> <thread_id>" as in the output of "show threads".
430  | 
431  |   Assumes the command is like "stop query 11 17". 
432  |   This is to limit ambiguities (a new thread on the same socket, for example).
433  | . 
434  |   ++++++++++++++++++++++++++++++++++++++*/
435  | int stop_query(char *input, GString *output, sk_conn_st *condat) 
436  | {
437  |   int fd;
438  |   unsigned thr;
439  | 
440  |   
441  |   if( sscanf(input, "%d %ud", &fd, &thr) < 2 ) {
442  |     g_string_append(output,"error!!");
443  |     return PC_RET_ERR;
444  |   }
445  |   else {
446  |     TA_trigger("whois", fd, thr);
447  |     return 0;
448  |   }
449  | }