/*
- * Copyright (C) 1997-2011 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
-/** \file client.c the client program used to connect to para_server */
+/** \file client.c The client program used to connect to para_server. */
#include <regex.h>
#include <signal.h>
#include "afs_completion.h"
struct exec_task {
- struct task task;
+ struct task *task;
struct btr_node *btrn;
char *result_buf;
size_t result_size;
static void exec_pre_select(struct sched *s, struct task *t)
{
- struct exec_task *et = container_of(t, struct exec_task, task);
+ struct exec_task *et = task_context(t);
int ret = btr_node_status(et->btrn, 0, BTR_NT_LEAF);
if (ret != 0)
sched_min_delay(s);
}
-static void exec_post_select(__a_unused struct sched *s, struct task *t)
+static int exec_post_select(__a_unused struct sched *s, struct task *t)
{
- struct exec_task *et = container_of(t, struct exec_task, task);
+ struct exec_task *et = task_context(t);
struct btr_node *btrn = et->btrn;
char *buf;
size_t sz;
int ret;
ret = btr_node_status(btrn, 0, BTR_NT_LEAF);
- if (ret <= 0) {
- t->error = ret;
- return;
- }
+ if (ret <= 0)
+ return ret;
sz = btr_next_buffer(btrn, &buf);
if (sz <= 1)
goto out;
et->result_buf[et->result_size - 1] = '\0';
out:
btr_consume(btrn, sz);
+ return 0;
}
static int make_client_argv(const char *line)
int ret;
struct sched command_sched = {.default_timeout = {.tv_sec = 1}};
struct exec_task exec_task = {
- .task = {
- .pre_select = exec_pre_select,
- .post_select = exec_post_select,
- .status = "client exec task",
- },
.result_buf = para_strdup(""),
.result_size = 1,
};
goto out;
exec_task.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "exec_collect"));
- register_task(&command_sched, &exec_task.task);
+ exec_task.task = task_register(&(struct task_info) {
+ .name = "client exec",
+ .pre_select = exec_pre_select,
+ .post_select = exec_post_select,
+ .context = &exec_task,
+ }, &command_sched);
ret = client_connect(ct, &command_sched, NULL, exec_task.btrn);
if (ret < 0)
goto out;
schedule(&command_sched);
+ sched_shutdown(&command_sched);
*result = exec_task.result_buf;
- btr_remove_node(exec_task.btrn);
- client_disconnect(ct);
+ btr_remove_node(&exec_task.btrn);
ret = 1;
out:
- btr_free_node(exec_task.btrn);
+ btr_remove_node(&exec_task.btrn);
if (ret < 0)
free(exec_task.result_buf);
return ret;
free(orig);
}
sl[2 * num_atts] = NULL;
- ret = i9e_extract_completions(ci->word, sl, &cr->matches);
+ i9e_extract_completions(ci->word, sl, &cr->matches);
out:
free(buf);
free_argv(sl);
{
int ret;
- client_disconnect(ct);
- if (!line || !*line)
- return 0;
- PARA_DEBUG_LOG("line handler: %s\n", line);
+ PARA_DEBUG_LOG("line: %s\n", line);
ret = make_client_argv(line);
- if (ret < 0)
+ if (ret <= 0)
return ret;
ret = client_connect(ct, &sched, NULL, NULL);
if (ret < 0)
return ret;
- i9e_attach_to_stdout(ct->btrn);
+ i9e_attach_to_stdout(ct->btrn[0]);
return 1;
}
-static void client_sighandler(int s)
-{
- i9e_signal_dispatch(s);
-}
-
static struct i9e_completer completers[] = {
SERVER_COMPLETERS
AFS_COMPLETERS
.completers = completers,
};
- PARA_NOTICE_LOG("\n%s\n", VERSION_TEXT("client"));
+ PARA_NOTICE_LOG("\n%s\n", version_text("client"));
if (ct->conf.history_file_given)
history_file = para_strdup(ct->conf.history_file_arg);
else {
}
ici.history_file = history_file;
- act.sa_handler = client_sighandler;
+ act.sa_handler = i9e_signal_dispatch;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, NULL);
goto out;
para_log = i9e_log;
ret = schedule(&sched);
+ sched_shutdown(&sched);
i9e_close();
para_log = stderr_log;
out:
#endif /* HAVE_READLINE */
-static void supervisor_post_select(struct sched *s, struct task *t)
+struct supervisor_task {
+ bool stdout_task_started;
+ struct task *task;
+};
+
+static int supervisor_post_select(struct sched *s, struct task *t)
{
- if (ct->task.error < 0) {
- t->error = ct->task.error;
- return;
+ struct supervisor_task *svt = task_context(t);
+
+ if (ct->task.error < 0)
+ return ct->task.error;
+ if (!svt->stdout_task_started && ct->status == CL_EXECUTING) {
+ stdout_task_register(&sot, s);
+ svt->stdout_task_started = true;
+ return 1;
}
if (ct->status == CL_SENDING) {
- stdin_set_defaults(&sit);
- register_task(s, &sit.task);
- t->error = -E_TASK_STARTED;
- return;
- }
- if (ct->status == CL_RECEIVING) {
- stdout_set_defaults(&sot);
- register_task(s, &sot.task);
- t->error = -E_TASK_STARTED; return;
+ stdin_task_register(&sit, s);
+ return -E_TASK_STARTED;
}
+ return 0;
}
-static struct task svt = {
- .post_select = supervisor_post_select,
- .status = "supervisor task"
-};
+static struct supervisor_task supervisor_task;
/**
* The client program to connect to para_server.
*/
sit.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
- ret = client_open(argc, argv, &ct, &client_loglevel, sit.btrn, NULL, &sched);
+ ret = client_connect(ct, &sched, sit.btrn, NULL);
if (ret < 0)
goto out;
sot.btrn = btr_new_node(&(struct btr_node_description)
- EMBRACE(.name = "stdout", .parent = ct->btrn));
- register_task(&sched, &svt);
+ EMBRACE(.name = "stdout", .parent = ct->btrn[0]));
+ supervisor_task.task = task_register(&(struct task_info) {
+ .name = "supervisor",
+ .post_select = supervisor_post_select,
+ .context = &supervisor_task,
+ }, &sched);
+
ret = schedule(&sched);
+ if (ret >= 0 && ct->task.error < 0) {
+ switch(ct->task.error) {
+ /* these are not errors */
+ case -E_SERVER_CMD_SUCCESS:
+ case -E_EOF:
+ case -E_SERVER_EOF:
+ case -E_BTR_EOF:
+ ret = 0;
+ break;
+ default: ret = -E_SERVER_CMD_FAILURE;
+ }
+ }
+ sched_shutdown(&sched);
out:
+ if (ret < 0)
+ PARA_ERROR_LOG("%s\n", para_strerror(-ret));
client_close(ct);
- btr_free_node(sit.btrn);
- btr_free_node(sot.btrn);
- if (ret < 0) {
- /* can not use PARA_LOG here because ct is NULL */
- fprintf(stderr, "%s\n", para_strerror(-ret));
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
+ btr_remove_node(&sit.btrn);
+ btr_remove_node(&sot.btrn);
+ return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
}