You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by ab...@apache.org on 2015/03/28 21:09:57 UTC

celix git commit: CELIX-230: * Updated command error handling * Updated activator error handling * Updated shell error handling

Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-230_Refactoring_of_the_shell_command_service 4d52743ee -> bafe2efb3


CELIX-230:
* Updated command error handling
* Updated activator error handling
* Updated shell error handling


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/bafe2efb
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/bafe2efb
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/bafe2efb

Branch: refs/heads/feature/CELIX-230_Refactoring_of_the_shell_command_service
Commit: bafe2efb37e8bad0d136cb6b17dd78c16af6de24
Parents: 4d52743
Author: Alexander Broekhuis <a....@gmail.com>
Authored: Sat Mar 28 21:09:53 2015 +0100
Committer: Alexander Broekhuis <a....@gmail.com>
Committed: Sat Mar 28 21:09:53 2015 +0100

----------------------------------------------------------------------
 framework/private/src/bundle_context.c |   3 +
 shell/private/include/shell_private.h  |  20 +-
 shell/private/include/std_commands.h   |   8 +-
 shell/private/src/activator.c          | 298 +++++++++++++++++---------
 shell/private/src/help_command.c       | 104 +++++----
 shell/private/src/log_command.c        |   3 +-
 shell/private/src/ps_command.c         | 219 +++++++++++--------
 shell/private/src/shell.c              | 319 +++++++++++++++++++---------
 shell/private/src/start_command.c      |  76 ++++---
 shell/private/src/stop_command.c       |  81 ++++---
 shell/public/include/command.h         |   4 +
 shell/public/include/shell.h           |   9 +-
 12 files changed, 737 insertions(+), 407 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/framework/private/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/framework/private/src/bundle_context.c b/framework/private/src/bundle_context.c
index be6333d..76e377f 100644
--- a/framework/private/src/bundle_context.c
+++ b/framework/private/src/bundle_context.c
@@ -278,6 +278,9 @@ celix_status_t bundleContext_getBundleById(bundle_context_pt context, long id, b
         status = CELIX_ILLEGAL_ARGUMENT;
     } else {
         *bundle = framework_getBundleById(context->framework, id);
+        if (*bundle == NULL) {
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
     }
 
     framework_logIfError(logger, status, NULL, "Failed to get bundle [id=%ld]", id);

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/include/shell_private.h
----------------------------------------------------------------------
diff --git a/shell/private/include/shell_private.h b/shell/private/include/shell_private.h
index 9734ad5..5761431 100644
--- a/shell/private/include/shell_private.h
+++ b/shell/private/include/shell_private.h
@@ -33,20 +33,18 @@
 #include "command.h"
 
 struct shell {
-	bundle_context_pt bundleContext;
-	hash_map_pt commandReferenceMap;
-	hash_map_pt commandNameMap;
+	bundle_context_pt bundle_context_ptr;
+	hash_map_pt command_reference_map_ptr;
+	hash_map_pt command_name_map_ptr;
 };
 
-celix_status_t shell_create(bundle_context_pt, shell_service_pt* shellService);
-celix_status_t shell_destroy(shell_service_pt* shellService);
-celix_status_t shell_addCommand(shell_pt shell, service_reference_pt reference);
+celix_status_t shell_create(bundle_context_pt context_ptr, shell_service_pt *shell_service_ptr);
+celix_status_t shell_destroy(shell_service_pt *shell_service_ptr);
+celix_status_t shell_addCommand(shell_pt shell_ptr, service_reference_pt reference_ptr);
+celix_status_t shell_removeCommand(shell_pt shell_ptr, service_reference_pt reference_ptr);
 
-
-char * shell_getCommandUsage(shell_pt shell, char * commandName);
-char * shell_getCommandDescription(shell_pt shell, char * commandName);
 celix_status_t shell_getCommandReference(shell_pt shell_ptr, char *command_name_str, service_reference_pt *command_reference_ptr);
-void shell_executeCommand(shell_pt shell, char * commandLine, void (*out)(char *), void (*error)(char *));
-void shell_serviceChanged(service_listener_pt listener, service_event_pt event);
+celix_status_t shell_executeCommand(shell_pt shell_ptr, char *command_line_str, void (*out)(char *), void (*error)(char *));
+celix_status_t shell_serviceChanged(service_listener_pt listener_ptr, service_event_pt event_ptr);
 
 #endif /* SHELL_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/include/std_commands.h
----------------------------------------------------------------------
diff --git a/shell/private/include/std_commands.h b/shell/private/include/std_commands.h
index cb7322c..ef7f37e 100644
--- a/shell/private/include/std_commands.h
+++ b/shell/private/include/std_commands.h
@@ -27,8 +27,12 @@
 #ifndef __STD_COMMANDS_H_
 #define __STD_COMMANDS_H_
 
-celix_status_t psCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
-celix_status_t startCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
+#include "celix_errno.h"
+
+#define OSGI_SHELL_COMMAND_SEPARATOR " "
+
+celix_status_t psCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr);
+celix_status_t startCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr);
 celix_status_t stopCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
 celix_status_t installCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
 celix_status_t uninstallCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/activator.c
