RIP BOOL. Convert BOOL -> bool. I found a few interesting
[ira/wip.git] / source3 / torture / vfstest.c
1 /* 
2    Unix SMB/CIFS implementation.
3    VFS module tester
4
5    Copyright (C) Simo Sorce 2002
6    Copyright (C) Eric Lorimer 2002
7    Copyright (C) Jelmer Vernooij 2002,2003
8
9    Most of this code was ripped off of rpcclient.
10    Copyright (C) Tim Potter 2000-2001
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "vfstest.h"
28
29 /* List to hold groups of commands */
30 static struct cmd_list {
31         struct cmd_list *prev, *next;
32         struct cmd_set *cmd_set;
33 } *cmd_list;
34
35 extern pstring user_socket_options;
36
37 /****************************************************************************
38 handle completion of commands for readline
39 ****************************************************************************/
40 static char **completion_fn(const char *text, int start, int end)
41 {
42 #define MAX_COMPLETIONS 100
43         char **matches;
44         int i, count=0;
45         struct cmd_list *commands = cmd_list;
46
47         if (start) 
48                 return NULL;
49
50         /* make sure we have a list of valid commands */
51         if (!commands) 
52                 return NULL;
53
54         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
55         if (!matches) return NULL;
56
57         matches[count++] = SMB_STRDUP(text);
58         if (!matches[0]) return NULL;
59
60         while (commands && count < MAX_COMPLETIONS-1) 
61         {
62                 if (!commands->cmd_set)
63                         break;
64                 
65                 for (i=0; commands->cmd_set[i].name; i++)
66                 {
67                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
68                                 commands->cmd_set[i].fn) 
69                         {
70                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
71                                 if (!matches[count]) 
72                                         return NULL;
73                                 count++;
74                         }
75                 }
76                 
77                 commands = commands->next;
78                 
79         }
80
81         if (count == 2) {
82                 SAFE_FREE(matches[0]);
83                 matches[0] = SMB_STRDUP(matches[1]);
84         }
85         matches[count] = NULL;
86         return matches;
87 }
88
89 static char* next_command(char** cmdstr)
90 {
91         static pstring          command;
92         char                    *p;
93         
94         if (!cmdstr || !(*cmdstr))
95                 return NULL;
96         
97         p = strchr_m(*cmdstr, ';');
98         if (p)
99                 *p = '\0';
100         pstrcpy(command, *cmdstr);
101         *cmdstr = p;
102         
103         return command;
104 }
105
106 /* Load specified configuration file */
107 static NTSTATUS cmd_conf(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
108                         int argc, const char **argv)
109 {
110         if (argc != 2) {
111                 printf("Usage: %s <smb.conf>\n", argv[0]);
112                 return NT_STATUS_OK;
113         }
114
115         if (!lp_load(argv[1], False, True, False, True)) {
116                 printf("Error loading \"%s\"\n", argv[1]);
117                 return NT_STATUS_OK;
118         }
119
120         printf("\"%s\" successfully loaded\n", argv[1]);
121         return NT_STATUS_OK;
122 }
123         
124 /* Display help on commands */
125 static NTSTATUS cmd_help(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
126                          int argc, const char **argv)
127 {
128         struct cmd_list *tmp;
129         struct cmd_set *tmp_set;
130
131         /* Usage */
132         if (argc > 2) {
133                 printf("Usage: %s [command]\n", argv[0]);
134                 return NT_STATUS_OK;
135         }
136
137         /* Help on one command */
138
139         if (argc == 2) {
140                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
141                         
142                         tmp_set = tmp->cmd_set;
143
144                         while(tmp_set->name) {
145                                 if (strequal(argv[1], tmp_set->name)) {
146                                         if (tmp_set->usage &&
147                                             tmp_set->usage[0])
148                                                 printf("%s\n", tmp_set->usage);
149                                         else
150                                                 printf("No help for %s\n", tmp_set->name);
151
152                                         return NT_STATUS_OK;
153                                 }
154
155                                 tmp_set++;
156                         }
157                 }
158
159                 printf("No such command: %s\n", argv[1]);
160                 return NT_STATUS_OK;
161         }
162
163         /* List all commands */
164
165         for (tmp = cmd_list; tmp; tmp = tmp->next) {
166
167                 tmp_set = tmp->cmd_set;
168
169                 while(tmp_set->name) {
170
171                         printf("%15s\t\t%s\n", tmp_set->name,
172                                tmp_set->description ? tmp_set->description:
173                                "");
174
175                         tmp_set++;
176                 }
177         }
178
179         return NT_STATUS_OK;
180 }
181
182 /* Change the debug level */
183 static NTSTATUS cmd_debuglevel(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
184 {
185         if (argc > 2) {
186                 printf("Usage: %s [debuglevel]\n", argv[0]);
187                 return NT_STATUS_OK;
188         }
189
190         if (argc == 2) {
191                 DEBUGLEVEL = atoi(argv[1]);
192         }
193
194         printf("debuglevel is %d\n", DEBUGLEVEL);
195
196         return NT_STATUS_OK;
197 }
198
199 static NTSTATUS cmd_freemem(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
200 {
201         /* Cleanup */
202         talloc_destroy(mem_ctx);
203         mem_ctx = NULL;
204         vfs->data = NULL;
205         vfs->data_size = 0;
206         return NT_STATUS_OK;
207 }
208
209 static NTSTATUS cmd_quit(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
210 {
211         /* Cleanup */
212         talloc_destroy(mem_ctx);
213
214         exit(0);
215         return NT_STATUS_OK; /* NOTREACHED */
216 }
217
218 static struct cmd_set vfstest_commands[] = {
219
220         { "GENERAL OPTIONS" },
221
222         { "conf",       cmd_conf,       "Load smb configuration file", "conf <smb.conf>" },
223         { "help",       cmd_help,       "Get help on commands", "" },
224         { "?",          cmd_help,       "Get help on commands", "" },
225         { "debuglevel", cmd_debuglevel, "Set debug level", "" },
226         { "freemem",    cmd_freemem,    "Free currently allocated buffers", "" },
227         { "exit",       cmd_quit,       "Exit program", "" },
228         { "quit",       cmd_quit,       "Exit program", "" },
229
230         { NULL }
231 };
232
233 static struct cmd_set separator_command[] = {
234         { "---------------", NULL,      "----------------------" },
235         { NULL }
236 };
237
238
239 extern struct cmd_set vfs_commands[];
240 static struct cmd_set *vfstest_command_list[] = {
241         vfstest_commands,
242         vfs_commands,
243         NULL
244 };
245
246 static void add_command_set(struct cmd_set *cmd_set)
247 {
248         struct cmd_list *entry;
249
250         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
251                 DEBUG(0, ("out of memory\n"));
252                 return;
253         }
254
255         ZERO_STRUCTP(entry);
256
257         entry->cmd_set = cmd_set;
258         DLIST_ADD(cmd_list, entry);
259 }
260
261 static NTSTATUS do_cmd(struct vfs_state *vfs, struct cmd_set *cmd_entry, char *cmd)
262 {
263         const char *p = cmd;
264         char **argv = NULL;
265         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
266         pstring buf;
267         TALLOC_CTX *mem_ctx = NULL;
268         int argc = 0, i;
269
270         /* Count number of arguments first time through the loop then
271            allocate memory and strdup them. */
272
273  again:
274         while(next_token(&p, buf, " ", sizeof(buf))) {
275                 if (argv) {
276                         argv[argc] = SMB_STRDUP(buf);
277                 }
278                 
279                 argc++;
280         }
281                                 
282         if (!argv) {
283
284                 /* Create argument list */
285
286                 argv = SMB_MALLOC_ARRAY(char *, argc);
287                 memset(argv, 0, sizeof(char *) * argc);
288
289                 if (!argv) {
290                         fprintf(stderr, "out of memory\n");
291                         result = NT_STATUS_NO_MEMORY;
292                         goto done;
293                 }
294                                         
295                 p = cmd;
296                 argc = 0;
297                                         
298                 goto again;
299         }
300
301         /* Call the function */
302
303         if (cmd_entry->fn) {
304
305                 if (mem_ctx == NULL) {
306                         /* Create mem_ctx */
307                         if (!(mem_ctx = talloc_init("do_cmd"))) {
308                                 DEBUG(0, ("talloc_init() failed\n"));
309                                 goto done;
310                         }
311                 }
312
313                 /* Run command */
314                 result = cmd_entry->fn(vfs, mem_ctx, argc, (const char **)argv);
315
316         } else {
317                 fprintf (stderr, "Invalid command\n");
318                 goto done;
319         }
320
321  done:
322                                                 
323         /* Cleanup */
324
325         if (argv) {
326                 for (i = 0; i < argc; i++)
327                         SAFE_FREE(argv[i]);
328         
329                 SAFE_FREE(argv);
330         }
331         
332         return result;
333 }
334
335 /* Process a command entered at the prompt or as part of -c */
336 static NTSTATUS process_cmd(struct vfs_state *vfs, char *cmd)
337 {
338         struct cmd_list *temp_list;
339         bool found = False;
340         pstring buf;
341         const char *p = cmd;
342         NTSTATUS result = NT_STATUS_OK;
343         int len = 0;
344
345         if (cmd[strlen(cmd) - 1] == '\n')
346                 cmd[strlen(cmd) - 1] = '\0';
347
348         if (!next_token(&p, buf, " ", sizeof(buf))) {
349                 return NT_STATUS_OK;
350         }
351
352         /* strip the trainly \n if it exsists */
353         len = strlen(buf);
354         if (buf[len-1] == '\n')
355                 buf[len-1] = '\0';
356
357         /* Search for matching commands */
358
359         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
360                 struct cmd_set *temp_set = temp_list->cmd_set;
361
362                 while(temp_set->name) {
363                         if (strequal(buf, temp_set->name)) {
364                                 found = True;
365                                 result = do_cmd(vfs, temp_set, cmd);
366
367                                 goto done;
368                         }
369                         temp_set++;
370                 }
371         }
372
373  done:
374         if (!found && buf[0]) {
375                 printf("command not found: %s\n", buf);
376                 return NT_STATUS_OK;
377         }
378
379         if (!NT_STATUS_IS_OK(result)) {
380                 printf("result was %s\n", nt_errstr(result));
381         }
382
383         return result;
384 }
385
386 static void process_file(struct vfs_state *pvfs, char *filename) {
387         FILE *file;
388         char command[3 * PATH_MAX];
389
390         if (*filename == '-') {
391                 file = stdin;
392         } else {
393                 file = fopen(filename, "r");
394                 if (file == NULL) {
395                         printf("vfstest: error reading file (%s)!", filename);
396                         printf("errno n.%d: %s", errno, strerror(errno));
397                         exit(-1);
398                 }
399         }
400
401         while (fgets(command, 3 * PATH_MAX, file) != NULL) {
402                 process_cmd(pvfs, command);
403         }
404 }
405
406 void exit_server(const char *reason)
407 {
408         DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
409         exit(0);
410 }
411
412 void exit_server_cleanly(const char *const reason)
413 {
414         exit_server("normal exit");
415 }
416
417 static int server_fd = -1;
418 int last_message = -1;
419
420 int smbd_server_fd(void)
421 {
422                 return server_fd;
423 }
424
425 void reload_printers(void)
426 {
427         return;
428 }
429
430 /****************************************************************************
431  Reload the services file.
432 **************************************************************************/
433
434 bool reload_services(bool test)
435 {
436         bool ret;
437         
438         if (lp_loaded()) {
439                 pstring fname;
440                 pstrcpy(fname,lp_configfile());
441                 if (file_exist(fname, NULL) &&
442                     !strcsequal(fname, dyn_CONFIGFILE)) {
443                         pstrcpy(dyn_CONFIGFILE, fname);
444                         test = False;
445                 }
446         }
447
448         reopen_logs();
449
450         if (test && !lp_file_list_changed())
451                 return(True);
452
453         lp_killunused(conn_snum_used);
454         
455         ret = lp_load(dyn_CONFIGFILE, False, False, True, True);
456
457         /* perhaps the config filename is now set */
458         if (!test)
459                 reload_services(True);
460
461         reopen_logs();
462
463         load_interfaces();
464
465         {
466                 if (smbd_server_fd() != -1) {      
467                         set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
468                         set_socket_options(smbd_server_fd(), user_socket_options);
469                 }
470         }
471
472         mangle_reset_cache();
473         reset_stat_cache();
474
475         /* this forces service parameters to be flushed */
476         set_current_service(NULL,0,True);
477
478         return (ret);
479 }
480
481 struct event_context *smbd_event_context(void)
482 {
483         static struct event_context *ctx;
484
485         if (!ctx && !(ctx = event_context_init(NULL))) {
486                 smb_panic("Could not init smbd event context\n");
487         }
488         return ctx;
489 }
490
491 struct messaging_context *smbd_messaging_context(void)
492 {
493         static struct messaging_context *ctx;
494
495         if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
496                                            smbd_event_context()))) {
497                 smb_panic("Could not init smbd messaging context\n");
498         }
499         return ctx;
500 }
501
502 /* Main function */
503
504 int main(int argc, char *argv[])
505 {
506         static char             *cmdstr = NULL;
507         struct cmd_set          **cmd_set;
508         static struct vfs_state vfs;
509         int i;
510         static char             *filename = NULL;
511
512         /* make sure the vars that get altered (4th field) are in
513            a fixed location or certain compilers complain */
514         poptContext pc;
515         struct poptOption long_options[] = {
516                 POPT_AUTOHELP
517                 {"file",        'f', POPT_ARG_STRING,   &filename, 0, },
518                 {"command",     'c', POPT_ARG_STRING,   &cmdstr, 0, "Execute specified list of commands" },
519                 POPT_COMMON_SAMBA
520                 POPT_TABLEEND
521         };
522
523         load_case_tables();
524
525         setlinebuf(stdout);
526
527         pc = poptGetContext("vfstest", argc, (const char **) argv,
528                             long_options, 0);
529         
530         while(poptGetNextOpt(pc) != -1);
531
532
533         poptFreeContext(pc);
534
535         /* TODO: check output */
536         reload_services(False);
537
538         /* the following functions are part of the Samba debugging
539            facilities.  See lib/debug.c */
540         setup_logging("vfstest", True);
541         
542         /* Load command lists */
543
544         cmd_set = vfstest_command_list;
545
546         while(*cmd_set) {
547                 add_command_set(*cmd_set);
548                 add_command_set(separator_command);
549                 cmd_set++;
550         }
551
552         /* some basic initialization stuff */
553         sec_init();
554         conn_init();
555         vfs.conn = conn_new();
556         string_set(&vfs.conn->user,"vfstest");
557         for (i=0; i < 1024; i++)
558                 vfs.files[i] = NULL;
559
560         /* some advanced initiliazation stuff */
561         smbd_vfs_init(vfs.conn);
562
563         /* Do we have a file input? */
564         if (filename && filename[0]) {
565                 process_file(&vfs, filename);
566                 return 0;
567         }
568
569         /* Do anything specified with -c */
570         if (cmdstr && cmdstr[0]) {
571                 char    *cmd;
572                 char    *p = cmdstr;
573  
574                 while((cmd=next_command(&p)) != NULL) {
575                         process_cmd(&vfs, cmd);
576                 }
577                 
578                 return 0;
579         }
580
581         /* Loop around accepting commands */
582
583         while(1) {
584                 pstring prompt;
585                 char *line;
586
587                 slprintf(prompt, sizeof(prompt) - 1, "vfstest $> ");
588
589                 line = smb_readline(prompt, NULL, completion_fn);
590
591                 if (line == NULL)
592                         break;
593
594                 if (line[0] != '\n')
595                         process_cmd(&vfs, line);
596         }
597         
598         conn_free(vfs.conn);
599         return 0;
600 }