2016-04-01 20:58:15 +08:00
|
|
|
/*=============================================================================
|
|
|
|
# Filename: gconsole.cpp
|
|
|
|
# Author: Bookug Lobert
|
|
|
|
# Mail: 1181955272@qq.com
|
|
|
|
# Last Modified: 2016-02-26 19:28
|
|
|
|
# Description:
|
|
|
|
This is a console integrating all commands in Gstore System and others. It
|
|
|
|
provides completion of command names, line editing features, and access to the
|
|
|
|
history list.
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
|
|
#include "../Database/Database.h"
|
|
|
|
#include "../Util/Util.h"
|
|
|
|
#include "GstoreConnector.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
//extern char *xmalloc PARAMS((size_t));
|
|
|
|
|
|
|
|
//The names of functions that actually do the manipulation.
|
|
|
|
//common commands
|
|
|
|
int help_handler PARAMS((char *));
|
|
|
|
int quit_handler PARAMS((char *));
|
|
|
|
//C/S commands
|
|
|
|
int connect_handler PARAMS((char *));
|
|
|
|
int disconnect_handler PARAMS((char *));
|
|
|
|
//system commands
|
|
|
|
int list_handler PARAMS((char *));
|
|
|
|
int view_handler PARAMS((char *));
|
|
|
|
int rename_handler PARAMS((char *));
|
|
|
|
int stat_handler PARAMS((char *));
|
|
|
|
int pwd_handler PARAMS((char *));
|
|
|
|
int delete_handler PARAMS((char *));
|
|
|
|
int cd_handler PARAMS((char *));
|
|
|
|
//remote commands
|
|
|
|
int build_handler PARAMS((char *));
|
|
|
|
int drop_handler PARAMS((char *));
|
|
|
|
int load_handler PARAMS((char *));
|
|
|
|
int unload_handler PARAMS((char *));
|
|
|
|
int query_handler PARAMS((char *));
|
|
|
|
int show_handler PARAMS((char *));
|
|
|
|
|
|
|
|
//A structure which contains information on the commands this program can understand.
|
|
|
|
typedef struct {
|
|
|
|
const char *name; // User printable name of the function
|
|
|
|
rl_icpfunc_t *func; // Function to call to do the job
|
|
|
|
const char *doc; // Documentation for this function
|
|
|
|
} COMMAND;
|
|
|
|
//
|
|
|
|
COMMAND native_commands[] = {
|
|
|
|
{ "help", help_handler, "Display this text" },
|
|
|
|
{ "?", help_handler, "Synonym for `help'" },
|
|
|
|
{ "quit", quit_handler, "Quit this console" },
|
|
|
|
{ "connect", connect_handler, "Connect to a server running Gstore" },
|
|
|
|
{ "show", show_handler, "Show the database name which is used now" },
|
|
|
|
{ "build", build_handler, "Build a database from a dataset" },
|
|
|
|
{ "drop", drop_handler, "Drop a database according to the given path" },
|
|
|
|
{ "load", load_handler, "Load a existing database" },
|
|
|
|
{ "unload", unload_handler, "Unload the current used database" },
|
|
|
|
{ "query", query_handler, "Answer a SPARQL query" },
|
|
|
|
|
2016-04-30 16:56:37 +08:00
|
|
|
//{ "cd", cd_handler, "Change to directory DIR" },
|
|
|
|
//{ "delete", delete_handler, "Delete FILE" },
|
|
|
|
//{ "list", list_handler, "List files in DIR" },
|
|
|
|
//{ "ls", list_handler, "Synonym for `list'" },
|
|
|
|
//{ "pwd", pwd_handler, "Print the current working directory" },
|
|
|
|
//{ "rename", rename_handler, "Rename FILE to NEWNAME" },
|
|
|
|
//{ "stat", stat_handler, "Print out statistics on FILE" },
|
|
|
|
//{ "view", view_handler, "View the contents of FILE" },
|
2016-04-01 20:58:15 +08:00
|
|
|
|
|
|
|
{NULL, NULL, NULL }
|
|
|
|
//char* rl_icpfunc_t*, char*
|
|
|
|
};
|
|
|
|
//
|
|
|
|
COMMAND remote_commands[] = {
|
|
|
|
{ "help", help_handler, "Display this text" },
|
|
|
|
{ "?", help_handler, "Synonym for `help'" },
|
|
|
|
{ "show", show_handler, "Show the database name which is used now" },
|
|
|
|
{ "build", build_handler, "Build a database from a dataset" },
|
|
|
|
{ "drop", drop_handler, "Drop a database according to the given path" },
|
|
|
|
{ "load", load_handler, "Load a existing database" },
|
|
|
|
{ "unload", unload_handler, "Unload the current used database" },
|
|
|
|
{ "query", query_handler, "Answer a SPARQL query" },
|
|
|
|
{ "disconnect", disconnect_handler, "Disconnect the current server connection" },
|
|
|
|
|
|
|
|
{NULL, NULL, NULL }
|
|
|
|
//char* rl_icpfunc_t*, char*
|
|
|
|
};
|
|
|
|
COMMAND *current_commands = native_commands; //according to gc ?= NULL
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Forward declarations.
|
|
|
|
//
|
|
|
|
char *dupstr(const char*);
|
|
|
|
//
|
|
|
|
char *stripwhite(char *);
|
|
|
|
//
|
|
|
|
COMMAND *find_command(char *);
|
|
|
|
//
|
|
|
|
void initialize_readline();
|
|
|
|
//
|
|
|
|
int execute_line(char *);
|
|
|
|
//
|
|
|
|
int valid_argument(char *, char *);
|
|
|
|
//
|
|
|
|
int too_dangerous(char *);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Global variables
|
|
|
|
//The name of this program, as taken from argv[0].
|
|
|
|
char *progname;
|
|
|
|
//
|
|
|
|
//When true, this global means the user is done using this program.
|
|
|
|
bool done = false; //still running
|
|
|
|
//
|
|
|
|
//server-client mode or local engine mode
|
|
|
|
GstoreConnector *gc = NULL; //local mode by default
|
|
|
|
//redirect mechanism, only useful for query
|
|
|
|
FILE *output = stdout;
|
|
|
|
//current using database in local
|
|
|
|
Database *current_database = NULL;
|
|
|
|
|
|
|
|
//TODO:how to support commands scripts out or in console
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
Util util;
|
|
|
|
#endif
|
|
|
|
char *line, *s;
|
|
|
|
progname = argv[0];
|
|
|
|
|
|
|
|
fprintf(stderr, "notice that commands are a little different between native mode and remote mode!\n");
|
|
|
|
|
|
|
|
initialize_readline(); //Bind our completer
|
|
|
|
|
|
|
|
//Loop reading and executing lines until the user quits.
|
|
|
|
while(!done)
|
|
|
|
{
|
|
|
|
if(gc == NULL)
|
|
|
|
line = readline("gstore>");
|
|
|
|
else
|
|
|
|
line = readline("server>");
|
|
|
|
|
|
|
|
//BETTER:multi lines input in alignment?need separators like ';' in gclient.cpp
|
|
|
|
|
|
|
|
if(line == NULL) //EOF or Ctrl-D
|
|
|
|
{
|
|
|
|
if(current_database != NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "\nplease unload your database before quiting!\n\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
printf("\n\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Remove leading and trailing whitespace from the line.
|
|
|
|
//Then, if there is anything left, add it to the history
|
|
|
|
//list and execute it.
|
|
|
|
s = stripwhite(line);
|
|
|
|
|
|
|
|
if(*s)
|
|
|
|
{
|
|
|
|
add_history(s);
|
|
|
|
execute_line(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(line);
|
|
|
|
}
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
/* */
|
|
|
|
/* Some Utilities */
|
|
|
|
/* */
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
char *
|
|
|
|
dupstr(const char *s)
|
|
|
|
{
|
|
|
|
char *r;
|
|
|
|
int len = strlen(s) + 1;
|
|
|
|
r = (char *)malloc(len); //BETTER:xmalloc?
|
|
|
|
memset(r, 0, sizeof(char) * (len));
|
|
|
|
strcpy(r, s);
|
|
|
|
return(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute a command line
|
|
|
|
int
|
|
|
|
execute_line(char *line)
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
COMMAND *cmd;
|
|
|
|
char *word = NULL;
|
|
|
|
|
|
|
|
output = stdout;
|
|
|
|
//to find if redirected
|
|
|
|
bool is_redirected = false;
|
|
|
|
int j = strlen(line) - 1;
|
|
|
|
while(j > -1)
|
|
|
|
{
|
|
|
|
if(line[j] == '"')
|
|
|
|
break;
|
|
|
|
else if(line[j] == '>')
|
|
|
|
{
|
|
|
|
is_redirected = true;
|
|
|
|
i = j;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
j--;
|
|
|
|
}
|
|
|
|
if(is_redirected)
|
|
|
|
{
|
|
|
|
j++;
|
|
|
|
while(line[j] && whitespace(line[j]))
|
|
|
|
{
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
fprintf(stderr, "the file is: %s\n", line+j);
|
|
|
|
if((output = fopen(line+j, "w+")) == NULL)
|
|
|
|
{
|
|
|
|
output = stdout;
|
|
|
|
fprintf(stderr, "fail to open %s\n", line+j);
|
|
|
|
}
|
|
|
|
line[i] = '\0';
|
|
|
|
}
|
|
|
|
//BETTER: how about >> ?
|
|
|
|
|
|
|
|
//Isolate the command word.
|
|
|
|
i = 0;
|
|
|
|
while(line[i] && whitespace(line[i]))
|
|
|
|
i++;
|
|
|
|
word = line + i;
|
|
|
|
|
|
|
|
while(line[i] && !whitespace(line[i]))
|
|
|
|
i++;
|
|
|
|
|
|
|
|
if(line[i])
|
|
|
|
line[i++] = '\0';
|
|
|
|
|
|
|
|
//command = find_command(word);
|
|
|
|
cmd = find_command(word);
|
|
|
|
|
|
|
|
if(!cmd)
|
|
|
|
{
|
|
|
|
if(gc == NULL)
|
|
|
|
fprintf(stderr, "now is in native mode!\n");
|
|
|
|
else
|
|
|
|
fprintf(stderr, "now is in remote mode!\n");
|
|
|
|
fprintf(stderr, "%s: No such command for gconsole.\n", word);
|
|
|
|
if(output != stdout)
|
|
|
|
fclose(output);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Get argument to command, if any.
|
|
|
|
while(line[i] && whitespace(line[i]))
|
|
|
|
i++;
|
|
|
|
word = line + i;
|
|
|
|
|
|
|
|
int ret = cmd->func(word);
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "all done, now to close the file!\n");
|
|
|
|
#endif
|
|
|
|
if(output != stdout)
|
|
|
|
fclose(output);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look up NAME as the name of a command, and return a pointer to that
|
|
|
|
// command. Return a NULL pointer if NAME isn't a command name.
|
|
|
|
COMMAND *
|
|
|
|
find_command(char *name)
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
for(i = 0; current_commands[i].name; i++)
|
|
|
|
{
|
|
|
|
//fprintf(stderr, "%s - %s\n", name, current_commands[i].name);
|
|
|
|
if(strcmp(name, current_commands[i].name) == 0)
|
|
|
|
return(¤t_commands[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return((COMMAND*)NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Strip whitespace from the start and end of STRING. Return a pointer into STRING.
|
|
|
|
char *
|
|
|
|
stripwhite(char *string)
|
|
|
|
{
|
|
|
|
register char *s, *t;
|
|
|
|
|
|
|
|
for(s = string; whitespace(*s); s++)
|
|
|
|
;
|
|
|
|
|
|
|
|
if(*s == 0)
|
|
|
|
return(s);
|
|
|
|
|
|
|
|
t = s + strlen(s) - 1;
|
|
|
|
while(t > s && whitespace(*t))
|
|
|
|
t--;
|
|
|
|
*++t = '\0';
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Function which tells you that you can't do this.
|
|
|
|
int
|
|
|
|
too_dangerous(char *caller)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: Too dangerous for me to distribute. Write it yourself.\n",
|
|
|
|
caller);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return non-zero if ARG is a valid argument for CALLER, else print an error message and return zero.
|
|
|
|
int
|
|
|
|
valid_argument(char *caller, char *arg)
|
|
|
|
{
|
|
|
|
if(!arg || !*arg)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s: Argument required.\n", caller);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
/* */
|
|
|
|
/* Interface to Readline Completion */
|
|
|
|
/* */
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
char *command_generator PARAMS((const char *, int));
|
|
|
|
char **gconsole_completion PARAMS((const char *, int, int));
|
|
|
|
|
|
|
|
/* Tell the GNU Readline library how to complete. We want to try to complete
|
|
|
|
on command names if this is the first word in the line, or on filenames
|
|
|
|
if not. */
|
|
|
|
void
|
|
|
|
initialize_readline()
|
|
|
|
{
|
|
|
|
/* Allow conditional parsing of the ~/.inputrc file. */
|
|
|
|
rl_readline_name = "gconsole";
|
|
|
|
|
|
|
|
/* Tell the completer that we want a crack first. */
|
|
|
|
rl_attempted_completion_function = gconsole_completion;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempt to complete on the contents of TEXT. START and END bound the
|
|
|
|
region of rl_line_buffer that contains the word to complete. TEXT is
|
|
|
|
the word to complete. We can use the entire contents of rl_line_buffer
|
|
|
|
in case we want to do some simple parsing. Return the array of matches,
|
|
|
|
or NULL if there aren't any. */
|
|
|
|
char **
|
|
|
|
gconsole_completion(const char *text, int start, int end)
|
|
|
|
{
|
|
|
|
char **matches;
|
|
|
|
|
|
|
|
matches =(char **)NULL;
|
|
|
|
|
|
|
|
//If this word is at the start of the line, then it is a command
|
|
|
|
//to complete. Otherwise it is the name of a file in the current directory.
|
|
|
|
if(start == 0)
|
|
|
|
matches = rl_completion_matches(text, command_generator);
|
|
|
|
|
|
|
|
return(matches);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Generator function for command completion. STATE lets us know whether
|
|
|
|
to start from scratch; without any state(i.e. STATE == 0), then we
|
|
|
|
start at the top of the list. */
|
|
|
|
char *
|
|
|
|
command_generator(const char *text, int state)
|
|
|
|
{
|
|
|
|
static int list_index, len;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
/* If this is a new word to complete, initialize now. This includes
|
|
|
|
saving the length of TEXT for efficiency, and initializing the index
|
|
|
|
variable to 0. */
|
|
|
|
if(!state)
|
|
|
|
{
|
|
|
|
list_index = 0;
|
|
|
|
len = strlen(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the next name which partially matches from the command list. */
|
|
|
|
while((name = current_commands[list_index].name) != NULL)
|
|
|
|
{
|
|
|
|
list_index++;
|
|
|
|
|
|
|
|
if(strncmp(name, text, len) == 0)
|
|
|
|
return(dupstr(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If no names matched, then return NULL. */
|
|
|
|
return((char *)NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
/* */
|
|
|
|
/* gconsole commands */
|
|
|
|
/* */
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
// String to pass to system(). This is for the LIST, VIEW and RENAME commands.
|
|
|
|
static char syscom[1024];
|
|
|
|
|
|
|
|
//Print out help for ARG, or for all of the commands if ARG is not present.
|
|
|
|
int
|
|
|
|
help_handler(char *args)
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
int printed = 0;
|
|
|
|
|
|
|
|
for(i = 0; current_commands[i].name; i++)
|
|
|
|
{
|
|
|
|
if(args == NULL || !*args)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s\t\t%s.\n", current_commands[i].name, current_commands[i].doc);
|
|
|
|
printed++;
|
|
|
|
}
|
|
|
|
else if(strcmp(args, current_commands[i].name) == 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s\t\t%s.\n", current_commands[i].name, current_commands[i].doc);
|
|
|
|
printed++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(printed == 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "No commands match `%s'. Possibilties are:\n", args);
|
|
|
|
|
|
|
|
for(i = 0; current_commands[i].name; i++)
|
|
|
|
{
|
|
|
|
//Print in six columns.
|
|
|
|
if(printed == 6)
|
|
|
|
{
|
|
|
|
printed = 0;
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "%s\t", current_commands[i].name);
|
|
|
|
printed++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(printed)
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
quit_handler(char *args)
|
|
|
|
{
|
|
|
|
if(gc != NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "this command cannot be used when in remote mode!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(current_database != NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "please unload your database before quiting!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
done = true;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
connect_handler(char *args)
|
|
|
|
{
|
|
|
|
if(gc != NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "this command cannot be used when in remote mode!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(current_database != NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "please unload your local database before entering remote mode!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int port = 3305;
|
|
|
|
string ip = "127.0.0.1"; //maybe "localhost"
|
|
|
|
|
|
|
|
if(args != NULL && *args != '\0')
|
|
|
|
{
|
|
|
|
fprintf(stderr, "arguments specified!\n");
|
|
|
|
//BETTER:a common parse module for string? separted with ' ', '\t' or '"'
|
|
|
|
//BETTER:only port and only ip are supported
|
|
|
|
int i = 0;
|
|
|
|
while(args[i] && !whitespace(args[i]))
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
args[i++] = '\0';
|
|
|
|
ip = string(args);
|
|
|
|
while(args[i] && whitespace(args[i]))
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
port = atoi(args+i);
|
|
|
|
}
|
|
|
|
|
|
|
|
//initialize the GStore server's IP address and port.
|
|
|
|
gc = new GstoreConnector(ip, port);
|
|
|
|
//if(!gc->connect())
|
|
|
|
//{
|
|
|
|
//delete gc;
|
|
|
|
//gc = NULL;
|
|
|
|
//return -1;
|
|
|
|
//}
|
|
|
|
current_commands = remote_commands;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
disconnect_handler(char *args)
|
|
|
|
{
|
|
|
|
if(gc == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "this command cannot be used when in native mode!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(gc->show() != "\n[empty]\n")
|
|
|
|
{
|
|
|
|
fprintf(stderr, "please unload your server database before entering native mode!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
delete gc;
|
|
|
|
gc = NULL;
|
|
|
|
current_commands = native_commands;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
show_handler(char *args)
|
|
|
|
{
|
|
|
|
//BETTER:show all or inuse, ls|grep "\.db" > ans.txt, as well as server
|
|
|
|
if(gc != NULL)
|
|
|
|
{
|
|
|
|
string database = gc->show();
|
|
|
|
fprintf(stderr, "%s", database.c_str());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//native mode
|
|
|
|
if(current_database == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "no database used now!\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s\n", current_database->getName().c_str());
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
build_handler(char *args)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while(args[i] && !whitespace(args[i]))
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
args[i++] = '\0';
|
|
|
|
//BETTER:the position is the root of Gstore by default
|
|
|
|
//(or change to a specified folder later)
|
|
|
|
string database = string(args) + string(".db");
|
|
|
|
string dataset = string(args + i);
|
|
|
|
while(args[i] && whitespace(args[i]))
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//NOTICE: when in remote mode, the dataset should be placed in the server! And the exact path can only be got in the server
|
|
|
|
//we can deal with it in Database
|
|
|
|
if(gc != NULL) //remote mode
|
|
|
|
{
|
|
|
|
// QUERY:how to interact:string?dict(0:string)?json(service_id, service_args)?
|
|
|
|
// Here uses the Cpp API Wrapper
|
|
|
|
// build a new database by a RDF file.
|
|
|
|
// note that the relative path is related to gserver.
|
|
|
|
if(gc->build(database, dataset))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//gc == NULL, native mode
|
|
|
|
//string ret = Util::getExactPath(args + i);
|
|
|
|
//const char *path = ret.c_str();
|
|
|
|
//if(path == NULL)
|
|
|
|
//{
|
|
|
|
//fprintf(stderr, "invalid path of dataset!\n");
|
|
|
|
//return -1;
|
|
|
|
//}
|
|
|
|
//#ifdef DEBUG
|
|
|
|
//fprintf(stderr, "%s;\n", path);
|
|
|
|
//#endif
|
|
|
|
//dataset = string(path);
|
|
|
|
//free(path);
|
|
|
|
|
|
|
|
//system("clock");
|
|
|
|
cout << "import dataset to build database..." << endl;
|
|
|
|
fprintf(stderr, "DB_store: %s\tRDF_data: %s\n", database.c_str(), dataset.c_str());
|
|
|
|
if(current_database != NULL)
|
|
|
|
{
|
|
|
|
delete current_database;
|
|
|
|
}
|
|
|
|
current_database = new Database(database);
|
|
|
|
bool flag = current_database->build(dataset);
|
|
|
|
//system("clock");
|
|
|
|
if(flag)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "import RDF file to database done.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "import RDF file to database fail.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
drop_handler(char *args)
|
|
|
|
{
|
|
|
|
//TODO:native and remote
|
|
|
|
//NOTICE: not using databases, drop a given one at a time
|
|
|
|
if(current_database != NULL) //how to judge when remote
|
|
|
|
{
|
|
|
|
fprintf(stderr, "please donot use this command when you are using a database!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(args == NULL || *args == '\0')
|
|
|
|
{
|
|
|
|
fprintf(stderr, "invalid arguments!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char info[] = "drop";
|
|
|
|
too_dangerous(info);
|
|
|
|
//DEBUG:not works
|
|
|
|
//return remove(args);
|
|
|
|
//TODO:only drop when *.db, avoid other files be removed
|
|
|
|
//string cmd = string("rm -rf ") + string(args);
|
|
|
|
//fprintf(stderr, "%s\n", cmd.c_str());
|
|
|
|
//return system(cmd.c_str());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
load_handler(char *args)
|
|
|
|
{
|
|
|
|
string database = string(args);
|
|
|
|
if(gc != NULL)
|
|
|
|
{
|
|
|
|
gc->load(database);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(current_database != NULL)
|
|
|
|
{
|
|
|
|
//current_database->unload();
|
|
|
|
delete current_database;
|
|
|
|
}
|
|
|
|
current_database = new Database(database);
|
|
|
|
current_database->load();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
unload_handler(char *args)
|
|
|
|
{
|
|
|
|
//unload the using database, no args needed
|
|
|
|
if(args != NULL && *args != '\0')
|
|
|
|
{
|
|
|
|
fprintf(stderr, "arguments invalid!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(gc != NULL)
|
|
|
|
{
|
|
|
|
// unload this database
|
|
|
|
string database = gc->show();
|
|
|
|
if(database == "\n[empty]\n")
|
|
|
|
{
|
|
|
|
fprintf(stderr, "no database used now!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
gc->unload(database.substr(1, database.length()-2));
|
|
|
|
}
|
|
|
|
|
|
|
|
//native mode
|
|
|
|
if(current_database == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "no database used now!\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//current_database->unload();
|
|
|
|
delete current_database;
|
|
|
|
current_database = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
query_handler(char *args)
|
|
|
|
{
|
|
|
|
if(args == NULL || *args == '\0')
|
|
|
|
{
|
|
|
|
fprintf(stderr, "invalid arguments!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
string sparql = "";
|
|
|
|
if(*args == '"') //query quoted in string
|
|
|
|
{
|
|
|
|
int i = strlen(args) - 1;
|
|
|
|
if(i > 0 && args[i] == '"')
|
|
|
|
{
|
|
|
|
args[i] = '\0';
|
|
|
|
sparql = string(args+1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "invalid arguments!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else //query in file indicated by this path
|
|
|
|
{
|
|
|
|
//NOTICE:the query is native, not in server!
|
|
|
|
string ret = Util::getExactPath(args);
|
|
|
|
const char *path = ret.c_str();
|
|
|
|
if(path == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "invalid path of query!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "%s;\n", path);
|
|
|
|
#endif
|
|
|
|
sparql = Util::getQueryFromFile(path);
|
|
|
|
//free(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sparql.empty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "%s;\n", sparql.c_str());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(gc != NULL)
|
|
|
|
{
|
|
|
|
//QUERY:how to use query path in the server
|
|
|
|
//execute SPARQL query on this database.
|
|
|
|
string answer = gc->query(sparql);
|
|
|
|
fprintf(output, "%s\n", answer.c_str());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(current_database == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "no database in use!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ResultSet rs;
|
|
|
|
bool ret = current_database->query(sparql, rs, output);
|
|
|
|
if(ret)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "query() returns true!\n");
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "query() returns false!\n");
|
|
|
|
#endif
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
list_handler(char *args)
|
|
|
|
{
|
|
|
|
char info[] = "";
|
|
|
|
if(!args)
|
|
|
|
args = info;
|
|
|
|
|
|
|
|
sprintf(syscom, "ls -FClg %s", args);
|
|
|
|
return(system(syscom));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
view_handler(char *args)
|
|
|
|
{
|
|
|
|
char info[] = "view";
|
|
|
|
if(!valid_argument(info, args))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
#if defined(__MSDOS__)
|
|
|
|
//more.com doesn't grok slashes in pathnames
|
|
|
|
sprintf(syscom, "less %s", args);
|
|
|
|
#else
|
|
|
|
sprintf(syscom, "more %s", args);
|
|
|
|
#endif
|
|
|
|
return(system(syscom));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rename_handler(char *args)
|
|
|
|
{
|
|
|
|
char info[] = "rename";
|
|
|
|
too_dangerous(info);
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
stat_handler(char *args)
|
|
|
|
{
|
|
|
|
struct stat finfo;
|
|
|
|
char info[] = "stat";
|
|
|
|
|
|
|
|
if(!valid_argument(info, args))
|
|
|
|
return(1);
|
|
|
|
|
|
|
|
if(stat(args, &finfo) == -1)
|
|
|
|
{
|
|
|
|
perror(args);
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Statistics for `%s':\n", args);
|
|
|
|
|
|
|
|
printf("%s has %d link%s, and is %d byte%s in length.\n",
|
|
|
|
args,
|
|
|
|
(int)finfo.st_nlink,
|
|
|
|
(finfo.st_nlink == 1) ? "" : "s",
|
|
|
|
(int)finfo.st_size,
|
|
|
|
(finfo.st_size == 1) ? "" : "s");
|
|
|
|
printf("Inode Last Change at: %s", ctime(&finfo.st_ctime));
|
|
|
|
printf(" Last access at: %s", ctime(&finfo.st_atime));
|
|
|
|
printf(" Last modified at: %s", ctime(&finfo.st_mtime));
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
delete_handler(char *args)
|
|
|
|
{
|
|
|
|
char info[] = "delete";
|
|
|
|
too_dangerous(info);
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
cd_handler(char *args)
|
|
|
|
{
|
|
|
|
if(chdir(args) == -1)
|
|
|
|
{
|
|
|
|
perror(args);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char info[] = "";
|
|
|
|
pwd_handler(info);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
pwd_handler(char *args)
|
|
|
|
{
|
|
|
|
// no need for args
|
|
|
|
if(args != NULL && *args != '\0')
|
|
|
|
{
|
|
|
|
fprintf(stderr, "invalid arguments!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
char dir[1024], *s;
|
|
|
|
|
|
|
|
s = getcwd(dir, sizeof(dir) - 1);
|
|
|
|
if(s == 0)
|
|
|
|
{
|
|
|
|
printf("Error getting pwd: %s\n", dir);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Current directory is %s\n", dir);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|