----------------------------------------------------------------------
diff --git a/shell/private/src/activator.c b/shell/private/src/activator.c
index cfa8bb3..6915e82 100644
--- a/shell/private/src/activator.c
+++ b/shell/private/src/activator.c
@@ -51,143 +51,231 @@ struct bundle_instance {
 
 typedef struct bundle_instance *bundle_instance_pt;
 
-celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
-	celix_status_t status;
+celix_status_t bundleActivator_create(bundle_context_pt context_ptr, void **_pptr) {
+	celix_status_t status = CELIX_SUCCESS;
 
-	bundle_instance_pt bi = (bundle_instance_pt) calloc(1, sizeof(struct bundle_instance));
+    bundle_instance_pt instance_ptr = NULL;
 
-	if (!bi) {
-		status = CELIX_ENOMEM;
-	}
-	else if (userData == NULL) {
-		status = CELIX_ILLEGAL_ARGUMENT;
-		free(bi);
-	}
-	else {
-		status = shell_create(context, &bi->shellService);
-
-        bi->std_commands[0] = (struct command) {.exec = psCommand_execute, .name = "ps", .description = "list installed bundles.", .usage = "ps [-l | -s | -u]"};
-        bi->std_commands[1] = (struct command) {.exec = startCommand_execute, .name = "start", .description = "start bundle(s).", .usage = "start <id> [<id> ...]"};
-        bi->std_commands[2] = (struct command) {.exec = stopCommand_execute, .name = "stop", .description = "stop bundle(s).", .usage = "stop <id> [<id> ...]"};
-        bi->std_commands[3] = (struct command) {.exec = installCommand_execute, .name = "install", .description = "install bundle(s).", .usage = "install <file> [<file> ...]"};
-        bi->std_commands[4] = (struct command) {.exec = uninstallCommand_execute, .name = "uninstall", .description = "uninstall bundle(s).", .usage = "uninstall <file> [<file> ...]"};
-        bi->std_commands[5] = (struct command) {.exec = updateCommand_execute, .name = "update", .description = "update bundle(s).", .usage = "update <id> [<URL>]"};
-        bi->std_commands[6] = (struct command) {.exec = helpCommand_execute, .name = "help", .description = "display available commands and description.", .usage = "help <command>]"};
-        bi->std_commands[7] = (struct command) {.exec = logCommand_execute, .name = "log", .description = "print log.", .usage = "log"};
-        bi->std_commands[8] = (struct command) {.exec = inspectCommand_execute, .name = "inspect", .description = "inspect services and components.", .usage = "inspect (service) (capability|requirement) [<id> ...]"};
-        bi->std_commands[9] = (struct command) {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; /*marker for last element*/
-
-        int i = 0;
-        while (bi->std_commands[i].exec != NULL) {
-            bi->std_commands[i].props = properties_create();
-            if (bi->std_commands[i].props != NULL) {
-                    properties_set(bi->std_commands[i].props, "command.name", bi->std_commands[i].name);
-                    properties_set(bi->std_commands[i].props, "command.usage", bi->std_commands[i].usage);
-                    properties_set(bi->std_commands[i].props, "command.description", bi->std_commands[i].description);
-
-                    bi->std_commands[i].service = calloc(1, sizeof(struct commandService));
-                    if (bi->std_commands[i].service != NULL) {
-                        bi->std_commands[i].service->handle = context;
-                        bi->std_commands[i].service->executeCommand = bi->std_commands[i].exec;
-                    } else {
-                            status = CELIX_ENOMEM;
-                            break;
-                    }
-            } else {
-                    status = CELIX_ENOMEM;
-                    break;
+    if (!_pptr || !context_ptr) {
+        status = CELIX_ENOMEM;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        instance_ptr = (bundle_instance_pt) calloc(1, sizeof(struct bundle_instance));
+        if (!instance_ptr) {
+            status = CELIX_ENOMEM;
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+        status = shell_create(context_ptr, &instance_ptr->shellService);
+    }
+
+    if (status == CELIX_SUCCESS) {
+        instance_ptr->std_commands[0] =
+                (struct command) {
+                        .exec = psCommand_execute,
+                        .name = "ps",
+                        .description = "list installed bundles.",
+                        .usage = "ps [-l | -s | -u]"
+                };
+        instance_ptr->std_commands[1] =
+                (struct command) {
+                        .exec = startCommand_execute,
+                        .name = "start",
+                        .description = "start bundle(s).",
+                        .usage = "start <id> [<id> ...]"
+                };
+        instance_ptr->std_commands[2] =
+                (struct command) {
+                        .exec = stopCommand_execute,
+                        .name = "stop",
+                        .description = "stop bundle(s).",
+                        .usage = "stop <id> [<id> ...]"
+                };
+        instance_ptr->std_commands[3] =
+                (struct command) {
+                        .exec = installCommand_execute,
+                        .name = "install",
+                        .description = "install bundle(s).",
+                        .usage = "install <file> [<file> ...]"
+                };
+        instance_ptr->std_commands[4] =
+                (struct command) {
+                        .exec = uninstallCommand_execute,
+                        .name = "uninstall",
+                        .description = "uninstall bundle(s).",
+                        .usage = "uninstall <file> [<file> ...]"
+                };
+        instance_ptr->std_commands[5] =
+                (struct command) {
+                        .exec = updateCommand_execute,
+                        .name = "update",
+                        .description = "update bundle(s).",
+                        .usage = "update <id> [<URL>]"
+                };
+        instance_ptr->std_commands[6] =
+                (struct command) {
+                        .exec = helpCommand_execute,
+                        .name = "help",
+                        .description = "display available commands and description.",
+                        .usage = "help <command>]"
+                };
+        instance_ptr->std_commands[7] =
+                (struct command) {
+                        .exec = logCommand_execute,
+                        .name = "log",
+                        .description = "print log.",
+                        .usage = "log"
+                };
+        instance_ptr->std_commands[8] =
+                (struct command) {
+                        .exec = inspectCommand_execute,
+                        .name = "inspect",
+                        .description = "inspect services and components.",
+                        .usage = "inspect (service) (capability|requirement) [<id> ...]"
+                };
+        instance_ptr->std_commands[9] =
+                (struct command) { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /*marker for last element*/
+
+        unsigned int i = 0;
+        while (instance_ptr->std_commands[i].exec != NULL) {
+            instance_ptr->std_commands[i].props = properties_create();
+            if (!instance_ptr->std_commands[i].props) {
+                status = CELIX_BUNDLE_EXCEPTION;
+                break;
             }
-              
+
+            properties_set(instance_ptr->std_commands[i].props, OSGI_SHELL_COMMAND_NAME, instance_ptr->std_commands[i].name);
+            properties_set(instance_ptr->std_commands[i].props, OSGI_SHELL_COMMAND_USAGE, instance_ptr->std_commands[i].usage);
+            properties_set(instance_ptr->std_commands[i].props, OSGI_SHELL_COMMAND_DESCRIPTION, instance_ptr->std_commands[i].description);
+
+            instance_ptr->std_commands[i].service = calloc(1, sizeof(*instance_ptr->std_commands[i].service));
+            if (!instance_ptr->std_commands[i].service) {
+                status = CELIX_ENOMEM;
+                break;
+            }
+
+            instance_ptr->std_commands[i].service->handle = context_ptr;
+            instance_ptr->std_commands[i].service->executeCommand = instance_ptr->std_commands[i].exec;
+
             i += 1;
+        }
     }
 
-		if (status != CELIX_SUCCESS) {
-			printf("shell_create failed\n");
-		}
+    if (status == CELIX_SUCCESS) {
+        *_pptr = instance_ptr;
+    }
 
-		(*userData) = bi;
-	}
+
+    if (status != CELIX_SUCCESS) {
+        bundleActivator_destroy(instance_ptr, context_ptr);
+    }
 
 	return status;
 }
 
-celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
-	celix_status_t status;
-	bundle_instance_pt bi = (bundle_instance_pt) userData;
+celix_status_t bundleActivator_start(void *_ptr, bundle_context_pt context_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
 
-	status = bundleContext_registerService(context, (char *) OSGI_SHELL_SERVICE_NAME, bi->shellService, NULL, &bi->registration);
+	bundle_instance_pt instance_ptr  = (bundle_instance_pt) _ptr;
+    array_list_pt references_ptr     = NULL;
+    service_listener_pt listener_ptr = NULL;
 
-	if (status == CELIX_SUCCESS) {
-		array_list_pt references = NULL;
-		service_listener_pt listener = (service_listener_pt) calloc(1, sizeof(*listener));
+    if (!instance_ptr || !context_ptr) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
 
-		bi->listener = listener;
-		listener->handle = bi->shellService->shell;
-		listener->serviceChanged = (void *) shell_serviceChanged;
+    if (status == CELIX_SUCCESS) {
+        status = bundleContext_registerService(context_ptr, (char *) OSGI_SHELL_SERVICE_NAME, instance_ptr->shellService, NULL, &instance_ptr->registration);
+    }
 
-		status = bundleContext_addServiceListener(context, listener, "(objectClass=commandService)");
-		status = bundleContext_getServiceReferences(context, "commandService", NULL, &references);
+	if (status == CELIX_SUCCESS) {
+        listener_ptr = (service_listener_pt) calloc(1, sizeof(*listener_ptr));
+        if (!listener_ptr) {
+            status = CELIX_ENOMEM;
+        }
+    }
 
-		if (status == CELIX_SUCCESS) {
-			int i = 0;
+    if (status == CELIX_SUCCESS) {
+        instance_ptr->listener = listener_ptr;
+        listener_ptr->handle = instance_ptr->shellService->shell;
+        listener_ptr->serviceChanged = (void *) shell_serviceChanged;
+
+        status = bundleContext_addServiceListener(context_ptr, listener_ptr, "(objectClass=commandService)");
+    }
 
-			for (i = 0; i < arrayList_size(references); i++) {
-				shell_addCommand(bi->shellService->shell, arrayList_get(references, i));
-			}
-		}
+    if (status == CELIX_SUCCESS) {
+        status = bundleContext_getServiceReferences(context_ptr, "commandService", NULL, &references_ptr);
+    }
 
-		if (status == CELIX_SUCCESS) {
+    if (status == CELIX_SUCCESS) {
+        for (unsigned int i = 0; i < arrayList_size(references_ptr); i++) {
+            shell_addCommand(instance_ptr->shellService->shell, arrayList_get(references_ptr, i));
+        }
+    }
 
-            int i = 0;
-            while (bi->std_commands[i].exec != NULL) {
-                    status = bundleContext_registerService(context, (char *)OSGI_SHELL_COMMAND_SERVICE_NAME, bi->std_commands[i].service, bi->std_commands[i].props, &bi->std_commands[i].reg);
-                    if (status != CELIX_SUCCESS) {
-                            break;
-                    }
-                    i += 1;
+    if (status == CELIX_SUCCESS) {
+        for (unsigned int i = 0; instance_ptr->std_commands[i].exec != NULL; i++) {
+            status = bundleContext_registerService(context_ptr, (char *) OSGI_SHELL_COMMAND_SERVICE_NAME,
+                                                   instance_ptr->std_commands[i].service,
+                                                   instance_ptr->std_commands[i].props,
+                                                   &instance_ptr->std_commands[i].reg);
+            if (status != CELIX_SUCCESS) {
+                break;
             }
 
-		}
-		arrayList_destroy(references);
+        }
+		arrayList_destroy(references_ptr);
 	}
 
+    if (status != CELIX_SUCCESS) {
+        bundleActivator_stop(_ptr, context_ptr);
+    }
+
 	return status;
 }
 
-celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
-	celix_status_t status;
-	bundle_instance_pt bi = (bundle_instance_pt) userData;
-
-            int i = 0;
-            while (bi->std_commands[i].exec != NULL) {
-                    if (bi->std_commands[i].reg!= NULL) {
-                            serviceRegistration_unregister(bi->std_commands[i].reg);
-                        bi->std_commands[i].reg = NULL;
-                        bi->std_commands[i].props = NULL;
-                    }
-                    i += 1;
+celix_status_t bundleActivator_stop(void *_ptr, bundle_context_pt context_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+    celix_status_t sub_status;
+
+	bundle_instance_pt instance_ptr = (bundle_instance_pt) _ptr;
+
+    if (instance_ptr) {
+        for (unsigned int i = 0; instance_ptr->std_commands[i].exec != NULL; i++) {
+            if (instance_ptr->std_commands[i].reg != NULL) {
+                status = serviceRegistration_unregister(instance_ptr->std_commands[i].reg);
+                instance_ptr->std_commands[i].reg = NULL;
+                instance_ptr->std_commands[i].props = NULL;
             }
+        }
+    }
 
-	status = bundleContext_removeServiceListener(context, bi->listener);
+	sub_status = bundleContext_removeServiceListener(context_ptr, instance_ptr->listener);
+    if (status == CELIX_SUCCESS && sub_status != CELIX_SUCCESS) {
+        status = sub_status;
+    }
 
 	return status;
 }
 
-celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
-	bundle_instance_pt bi = (bundle_instance_pt) userData;
-
-  int i = 0;
-  while (bi->std_commands[i].exec != NULL) {
-          if (bi->std_commands[i].props != NULL) {
-                  properties_destroy(bi->std_commands[i].props);
-          } 
-          if (bi->std_commands[i].service != NULL) {
-                  free(bi->std_commands[i].service);
-          }
-          i += 1;
-  }
-
-    free(bi);
+celix_status_t bundleActivator_destroy(void *_ptr, bundle_context_pt __attribute__((__unused__)) context_ptr) {
+    bundle_instance_pt instance_ptr = (bundle_instance_pt) _ptr;
+
+    if (instance_ptr) {
+        for (unsigned int i = 0; instance_ptr->std_commands[i].exec != NULL; i++) {
+            free(instance_ptr->std_commands[i].service);
+
+            if (instance_ptr->std_commands[i].props != NULL) {
+                properties_destroy(instance_ptr->std_commands[i].props);
+            }
+        }
+    }
+
+    shell_destroy(&instance_ptr->shellService);
+
+    free(instance_ptr);
 
 	return CELIX_SUCCESS;
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/help_command.c
----------------------------------------------------------------------
diff --git a/shell/private/src/help_command.c b/shell/private/src/help_command.c
index 75be274..78b6b01 100644
--- a/shell/private/src/help_command.c
+++ b/shell/private/src/help_command.c
@@ -29,56 +29,88 @@
 #include "array_list.h"
 #include "bundle_context.h"
 #include "shell.h"
+#include "std_commands.h"
 
-celix_status_t helpCommand_execute(void *handle, char * line, FILE *outStream, FILE *errStream) {
-	bundle_context_pt context = handle;
-	service_reference_pt shellService = NULL;
-	bundleContext_getServiceReference(context, (char *) OSGI_SHELL_SERVICE_NAME, &shellService);
+celix_status_t helpCommand_execute(void *_ptr, char *line_str, FILE *out_ptr, FILE *err_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
 
-	if (shellService != NULL) {
-		shell_service_pt shell = NULL;
-		bundleContext_getService(context, shellService, (void **) &shell);
+	bundle_context_pt context_ptr = _ptr;
+	service_reference_pt shell_service_reference_ptr = NULL;
+	shell_service_pt shell_ptr = NULL;
 
-		if (shell != NULL) {
-			char delims[] = " ";
-			char * sub = NULL;
-			char *save_ptr = NULL;
+	if (!context_ptr || !line_str || !out_ptr || !err_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_getServiceReference(context_ptr, (char *) OSGI_SHELL_SERVICE_NAME, &shell_service_reference_ptr);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_getService(context_ptr, shell_service_reference_ptr, (void **) &shell_ptr);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		uint32_t out_len = 256;
+		char *sub = NULL;
+		char *save_ptr = NULL;
+		char out_str[out_len];
+
+		memset(out_str, 0, sizeof(out_str));
+
+		strtok_r(line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+		sub = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
 
-			sub = strtok_r(line, delims, &save_ptr);
-			sub = strtok_r(NULL, delims, &save_ptr);
+		if (sub == NULL) {
+			unsigned int i;
+			array_list_pt commands = NULL;
 
-			if (sub == NULL) {
-				int i;
-				array_list_pt commands = shell->getCommands(shell->shell);
+			status = shell_ptr->getCommands(shell_ptr->shell, &commands);
+			for (i = 0; i < arrayList_size(commands); i++) {
+				char *name = arrayList_get(commands, i);
+				fprintf(out_ptr, "%s\n", name);
+			}
+			fprintf(out_ptr, "\nUse 'help <command-name>' for more information.\n");
+		} else {
+			bool found = false;
+			while (sub != NULL) {
+				unsigned int i;
+				array_list_pt commands = NULL;
+				status = shell_ptr->getCommands(shell_ptr->shell, &commands);
 				for (i = 0; i < arrayList_size(commands); i++) {
 					char *name = arrayList_get(commands, i);
-					fprintf(outStream, "%s\n", name);
-				}
-				fprintf(outStream, "\nUse 'help <command-name>' for more information.\n");
-			} else {
-				bool found = false;
-				while (sub != NULL) {
-					int i;
-					array_list_pt commands = shell->getCommands(shell->shell);
-					for (i = 0; i < arrayList_size(commands); i++) {
-						char *name = arrayList_get(commands, i);
-						if (strcmp(sub, name) == 0) {
-							char *desc = shell->getCommandDescription(shell->shell, name);
-							char *usage = shell->getCommandUsage(shell->shell, name);
+					if (strcmp(sub, name) == 0) {
+						celix_status_t sub_status_desc;
+						celix_status_t sub_status_usage;
+
+						char *usage_str = NULL;
+						char *desc_str = NULL;
+
+						sub_status_desc = shell_ptr->getCommandDescription(shell_ptr->shell, name, &desc_str);
+						sub_status_usage = shell_ptr->getCommandUsage(shell_ptr->shell, name, &usage_str);
 
+						if (sub_status_usage == CELIX_SUCCESS && sub_status_desc == CELIX_SUCCESS) {
 							if (found) {
-								fprintf(outStream, "---\n");
+								fprintf(out_ptr, "---\n");
 							}
 							found = true;
-							fprintf(outStream, "Command     : %s\n", name);
-							fprintf(outStream, "Usage       : %s\n", usage);
-							fprintf(outStream, "Description : %s\n", desc);
+							fprintf(out_ptr, "Command     : %s\n", name);
+							fprintf(out_ptr, "Usage       : %s\n", usage_str);
+							fprintf(out_ptr, "Description : %s\n", desc_str);
+						}
+
+						if (sub_status_desc != CELIX_SUCCESS && status == CELIX_SUCCESS) {
+							status = sub_status_desc;
+						}
+						if (sub_status_usage != CELIX_SUCCESS && status == CELIX_SUCCESS) {
+							status = sub_status_usage;
 						}
 					}
-					sub = strtok_r(NULL, delims, &save_ptr);
 				}
+				sub = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
 			}
 		}
 	}
-	return CELIX_SUCCESS;
-}
+
+	return status;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/log_command.c
----------------------------------------------------------------------
diff --git a/shell/private/src/log_command.c b/shell/private/src/log_command.c
index 95679ca..a1f77c1 100644
--- a/shell/private/src/log_command.c
+++ b/shell/private/src/log_command.c
@@ -52,7 +52,8 @@ void logCommand_execute(bundle_context_pt context, char *line, FILE *outStream,
 			char *level = NULL;
 			char errorString[256];
 
-			logCommand_levelAsString(context, entry->level, &level);
+            strftime(time, 20, "%Y-%m-%d %H:%M:%S", localtime(&entry->time));
+            logCommand_levelAsString(context, entry->level, &level);
 
 			if (entry->errorCode > 0) {
 				celix_strerror(entry->errorCode, errorString, 256);

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/ps_command.c
----------------------------------------------------------------------
diff --git a/shell/private/src/ps_command.c b/shell/private/src/ps_command.c
index ce84e99..fca93de 100644
--- a/shell/private/src/ps_command.c
+++ b/shell/private/src/ps_command.c
@@ -33,112 +33,149 @@
 
 static char * psCommand_stateString(bundle_state_e state); 
 
-celix_status_t psCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream) {
-        celix_status_t status = CELIX_SUCCESS;
-        array_list_pt bundles = NULL;
-        bundle_context_pt context = handle;
+celix_status_t psCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr) {
+    celix_status_t status = CELIX_SUCCESS;
 
-        status = bundleContext_getBundles(context, &bundles);
+    bundle_context_pt context_ptr = _ptr;
+    array_list_pt bundles_ptr     = NULL;
 
-        bool showLocation = false;
-        bool showSymbolicName = false;
-        bool showUpdateLocation = false;
-        char * msg = "Name";
-        unsigned int i;
+    bool show_location        = false;
+    bool show_symbolic_name   = false;
+    bool show_update_location = false;
+    char *message_str         = "Name";
 
-        char delims[] = " ";
-        char * sub = NULL;
+    if (!context_ptr || !command_line_str || !out_ptr || !err_ptr) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        status = bundleContext_getBundles(context_ptr, &bundles_ptr);
+    }
+
+    if (status == CELIX_SUCCESS) {
+        char *sub_str = NULL;
         char *save_ptr = NULL;
-        sub = strtok_r(commandline, delims, &save_ptr);
-        sub = strtok_r(NULL, delims, &save_ptr);
-        while (sub != NULL) {
-                if (strcmp(sub, "-l") == 0) {
-                        showLocation = true;
-                        msg = "Location";
-                } else if (strcmp(sub, "-s") == 0) {
-                        showSymbolicName = true;
-                        msg = "Symbolic name";
-                } else if (strcmp(sub, "-u") == 0) {
-                        showUpdateLocation = true;
-                        msg = "Update location";
-                }
-                sub = strtok_r(NULL, delims, &save_ptr);
+
+        strtok_r(command_line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+        sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+        while (sub_str != NULL) {
+            if (strcmp(sub_str, "-l") == 0) {
+                show_location = true;
+                message_str = "Location";
+            } else if (strcmp(sub_str, "-s") == 0) {
+                show_symbolic_name = true;
+                message_str = "Symbolic name";
+            } else if (strcmp(sub_str, "-u") == 0) {
+                show_update_location = true;
+                message_str = "Update location";
+            }
+            sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
         }
 
-        fprintf(outStream, "  %-5s %-12s %s\n", "ID", "State", msg);
+        fprintf(out_ptr, "  %-5s %-12s %s\n", "ID", "State", message_str);
+
+        unsigned int size = arrayList_size(bundles_ptr);
+        bundle_pt bundles_array_ptr[size];
 
-        unsigned int size = arrayList_size(bundles);
-        bundle_pt bundlesA[size];
-        for (i = 0; i < size; i++) {
-                bundlesA[i] = arrayList_get(bundles, i);
+        for (unsigned int i = 0; i < size; i++) {
+            bundles_array_ptr[i] = arrayList_get(bundles_ptr, i);
         }
 
-        int j;
-        for(i=0; i < size - 1; i++) {
-                for(j=i+1; j < size; j++) {
-                        bundle_pt first = bundlesA[i];
-                        bundle_pt second = bundlesA[j];
-
-                        bundle_archive_pt farchive = NULL, sarchive = NULL;
-                        long fid, sid;
-
-                        bundle_getArchive(first, &farchive);
-                        bundleArchive_getId(farchive, &fid);
-                        bundle_getArchive(second, &sarchive);
-                        bundleArchive_getId(sarchive, &sid);
-
-                        if(fid > sid)
-                        {
-                                // these three lines swap the elements bundles[i] and bundles[j].
-                                bundle_pt temp = bundlesA[i];
-                                bundlesA[i] = bundlesA[j];
-                                bundlesA[j] = temp;
-                        }
+        for (unsigned int i = 0; i < size - 1; i++) {
+            for (unsigned int j = i + 1; j < size; j++) {
+                bundle_pt first_ptr = bundles_array_ptr[i];
+                bundle_pt second_ptr = bundles_array_ptr[j];
+
+                bundle_archive_pt first_archive_ptr = NULL;
+                bundle_archive_pt second_archive_ptr = NULL;
+
+                long first_id;
+                long second_id;
+
+                bundle_getArchive(first_ptr, &first_archive_ptr);
+                bundle_getArchive(second_ptr, &second_archive_ptr);
+
+                bundleArchive_getId(first_archive_ptr, &first_id);
+                bundleArchive_getId(second_archive_ptr, &second_id);
+
+                if (first_id > second_id) {
+                    bundle_pt temp_ptr = bundles_array_ptr[i];
+                    bundles_array_ptr[i] = bundles_array_ptr[j];
+                    bundles_array_ptr[j] = temp_ptr;
                 }
+            }
         }
-        for (i = 0; i < size; i++) {
-                //bundle_pt bundle = (bundle_pt) arrayList_get(bundles, i);
-                bundle_pt bundle = bundlesA[i];
-                bundle_archive_pt archive = NULL;
-                long id;
-                bundle_state_e state;
-                char * stateString = NULL;
-                module_pt module = NULL;
-                char * name = NULL;
-
-                bundle_getArchive(bundle, &archive);
-                bundleArchive_getId(archive, &id);
-                bundle_getState(bundle, &state);
-                stateString = psCommand_stateString(state);
-                bundle_getCurrentModule(bundle, &module);
-                module_getSymbolicName(module, &name);
-                if (showLocation) {
-                        bundleArchive_getLocation(archive, &name);
-                } else if (showSymbolicName) {
-                        // do nothing
-                } else if (showUpdateLocation) {
-                        bundleArchive_getLocation(archive, &name);
+
+        for (unsigned int i = 0; i < size - 1; i++) {
+            celix_status_t sub_status;
+
+            bundle_pt bundle_ptr = bundles_array_ptr[i];
+
+            bundle_archive_pt archive_ptr = NULL;
+            long id = 0;
+            bundle_state_e state = OSGI_FRAMEWORK_BUNDLE_UNKNOWN;
+            char *state_str = NULL;
+            module_pt module_ptr = NULL;
+            char *name_str = NULL;
+
+            sub_status = bundle_getArchive(bundle_ptr, &archive_ptr);
+            if (sub_status == CELIX_SUCCESS) {
+                sub_status = bundleArchive_getId(archive_ptr, &id);
+            }
+
+            if (sub_status == CELIX_SUCCESS) {
+                sub_status = bundle_getState(bundle_ptr, &state);
+            }
+
+            if (sub_status == CELIX_SUCCESS) {
+                state_str = psCommand_stateString(state);
+
+                sub_status = bundle_getCurrentModule(bundle_ptr, &module_ptr);
+            }
+
+            if (sub_status == CELIX_SUCCESS) {
+                sub_status = module_getSymbolicName(module_ptr, &name_str);
+            }
+
+            if (sub_status == CELIX_SUCCESS) {
+                if (show_location) {
+                    sub_status = bundleArchive_getLocation(archive_ptr, &name_str);
+                } else if (show_symbolic_name) {
+                    // do nothing
+                } else if (show_update_location) {
+                    sub_status = bundleArchive_getLocation(archive_ptr, &name_str);
                 }
+            }
+
+            if (sub_status == CELIX_SUCCESS) {
+                fprintf(out_ptr, "  %-5ld %-12s %s\n", id, state_str, name_str);
+            }
 
-                fprintf(outStream, "  %-5ld %-12s %s\n", id, stateString, name);
+            if (sub_status != CELIX_SUCCESS) {
+                status = sub_status;
+                break;
+            }
         }
-        arrayList_destroy(bundles);
-        return status;
+
+        arrayList_destroy(bundles_ptr);
+    }
+
+    return status;
 }
 
 static char * psCommand_stateString(bundle_state_e state) {
-	switch (state) {
-		case OSGI_FRAMEWORK_BUNDLE_ACTIVE:
-			return "Active      ";
-		case OSGI_FRAMEWORK_BUNDLE_INSTALLED:
-			return "Installed   ";
-		case OSGI_FRAMEWORK_BUNDLE_RESOLVED:
-			return "Resolved    ";
-		case OSGI_FRAMEWORK_BUNDLE_STARTING:
-			return "Starting    ";
-		case OSGI_FRAMEWORK_BUNDLE_STOPPING:
-			return "Stopping    ";
-		default:
-			return "Unknown     ";
-	}
+    switch (state) {
+        case OSGI_FRAMEWORK_BUNDLE_ACTIVE:
+            return "Active      ";
+        case OSGI_FRAMEWORK_BUNDLE_INSTALLED:
+            return "Installed   ";
+        case OSGI_FRAMEWORK_BUNDLE_RESOLVED:
+            return "Resolved    ";
+        case OSGI_FRAMEWORK_BUNDLE_STARTING:
+            return "Starting    ";
+        case OSGI_FRAMEWORK_BUNDLE_STOPPING:
+            return "Stopping    ";
+        default:
+            return "Unknown     ";
+    }
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/shell.c
----------------------------------------------------------------------
diff --git a/shell/private/src/shell.c b/shell/private/src/shell.c
index 3500d89..03c30da 100644
--- a/shell/private/src/shell.c
+++ b/shell/private/src/shell.c
@@ -29,122 +29,229 @@
 #include "celix_errno.h"
 
 #include "shell_private.h"
-#include "bundle_activator.h"
-#include "bundle_context.h"
-#include "service_registration.h"
-#include "service_listener.h"
 
 #include "utils.h"
 
-static command_service_pt shell_getCommand(shell_pt shell, char * commandName);
-array_list_pt shell_getCommands(shell_pt shell);
+celix_status_t shell_getCommands(shell_pt shell_ptr, array_list_pt *commands_ptr);
+celix_status_t shell_getCommandUsage(shell_pt shell_ptr, char *command_name_str, char **usage_pstr);
+celix_status_t shell_getCommandDescription(shell_pt shell_ptr, char *command_name_str, char **command_description_pstr);
 
-celix_status_t shell_create(bundle_context_pt context, shell_service_pt* shellService) {
-	celix_status_t status = CELIX_ENOMEM;
+celix_status_t shell_create(bundle_context_pt context_ptr, shell_service_pt *shell_service_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
 
-	shell_service_pt lclService = (shell_service_pt) calloc(1, sizeof(struct shellService));
-	shell_pt lclShell = (shell_pt) calloc(1, sizeof(struct shell));
+	if (!context_ptr || !shell_service_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
 
-	if (lclService && lclShell) {
-		lclShell->bundleContext = context;
-		lclShell->commandNameMap = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-		lclShell->commandReferenceMap = hashMap_create(NULL, NULL, NULL, NULL);
-		lclService->shell = lclShell;
+	if (status == CELIX_SUCCESS) {
+		*shell_service_ptr =  calloc(1, sizeof(**shell_service_ptr));
+		if (!*shell_service_ptr) {
+			status = CELIX_ENOMEM;
+		}
+	}
 
-		lclService->getCommands = shell_getCommands;
-		lclService->getCommandDescription = shell_getCommandDescription;
-		lclService->getCommandUsage = shell_getCommandUsage;
-		lclService->getCommandReference = shell_getCommandReference;
-		lclService->executeCommand = shell_executeCommand;
+	if (status == CELIX_SUCCESS) {
+		(*shell_service_ptr)->shell = calloc(1, sizeof(*(*shell_service_ptr)->shell));
+		if (!(*shell_service_ptr)->shell) {
+			status = CELIX_ENOMEM;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		(*shell_service_ptr)->shell->bundle_context_ptr = context_ptr;
+		(*shell_service_ptr)->shell->command_name_map_ptr = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+		(*shell_service_ptr)->shell->command_reference_map_ptr = hashMap_create(NULL, NULL, NULL, NULL);
+
+		(*shell_service_ptr)->getCommands = shell_getCommands;
+		(*shell_service_ptr)->getCommandDescription = shell_getCommandDescription;
+		(*shell_service_ptr)->getCommandUsage = shell_getCommandUsage;
+		(*shell_service_ptr)->getCommandReference = shell_getCommandReference;
+		(*shell_service_ptr)->executeCommand = shell_executeCommand;
+	}
 
-		*shellService = lclService;
-		status = CELIX_SUCCESS;
+	if (status != CELIX_SUCCESS) {
+		shell_destroy(shell_service_ptr);
 	}
 
 	return status;
 }
 
-celix_status_t shell_destroy(shell_service_pt* shellService) {
+celix_status_t shell_destroy(shell_service_pt *shell_service_ptr) {
 	celix_status_t status = CELIX_SUCCESS;
 
-	hashMap_destroy((*shellService)->shell->commandNameMap, false, false);
-	hashMap_destroy((*shellService)->shell->commandReferenceMap, false, false);
+	if (!shell_service_ptr || !*shell_service_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
 
-	free((*shellService)->shell);
-	free(*shellService);
+	if (status == CELIX_SUCCESS) {
+		if ((*shell_service_ptr)->shell) {
+			if ((*shell_service_ptr)->shell->command_name_map_ptr) {
+				hashMap_destroy((*shell_service_ptr)->shell->command_name_map_ptr, false, false);
+			}
+			if ((*shell_service_ptr)->shell->command_reference_map_ptr) {
+				hashMap_destroy((*shell_service_ptr)->shell->command_reference_map_ptr, false, false);
+			}
+			free((*shell_service_ptr)->shell);
+			(*shell_service_ptr)->shell = NULL;
+		}
+		free(*shell_service_ptr);
+		*shell_service_ptr = NULL;
+	}
 
 	return status;
 }
 
-celix_status_t shell_addCommand(shell_pt shell, service_reference_pt reference) {
+celix_status_t shell_addCommand(shell_pt shell_ptr, service_reference_pt reference_ptr) {
 	celix_status_t status = CELIX_SUCCESS;
+	command_service_pt command_ptr = NULL;
+	char *name_str = NULL;
+
+	if (!shell_ptr && !reference_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_getService(shell_ptr->bundle_context_ptr, reference_ptr, (void **) &command_ptr);
+		if (!command_ptr) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceReference_getProperty(reference_ptr, "command.name", &name_str);
+		if (!name_str) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		hashMap_put(shell_ptr->command_name_map_ptr, name_str, command_ptr);
+		hashMap_put(shell_ptr->command_reference_map_ptr, reference_ptr, command_ptr);
+	}
 
-	command_service_pt command = NULL;
-	void *cmd = NULL;
-    char *name = NULL;
-	bundleContext_getService(shell->bundleContext, reference, &cmd);
-  serviceReference_getProperty(reference, "command.name", &name);
-	command = (command_service_pt) cmd;
-    if (name != NULL) {
-	    hashMap_put(shell->commandNameMap, name, command);
-	    hashMap_put(shell->commandReferenceMap, reference, command);
-    } else {
-            status = CELIX_ILLEGAL_ARGUMENT;
-            fprintf(stderr, "TODO\n");
-            //TODO log to log service
-    }
+	if (status != CELIX_SUCCESS) {
+		shell_removeCommand(shell_ptr, reference_ptr);
+		fprintf(stderr, "Could not add Command. TODO\n");
+		//TODO log to log service
+	}
 
 	return status;
 }
 
-celix_status_t shell_removeCommand(shell_pt shell, service_reference_pt reference) {
+celix_status_t shell_removeCommand(shell_pt shell_ptr, service_reference_pt reference_ptr) {
 	celix_status_t status = CELIX_SUCCESS;
 
-	command_service_pt command = (command_service_pt) hashMap_remove(shell->commandReferenceMap, reference);
-    char *name = NULL;
-    serviceReference_getProperty(reference, "command.name", &name);
-	if (command != NULL && name != NULL) {
-		bool result = false;
-		hashMap_remove(shell->commandNameMap, name);
-		bundleContext_ungetService(shell->bundleContext, reference, &result);
-	} 
+	command_service_pt command_ptr = NULL;
+	char *name_str = NULL;
+
+	if (!shell_ptr || !reference_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		command_ptr = hashMap_remove(shell_ptr->command_reference_map_ptr, reference_ptr);
+		if (!command_ptr) {
+			status = CELIX_ILLEGAL_ARGUMENT;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceReference_getProperty(reference_ptr, "command.name", &name_str);
+		if (!name_str) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		hashMap_remove(shell_ptr->command_name_map_ptr, name_str);
+	}
+
+	celix_status_t sub_status = bundleContext_ungetService(shell_ptr->bundle_context_ptr, reference_ptr, NULL);
+	if (sub_status != CELIX_SUCCESS && status == CELIX_SUCCESS) {
+		status = sub_status;
+	}
+
+	sub_status = bundleContext_ungetServiceReference(shell_ptr->bundle_context_ptr, reference_ptr);
+	if (sub_status != CELIX_SUCCESS && status == CELIX_SUCCESS) {
+		status = sub_status;
+	}
 
 	return status;
 }
 
-array_list_pt shell_getCommands(shell_pt shell) {
-	array_list_pt commands = NULL;
-	hash_map_iterator_pt iter = hashMapIterator_create(shell->commandNameMap);
+celix_status_t shell_getCommands(shell_pt shell_ptr, array_list_pt *commands_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	hash_map_iterator_pt iter = NULL;
 
-	arrayList_create(&commands);
-	while (hashMapIterator_hasNext(iter)) {
-		char * name = hashMapIterator_nextKey(iter);
-		arrayList_add(commands, name);
+	if (!shell_ptr || !commands_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
 	}
-	hashMapIterator_destroy(iter);
-	return commands;
+
+	if (status == CELIX_SUCCESS) {
+		iter = hashMapIterator_create(shell_ptr->command_name_map_ptr);
+		if (!iter) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		arrayList_create(commands_ptr);
+		while (hashMapIterator_hasNext(iter)) {
+			char *name_str = hashMapIterator_nextKey(iter);
+			arrayList_add(*commands_ptr, name_str);
+		}
+		hashMapIterator_destroy(iter);
+	}
+
+	return status;
 }
 
-char * shell_getCommandUsage(shell_pt shell, char * commandName) {
-	char *usage = NULL;
+
+celix_status_t shell_getCommandUsage(shell_pt shell_ptr, char *command_name_str, char **usage_pstr) {
+	celix_status_t status = CELIX_SUCCESS;
+
 	service_reference_pt reference = NULL;
-	shell_getCommandReference(shell, commandName, &reference);
-	if (reference) {
-		serviceReference_getProperty(reference, "command.usage", &usage);
+
+	if (!shell_ptr || !command_name_str || !usage_pstr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
 	}
 
-	return usage;
+	if (status == CELIX_SUCCESS) {
+		status = shell_getCommandReference(shell_ptr, command_name_str, &reference);
+		if (!reference) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceReference_getProperty(reference, "command.usage", usage_pstr);
+	}
+
+	return status;
 }
 
-char * shell_getCommandDescription(shell_pt shell, char * commandName) {
-	char *description = NULL;
+celix_status_t shell_getCommandDescription(shell_pt shell_ptr, char *command_name_str, char **command_description_pstr) {
+	celix_status_t status = CELIX_SUCCESS;
+
 	service_reference_pt reference = NULL;
-	shell_getCommandReference(shell, commandName, &reference);
-	if (reference) {
-		serviceReference_getProperty(reference, "command.description", &description);
+
+	if (!shell_ptr || !command_name_str || !command_description_pstr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
 	}
 
-	return description;
+	if (status == CELIX_SUCCESS) {
+		status = shell_getCommandReference(shell_ptr, command_name_str, &reference);
+		if (!reference) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		serviceReference_getProperty(reference, "command.description", command_description_pstr);
+	}
+
+	return status;
 }
 
 celix_status_t shell_getCommandReference(shell_pt shell_ptr, char *command_name_str, service_reference_pt *command_reference_ptr) {
@@ -156,7 +263,7 @@ celix_status_t shell_getCommandReference(shell_pt shell_ptr, char *command_name_
 
 	if (status == CELIX_SUCCESS) {
 		*command_reference_ptr = NULL;
-		hash_map_iterator_pt iter = hashMapIterator_create(shell_ptr->commandReferenceMap);
+		hash_map_iterator_pt iter = hashMapIterator_create(shell_ptr->command_reference_map_ptr);
 		while (hashMapIterator_hasNext(iter)) {
 			hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 			service_reference_pt reference = hashMapEntry_getKey(entry);
@@ -173,32 +280,52 @@ celix_status_t shell_getCommandReference(shell_pt shell_ptr, char *command_name_
 	return status;
 }
 
-void shell_executeCommand(shell_pt shell, char * commandLine, void (*out)(char *), void (*error)(char *)) {
-	unsigned int pos = strcspn(commandLine, " ");
-	char * commandName = (pos != strlen(commandLine)) ? string_ndup((char *) commandLine, pos) : strdup(commandLine);
-	command_service_pt command = shell_getCommand(shell, commandName);
-	if (command != NULL) {
-            printf("TODO\n");
-            //FIXME udpate shell_executeCommand with FILE
-		    //command->executeCommand(command->command, commandLine, out, error);
-            command->executeCommand(command->handle, commandLine, stdout, stderr);
-	} else {
-		error("No such command\n");
-	}
-	free(commandName);
-}
+celix_status_t shell_executeCommand(shell_pt shell_ptr, char *command_line_str, void (*out)(char *), void (*error)(char *)) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	command_service_pt command_ptr = NULL;
+
+	if (!shell_ptr || !command_line_str || !out || !error) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		size_t pos = strcspn(command_line_str, " ");
+
+		char *command_name_str = (pos != strlen(command_line_str)) ? strndup(command_line_str, pos) : strdup(command_line_str);
+		command_ptr = hashMap_get(shell_ptr->command_name_map_ptr, command_name_str);
+		free(command_name_str);
+		if (!command_ptr) {
+			error("No such command");
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		printf("TODO\n");
+		//FIXME udpate shell_executeCommand with FILE
+		status = command_ptr->executeCommand(command_ptr->handle, command_line_str, stdout, stderr);
+	}
 
-static command_service_pt shell_getCommand(shell_pt shell, char * commandName) {
-	command_service_pt command = hashMap_get(shell->commandNameMap, commandName);
-	return (command == NULL) ? NULL : command;
+	return status;
 }
 
-void shell_serviceChanged(service_listener_pt listener, service_event_pt event) {
-	shell_pt shell = (shell_pt) listener->handle;
-	if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) {
-		shell_addCommand(shell, event->reference);
-	} else if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) {
-		shell_removeCommand(shell, event->reference);
+celix_status_t shell_serviceChanged(service_listener_pt listener_ptr, service_event_pt event_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!listener_ptr || !event_ptr || !listener_ptr->handle || !event_ptr->type || !event_ptr->reference) {
+		status = CELIX_ILLEGAL_ARGUMENT;
 	}
+
+	if (status == CELIX_SUCCESS) {
+		shell_pt shell_ptr = (shell_pt) listener_ptr->handle;
+		if (event_ptr->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) {
+			status = shell_addCommand(shell_ptr, event_ptr->reference);
+		} else if (event_ptr->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) {
+			status = shell_removeCommand(shell_ptr, event_ptr->reference);
+		}
+	}
+
+	return status;
 }
 

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/start_command.c
----------------------------------------------------------------------
diff --git a/shell/private/src/start_command.c b/shell/private/src/start_command.c
index 0e5f5e0..f43699a 100644
--- a/shell/private/src/start_command.c
+++ b/shell/private/src/start_command.c
@@ -27,38 +27,58 @@
 #include <string.h>
 #include <stdio.h>
 
-#include "celix_errno.h"
 #include "std_commands.h"
-#include "array_list.h"
 #include "bundle_context.h"
-#include "bundle.h"
 
-celix_status_t startCommand_execute(void *handle, char * line, FILE *outStream, FILE *errStream) {
-  celix_status_t status = CELIX_SUCCESS;
-  bundle_context_pt context = handle;
+celix_status_t startCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr) {
+    celix_status_t status = CELIX_SUCCESS;
 
-	char delims[] = " ";
-	char * sub = NULL;
-	char *save_ptr = NULL;
-	sub = strtok_r(line, delims, &save_ptr);
-	sub = strtok_r(NULL, delims, &save_ptr);
-	if (sub == NULL) {
-		fprintf(outStream, "Incorrect number of arguments.\n");
-	} else {
-		while (sub != NULL) {
-			long id = atol(sub);
-			bundle_pt bundle = NULL;
-			bundleContext_getBundleById(context, id, &bundle);
-			if (bundle != NULL) {
-				bundle_startWithOptions(bundle, 0);
-			} else {
-        fprintf(errStream, "Bundle id '%li' is invalid\n", id);
+    bundle_context_pt context_ptr = _ptr;
+
+    if (!context_ptr || !command_line_str || !out_ptr || !err_ptr) {
         status = CELIX_ILLEGAL_ARGUMENT;
-        break;
-			}
-			sub = strtok_r(NULL, delims, &save_ptr);
-		}
-	}
+    }
+
+    if (status == CELIX_SUCCESS) {
+        char *sub_str = NULL;
+        char *save_ptr = NULL;
+
+        strtok_r(command_line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+        sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+
+        if (sub_str == NULL) {
+            fprintf(out_ptr, "Incorrect number of arguments.\n");
+        } else {
+            while (sub_str != NULL) {
+                celix_status_t sub_status = CELIX_SUCCESS;
+
+                bundle_pt bundle_ptr = NULL;
+
+                char *end_str = NULL;
+                long id = strtol(sub_str, &end_str, 10);
+                if (*end_str) {
+                    sub_status = CELIX_ILLEGAL_ARGUMENT;
+                    fprintf(err_ptr, "Bundle id '%s' is invalid, problem at %s\n", sub_str, end_str);
+                }
+
+                if (sub_status == CELIX_SUCCESS) {
+                    sub_status = bundleContext_getBundleById(context_ptr, id, &bundle_ptr);
+                }
+
+                if (sub_status == CELIX_SUCCESS) {
+                    bundle_startWithOptions(bundle_ptr, 0);
+                }
+
+                if (sub_status != CELIX_SUCCESS) {
+                    status = sub_status;
+                    break;
+                }
+
+                sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+            }
+        }
+
+    }
 
-  return status;
+    return status;
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/private/src/stop_command.c
----------------------------------------------------------------------
diff --git a/shell/private/src/stop_command.c b/shell/private/src/stop_command.c
index a790c74..0093c99 100644
--- a/shell/private/src/stop_command.c
+++ b/shell/private/src/stop_command.c
@@ -26,42 +26,57 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "array_list.h"
 #include "bundle_context.h"
-#include "bundle.h"
-#include "utils.h"
+#include "std_commands.h"
 
-celix_status_t stopCommand_execute(void *handle, char *line, FILE *outStream, FILE *errStream) {
-	celix_status_t status = CELIX_SUCCESS;
-	bundle_context_pt context = handle;
-    char delims[] = " ";
-	char * sub = NULL;
-	char *save_ptr = NULL;
+celix_status_t stopCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr) {
+    celix_status_t status = CELIX_SUCCESS;
 
-	sub = strtok_r(line, delims, &save_ptr);
-	sub = strtok_r(NULL, delims, &save_ptr);
+    bundle_context_pt context_ptr = _ptr;
 
-	if (sub == NULL) {
-		fprintf(outStream, "Incorrect number of arguments.\n");
-	} else {
-		while (sub != NULL) {
-			bool numeric;
-			utils_isNumeric(sub, &numeric);
-			if (numeric) {
-				long id = atol(sub);
-				bundle_pt bundle = NULL;
-				bundleContext_getBundleById(context, id, &bundle);
-				if (bundle != NULL) {
-					bundle_stopWithOptions(bundle, 0);
-				} else {
-					fprintf(outStream, "Bundle id is invalid.");
-				}
-			} else {
-				fprintf(outStream, "Bundle id should be a number (bundle id).\n");
-			}
-			sub = strtok_r(NULL, delims, &save_ptr);
-		}
-	}
+    if (!context_ptr || !command_line_str || !out_ptr || !err_ptr) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
 
-	return status;
+    if (status == CELIX_SUCCESS) {
+        char *sub_str = NULL;
+        char *save_ptr = NULL;
+
+        strtok_r(command_line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+        sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+
+        if (sub_str == NULL) {
+            fprintf(out_ptr, "Incorrect number of arguments.\n");
+        } else {
+            while (sub_str != NULL) {
+                celix_status_t sub_status = CELIX_SUCCESS;
+
+                bundle_pt bundle_ptr = NULL;
+
+                char *end_str = NULL;
+                long id = strtol(sub_str, &end_str, 10);
+                if (*end_str) {
+                    sub_status = CELIX_ILLEGAL_ARGUMENT;
+                    fprintf(err_ptr, "Bundle id '%s' is invalid, problem at %s\n", sub_str, end_str);
+                }
+
+                if (sub_status == CELIX_SUCCESS) {
+                    sub_status = bundleContext_getBundleById(context_ptr, id, &bundle_ptr);
+                }
+
+                if (sub_status == CELIX_SUCCESS) {
+                    bundle_stopWithOptions(bundle_ptr, 0);
+                }
+
+                if (sub_status != CELIX_SUCCESS) {
+                    status = sub_status;
+                    break;
+                }
+
+                sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+            }
+        }
+    }
+
+    return status;
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/public/include/command.h
----------------------------------------------------------------------
diff --git a/shell/public/include/command.h b/shell/public/include/command.h
index 710bf9d..fce2ca4 100644
--- a/shell/public/include/command.h
+++ b/shell/public/include/command.h
@@ -29,6 +29,10 @@
 
 #include "celix_errno.h"
 
+#define OSGI_SHELL_COMMAND_NAME "command.name"
+#define OSGI_SHELL_COMMAND_USAGE "command.usage"
+#define OSGI_SHELL_COMMAND_DESCRIPTION "command.description"
+
 static const char * const OSGI_SHELL_COMMAND_SERVICE_NAME = "commandService";
 
 typedef struct commandService * command_service_pt;

http://git-wip-us.apache.org/repos/asf/celix/blob/bafe2efb/shell/public/include/shell.h
----------------------------------------------------------------------
diff --git a/shell/public/include/shell.h b/shell/public/include/shell.h
index 9fe60b4..c6f1792 100644
--- a/shell/public/include/shell.h
+++ b/shell/public/include/shell.h
@@ -36,11 +36,12 @@ typedef struct shell * shell_pt;
 
 struct shellService {
 	shell_pt shell;
-	array_list_pt (*getCommands)(shell_pt shell);
-	char * (*getCommandUsage)(shell_pt shell, char * commandName);
-	char * (*getCommandDescription)(shell_pt shell, char * commandName);
+
+	celix_status_t (*getCommands)(shell_pt shell_ptr, array_list_pt *commands_ptr);
+	celix_status_t (*getCommandUsage)(shell_pt shell_ptr, char *command_name_str, char **usage_str);
+	celix_status_t (*getCommandDescription)(shell_pt shell_ptr, char *command_name_str, char **command_description_str);
 	celix_status_t (*getCommandReference)(shell_pt shell_ptr, char *command_name_str, service_reference_pt *command_reference_ptr);
-	void (*executeCommand)(shell_pt shell, char * commandLine, void (*out)(char *), void (*error)(char *));
+	celix_status_t (*executeCommand)(shell_pt shell_ptr, char * command_line_str, void (*out)(char *), void (*error)(char *));
 };
 
 typedef struct shellService * shell_service_pt;