smbtorture: Refactor interactive shell into independent commands.
[gd/samba-autobuild/.git] / source4 / torture / shell.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    Copyright (C) Jelmer Vernooij 2006-2008
6    Copyright (C) James Peach 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/readline.h"
24 #include "lib/smbreadline/smbreadline.h"
25 #include "torture/smbtorture.h"
26
27 struct shell_command;
28
29 typedef void (*shell_function)(const struct shell_command *,
30         struct torture_context *, int, const char **);
31
32 static void shell_quit(const struct shell_command *,
33         struct torture_context *, int, const char **);
34 static void shell_help(const struct shell_command *,
35         struct torture_context *, int, const char **);
36 static void shell_set(const struct shell_command *,
37         struct torture_context *, int, const char **);
38 static void shell_run(const struct shell_command *,
39         struct torture_context *, int, const char **);
40 static void shell_list(const struct shell_command *,
41         struct torture_context *, int, const char **);
42
43 static void shell_usage(const struct shell_command *);
44 static bool match_command(const char *, const struct shell_command *);
45
46 struct shell_command
47 {
48     shell_function  handler;
49     const char *    name;
50     const char *    usage;
51     const char *    help;
52 } shell_command;
53
54 static const struct shell_command commands[] =
55 {
56     {
57         shell_help, "help", NULL,
58         "print this help message"
59     },
60
61     {
62         shell_quit, "quit", NULL,
63         "exit smbtorture"
64     },
65
66     {
67         shell_list, "list", NULL,
68         "list the available tests"
69     },
70
71     {
72         shell_set, "set", "[NAME VALUE]",
73         "print or set test configuration parameters"
74     },
75
76     {
77         shell_run, "run", "[TESTNAME]",
78         "run the specified test"
79     }
80 };
81
82 void torture_shell(struct torture_context *tctx)
83 {
84         char *cline;
85         int argc;
86         const char **argv;
87         int ret;
88         int i;
89
90         while (1) {
91                 cline = smb_readline("torture> ", NULL, NULL);
92
93                 if (cline == NULL)
94                         return;
95
96 #if HAVE_ADD_HISTORY
97                 add_history(cline);
98 #endif
99
100                 ret = poptParseArgvString(cline, &argc, &argv);
101                 if (ret != 0) {
102                         fprintf(stderr, "Error parsing line\n");
103                         continue;
104                 }
105
106                 for (i = 0; i < ARRAY_SIZE(commands); i++) {
107                         if (match_command(argv[0], &commands[i])) {
108                                 argc--;
109                                 argv++;
110                                 commands[i].handler(&commands[i],
111                                         tctx, argc, argv);
112                                 break;
113                         }
114                 }
115
116                 free(cline);
117         }
118 }
119
120 static void shell_quit(const struct shell_command * command,
121         struct torture_context *tctx, int argc, const char **argv)
122 {
123     exit(0);
124 }
125
126 static void shell_help(const struct shell_command * command,
127         struct torture_context *tctx, int argc, const char **argv)
128 {
129     int i;
130
131     fprintf(stdout, "Available commands:\n");
132     for (i = 0; i < ARRAY_SIZE(commands); i++) {
133             fprintf(stdout, "\t%s - %s\n",
134                     commands[i].name, commands[i].help);
135     }
136 }
137
138 static void shell_set(const struct shell_command *command,
139         struct torture_context *tctx, int argc, const char **argv)
140 {
141         char * name;
142
143         switch (argc) {
144         case 0:
145             lp_dump(tctx->lp_ctx, stdout,
146                     false /* show_defaults */,
147                     0 /* skip services */);
148             break;
149
150         case 2:
151             name = talloc_asprintf(NULL, "torture:%s", argv[0]);
152             lp_set_cmdline(tctx->lp_ctx, name, argv[1]);
153             talloc_free(name);
154             break;
155
156         default:
157             shell_usage(command);
158         }
159 }
160
161 static void shell_run(const struct shell_command * command,
162         struct torture_context *tctx, int argc, const char **argv)
163 {
164     if (argc != 1) {
165         shell_usage(command);
166         return;
167     }
168
169     torture_run_named_tests(tctx, argv[0], NULL /* restricted */);
170 }
171
172 static void shell_list(const struct shell_command * command,
173         struct torture_context *tctx, int argc, const char **argv)
174 {
175     if (argc != 0) {
176         shell_usage(command);
177         return;
178     }
179
180     torture_print_tests(true);
181 }
182
183 static void shell_usage(const struct shell_command * command)
184 {
185     if (command->usage) {
186             fprintf(stderr, "Usage: %s %s\n",
187                     command->name, command->usage);
188     } else {
189             fprintf(stderr, "Usage: %s\n",
190                     command->name);
191     }
192 }
193
194 static bool match_command(const char * name,
195         const struct shell_command * command)
196 {
197         if (!strcmp(name, command->name)) {
198                 return true;
199         }
200
201         if (name[0] == command->name[0] && name[1] == '\0') {
202             return true;
203         }
204
205         return false;
206 }
207