#include "includes.h"
#include "vfstest.h"
static struct cmd_list {
struct cmd_list *prev, *next;
struct cmd_set *cmd_set;
} *cmd_list;
extern pstring user_socket_options;
static char **completion_fn(const char *text, int start, int end)
{
#define MAX_COMPLETIONS 100
char **matches;
int i, count=0;
struct cmd_list *commands = cmd_list;
if (start)
return NULL;
if (!commands)
return NULL;
matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
if (!matches) return NULL;
matches[count++] = SMB_STRDUP(text);
if (!matches[0]) return NULL;
while (commands && count < MAX_COMPLETIONS-1)
{
if (!commands->cmd_set)
break;
for (i=0; commands->cmd_set[i].name; i++)
{
if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
commands->cmd_set[i].fn)
{
matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
if (!matches[count])
return NULL;
count++;
}
}
commands = commands->next;
}
if (count == 2) {
SAFE_FREE(matches[0]);
matches[0] = SMB_STRDUP(matches[1]);
}
matches[count] = NULL;
return matches;
}
static char* next_command(char** cmdstr)
{
static pstring command;
char *p;
if (!cmdstr || !(*cmdstr))
return NULL;
p = strchr_m(*cmdstr, ';');
if (p)
*p = '\0';
pstrcpy(command, *cmdstr);
*cmdstr = p;
return command;
}
static NTSTATUS cmd_conf(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
int argc, const char **argv)
{
if (argc != 2) {
printf("Usage: %s <smb.conf>\n", argv[0]);
return NT_STATUS_OK;
}
if (!lp_load(argv[1], False, True, False, True)) {
printf("Error loading \"%s\"\n", argv[1]);
return NT_STATUS_OK;
}
printf("\"%s\" successfully loaded\n", argv[1]);
return NT_STATUS_OK;
}
static NTSTATUS cmd_help(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
int argc, const char **argv)
{
struct cmd_list *tmp;
struct cmd_set *tmp_set;
if (argc > 2) {
printf("Usage: %s [command]\n", argv[0]);
return NT_STATUS_OK;
}
if (argc == 2) {
for (tmp = cmd_list; tmp; tmp = tmp->next) {
tmp_set = tmp->cmd_set;
while(tmp_set->name) {
if (strequal(argv[1], tmp_set->name)) {
if (tmp_set->usage &&
tmp_set->usage[0])
printf("%s\n", tmp_set->usage);
else
printf("No help for %s\n", tmp_set->name);
return NT_STATUS_OK;
}
tmp_set++;
}
}
printf("No such command: %s\n", argv[1]);
return NT_STATUS_OK;
}
for (tmp = cmd_list; tmp; tmp = tmp->next) {
tmp_set = tmp->cmd_set;
while(tmp_set->name) {
printf("%15s\t\t%s\n", tmp_set->name,
tmp_set->description ? tmp_set->description:
"");
tmp_set++;
}
}
return NT_STATUS_OK;
}
static NTSTATUS cmd_debuglevel(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
if (argc > 2) {
printf("Usage: %s [debuglevel]\n", argv[0]);
return NT_STATUS_OK;
}
if (argc == 2) {
DEBUGLEVEL = atoi(argv[1]);
}
printf("debuglevel is %d\n", DEBUGLEVEL);
return NT_STATUS_OK;
}
static NTSTATUS cmd_freemem(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
talloc_destroy(mem_ctx);
mem_ctx = NULL;
vfs->data = NULL;
vfs->data_size = 0;
return NT_STATUS_OK;
}
static NTSTATUS cmd_quit(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
talloc_destroy(mem_ctx);
exit(0);
return NT_STATUS_OK;
}
static struct cmd_set vfstest_commands[] = {
{ "GENERAL OPTIONS" },
{ "conf", cmd_conf, "Load smb configuration file", "conf <smb.conf>" },
{ "help", cmd_help, "Get help on commands", "" },
{ "?", cmd_help, "Get help on commands", "" },
{ "debuglevel", cmd_debuglevel, "Set debug level", "" },
{ "freemem", cmd_freemem, "Free currently allocated buffers", "" },
{ "exit", cmd_quit, "Exit program", "" },
{ "quit", cmd_quit, "Exit program", "" },
{ NULL }
};
static struct cmd_set separator_command[] = {
{ "---------------", NULL, "----------------------" },
{ NULL }
};
extern struct cmd_set vfs_commands[];
static struct cmd_set *vfstest_command_list[] = {
vfstest_commands,
vfs_commands,
NULL
};
static void add_command_set(struct cmd_set *cmd_set)
{
struct cmd_list *entry;
if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
DEBUG(0, ("out of memory\n"));
return;
}
ZERO_STRUCTP(entry);
entry->cmd_set = cmd_set;
DLIST_ADD(cmd_list, entry);
}
static NTSTATUS do_cmd(struct vfs_state *vfs, struct cmd_set *cmd_entry, char *cmd)
{
const char *p = cmd;
char **argv = NULL;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
pstring buf;
TALLOC_CTX *mem_ctx = NULL;
int argc = 0, i;
again:
while(next_token(&p, buf, " ", sizeof(buf))) {
if (argv) {
argv[argc] = SMB_STRDUP(buf);
}
argc++;
}
if (!argv) {
argv = SMB_MALLOC_ARRAY(char *, argc);
memset(argv, 0, sizeof(char *) * argc);
if (!argv) {
fprintf(stderr, "out of memory\n");
result = NT_STATUS_NO_MEMORY;
goto done;
}
p = cmd;
argc = 0;
goto again;
}
if (cmd_entry->fn) {
if (mem_ctx == NULL) {
if (!(mem_ctx = talloc_init("do_cmd"))) {
DEBUG(0, ("talloc_init() failed\n"));
goto done;
}
}
result = cmd_entry->fn(vfs, mem_ctx, argc, (const char **)argv);
} else {
fprintf (stderr, "Invalid command\n");
goto done;
}
done:
if (argv) {
for (i = 0; i < argc; i++)
SAFE_FREE(argv[i]);
SAFE_FREE(argv);
}
return result;
}
static NTSTATUS process_cmd(struct vfs_state *vfs, char *cmd)
{
struct cmd_list *temp_list;
BOOL found = False;
pstring buf;
const char *p = cmd;
NTSTATUS result = NT_STATUS_OK;
int len = 0;
if (cmd[strlen(cmd) - 1] == '\n')
cmd[strlen(cmd) - 1] = '\0';
if (!next_token(&p, buf, " ", sizeof(buf))) {
return NT_STATUS_OK;
}
len = strlen(buf);
if (buf[len-1] == '\n')
buf[len-1] = '\0';
for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
struct cmd_set *temp_set = temp_list->cmd_set;
while(temp_set->name) {
if (strequal(buf, temp_set->name)) {
found = True;
result = do_cmd(vfs, temp_set, cmd);
goto done;
}
temp_set++;
}
}
done:
if (!found && buf[0]) {
printf("command not found: %s\n", buf);
return NT_STATUS_OK;
}
if (!NT_STATUS_IS_OK(result)) {
printf("result was %s\n", nt_errstr(result));
}
return result;
}
static void process_file(struct vfs_state *pvfs, char *filename) {
FILE *file;
char command[3 * PATH_MAX];
if (*filename == '-') {
file = stdin;
} else {
file = fopen(filename, "r");
if (file == NULL) {
printf("vfstest: error reading file (%s)!", filename);
printf("errno n.%d: %s", errno, strerror(errno));
exit(-1);
}
}
while (fgets(command, 3 * PATH_MAX, file) != NULL) {
process_cmd(pvfs, command);
}
}
void exit_server(const char *reason)
{
DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
exit(0);
}
void exit_server_cleanly(const char *const reason)
{
exit_server("normal exit");
}
static int server_fd = -1;
int last_message = -1;
int smbd_server_fd(void)
{
return server_fd;
}
void reload_printers(void)
{
return;
}
BOOL reload_services(BOOL test)
{
BOOL ret;
if (lp_loaded()) {
pstring fname;
pstrcpy(fname,lp_configfile());
if (file_exist(fname, NULL) &&
!strcsequal(fname, dyn_CONFIGFILE)) {
pstrcpy(dyn_CONFIGFILE, fname);
test = False;
}
}
reopen_logs();
if (test && !lp_file_list_changed())
return(True);
lp_killunused(conn_snum_used);
ret = lp_load(dyn_CONFIGFILE, False, False, True, True);
if (!test)
reload_services(True);
reopen_logs();
load_interfaces();
{
if (smbd_server_fd() != -1) {
set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
set_socket_options(smbd_server_fd(), user_socket_options);
}
}
mangle_reset_cache();
reset_stat_cache();
set_current_service(NULL,0,True);
return (ret);
}
struct event_context *smbd_event_context(void)
{
static struct event_context *ctx;
if (!ctx && !(ctx = event_context_init(NULL))) {
smb_panic("Could not init smbd event context\n");
}
return ctx;
}
struct messaging_context *smbd_messaging_context(void)
{
static struct messaging_context *ctx;
if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
smbd_event_context()))) {
smb_panic("Could not init smbd messaging context\n");
}
return ctx;
}
int main(int argc, char *argv[])
{
static char *cmdstr = NULL;
struct cmd_set **cmd_set;
static struct vfs_state vfs;
int i;
static char *filename = NULL;
poptContext pc;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"file", 'f', POPT_ARG_STRING, &filename, 0, },
{"command", 'c', POPT_ARG_STRING, &cmdstr, 0, "Execute specified list of commands" },
POPT_COMMON_SAMBA
POPT_TABLEEND
};
load_case_tables();
setlinebuf(stdout);
pc = poptGetContext("vfstest", argc, (const char **) argv,
long_options, 0);
while(poptGetNextOpt(pc) != -1);
poptFreeContext(pc);
reload_services(False);
setup_logging("vfstest", True);
cmd_set = vfstest_command_list;
while(*cmd_set) {
add_command_set(*cmd_set);
add_command_set(separator_command);
cmd_set++;
}
sec_init();
conn_init();
vfs.conn = conn_new();
string_set(&vfs.conn->user,"vfstest");
for (i=0; i < 1024; i++)
vfs.files[i] = NULL;
smbd_vfs_init(vfs.conn);
if (filename && filename[0]) {
process_file(&vfs, filename);
return 0;
}
if (cmdstr && cmdstr[0]) {
char *cmd;
char *p = cmdstr;
while((cmd=next_command(&p)) != NULL) {
process_cmd(&vfs, cmd);
}
return 0;
}
while(1) {
pstring prompt;
char *line;
slprintf(prompt, sizeof(prompt) - 1, "vfstest $> ");
line = smb_readline(prompt, NULL, completion_fn);
if (line == NULL)
break;
if (line[0] != '\n')
process_cmd(&vfs, line);
}
conn_free(vfs.conn);
return 0;
}