version 1.35, 2010/07/19 18:27:38 |
version 1.36, 2010/07/24 20:11:59 |
|
|
|
|
void server_client_handle_key(int, struct mouse_event *, void *); |
void server_client_handle_key(int, struct mouse_event *, void *); |
void server_client_repeat_timer(int, short, void *); |
void server_client_repeat_timer(int, short, void *); |
|
void server_client_check_exit(struct client *); |
void server_client_check_redraw(struct client *); |
void server_client_check_redraw(struct client *); |
void server_client_set_title(struct client *); |
void server_client_set_title(struct client *); |
void server_client_reset_state(struct client *); |
void server_client_reset_state(struct client *); |
|
void server_client_in_callback(struct bufferevent *, short, void *); |
|
void server_client_out_callback(struct bufferevent *, short, void *); |
|
void server_client_err_callback(struct bufferevent *, short, void *); |
|
|
int server_client_msg_dispatch(struct client *); |
int server_client_msg_dispatch(struct client *); |
void server_client_msg_command(struct client *, struct msg_command_data *); |
void server_client_msg_command(struct client *, struct msg_command_data *); |
|
|
|
|
ARRAY_INIT(&c->prompt_hdata); |
ARRAY_INIT(&c->prompt_hdata); |
|
|
c->stdin_file = NULL; |
c->stdin_event = NULL; |
c->stdout_file = NULL; |
c->stdout_event = NULL; |
c->stderr_file = NULL; |
c->stderr_event = NULL; |
|
|
c->tty.fd = -1; |
c->tty.fd = -1; |
c->title = NULL; |
c->title = NULL; |
|
|
if (c->flags & CLIENT_TERMINAL) |
if (c->flags & CLIENT_TERMINAL) |
tty_free(&c->tty); |
tty_free(&c->tty); |
|
|
if (c->stdin_file != NULL) |
if (c->stdin_fd != -1) |
fclose(c->stdin_file); |
close(c->stdin_fd); |
if (c->stdout_file != NULL) |
if (c->stdin_event != NULL) |
fclose(c->stdout_file); |
bufferevent_free(c->stdin_event); |
if (c->stderr_file != NULL) |
if (c->stdout_fd != -1) |
fclose(c->stderr_file); |
close(c->stdout_fd); |
|
if (c->stdout_event != NULL) |
|
bufferevent_free(c->stdout_event); |
|
if (c->stderr_fd != -1) |
|
close(c->stderr_fd); |
|
if (c->stderr_event != NULL) |
|
bufferevent_free(c->stderr_event); |
|
|
screen_free(&c->status); |
screen_free(&c->status); |
job_tree_free(&c->status_jobs); |
job_tree_free(&c->status_jobs); |
|
|
|
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { |
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { |
c = ARRAY_ITEM(&clients, i); |
c = ARRAY_ITEM(&clients, i); |
if (c == NULL || c->session == NULL) |
if (c == NULL) |
continue; |
continue; |
|
|
server_client_check_redraw(c); |
server_client_check_exit(c); |
server_client_reset_state(c); |
if (c->session != NULL) { |
|
server_client_check_redraw(c); |
|
server_client_reset_state(c); |
|
} |
} |
} |
|
|
/* |
/* |
|
|
c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT); |
c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT); |
} |
} |
|
|
|
/* Check if client should be exited. */ |
|
void |
|
server_client_check_exit(struct client *c) |
|
{ |
|
struct msg_exit_data exitdata; |
|
|
|
if (!(c->flags & CLIENT_EXIT)) |
|
return; |
|
|
|
if (c->stdout_fd != -1 && c->stdout_event != NULL && |
|
EVBUFFER_LENGTH(c->stdout_event->output) != 0) |
|
return; |
|
if (c->stderr_fd != -1 && c->stderr_event != NULL && |
|
EVBUFFER_LENGTH(c->stderr_event->output) != 0) |
|
return; |
|
|
|
exitdata.retcode = c->retcode; |
|
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata); |
|
|
|
c->flags &= ~CLIENT_EXIT; |
|
} |
|
|
/* Check for client redraws. */ |
/* Check for client redraws. */ |
void |
void |
server_client_check_redraw(struct client *c) |
server_client_check_redraw(struct client *c) |
|
|
xfree(title); |
xfree(title); |
} |
} |
|
|
|
/* |
|
* Error callback for client stdin. Caller must increase reference count when |
|
* enabling event! |
|
*/ |
|
void |
|
server_client_in_callback( |
|
unused struct bufferevent *bufev, unused short what, void *data) |
|
{ |
|
struct client *c = data; |
|
|
|
c->references--; |
|
if (c->flags & CLIENT_DEAD) |
|
return; |
|
|
|
bufferevent_disable(c->stdin_event, EV_READ|EV_WRITE); |
|
close(c->stdin_fd); |
|
c->stdin_fd = -1; |
|
|
|
if (c->stdin_callback != NULL) |
|
c->stdin_callback(c, c->stdin_data); |
|
} |
|
|
|
/* Error callback for client stdout. */ |
|
void |
|
server_client_out_callback( |
|
unused struct bufferevent *bufev, unused short what, unused void *data) |
|
{ |
|
struct client *c = data; |
|
|
|
bufferevent_disable(c->stdout_event, EV_READ|EV_WRITE); |
|
close(c->stdout_fd); |
|
c->stdout_fd = -1; |
|
} |
|
|
|
/* Error callback for client stderr. */ |
|
void |
|
server_client_err_callback( |
|
unused struct bufferevent *bufev, unused short what, unused void *data) |
|
{ |
|
struct client *c = data; |
|
|
|
bufferevent_disable(c->stderr_event, EV_READ|EV_WRITE); |
|
close(c->stderr_fd); |
|
c->stderr_fd = -1; |
|
} |
|
|
/* Dispatch message from client. */ |
/* Dispatch message from client. */ |
int |
int |
server_client_msg_dispatch(struct client *c) |
server_client_msg_dispatch(struct client *c) |
|
|
struct msg_identify_data identifydata; |
struct msg_identify_data identifydata; |
struct msg_environ_data environdata; |
struct msg_environ_data environdata; |
ssize_t n, datalen; |
ssize_t n, datalen; |
|
int mode; |
|
|
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) |
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) |
return (-1); |
return (-1); |
|
|
fatalx("MSG_IDENTIFY missing fd"); |
fatalx("MSG_IDENTIFY missing fd"); |
memcpy(&identifydata, imsg.data, sizeof identifydata); |
memcpy(&identifydata, imsg.data, sizeof identifydata); |
|
|
c->stdin_file = fdopen(imsg.fd, "r"); |
c->stdin_fd = imsg.fd; |
if (c->stdin_file == NULL) |
c->stdin_event = bufferevent_new(imsg.fd, NULL, NULL, |
fatal("fdopen(stdin) failed"); |
server_client_in_callback, c); |
|
if (c->stdin_event == NULL) |
|
fatalx("failed to create stdin event"); |
|
|
|
if ((mode = fcntl(imsg.fd, F_GETFL)) != -1) |
|
fcntl(imsg.fd, F_SETFL, mode|O_NONBLOCK); |
|
if (fcntl(imsg.fd, F_SETFD, FD_CLOEXEC) == -1) |
|
fatal("fcntl failed"); |
|
|
server_client_msg_identify(c, &identifydata, imsg.fd); |
server_client_msg_identify(c, &identifydata, imsg.fd); |
break; |
break; |
case MSG_STDOUT: |
case MSG_STDOUT: |
|
|
if (imsg.fd == -1) |
if (imsg.fd == -1) |
fatalx("MSG_STDOUT missing fd"); |
fatalx("MSG_STDOUT missing fd"); |
|
|
c->stdout_file = fdopen(imsg.fd, "w"); |
c->stdout_fd = imsg.fd; |
if (c->stdout_file == NULL) |
c->stdout_event = bufferevent_new(imsg.fd, NULL, NULL, |
fatal("fdopen(stdout) failed"); |
server_client_out_callback, c); |
|
if (c->stdout_event == NULL) |
|
fatalx("failed to create stdout event"); |
|
|
|
if ((mode = fcntl(imsg.fd, F_GETFL)) != -1) |
|
fcntl(imsg.fd, F_SETFL, mode|O_NONBLOCK); |
|
if (fcntl(imsg.fd, F_SETFD, FD_CLOEXEC) == -1) |
|
fatal("fcntl failed"); |
break; |
break; |
case MSG_STDERR: |
case MSG_STDERR: |
if (datalen != 0) |
if (datalen != 0) |
|
|
if (imsg.fd == -1) |
if (imsg.fd == -1) |
fatalx("MSG_STDERR missing fd"); |
fatalx("MSG_STDERR missing fd"); |
|
|
c->stderr_file = fdopen(imsg.fd, "w"); |
c->stderr_fd = imsg.fd; |
if (c->stderr_file == NULL) |
c->stderr_event = bufferevent_new(imsg.fd, NULL, NULL, |
fatal("fdopen(stderr) failed"); |
server_client_err_callback, c); |
|
if (c->stderr_event == NULL) |
|
fatalx("failed to create stderr event"); |
|
|
|
if ((mode = fcntl(imsg.fd, F_GETFL)) != -1) |
|
fcntl(imsg.fd, F_SETFL, mode|O_NONBLOCK); |
|
if (fcntl(imsg.fd, F_SETFD, FD_CLOEXEC) == -1) |
|
fatal("fcntl failed"); |
break; |
break; |
case MSG_RESIZE: |
case MSG_RESIZE: |
if (datalen != 0) |
if (datalen != 0) |
|
|
va_list ap; |
va_list ap; |
|
|
va_start(ap, fmt); |
va_start(ap, fmt); |
vfprintf(ctx->cmdclient->stderr_file, fmt, ap); |
evbuffer_add_vprintf(ctx->cmdclient->stderr_event->output, fmt, ap); |
va_end(ap); |
va_end(ap); |
|
|
fputc('\n', ctx->cmdclient->stderr_file); |
bufferevent_write(ctx->cmdclient->stderr_event, "\n", 1); |
fflush(ctx->cmdclient->stderr_file); |
|
|
|
ctx->cmdclient->retcode = 1; |
ctx->cmdclient->retcode = 1; |
} |
} |
|
|
|
|
va_list ap; |
va_list ap; |
|
|
va_start(ap, fmt); |
va_start(ap, fmt); |
vfprintf(ctx->cmdclient->stdout_file, fmt, ap); |
evbuffer_add_vprintf(ctx->cmdclient->stdout_event->output, fmt, ap); |
va_end(ap); |
va_end(ap); |
|
|
fputc('\n', ctx->cmdclient->stdout_file); |
bufferevent_write(ctx->cmdclient->stdout_event, "\n", 1); |
fflush(ctx->cmdclient->stdout_file); |
|
} |
} |
|
|
/* Callback to send print message to client, if not quiet. */ |
/* Callback to send print message to client, if not quiet. */ |
|
|
return; |
return; |
|
|
va_start(ap, fmt); |
va_start(ap, fmt); |
vfprintf(ctx->cmdclient->stdout_file, fmt, ap); |
evbuffer_add_vprintf(ctx->cmdclient->stdout_event->output, fmt, ap); |
va_end(ap); |
va_end(ap); |
|
|
fputc('\n', ctx->cmdclient->stdout_file); |
bufferevent_write(ctx->cmdclient->stdout_event, "\n", 1); |
fflush(ctx->cmdclient->stdout_file); |
|
} |
} |
|
|
/* Handle command message. */ |
/* Handle command message. */ |
void |
void |
server_client_msg_command(struct client *c, struct msg_command_data *data) |
server_client_msg_command(struct client *c, struct msg_command_data *data) |
{ |
{ |
struct cmd_ctx ctx; |
struct cmd_ctx ctx; |
struct cmd_list *cmdlist = NULL; |
struct cmd_list *cmdlist = NULL; |
struct msg_exit_data exitdata; |
int argc; |
int argc; |
char **argv, *cause; |
char **argv, *cause; |
|
|
|
ctx.error = server_client_msg_error; |
ctx.error = server_client_msg_error; |
ctx.print = server_client_msg_print; |
ctx.print = server_client_msg_print; |
|
|
} |
} |
cmd_free_argv(argc, argv); |
cmd_free_argv(argc, argv); |
|
|
if (cmd_list_exec(cmdlist, &ctx) != 1) { |
if (cmd_list_exec(cmdlist, &ctx) != 1) |
exitdata.retcode = c->retcode; |
c->flags |= CLIENT_EXIT; |
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata); |
|
} |
|
cmd_list_free(cmdlist); |
cmd_list_free(cmdlist); |
return; |
return; |
|
|
error: |
error: |
if (cmdlist != NULL) |
if (cmdlist != NULL) |
cmd_list_free(cmdlist); |
cmd_list_free(cmdlist); |
exitdata.retcode = c->retcode; |
c->flags |= CLIENT_EXIT; |
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata); |
|
} |
} |
|
|
/* Handle identify message. */ |
/* Handle identify message. */ |