$(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
$(write_objs) $(afh_objs) $(play_objs))
deps := $(addprefix $(dep_dir)/, $(filter-out %.cmdline.d, $(all_objs:.o=.d)))
-converted_executables := audioc
+converted_executables := audioc client
unconverted_executables := $(filter-out $(converted_executables), $(executables))
audioc_objs += audioc.lsg.o
-audiod_objs += audiod_cmd.lsg.o recv_cmd.lsg.o
+audiod_objs += audiod_cmd.lsg.o recv_cmd.lsg.o client.lsg.o
server_objs += server_cmd.lsg.o
play_objs += play_cmd.lsg.o recv_cmd.lsg.o
recv_objs += recv_cmd.lsg.o
+client_objs += client.lsg.o
m4_deps := $(addprefix $(m4depdir)/, $(addsuffix .m4d, $(unconverted_executables)))
m4_lls_deps := audiod_cmd server_cmd play_cmd recv_cmd $(converted_executables)
para_audioc \
para_audiod \
+para_client \
para_play \
para_recv \
para_server \
#include <lopsub.h>
#include "recv_cmd.lsg.h"
+#include "client.lsg.h"
#include "para.h"
#include "error.h"
#include "crypt.h"
#include "recv.h"
#include "filter.h"
#include "grab_client.h"
-#include "client.cmdline.h"
#include "client.h"
#include "audiod.h"
#include "net.h"
#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"
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);
result->matches = i9e_complete_commands(ci->word, completers);
}
-static void version_completer(struct i9e_completion_info *ci,
+static void stat_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *opts[] = {"-v", NULL};
+ char *opts[] = {LSG_SERVER_CMD_STAT_OPTS, NULL};
i9e_complete_option(opts, ci, cr);
}
-static void stat_completer(struct i9e_completion_info *ci,
+static void version_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_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", "-l=s", "-l=l", "-l=v", "-l=p", "-l=m", "-l=c",
- "-p", "-a", "-r", "-d", "-s=p", "-s=l", "-s=s", "-s=n", "-s=f",
- "-s=c", "-s=i", "-s=y", "-s=b", "-s=d", "-s=a", "-F", "-b", 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};
+ char *opts[] = {LSG_SERVER_CMD_LSATT_OPTS, NULL};
i9e_complete_option(opts, ci, cr);
}
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[] = {
#define LSG_SERVER_CMD_CMD(_name) {.name = #_name, \
.completer = _name ## _completer}
- LSG_SERVER_CMD_COMMANDS
+ 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);
}
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 */
struct btr_node *btrn[2];
/** The hash value of the decrypted challenge. */
unsigned char *challenge_hash;
- /** The configuration (including the command). */
- struct client_args_info conf;
+ /** The parsed command line (including the command). */
+ struct lls_parse_result *lpr;
/** The config file for client options. */
char *config_file;
/** The RSA private key. */
char **features;
};
+#define CLIENT_CMD_PTR (lls_cmd(0, client_suite))
+#define CLIENT_OPT_RESULT(_name, _lpr) \
+ (lls_opt_result(LSG_CLIENT_PARA_CLIENT_OPT_ ## _name, _lpr))
+#define CLIENT_OPT_GIVEN(_name, _lpr) \
+ (lls_opt_given(CLIENT_OPT_RESULT(_name, _lpr)))
+#define CLIENT_OPT_UINT32_VAL(_name, _lpr) \
+ (lls_uint32_val(0, CLIENT_OPT_RESULT(_name, _lpr)))
+#define CLIENT_OPT_STRING_VAL(_name, _lpr) \
+ (lls_string_val(0, CLIENT_OPT_RESULT(_name, _lpr)))
+
void client_close(struct client_task *ct);
int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
int *loglevel);
#include <arpa/inet.h>
#include <sys/un.h>
#include <netdb.h>
+#include <lopsub.h>
+#include "client.lsg.h"
#include "para.h"
#include "error.h"
#include "list.h"
#include "fd.h"
#include "sideband.h"
#include "string.h"
-#include "client.cmdline.h"
#include "client.h"
#include "buffer_tree.h"
#include "version.h"
-#include "ggo.h"
/** The size of the receiving buffer. */
#define CLIENT_BUFSIZE 4000
free(ct->user);
free(ct->config_file);
free(ct->key_file);
- client_cmdline_parser_free(&ct->conf);
+ lls_free_parse_result(ct->lpr, CLIENT_CMD_PTR);
free(ct->challenge_hash);
sb_free(ct->sbc[0]);
sb_free(ct->sbc[1]);
int i;
char *command, *p;
size_t len = 0;
+ unsigned num_inputs = lls_num_inputs(ct->lpr);
if (ct->sbc[1])
return send_sb(ct, 0, NULL, 0, 0, false);
- for (i = 0; i < ct->conf.inputs_num; i++)
- len += strlen(ct->conf.inputs[i]) + 1;
+ for (i = 0; i < num_inputs; i++)
+ len += strlen(lls_input(i, ct->lpr)) + 1;
p = command = para_malloc(len);
- for (i = 0; i < ct->conf.inputs_num; i++) {
- strcpy(p, ct->conf.inputs[i]);
- p += strlen(ct->conf.inputs[i]) + 1;
+ for (i = 0; i < num_inputs; i++) {
+ const char *str = lls_input(i, ct->lpr);
+ strcpy(p, str);
+ p += strlen(str) + 1;
}
PARA_DEBUG_LOG("--> %s\n", command);
return send_sb(ct, 0, command, len, SBD_COMMAND, false);
struct btr_node *parent, struct btr_node *child)
{
int ret;
+ const char *host = CLIENT_OPT_STRING_VAL(HOSTNAME, ct->lpr);
+ uint32_t port = CLIENT_OPT_UINT32_VAL(SERVER_PORT, ct->lpr);
- PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
- ct->conf.server_port_arg);
+ PARA_NOTICE_LOG("connecting %s:%u\n", host, port);
ct->scc.fd = -1;
- ret = para_connect_simple(IPPROTO_TCP, ct->conf.hostname_arg,
- ct->conf.server_port_arg);
+ ret = para_connect_simple(IPPROTO_TCP, host, port);
if (ret < 0)
return ret;
ct->scc.fd = ret;
return ret;
}
-__noreturn static void print_help_and_die(struct client_task *ct)
+static void handle_help_flag(struct lls_parse_result *lpr)
{
- struct ggo_help h = DEFINE_GGO_HELP(client);
- bool d = ct->conf.detailed_help_given;
+ char *help;
- ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS);
- exit(0);
+ if (CLIENT_OPT_GIVEN(DETAILED_HELP, lpr))
+ help = lls_long_help(CLIENT_CMD_PTR);
+ else if (CLIENT_OPT_GIVEN(HELP, lpr))
+ help = lls_short_help(CLIENT_CMD_PTR);
+ else
+ return;
+ printf("%s\n", help);
+ free(help);
+ exit(EXIT_SUCCESS);
}
/**
int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
int *loglevel)
{
- char *home = para_homedir();
- int ret;
- struct client_task *ct = para_calloc(sizeof(struct client_task));
-
- *ct_ptr = ct;
- ct->scc.fd = -1;
- ret = -E_CLIENT_SYNTAX;
- if (client_cmdline_parser(argc, argv, &ct->conf))
- goto out;
- version_handle_flag("client", ct->conf.version_given);
- if (ct->conf.help_given || ct->conf.detailed_help_given)
- print_help_and_die(ct);
-
- ct->config_file = ct->conf.config_file_given?
- para_strdup(ct->conf.config_file_arg) :
- make_message("%s/.paraslash/client.conf", home);
- ret = file_exists(ct->config_file);
- if (!ret && ct->conf.config_file_given) {
- ret = -E_NO_CONFIG;
+ const struct lls_command *cmd = CLIENT_CMD_PTR;
+ void *map;
+ size_t sz;
+ struct lls_parse_result *lpr;
+ int ret, ll;
+ struct client_task *ct;
+ char *cf = NULL, *kf = NULL, *user, *errctx, *home = para_homedir();
+
+ ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx));
+ if (ret < 0)
goto out;
- }
- if (ret) {
- struct client_cmdline_parser_params params = {
- .override = 0,
- .initialize = 0,
- .check_required = 0,
- .check_ambiguity = 0,
- .print_errors = 0
- };
- ret = -E_BAD_CONFIG;
- if (client_cmdline_parser_config_file(ct->config_file,
- &ct->conf, ¶ms))
+ ll = CLIENT_OPT_UINT32_VAL(LOGLEVEL, lpr);
+ version_handle_flag("client", CLIENT_OPT_GIVEN(VERSION, lpr));
+ handle_help_flag(lpr);
+
+ if (CLIENT_OPT_GIVEN(CONFIG_FILE, lpr))
+ cf = para_strdup(CLIENT_OPT_STRING_VAL(CONFIG_FILE, lpr));
+ else
+ cf = make_message("%s/.paraslash/client.conf", home);
+ ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
+ if (ret < 0) {
+ if (ret != -E_EMPTY && ret != -ERRNO_TO_PARA_ERROR(ENOENT))
+ goto out;
+ if (ret == -ERRNO_TO_PARA_ERROR(ENOENT) &&
+ CLIENT_OPT_GIVEN(CONFIG_FILE, lpr))
goto out;
+ } else {
+ int cf_argc;
+ char **cf_argv;
+ struct lls_parse_result *cf_lpr, *merged_lpr;
+ ret = lls(lls_convert_config(map, sz, NULL, &cf_argv, &errctx));
+ para_munmap(map, sz);
+ if (ret < 0)
+ goto out;
+ cf_argc = ret;
+ ret = lls(lls_parse(cf_argc, cf_argv, cmd, &cf_lpr, &errctx));
+ lls_free_argv(cf_argv);
+ if (ret < 0)
+ goto out;
+ ret = lls(lls_merge(lpr, cf_lpr, cmd, &merged_lpr,
+ &errctx));
+ lls_free_parse_result(cf_lpr, cmd);
+ if (ret < 0)
+ goto out;
+ lls_free_parse_result(lpr, cmd);
+ lpr = merged_lpr;
}
- ct->user = ct->conf.user_given?
- para_strdup(ct->conf.user_arg) : para_logname();
+ /* success */
+ user = CLIENT_OPT_GIVEN(USER, lpr)?
+ para_strdup(CLIENT_OPT_STRING_VAL(USER, lpr)) : para_logname();
- if (ct->conf.key_file_given)
- ct->key_file = para_strdup(ct->conf.key_file_arg);
+ if (CLIENT_OPT_GIVEN(KEY_FILE, lpr))
+ kf = para_strdup(CLIENT_OPT_STRING_VAL(KEY_FILE, lpr));
else {
- ct->key_file = make_message("%s/.paraslash/key.%s",
- home, ct->user);
- if (!file_exists(ct->key_file)) {
- free(ct->key_file);
- ct->key_file = make_message("%s/.ssh/id_rsa", home);
+ kf = make_message("%s/.paraslash/key.%s", home, user);
+ if (!file_exists(kf)) {
+ free(kf);
+ kf = make_message("%s/.ssh/id_rsa", home);
}
}
-
+ PARA_INFO_LOG("user: %s\n", user);
+ PARA_INFO_LOG("config file: %s\n", cf);
+ PARA_INFO_LOG("key file: %s\n", kf);
+ PARA_INFO_LOG("loglevel: %d\n", ll);
+ ct = para_calloc(sizeof(*ct));
+ ct->scc.fd = -1;
+ ct->lpr = lpr;
+ ct->key_file = kf;
+ ct->config_file = cf;
+ ct->user = user;
+ *ct_ptr = ct;
if (loglevel)
- *loglevel = get_loglevel_by_name(ct->conf.loglevel_arg);
- PARA_INFO_LOG("loglevel: %s\n", ct->conf.loglevel_arg);
- PARA_INFO_LOG("config_file: %s\n", ct->config_file);
- PARA_INFO_LOG("key_file: %s\n", ct->key_file);
- ret = ct->conf.inputs_num;
+ *loglevel = ll;
+ ret = lls_num_inputs(lpr);
out:
free(home);
if (ret < 0) {
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
+ free(errctx);
PARA_ERROR_LOG("%s\n", para_strerror(-ret));
- client_close(ct);
+ lls_free_parse_result(lpr, cmd);
+ free(cf);
+ free(kf);
*ct_ptr = NULL;
}
return ret;
if test -n "$CRYPTOLIB"; then
build_client="yes"
executables="$executables client"
- client_cmdline_objs="client"
client_errlist_objs="
client
net
crypt_common
base64
version
- ggo
"
if test "$CRYPTOLIB" = openssl; then
client_errlist_objs="$client_errlist_objs crypt"
if test $HAVE_READLINE = yes; then
client_errlist_objs="$client_errlist_objs interactive"
fi
- client_objs="add_cmdline($client_cmdline_objs) $client_errlist_objs"
- AC_SUBST(client_objs, add_dot_o($client_objs))
+ client_objs="$client_errlist_objs"
+ AC_SUBST(client_objs, add_dot_o($client_errlist_objs))
else
build_client="no"
fi
audiod
compress_filter
file_write
- client
amp_filter
prebuffer_filter
sync_filter
PARA_ERROR(BAD_BAND, "invalid or unexpected band designator"), \
PARA_ERROR(BAD_CHANNEL_COUNT, "channel count not supported"), \
PARA_ERROR(BAD_CHANNEL, "invalid channel"), \
- PARA_ERROR(BAD_CONFIG, "syntax error in config file"), \
PARA_ERROR(BAD_CT, "invalid chunk table or bad FEC configuration"), \
PARA_ERROR(BAD_FEATURE, "invalid feature request"), \
PARA_ERROR(BAD_FEC_HEADER, "invalid fec header"), \
PARA_ERROR(NO_AFHI, "audio format handler info required"), \
PARA_ERROR(NO_ATTRIBUTES, "no attributes defined yet"), \
PARA_ERROR(NO_AUDIO_FILE, "no audio file"), \
- PARA_ERROR(NO_CONFIG, "config file not found"), \
PARA_ERROR(NOFD, "did not receive open fd from afs"), \
PARA_ERROR(NO_FILTERS, "at least one filter must be given"), \
PARA_ERROR(NO_MATCH, "no matches"), \
+++ /dev/null
-args "--unamed-opts=command --no-handle-error --conf-parser --no-handle-version --no-handle-help"
-
-purpose "Communicate with para_server through the paraslash control port"
-
-include(header.m4)
-define(CURRENT_PROGRAM,para_client)
-define(DEFAULT_CONFIG_FILE,~/.paraslash/client.conf)
-define(DEFAULT_HISTORY_FILE,~/.paraslash/client.history)
-<qu>
-option "hostname" i
-#~~~~~~~~~~~~~~~~~~
-"ip or host to connect"
-string typestr = "host"
-default = "localhost"
-optional
-
-option "user" u
-#~~~~~~~~~~~~~~
-"paraslash username"
-string typestr = "username"
-default = "<current user>"
-optional
-
-option "server-port" p
-#~~~~~~~~~~~~~~~~~~~~~
-"port to connect"
-int typestr = "port"
-default = "2990"
-optional
-
-option "key-file" k
-#~~~~~~~~~~~~~~~~~~
-"path to private key"
-string typestr = "filename"
-optional
-details = "
- If not given, the following files are tried, in order:
- $HOME/.paraslash/key.$LOGNAME, $HOME/.ssh/id_rsa. It is a fatal
- error if the key file can not be opened, or is world-readable.
-"
-</qu>
-
-include(loglevel.m4)
-include(config_file.m4)
-include(history_file.m4)
-include(complete.m4)
+++ /dev/null
-<qu>
-option "complete" -
-#~~~~~~~~~~~~~~~~~~
-"print possible command line completions"
- flag off
- details = "
- If this flag is given, </qu>CURRENT_PROGRAM<qu> reads the environment
- variables COMP_LINE and COMP_POINT to obtain the current command line
- and the cursor position respectively, prints possible completions
- to stdout and exits.
-"
-</qu>
--- /dev/null
+m4_define(PROGRAM, para_client)
+m4_define(DEFAULT_HISTORY_FILE, ~/.paraslash/client.history)
+m4_define(DEFAULT_CONFIG_FILE,~/.paraslash/client.conf)
+[suite client]
+version-string = GIT_VERSION()
+[supercommand para_client]
+ purpose = Communicate with para_server through the paraslash control port
+ non-opts-name = [command [options]]
+ [description]
+ para_client is the program used to connect to a running instance of
+ para_server. If a command is provided, this command is sent to the
+ server and any output received from the server is echoed to stdout. If
+ no command is given, para_client enters interactive mode.
+ [/description]
+ m4_include(common-option-section.m4)
+ m4_include(help.m4)
+ m4_include(detailed-help.m4)
+ m4_include(version.m4)
+ m4_include(loglevel.m4)
+ m4_include(config-file.m4)
+ m4_include(history-file.m4)
+ m4_include(per-command-options-section.m4)
+ [option hostname]
+ short_opt = i
+ summary = IP address or name of the host where para_server is running
+ typestr = host
+ arg_info = required_arg
+ arg_type = string
+ default_val = localhost
+ [help]
+ Both IPv4 and IPv6 addresses are supported.
+ [/help]
+ [option user]
+ short_opt = u
+ summary = the paraslash username to authenticate as
+ arg_info = required_arg
+ arg_type = string
+ typestr = name
+ [help]
+ If this is not given, the current username is assumed.
+ [/help]
+ [option server-port]
+ short_opt = p
+ summary = the port on the remote host to connect
+ arg_info = required_arg
+ arg_type = uint32
+ typestr = portnumber
+ default_val = 2990
+ [help]
+ If this is not given, the current username is assumed.
+ [/help]
+ [option key-file]
+ short_opt = k
+ summary = path to private key
+ arg_info = required_arg
+ arg_type = string
+ typestr = filename
+ [help]
+ If not given, the following files are tried, in order:
+ $HOME/.paraslash/key.$LOGNAME, $HOME/.ssh/id_rsa. It is a fatal error
+ if the key file can not be opened, or is world-readable.
+ [/help]
+ m4_include(complete.m4)
--- /dev/null
+[option config-file]
+ short_opt = c
+ summary = path to alternative config file
+ arg_info = required_arg
+ arg_type = string
+ typestr = filename
+ [help]
+ default: DEFAULT_CONFIG_FILE()
+
+ PROGRAM() reads its config file right after parsing the options that
+ were given at the command line. If an option is given both at the
+ command line and in the config file, the value that was specified at
+ the command line takes precedence.
+ [/help]