From 9b57a503b599eb0d6f426e86a9766d11f4d2a70c Mon Sep 17 00:00:00 2001 From: "gu.martinm@gmail.com" Date: Mon, 17 Mar 2014 00:20:46 +0100 Subject: [PATCH] fixed #1. Using execvp instead of system. --- Daemon/javafork.c | 117 ++++++++++++++++++--- Daemon/javafork.h | 8 ++ .../src/main/java/de/fork/java/RemoteForkMain.java | 2 +- 3 files changed, 111 insertions(+), 16 deletions(-) diff --git a/Daemon/javafork.c b/Daemon/javafork.c index f6477b6..9a23807 100644 --- a/Daemon/javafork.c +++ b/Daemon/javafork.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -159,7 +158,7 @@ int main_daemon (char *address, int port, int queue) goto err; } - bzero((char*) &addr_server, sizeof(addr_server)); + memset((char*) &addr_server, 0, sizeof(addr_server)); addr_server.sin_family = AF_INET; if (inet_pton(AF_INET, address, &addr_server.sin_addr.s_addr) <= 0) { syslog (LOG_ERR, "error inet_pton: %m"); @@ -319,7 +318,7 @@ void *serverThread (void * arg) /*1. COMMAND LENGTH*/ /*First of all we receive the command size as a Java integer (4 bytes primitive type)*/ - bzero(buffer, sizeof(buffer)); + memset(buffer, 0, sizeof(buffer)); if (receive_from_socket (socket, buffer, sizeof(uint32_t), timeout, utimeout) < 0) goto err; @@ -337,7 +336,7 @@ void *serverThread (void * arg) goto err; } - bzero(command, ((commandLength) + 1)); + memset(command, 0, ((commandLength) + 1)); /*Wait max 2 seconds for data coming from client, otherwise exits with error.*/ if (receive_from_socket (socket, command, commandLength, timeout, utimeout) < 0) @@ -581,8 +580,7 @@ int polite_kill_and_wait(pid_t pid) } /*We are not sure if the child process is dead. In this case, */ - /*probably the child process is going to be an orphan and its */ - /*system process (if there is one) as well*/ + /*probably the child process is going to be an orphan one. */ syslog (LOG_ERR, "waitpid after SIGKILL did not work either: %m"); return -1; @@ -603,8 +601,9 @@ int fork_system(int socket, unsigned char *command) int childreturnstatus = -1; int returnValue = 0; /*return value from this function can be caught by upper layers,*/ /*OK by default*/ + sigset_t unBlockMask; /*Used by the child process in order to unblock the SIGCHLD signal, which was blocked by the main process.*/ int pollReturn; - unsigned char *tokenized_command; + char **args; @@ -660,11 +659,24 @@ int fork_system(int socket, unsigned char *command) closeSafely (sockfd); closeSafely (socket); - /*string tokenizer*/ - tokenized_command = strtok(command, " "); - /*TODO: I should use execve with setlocale and the environment.*/ - HERE EXECV + args = create_args(command); + if (args == NULL) { + syslog (LOG_ERR, "create args error: %m"); + /*Going to zombie state, hopefully waitpid will catch it*/ + _exit(EXIT_FAILURE); + } + if (args[0] == NULL) { + syslog (LOG_ERR, "command not found: %m"); + /*Going to zombie state, hopefully waitpid will catch it*/ + _exit(EXIT_FAILURE); + } + + if (execvp(args[0], (char **) args) < 0) { + syslog (LOG_ERR, "execvp error: %m"); + /*Going to zombie state, hopefully waitpid will catch it*/ + _exit(EXIT_FAILURE); + } } else { /*Parent process*/ @@ -680,7 +692,7 @@ int fork_system(int socket, unsigned char *command) pollReturn = poll(polls, 2, 100); if(pollReturn > 0) { if(polls[0].revents && POLLIN) { - bzero(buf,2000); + memset(buf, 0, 2000); n=TEMP_FAILURE_RETRY(read(out[0], &buf[sizeof(struct tcpforkhdr)], 2000-sizeof(struct tcpforkhdr))); //To network order, indeed it is the order used by Java (BIG ENDIAN). Anyway I am //swapping the bytes because it is required if you want to write portable code and @@ -713,7 +725,7 @@ int fork_system(int socket, unsigned char *command) } if(polls[1].revents && POLLIN) { - bzero(buf,2000); + memset(buf, 0, 2000); n=TEMP_FAILURE_RETRY(read(err[0], &buf[sizeof(struct tcpforkhdr)], 2000-sizeof(struct tcpforkhdr))); header->type = htonl(2); header->length = htonl(n); @@ -748,9 +760,10 @@ int fork_system(int socket, unsigned char *command) /* The child exited normally; get its exit code.*/ childreturnstatus = WEXITSTATUS(status); } - else + else { /*In case of error send an error status to the remote calling process*/ childreturnstatus = -1; + } break; } else if(waitpidReturn < 0) { @@ -772,7 +785,7 @@ int fork_system(int socket, unsigned char *command) } end: - bzero(buf,2000); + memset(buf, 0, 2000); header->type = htonl(3); header->length = htonl((childreturnstatus)); // Avoid SIGPIPE with MSG_NOSIGNAL flag. It just works on Linux OS (non portable code) @@ -793,6 +806,80 @@ err: } + +char* create_arg(char * token) +{ + size_t arg_len; + char * arg; + arg_len = strlen(token); + + if((arg = (char *)(malloc(sizeof(char) * (arg_len + 1)))) == NULL ) { + syslog (LOG_ERR, "create arg malloc error: %m"); + return NULL; + } + memset(arg, 0, arg_len + 1); + memcpy(arg, token, arg_len); + + return arg; +} + + + +char** create_args(char *command) +{ + unsigned int ARGS_SIZE = 50; + char delim[] = " \t\n\r\f"; + char *token; + char **args; + char *arg; + int args_count = 0; + int index; + + if ((args = (char *) malloc(sizeof(char *) * ARGS_SIZE)) == NULL) { + syslog (LOG_ERR, "init args malloc error: %m"); + return NULL; + } + + token = strtok(command, delim); + + while (token != NULL) { + if ((arg = create_arg(token)) == NULL) { + syslog (LOG_ERR, "create arg error: %m"); + goto err; + } + args[args_count] = arg; + + args_count += 1; + + if (args_count >= ARGS_SIZE) { + // TODO: check UINT_MAX limit + ARGS_SIZE = ARGS_SIZE + 100; + + if ((args = (char *) realloc(args, sizeof(char *) * ARGS_SIZE)) == NULL) { + syslog (LOG_ERR, "create args realloc error: %m"); + goto err; + } + } + + token = strtok(NULL, delim); + } + +end: + args[args_count] = NULL; + return args; +err: + /*Release memory.*/ + for (index = (args_count - 1); index >= 0; index--) { + free(args[index]); + } + free(args); + /*Return error.*/ + args = NULL; + goto end; +} + + + void sigint_handler(int sig) { if (daemonPID != getpid()) { diff --git a/Daemon/javafork.h b/Daemon/javafork.h index b0301f0..e6eb701 100644 --- a/Daemon/javafork.h +++ b/Daemon/javafork.h @@ -107,3 +107,11 @@ int wait_for_closed_socket (int socket, long timeout); int polite_kill_and_wait(pid_t pid); + + + +char* create_arg(char * token); + + + +char** create_args(char *command); diff --git a/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java b/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java index 10b021d..01fc99e 100644 --- a/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java +++ b/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java @@ -22,7 +22,7 @@ public class RemoteForkMain { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final PrintStream stdout = new PrintStream(baos); - final String command = "sleep 10; ls -lah"; + final String command = "ls -lah"; final ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); final PrintStream stderr = new PrintStream(baos2); int result; -- 2.1.4