qrexec: return remote process status as qrexec-client-vm exit code

This doesn't cover all the cases, because local process could want to
receive that value (currently it cant), but I can't think of any simple,
*compatible* way to pass it there.
This commit is contained in:
Marek Marczykowski-Górecki 2015-03-16 21:32:34 +01:00
parent 1aa05ebc36
commit 4eb1d72aee
3 changed files with 23 additions and 17 deletions

View File

@ -181,16 +181,17 @@ int handle_input(libvchan_t *vchan, int fd, int msg_type)
/* handle data from vchan and send it to specified FD /* handle data from vchan and send it to specified FD
* Return: * Return:
* -2 - remote process terminated, do not send more data to it * -2 - remote process terminated, do not send more data to it
* in this case "status" will be set
* -1 - vchan error occurred * -1 - vchan error occurred
* 0 - EOF received, do not attempt to access this FD again * 0 - EOF received, do not attempt to access this FD again
* 1 - some data processed, call it again when buffer space and more data * 1 - some data processed, call it again when buffer space and more data
* available * available
*/ */
int handle_remote_data(libvchan_t *data_vchan, int stdin_fd)
int handle_remote_data(libvchan_t *data_vchan, int stdin_fd, int *status)
{ {
struct msg_header hdr; struct msg_header hdr;
char buf[MAX_DATA_CHUNK]; char buf[MAX_DATA_CHUNK];
int status;
/* TODO: set stdin_fd to non-blocking mode and handle its buffering */ /* TODO: set stdin_fd to non-blocking mode and handle its buffering */
while (libvchan_data_ready(data_vchan) > 0) { while (libvchan_data_ready(data_vchan) > 0) {
@ -245,24 +246,24 @@ int handle_remote_data(libvchan_t *data_vchan, int stdin_fd)
case MSG_DATA_EXIT_CODE: case MSG_DATA_EXIT_CODE:
/* remote process exited, so there is no sense to send any data /* remote process exited, so there is no sense to send any data
* to it */ * to it */
if (hdr.len < sizeof(status)) if (hdr.len < sizeof(*status))
status = 255; *status = 255;
else else
memcpy(&status, buf, sizeof(status)); memcpy(status, buf, sizeof(*status));
fprintf(stderr, "Remote service process exited with code %d\n", status);
return -2; return -2;
} }
} }
return 1; return 1;
} }
void process_child_io(libvchan_t *data_vchan, int process_child_io(libvchan_t *data_vchan,
int stdin_fd, int stdout_fd, int stderr_fd) int stdin_fd, int stdout_fd, int stderr_fd)
{ {
fd_set rdset, wrset; fd_set rdset, wrset;
int vchan_fd; int vchan_fd;
sigset_t selectmask; sigset_t selectmask;
int child_process_status = -1; int child_process_status = -1;
int remote_process_status = -1;
int ret, max_fd; int ret, max_fd;
struct timespec zero_timeout = { 0, 0 }; struct timespec zero_timeout = { 0, 0 };
@ -372,7 +373,7 @@ void process_child_io(libvchan_t *data_vchan,
} }
} }
/* handle_remote_data will check if any data is available */ /* handle_remote_data will check if any data is available */
switch (handle_remote_data(data_vchan, stdin_fd)) { switch (handle_remote_data(data_vchan, stdin_fd, &remote_process_status)) {
case -1: case -1:
handle_vchan_error("read"); handle_vchan_error("read");
break; break;
@ -388,16 +389,18 @@ void process_child_io(libvchan_t *data_vchan,
stdout_fd = -1; stdout_fd = -1;
close(stderr_fd); close(stderr_fd);
stderr_fd = -1; stderr_fd = -1;
/* we do not care for any local process */ /* if we do not care for any local process, return remote process code */
return; if (child_process_pid == 0)
return remote_process_status;
break; break;
} }
} }
return child_process_status;
} }
/* Behaviour depends on type parameter: /* Behaviour depends on type parameter:
* MSG_SERVICE_CONNECT - create vchan server, pass the data to/from given FDs * MSG_SERVICE_CONNECT - create vchan server, pass the data to/from given FDs
* (stdin_fd, stdout_fd, stderr_fd), then return 0 * (stdin_fd, stdout_fd, stderr_fd), then return remote process exit code
* MSG_JUST_EXEC - connect to vchan server, fork+exec process given by cmdline * MSG_JUST_EXEC - connect to vchan server, fork+exec process given by cmdline
* parameter, send artificial exit code "0" (local process can still be * parameter, send artificial exit code "0" (local process can still be
* running), then return 0 * running), then return 0
@ -453,7 +456,7 @@ int handle_new_process_common(int type, int connect_domain, int connect_port,
case MSG_SERVICE_CONNECT: case MSG_SERVICE_CONNECT:
child_process_pid = 0; child_process_pid = 0;
stdout_msg_type = MSG_DATA_STDIN; stdout_msg_type = MSG_DATA_STDIN;
process_child_io(data_vchan, stdin_fd, stdout_fd, stderr_fd); exit_code = process_child_io(data_vchan, stdin_fd, stdout_fd, stderr_fd);
break; break;
} }
libvchan_close(data_vchan); libvchan_close(data_vchan);
@ -488,12 +491,15 @@ pid_t handle_new_process(int type, int connect_domain, int connect_port,
return 0; return 0;
} }
void handle_data_client(int type, int connect_domain, int connect_port, /* Returns exit code of remote process */
int handle_data_client(int type, int connect_domain, int connect_port,
int stdin_fd, int stdout_fd, int stderr_fd) int stdin_fd, int stdout_fd, int stderr_fd)
{ {
int exit_code;
assert(type == MSG_SERVICE_CONNECT); assert(type == MSG_SERVICE_CONNECT);
handle_new_process_common(type, connect_domain, connect_port, exit_code = handle_new_process_common(type, connect_domain, connect_port,
NULL, 0, stdin_fd, stdout_fd, stderr_fd); NULL, 0, stdin_fd, stdout_fd, stderr_fd);
return exit_code;
} }

View File

@ -28,7 +28,7 @@ void do_exec(const char *cmd);
pid_t handle_new_process(int type, pid_t handle_new_process(int type,
int connect_domain, int connect_port, int connect_domain, int connect_port,
char *cmdline, int cmdline_len); char *cmdline, int cmdline_len);
void handle_data_client(int type, int handle_data_client(int type,
int connect_domain, int connect_port, int connect_domain, int connect_port,
int stdin_fd, int stdout_fd, int stderr_fd); int stdin_fd, int stdout_fd, int stderr_fd);

View File

@ -154,12 +154,12 @@ int main(int argc, char **argv)
close(inpipe[0]); close(inpipe[0]);
close(outpipe[1]); close(outpipe[1]);
handle_data_client(MSG_SERVICE_CONNECT, ret = handle_data_client(MSG_SERVICE_CONNECT,
exec_params.connect_domain, exec_params.connect_port, exec_params.connect_domain, exec_params.connect_port,
inpipe[1], outpipe[0], -1); inpipe[1], outpipe[0], -1);
close(trigger_fd); close(trigger_fd);
waitpid(child_pid, &i, 0); waitpid(child_pid, &i, 0);
return 0; return ret;
} }