-/*
- * 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_common.c Common functions of para_client and para_audiod. */
#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 "lsu.h"
#include "sched.h"
#include "crypt.h"
#include "net.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
if (!ct)
return;
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]);
else if (ret > 0)
para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno);
}
- /* fall though */
+ /* fallthrough */
case CL_EXECUTING:
if (ct->btrn[0]) {
ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT);
return ret;
}
-static bool has_feature(const char *feature, struct client_task *ct)
-{
- return find_arg(feature, ct->features) >= 0? true : false;
-}
-
static int send_sb_command(struct client_task *ct)
{
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);
if (ret < 0 || n == 0)
goto out;
ct->features = parse_features(buf);
- if (!has_feature("sideband", ct)) {
- PARA_ERROR_LOG("server has no sideband support\n");
- ret = -E_INCOMPAT_FEAT;
- goto out;
- }
ct->status = CL_RECEIVED_WELCOME;
return 0;
case CL_RECEIVED_WELCOME: /* send auth command */
if (!FD_ISSET(ct->scc.fd, &s->wfds))
return 0;
- sprintf(buf, AUTH_REQUEST_MSG "%s sideband%s", ct->user,
- has_feature("aes_ctr128", ct)? ",aes_ctr128" : "");
+ sprintf(buf, AUTH_REQUEST_MSG "%s sideband,aes_ctr128",
+ ct->user);
PARA_INFO_LOG("--> %s\n", buf);
ret = write_buffer(ct->scc.fd, buf);
if (ret < 0)
/* decrypted challenge/session key buffer */
unsigned char crypt_buf[1024];
struct sb_buffer sbb;
- bool use_aes;
ret = recv_sb(ct, &s->rfds, &sbb);
if (ret <= 0)
}
n = sbb.iov.iov_len;
PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
- ret = priv_decrypt(ct->key_file, crypt_buf,
+ ret = apc_priv_decrypt(ct->key_file, crypt_buf,
sbb.iov.iov_base, n);
free(sbb.iov.iov_base);
if (ret < 0)
goto out;
ct->challenge_hash = para_malloc(HASH_SIZE);
- hash_function((char *)crypt_buf, CHALLENGE_SIZE, ct->challenge_hash);
- use_aes = has_feature("aes_ctr128", ct);
- ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN, use_aes);
- ct->scc.recv = sc_new(crypt_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
- SESSION_KEY_LEN, use_aes);
+ hash_function((char *)crypt_buf, APC_CHALLENGE_SIZE, ct->challenge_hash);
+ ct->scc.send = sc_new(crypt_buf + APC_CHALLENGE_SIZE, SESSION_KEY_LEN);
+ ct->scc.recv = sc_new(crypt_buf + APC_CHALLENGE_SIZE + SESSION_KEY_LEN,
+ SESSION_KEY_LEN);
hash_to_asc(ct->challenge_hash, buf);
PARA_INFO_LOG("--> %s\n", buf);
ct->status = CL_RECEIVED_CHALLENGE;
btr_consume(ct->btrn[1], sz);
}
}
- /* fall though */
+ /* fall through */
case CL_EXECUTING:
if (ct->btrn[0]) {
ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT);
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));
+ const struct lls_command *cmd = CLIENT_CMD_PTR;
+ struct lls_parse_result *lpr;
+ int ret, ll;
+ struct client_task *ct;
+ char *kf = NULL, *user, *errctx, *home = para_homedir();
- *ct_ptr = ct;
- ct->scc.fd = -1;
- ret = -E_CLIENT_SYNTAX;
- if (client_cmdline_parser(argc, argv, &ct->conf))
+ ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx));
+ if (ret < 0)
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;
+ version_handle_flag("client", CLIENT_OPT_GIVEN(VERSION, lpr));
+ handle_help_flag(lpr);
+
+ ret = lsu_merge_config_file_options(CLIENT_OPT_STRING_VAL(CONFIG_FILE, lpr),
+ "client.conf", &lpr, cmd, client_suite, 0U /* default flags */);
+ 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))
- goto out;
- }
- ct->user = ct->conf.user_given?
- para_strdup(ct->conf.user_arg) : para_logname();
+ /* success */
+ ll = CLIENT_OPT_UINT32_VAL(LOGLEVEL, lpr);
+ if (loglevel)
+ *loglevel = ll;
+ 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);
}
}
-
- 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;
+ PARA_INFO_LOG("user: %s\n", user);
+ 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->user = user;
+ *ct_ptr = ct;
+ ret = lls_num_inputs(lpr);
out:
free(home);
if (ret < 0) {
- PARA_ERROR_LOG("%s\n", para_strerror(-ret));
- client_close(ct);
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
+ free(errctx);
+ lls_free_parse_result(lpr, cmd);
+ free(kf);
*ct_ptr = NULL;
}
return ret;