-/*
- * Copyright (C) 1997 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 1997 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
/** \file client.c The client program used to connect to para_server. */
#include <regex.h>
#include <signal.h>
+#include <lopsub.h>
+#include "client.lsg.h"
#include "para.h"
#include "list.h"
#include "sched.h"
#include "crypt.h"
-#include "client.cmdline.h"
#include "string.h"
#include "stdin.h"
#include "stdout.h"
#include "error.h"
#include "version.h"
-INIT_CLIENT_ERRLISTS;
+/** Array of error strings. */
+DEFINE_PARA_ERRLIST;
static struct sched sched;
static struct client_task *ct;
#ifdef HAVE_READLINE
#include "interactive.h"
-#include "server.completion.h"
-#include "afs.completion.h"
+#include "server_cmd.lsg.h"
struct exec_task {
struct task *task;
return 0;
}
-static int make_client_argv(const char *line)
+/* Called from the line handler and the completers. This overwrites ct->lpr. */
+static int create_merged_lpr(const char *line)
{
- int ret;
+ const struct lls_command *cmd = CLIENT_CMD_PTR;
+ int argc, ret;
+ char *cmdline, **argv, *errctx;
+ struct lls_parse_result *argv_lpr;
+ static struct lls_parse_result *orig_lpr;
- free_argv(ct->conf.inputs);
- ret = create_argv(line, " ", &ct->conf.inputs);
- if (ret >= 0)
- ct->conf.inputs_num = ret;
+ if (!orig_lpr)
+ orig_lpr = ct->lpr;
+ ct->lpr = NULL;
+ cmdline = make_message("-- %s", line);
+ ret = create_shifted_argv(cmdline, " ", &argv);
+ free(cmdline);
+ if (ret < 0)
+ return ret;
+ argc = ret;
+ if (argc == 2) { /* no words (only blanks in line) */
+ free_argv(argv);
+ return 0;
+ }
+ argv[0] = para_strdup("--");
+ /*
+ * The original lpr for the interactive session has no non-option
+ * arguments. We create a fresh lpr from the words in "line" and merge
+ * it with the orignal lpr.
+ */
+ ret = lls(lls_parse(argc, argv, cmd, &argv_lpr, &errctx));
+ free_argv(argv);
+ if (ret < 0)
+ goto fail;
+ ret = lls(lls_merge(orig_lpr, argv_lpr, cmd, &ct->lpr, &errctx));
+ lls_free_parse_result(argv_lpr, cmd);
+ if (ret < 0)
+ goto fail;
+ return 1;
+fail:
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ free(errctx);
+ assert(ret < 0);
return ret;
}
+/* called from completers */
static int execute_client_command(const char *cmd, char **result)
{
int ret;
.result_buf = para_strdup(""),
.result_size = 1,
};
+ struct lls_parse_result *old_lpr = ct->lpr;
+
*result = NULL;
- ret = make_client_argv(cmd);
- if (ret < 0)
+ ret = create_merged_lpr(cmd);
+ if (ret <= 0)
goto out;
exec_task.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "exec_collect"));
goto out;
schedule(&command_sched);
sched_shutdown(&command_sched);
+ lls_free_parse_result(ct->lpr, CLIENT_CMD_PTR);
+ ct->lpr = old_lpr;
*result = exec_task.result_buf;
btr_remove_node(&exec_task.btrn);
ret = 1;
struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-i", "-l", "-r", NULL};
+ char *opts[] = {LSG_SERVER_CMD_LSIMG_OPTS, NULL};
if (ci->word[0] == '-')
return i9e_complete_option(opts, ci, cr);
I9E_DUMMY_COMPLETER(play);
I9E_DUMMY_COMPLETER(si);
I9E_DUMMY_COMPLETER(term);
-I9E_DUMMY_COMPLETER(version);
I9E_DUMMY_COMPLETER(stop);
I9E_DUMMY_COMPLETER(addatt);
I9E_DUMMY_COMPLETER(init);
static void stat_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-n=", "-p", NULL};
- //PARA_CRIT_LOG("word: %s\n", ci->word);
+ char *opts[] = {LSG_SERVER_CMD_STAT_OPTS, NULL};
+ i9e_complete_option(opts, ci, cr);
+}
+
+static void version_completer(struct i9e_completion_info *ci,
+ struct i9e_completion_result *cr)
+{
+ char *opts[] = {LSG_SERVER_CMD_VERSION_OPTS, NULL};
i9e_complete_option(opts, ci, cr);
}
static void add_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-a", "-l", "-f", "-v", "--", NULL};
+ char *opts[] = {LSG_SERVER_CMD_ADD_OPTS, NULL};
if (ci->word[0] == '-')
i9e_complete_option(opts, ci, cr);
static void ls_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {
- "--", "-l", "-ls", "-ll", "-lv", "-lp", "-lm", "-lc", "-p",
- "-a", "-r", "-d", "-sp", "-sl", "-ss", "-sn", "-sf", "-sc",
- "-si", "-sy", "-sb", "-sd", "-sa", NULL
- };
+ char *opts[] = {LSG_SERVER_CMD_LS_OPTS, NULL};
if (ci->word[0] == '-')
i9e_complete_option(opts, ci, cr);
cr->filename_completion_desired = true;
static void lsatt_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-i", "-l", "-r", NULL};
-
- if (ci->word[0] == '-')
- i9e_complete_option(opts, ci, cr);
- else
- complete_attributes(ci->word, &cr->matches);
+ char *opts[] = {LSG_SERVER_CMD_LSATT_OPTS, NULL};
+ i9e_complete_option(opts, ci, cr);
}
static void mvatt_completer(struct i9e_completion_info *ci,
static void check_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-a", "-m", "-p", NULL};
+ char *opts[] = {LSG_SERVER_CMD_CHECK_OPTS, NULL};
i9e_complete_option(opts, ci, cr);
}
static void rm_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-v", "-f", "-p", NULL};
+ char *opts[] = {LSG_SERVER_CMD_RM_OPTS, NULL};
if (ci->word[0] == '-') {
i9e_complete_option(opts, ci, cr);
static void touch_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-n=", "-l=", "-y=", "-i=", "-a=", "-v", "-p", NULL};
+ char *opts[] = {LSG_SERVER_CMD_TOUCH_OPTS, NULL};
if (ci->word[0] == '-')
i9e_complete_option(opts, ci, cr);
static void cpsi_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-a", "-y", "-i", "-l", "-n", "-v", NULL};
+ char *opts[] = {LSG_SERVER_CMD_CPSI_OPTS, NULL};
if (ci->word[0] == '-')
i9e_complete_option(opts, ci, cr);
static int client_i9e_line_handler(char *line)
{
int ret;
+ static bool first = true;
- PARA_DEBUG_LOG("line: %s\n", line);
- ret = make_client_argv(line);
+ if (first)
+ first = false;
+ else
+ lls_free_parse_result(ct->lpr, CLIENT_CMD_PTR);
+ ret = create_merged_lpr(line);
if (ret <= 0)
return ret;
ret = client_connect(ct, &sched, NULL, NULL);
}
static struct i9e_completer completers[] = {
- SERVER_COMPLETERS
- AFS_COMPLETERS
+#define LSG_SERVER_CMD_CMD(_name) {.name = #_name, \
+ .completer = _name ## _completer}
+ LSG_SERVER_CMD_SUBCOMMANDS
+#undef LSG_SERVER_CMD_CMD
{.name = NULL}
};
__noreturn static void interactive_session(void)
{
int ret;
- char *history_file;
struct sigaction act;
struct i9e_client_info ici = {
.fds = {0, 1, 2},
};
PARA_NOTICE_LOG("\n%s\n", version_text("client"));
- if (ct->conf.history_file_given)
- history_file = para_strdup(ct->conf.history_file_arg);
+ if (CLIENT_OPT_GIVEN(HISTORY_FILE, ct->lpr))
+ ici.history_file = para_strdup(CLIENT_OPT_STRING_VAL(
+ HISTORY_FILE, ct->lpr));
else {
char *home = para_homedir();
- history_file = make_message("%s/.paraslash/client.history",
+ ici.history_file = make_message("%s/.paraslash/client.history",
home);
free(home);
}
- ici.history_file = history_file;
-
act.sa_handler = i9e_signal_dispatch;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
__noreturn static void print_completions(void)
{
- int ret = i9e_print_completions(completers);
+ int ret;
+
+ ret = i9e_print_completions(completers);
exit(ret <= 0? EXIT_FAILURE : EXIT_SUCCESS);
}
*
* \return EXIT_SUCCESS or EXIT_FAILURE
*
- * \sa client_open(), stdin.c, stdout.c, para_client(1), para_server(1)
+ * \sa \ref client_open(), \ref stdin.c, \ref stdout.c, para_client(1),
+ * para_server(1).
*/
int main(int argc, char *argv[])
{
ret = client_parse_config(argc, argv, &ct, &client_loglevel);
if (ret < 0)
goto out;
- if (ct->conf.complete_given)
+ if (CLIENT_OPT_GIVEN(COMPLETE, ct->lpr))
print_completions();
if (ret == 0)
interactive_session(); /* does not return */