diff options
| -rw-r--r-- | doc/openocd.texi | 6 | ||||
| -rw-r--r-- | src/helper/options.c | 13 | ||||
| -rw-r--r-- | src/server/gdb_server.c | 26 | ||||
| -rw-r--r-- | src/server/server.c | 105 | ||||
| -rw-r--r-- | src/server/server.h | 15 | ||||
| -rw-r--r-- | src/server/tcl_server.c | 2 | ||||
| -rw-r--r-- | src/server/telnet_server.c | 4 | 
7 files changed, 82 insertions, 89 deletions
| diff --git a/doc/openocd.texi b/doc/openocd.texi index 230e47c9..77a0ad3b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -574,7 +574,6 @@ bash$ openocd --help  --debug      | -d       set debug level <0-3>  --log_output | -l       redirect log output to file <name>  --command    | -c       run <command> ---pipe       | -p       use pipes when talking to gdb  @end verbatim  If you don't give any @option{-f} or @option{-c} options, @@ -7052,11 +7051,12 @@ This would cause GDB to connect to the gdbserver on the local pc using port 3333  @item  A pipe connection is typically started as follows:  @example -target remote | openocd --pipe +target remote | openocd -c "gdb_port pipe; log_output openocd.log"  @end example  This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout).  Using this method has the advantage of GDB starting/stopping OpenOCD for the debug -session. +session. log_output sends the log output to a file to ensure that the pipe is +not saturated when using higher debug level outputs.  @end enumerate  To list the available OpenOCD commands type @command{monitor help} on the diff --git a/src/helper/options.c b/src/helper/options.c index 3a95df46..df4676d2 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -2,7 +2,7 @@   *   Copyright (C) 2004, 2005 by Dominic Rath                              *   *   Dominic.Rath@gmx.de                                                   *   *                                                                         * - *   Copyright (C) 2007,2008 Øyvind Harboe                                 * + *   Copyright (C) 2007-2010 Øyvind Harboe                                 *   *   oyvind.harboe@zylin.com                                               *   *                                                                         *   *   This program is free software; you can redistribute it and/or modify  * @@ -177,13 +177,9 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])  					add_config_command(optarg);  				}  				break; -			case 'p':	/* --pipe | -p */ -#if BUILD_ECOSBOARD == 1 -				/* pipes unsupported on hosted platforms */ -				LOG_WARNING("pipes not supported on this platform"); -#else -				server_use_pipes = 1; -#endif +			case 'p': +				LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; log_output openocd.log\"' instead."); +				add_config_command("gdb_port pipe; log_output openocd.log");  				break;  		}  	} @@ -198,7 +194,6 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])  		LOG_OUTPUT("--debug      | -d\tset debug level <0-3>\n");  		LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");  		LOG_OUTPUT("--command    | -c\trun <command>\n"); -		LOG_OUTPUT("--pipe       | -p\tuse pipes for gdb communication\n");  		exit(-1);  	} diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 54899589..7026ff21 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2387,42 +2387,22 @@ static int gdb_input(struct connection *connection)  	return ERROR_OK;  } -static int gdb_target_start(struct target *target, uint16_t port) +static int gdb_target_start(struct target *target, const char *port)  { -	bool use_pipes = 0 == port;  	struct gdb_service *gdb_service = malloc(sizeof(struct gdb_service));  	if (NULL == gdb_service)  		return -ENOMEM;  	gdb_service->target = target; -	add_service("gdb", use_pipes ? CONNECTION_PIPE : CONNECTION_TCP, +	return add_service("gdb",  			port, 1, &gdb_new_connection, &gdb_input,  			&gdb_connection_closed, gdb_service); - -	const char *name = target_name(target); -	if (use_pipes) -		LOG_DEBUG("gdb service for target '%s' using pipes", name); -	else -		LOG_DEBUG("gdb service for target '%s' on TCP port %u", name, port); -	return ERROR_OK;  }  static int gdb_target_add_one(struct target *target)  { -	long portnumber_parsed; -	/* If we can parse the port number -	 * then we increment the port number for the next target. -	 */ -	char *end_parse; -	portnumber_parsed = strtol(gdb_port_next, &end_parse, 0); -	if (!*end_parse) -	{ -		LOG_ERROR("Illegal port number"); -		return ERROR_FAIL; -	} - -	int retval = gdb_target_start(target, portnumber_parsed); +	int retval = gdb_target_start(target, gdb_port_next);  	if (retval == ERROR_OK)  	{  		long portnumber; diff --git a/src/server/server.c b/src/server/server.c index 435ddbb7..c7e1e40c 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -45,9 +45,6 @@ static struct service *services = NULL;  /* shutdown_openocd == 1: exit the main event loop, and quit the debugger */  static int shutdown_openocd = 0; -/* set when using pipes rather than tcp */ -int server_use_pipes = 0; -  static int add_connection(struct service *service, struct command_context *cmd_ctx)  {  	socklen_t address_size; @@ -80,7 +77,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c  				(char *)&flag,		/* the cast is historical cruft */  				sizeof(int));		/* length of option value */ -		LOG_INFO("accepting '%s' connection from %i", service->name, service->port); +		LOG_INFO("accepting '%s' connection from %s", service->name, service->port);  		if ((retval = service->new_connection(c)) != ERROR_OK)  		{  			close_socket(c->fd); @@ -88,8 +85,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c  			free(c);  			return retval;  		} -	} -	else if (service->type == CONNECTION_PIPE) +	} else if (service->type == CONNECTION_STDINOUT)  	{  		c->fd = service->fd;  		c->fd_out = fileno(stdout); @@ -97,10 +93,29 @@ static int add_connection(struct service *service, struct command_context *cmd_c  		/* do not check for new connections again on stdin */  		service->fd = -1; +		LOG_INFO("accepting '%s' connection from pipe", service->name); +		if ((retval = service->new_connection(c)) != ERROR_OK) +		{ +			LOG_ERROR("attempted '%s' connection rejected", service->name); +			free(c); +			return retval; +		} +	} else if (service->type == CONNECTION_PIPE) +	{ +		c->fd = service->fd;  		/* do not check for new connections again on stdin */  		service->fd = -1; -		LOG_INFO("accepting '%s' connection from pipe", service->name); +		char * out_file = alloc_printf("%so", service->port); +		c->fd_out = open(out_file, O_WRONLY); +		free(out_file); +		if (c->fd_out == -1) +		{ +			LOG_ERROR("could not open %s", service->port); +			exit(1); +		} + +		LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);  		if ((retval = service->new_connection(c)) != ERROR_OK)  		{  			LOG_ERROR("attempted '%s' connection rejected", service->name); @@ -130,7 +145,14 @@ static int remove_connection(struct service *service, struct connection *connect  		{  			service->connection_closed(c);  			if (service->type == CONNECTION_TCP) +			{  				close_socket(c->fd); +			} else if (service->type == CONNECTION_PIPE) +			{ +				/* The service will listen to the pipe again */ +				c->service->fd = c->fd; +			} +  			command_done(c->cmd_ctx);  			/* delete connection */ @@ -148,7 +170,8 @@ static int remove_connection(struct service *service, struct connection *connect  	return ERROR_OK;  } -int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv) +/* FIX! make service return error instead of invoking exit() */ +int add_service(char *name, const char *port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)  {  	struct service *c, **p;  	int so_reuseaddr_option = 1; @@ -156,9 +179,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int  	c = malloc(sizeof(struct service));  	c->name = strdup(name); -	c->type = type; -	c->port = port; -	c->max_connections = max_connections; +	c->port = strdup(port); +	c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */  	c->fd = -1;  	c->connections = NULL;  	c->new_connection = new_connection_handler; @@ -166,9 +188,28 @@ int add_service(char *name, enum connection_type type, unsigned short port, int  	c->connection_closed = connection_closed_handler;  	c->priv = priv;  	c->next = NULL; +	long portnumber; +	if (strcmp(c->port, "pipe") == 0) +	{ +		c->type = CONNECTION_STDINOUT; +	} else +	{ +		char *end; +		strtol(c->port, &end, 0); +		if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) +		{ +			c->portnumber = portnumber; +			c->type = CONNECTION_TCP; +		} else +		{ +			c->type = CONNECTION_PIPE; +		} +	} -	if (type == CONNECTION_TCP) +	if (c->type == CONNECTION_TCP)  	{ +		c->max_connections = max_connections; +  		if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  		{  			LOG_ERROR("error creating socket: %s", strerror(errno)); @@ -182,7 +223,7 @@ int add_service(char *name, enum connection_type type, unsigned short port, int  		memset(&c->sin, 0, sizeof(c->sin));  		c->sin.sin_family = AF_INET;  		c->sin.sin_addr.s_addr = INADDR_ANY; -		c->sin.sin_port = htons(port); +		c->sin.sin_port = htons(c->portnumber);  		if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)  		{ @@ -209,7 +250,7 @@ int add_service(char *name, enum connection_type type, unsigned short port, int  			exit(-1);  		}  	} -	else if (type == CONNECTION_PIPE) +	else if (c->type == CONNECTION_STDINOUT)  	{  		c->fd = fileno(stdin); @@ -225,10 +266,15 @@ int add_service(char *name, enum connection_type type, unsigned short port, int  		socket_nonblock(c->fd);  #endif  	} -	else +	else if (c->type == CONNECTION_PIPE)  	{ -		LOG_ERROR("unknown connection type: %d", type); -		exit(1); +		/* Pipe we're reading from */ +		c->fd = open(c->port, O_RDONLY | O_NONBLOCK); +		if (c->fd == -1) +		{ +			LOG_ERROR("could not open %s", c->port); +			exit(1); +		}  	}  	/* add to the end of linked list */ @@ -238,29 +284,6 @@ int add_service(char *name, enum connection_type type, unsigned short port, int  	return ERROR_OK;  } -int add_service_pipe(char *name, const char *port, int max_connections, -		new_connection_handler_t new_connection_handler, input_handler_t input_handler, -		connection_closed_handler_t connection_closed_handler, void *priv) -{ -	enum connection_type type = CONNECTION_TCP; -	long portnumber; -	char *end; -	strtol(port, &end, 0); -	if (!*end) -	{ -		if ((parse_long(port, &portnumber) == ERROR_OK) && (portnumber == 0)) -		{ -			type = CONNECTION_PIPE; -		} -	} else -	{ -		LOG_ERROR("Illegal port number %s", port); -		return ERROR_FAIL; -	} -	return add_service(name, type, portnumber, max_connections, new_connection_handler, -			input_handler, connection_closed_handler, priv); -} -  static int remove_services(void)  {  	struct service *c = services; @@ -278,6 +301,8 @@ static int remove_services(void)  			if (c->fd != -1)  				close(c->fd);  		} +		if (c->port) +			free((void *)c->port);  		if (c->priv)  			free(c->priv); diff --git a/src/server/server.h b/src/server/server.h index 2c9ed445..face1386 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -35,7 +35,8 @@  enum connection_type  {  	CONNECTION_TCP, -	CONNECTION_PIPE +	CONNECTION_PIPE, +	CONNECTION_STDINOUT  };  struct connection @@ -58,7 +59,8 @@ struct service  {  	char *name;  	enum connection_type type; -	unsigned short port; +	const char *port; +	unsigned short portnumber;  	int fd;  	struct sockaddr_in sin;  	int max_connections; @@ -70,12 +72,7 @@ struct service  	struct service *next;  }; -int add_service(char *name, enum connection_type type, unsigned short port, -		int max_connections, new_connection_handler_t new_connection_handler, -		input_handler_t in_handler, connection_closed_handler_t close_handler, -		void *priv); - -int add_service_pipe(char *name, const char *port, +int add_service(char *name, const char *port,  		int max_connections, new_connection_handler_t new_connection_handler,  		input_handler_t in_handler, connection_closed_handler_t close_handler,  		void *priv); @@ -115,8 +112,6 @@ SERVER_PIPE_COMMAND();  SERVER_PORT_COMMAND(); -extern int server_use_pipes; -  #define ERROR_SERVER_REMOTE_CLOSED	(-400)  #define ERROR_CONNECTION_REJECTED	(-401) diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index f82cafef..613eb23f 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -166,7 +166,7 @@ int tcl_init(void)  		return ERROR_OK;  	} -	return add_service_pipe("tcl", tcl_port, 1, +	return add_service("tcl", tcl_port, 1,  			&tcl_new_connection, &tcl_input,  			&tcl_closed, NULL);  } diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 420f5d70..00b4b5d2 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -592,9 +592,7 @@ int telnet_init(char *banner)  	telnet_service->banner = banner; -	add_service_pipe("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service); - -	return ERROR_OK; +	return add_service("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);  }  /* daemon configuration command telnet_port */ | 
