www.pudn.com > Net_apps.rar > shell.c


/* 
 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 
 * All rights reserved.  
 *  
 * Redistribution and use in source and binary forms, with or without modification,  
 * are permitted provided that the following conditions are met: 
 * 
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution. 
 * 3. The name of the author may not be used to endorse or promote products 
 *    derived from this software without specific prior written permission.  
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  
 * OF SUCH DAMAGE. 
 * 
 * This file is part of the lwIP TCP/IP stack. 
 *  
 * Author: Adam Dunkels  
 * 
 */ 
 
//#include  
//#include  
 
#include "..\include\L1\lwip\mem.h" 
#include "..\include\L1\lwip\debug.h" 
#include "..\include\L1\lwip\def.h" 
#include "..\include\L1\lwip\api.h" 
#include "..\include\L1\lwip\stats.h" 
//daniel 
#include "..\drive\include\drive.h" 
 
static unsigned char buffer[1024]; 
 
struct command { 
  struct netconn *conn; 
  s8_t (* exec)(struct command *); 
  u8_t nargs; 
  char *args[10]; 
}; 
 
#undef IP_HDRINCL 
 
#include  
#include  
#include  
#include  
 
#define ESUCCESS 0 
#define ESYNTAX -1 
#define ETOOFEW -2 
#define ETOOMANY -3 
#define ECLOSED -4 
 
#define NCONNS 10 
static struct netconn *conns[NCONNS]; 
 
static char help_msg[] = "Available commands:\n\ 
open [IP address] [TCP port]: opens a TCP connection to the specified address.\n\ 
lstn [TCP port]: sets up a server on the specified port.\n\ 
acpt [connection #]: waits for an incoming connection request.\n\ 
send [connection #] [message]: sends a message on a TCP connection.\n\ 
udpc [local UDP port] [IP address] [remote port]: opens a UDP \"connection\".\n\ 
udpl [local UDP port] [IP address] [remote port]: opens a UDP-Lite \"connection\".\n\ 
udpn [local UDP port] [IP address] [remote port]: opens a UDP \"connection\" without checksums.\n\ 
udpb [local port] [remote port]: opens a UDP broadcast \"connection\".\n\ 
usnd [connection #] [message]: sends a message on a UDP connection.\n\ 
recv [connection #]: recieves data on a TCP or UDP connection.\n\ 
clos [connection #]: closes a TCP or UDP connection.\n\ 
stat: prints out lwIP statistics.\n\ 
quit: quits.\n"; 
 
static char *stat_msgs[] = { 
  "Link level * transmitted ", 
  "             retransmitted ", 
  "           * received ", 
  "             forwarded ", 
  "           * dropped ", 
  "           * checksum errors ", 
  "           * length errors ", 
  "           * memory errors ", 
  "             routing errors ", 
  "             protocol errors ", 
  "             option errors ", 
  "           * misc errors ", 
  "             cache hits ",   
  "IP_FRAG    * transmitted ", 
  "             retransmitted ", 
  "           * received ", 
  "           * forwarded ", 
  "           * dropped ", 
  "           * checksum errors ", 
  "           * length errors ", 
  "           * memory errors ", 
  "           * routing errors ", 
  "           * protocol errors ", 
  "           * option errors ", 
  "           * misc errors ", 
  "             cache hits ", 
  "IP         * transmitted ", 
  "             retransmitted ", 
  "           * received ", 
  "           * forwarded ", 
  "           * dropped ", 
  "           * checksum errors ", 
  "           * length errors ", 
  "           * memory errors ", 
  "           * routing errors ", 
  "           * protocol errors ", 
  "           * option errors ", 
  "           * misc errors ", 
  "             cache hits ", 
  "ICMP       * transmitted ", 
  "             retransmitted ", 
  "           * received ", 
  "             forwarded ", 
  "           * dropped ", 
  "           * checksum errors ", 
  "             length errors ", 
  "           * memory errors ", 
  "             routing errors ", 
  "           * protocol errors ", 
  "             option errors ", 
  "           * misc errors ", 
  "             cache hits ",   
  "UDP        * transmitted ", 
  "             retransmitted ", 
  "           * received ", 
  "             forwarded ", 
  "           * dropped ", 
  "           * checksum errors ", 
  "           * length errors ", 
  "           * memory errors ", 
  "           * routing errors ", 
  "           * protocol errors ", 
  "             option errors ", 
  "           * misc errors ", 
  "             cache hits ",   
  "TCP        * transmitted ", 
  "           * retransmitted ", 
  "           * received ", 
  "             forwarded ", 
  "           * dropped ", 
  "           * checksum errors ", 
  "           * length errors ", 
  "           * memory errors ", 
  "           * routing errors ", 
  "           * protocol errors ", 
  "           * option errors ", 
  "           * misc errors ", 
  "           * cache hits ",   
  "Pbufs      * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "             pbuf_alloc() locked ", 
  "             pbuf_refresh() locked ", 
  "Memory     * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "Memp PBUF  * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "RAW PCB    * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "UDP PCB    * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "TCP PCB    * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "TCP LISTEN * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "TCP SEG    * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "Netbufs    * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "Netconns   * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "API msgs   * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "TCPIP msgs * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "Timeouts   * available ", 
  "           * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "Semaphores * used ", 
  "           * high water mark ", 
  "           * errors ", 
  "Mailboxes  * used ", 
  "           * high water mark ", 
  "           * errors " 
}; 
/*-----------------------------------------------------------------------------------*/ 
static void 
sendstr(const char *str, struct netconn *conn) 
{ 
  netconn_write(conn, (void *)str, strlen(str), NETCONN_NOCOPY); 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_open(struct command *com) 
{ 
  struct ip_addr ipaddr; 
  u16_t port; 
  int i; 
  err_t err; 
 
  if (inet_aton(com->args[0], (struct in_addr *)&ipaddr) == -1) { 
    sendstr(strerror(errno), com->conn); 
    return ESYNTAX; 
  } 
  port = strtol(com->args[1], NULL, 10); 
 
  /* Find the first unused connection in conns. */ 
  for(i = 0; i < NCONNS && conns[i] != NULL; i++); 
 
  if (i == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Opening connection to ", com->conn); 
  netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY); 
  sendstr(":", com->conn); 
  netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY); 
  sendstr("\n", com->conn); 
 
  conns[i] = netconn_new(NETCONN_TCP); 
  if (conns[i] == NULL) {     
    sendstr("Could not create connection identifier (out of memory).\n", com->conn);  
    return ESUCCESS; 
  } 
  err = netconn_connect(conns[i], &ipaddr, port); 
  if (err != ERR_OK) { 
    fprintf(stderr, "error %s\n", lwip_strerr(err)); 
    sendstr("Could not connect to remote host: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    return ESUCCESS; 
  } 
 
  sendstr("Opened connection, connection identifier is ", com->conn); 
  sprintf((char *)buffer, "%d\n", i); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
   
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_lstn(struct command *com) 
{ 
  u16_t port; 
  int i; 
  err_t err; 
 
  port = strtol(com->args[0], NULL, 10); 
 
  /* Find the first unused connection in conns. */ 
  for(i = 0; i < NCONNS && conns[i] != NULL; i++); 
 
  if (i == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Opening a listening connection on port ", com->conn); 
  netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY); 
  sendstr("\n", com->conn); 
 
  conns[i] = netconn_new(NETCONN_TCP); 
  if (conns[i] == NULL) {     
    sendstr("Could not create connection identifier (out of memory).\n", com->conn);  
    return ESUCCESS; 
  } 
   
  err = netconn_bind(conns[i], IP_ADDR_ANY, port); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not bind: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
   
  err = netconn_listen(conns[i]); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not listen: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Opened connection, connection identifier is ", com->conn); 
  sprintf((char *)buffer, "%d\n", i); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
   
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_clos(struct command *com) 
{ 
  int i; 
  err_t err; 
   
  i = strtol(com->args[0], NULL, 10); 
 
  if (i > NCONNS) { 
    sendstr("Connection identifier too high.\n", com->conn); 
    return ESUCCESS; 
  } 
  if (conns[i] == NULL) { 
    sendstr("Connection identifier not in use.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  err = netconn_close(conns[i]); 
  if (err != ERR_OK) { 
    sendstr("Could not close connection: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Connection closed.\n", com->conn); 
  netconn_delete(conns[i]); 
  conns[i] = NULL; 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_acpt(struct command *com) 
{ 
  int i, j; 
 
  /* Find the first unused connection in conns. */ 
  for(j = 0; j < NCONNS && conns[j] != NULL; j++); 
 
  if (j == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  i = strtol(com->args[0], NULL, 10); 
 
  if (i > NCONNS) { 
    sendstr("Connection identifier too high.\n", com->conn); 
    return ESUCCESS; 
  } 
  if (conns[i] == NULL) { 
    sendstr("Connection identifier not in use.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  conns[j] = netconn_accept(conns[i]); 
   
  if (conns[j] == NULL) { 
    sendstr("Could not accept connection: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(netconn_err(conns[i])), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Accepted connection, connection identifier for new connection is ", com->conn); 
  sprintf((char *)buffer, "%d\n", j); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
#if LWIP_STATS 
static s8_t 
com_stat(struct command *com) 
{ 
  int i; 
  char buf[100]; 
  u16_t len; 
   
  for(i = 0; i < sizeof(struct stats_) / 2; i++) { 
    len = sprintf(buf, "%d", ((u16_t *)&lwip_stats)[i]); 
    sendstr(stat_msgs[i], com->conn); 
    netconn_write(com->conn, buf, len, NETCONN_COPY); 
    sendstr("\n", com->conn); 
  } 
 
   
  return ESUCCESS; 
} 
#endif 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_send(struct command *com) 
{ 
  int i; 
  err_t err; 
  int len; 
   
  i = strtol(com->args[0], NULL, 10); 
 
  if (i > NCONNS) { 
    sendstr("Connection identifier too high.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  if (conns[i] == NULL) { 
    sendstr("Connection identifier not in use.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  len = strlen(com->args[1]); 
  com->args[1][len] = '\r'; 
  com->args[1][len + 1] = '\n'; 
  com->args[1][len + 2] = 0; 
   
  err = netconn_write(conns[i], com->args[1], len + 3, NETCONN_COPY); 
  if (err != ERR_OK) { 
    sendstr("Could not send data: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
   
  sendstr("Data enqueued for sending.\n", com->conn); 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_recv(struct command *com) 
{ 
  int i; 
  err_t err; 
  struct netbuf *buf; 
  u16_t len; 
   
  i = strtol(com->args[0], NULL, 10); 
 
  if (i > NCONNS) { 
    sendstr("Connection identifier too high.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  if (conns[i] == NULL) { 
    sendstr("Connection identifier not in use.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  buf = netconn_recv(conns[i]); 
  if (buf != NULL) { 
       
    netbuf_copy(buf, buffer, 1024); 
    len = netbuf_len(buf); 
    sendstr("Reading from connection:\n", com->conn); 
    netconn_write(com->conn, buffer, len, NETCONN_COPY); 
    netbuf_delete(buf); 
  } else { 
    sendstr("EOF.\n", com->conn);  
  } 
  err = netconn_err(conns[i]); 
  if (err != ERR_OK) { 
    sendstr("Could not receive data: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_udpc(struct command *com) 
{ 
  struct ip_addr ipaddr; 
  u16_t lport, rport; 
  int i; 
  err_t err; 
 
  lport = strtol(com->args[0], NULL, 10); 
  if (inet_aton(com->args[1], (struct in_addr *)&ipaddr) == -1) { 
    sendstr(strerror(errno), com->conn); 
    return ESYNTAX; 
  } 
  rport = strtol(com->args[2], NULL, 10); 
 
  /* Find the first unused connection in conns. */ 
  for(i = 0; i < NCONNS && conns[i] != NULL; i++); 
 
  if (i == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Setting up UDP connection from port ", com->conn); 
  netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY); 
  sendstr(" to ", com->conn); 
  netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY); 
  sendstr(":", com->conn); 
  netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY); 
  sendstr("\n", com->conn); 
 
  conns[i] = netconn_new(NETCONN_UDP); 
  if (conns[i] == NULL) {     
    sendstr("Could not create connection identifier (out of memory).\n", com->conn);  
    return ESUCCESS; 
  } 
 
  err = netconn_connect(conns[i], &ipaddr, rport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not connect to remote host: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  err = netconn_bind(conns[i], IP_ADDR_ANY, lport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not bind: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Connection set up, connection identifier is ", com->conn); 
  sprintf((char *)buffer, "%d\n", i); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
   
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_udpl(struct command *com) 
{ 
  struct ip_addr ipaddr; 
  u16_t lport, rport; 
  int i; 
  err_t err; 
 
  lport = strtol(com->args[0], NULL, 10); 
  if (inet_aton(com->args[1], (struct in_addr *)&ipaddr) == -1) { 
    sendstr(strerror(errno), com->conn); 
    return ESYNTAX; 
  } 
  rport = strtol(com->args[2], NULL, 10); 
 
  /* Find the first unused connection in conns. */ 
  for(i = 0; i < NCONNS && conns[i] != NULL; i++); 
 
  if (i == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Setting up UDP-Lite connection from port ", com->conn); 
  netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY); 
  sendstr(" to ", com->conn); 
  netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY); 
  sendstr(":", com->conn); 
  netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY); 
  sendstr("\n", com->conn); 
 
  conns[i] = netconn_new(NETCONN_UDPLITE); 
  if (conns[i] == NULL) {     
    sendstr("Could not create connection identifier (out of memory).\n", com->conn);  
    return ESUCCESS; 
  } 
 
  err = netconn_connect(conns[i], &ipaddr, rport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not connect to remote host: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  err = netconn_bind(conns[i], IP_ADDR_ANY, lport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not bind: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Connection set up, connection identifier is ", com->conn); 
  sprintf((char *)buffer, "%d\n", i); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
   
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_udpn(struct command *com) 
{ 
  struct ip_addr ipaddr; 
  u16_t lport, rport; 
  int i; 
  err_t err; 
 
  lport = strtol(com->args[0], NULL, 10); 
  if (inet_aton(com->args[1], (struct in_addr *)&ipaddr) == -1) { 
    sendstr(strerror(errno), com->conn); 
    return ESYNTAX; 
  } 
  rport = strtol(com->args[2], NULL, 10); 
 
  /* Find the first unused connection in conns. */ 
  for(i = 0; i < NCONNS && conns[i] != NULL; i++); 
 
  if (i == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Setting up UDP connection without checksums from port ", com->conn); 
  netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY); 
  sendstr(" to ", com->conn); 
  netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY); 
  sendstr(":", com->conn); 
  netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY); 
  sendstr("\n", com->conn); 
 
  conns[i] = netconn_new(NETCONN_UDPNOCHKSUM); 
  if (conns[i] == NULL) {     
    sendstr("Could not create connection identifier (out of memory).\n", com->conn);  
    return ESUCCESS; 
  } 
 
  err = netconn_connect(conns[i], &ipaddr, rport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not connect to remote host: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  err = netconn_bind(conns[i], IP_ADDR_ANY, lport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not bind: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Connection set up, connection identifier is ", com->conn); 
  sprintf((char *)buffer, "%d\n", i); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
   
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_udpb(struct command *com) 
{ 
  struct ip_addr ipaddr; 
  u16_t lport, rport; 
  int i; 
  err_t err; 
  struct ip_addr bcaddr; 
 
  lport = strtol(com->args[0], NULL, 10); 
  if (inet_aton(com->args[1], (struct in_addr *)&ipaddr) == -1) { 
    sendstr(strerror(errno), com->conn); 
    return ESYNTAX; 
  } 
  rport = strtol(com->args[2], NULL, 10); 
 
  /* Find the first unused connection in conns. */ 
  for(i = 0; i < NCONNS && conns[i] != NULL; i++); 
 
  if (i == NCONNS) { 
    sendstr("No more connections available, sorry.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Setting up UDP broadcast connection from port ", com->conn); 
  netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY); 
  sendstr(" to ", com->conn); 
  netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY); 
  sendstr("\n", com->conn); 
 
  conns[i] = netconn_new(NETCONN_UDP); 
  if (conns[i] == NULL) {     
    sendstr("Could not create connection identifier (out of memory).\n", com->conn);  
    return ESUCCESS; 
  } 
 
  err = netconn_connect(conns[i], &ipaddr, rport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not connect to remote host: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  IP4_ADDR(&bcaddr, 255,255,255,255); 
  err = netconn_bind(conns[i], &bcaddr, lport); 
  if (err != ERR_OK) { 
    netconn_delete(conns[i]); 
    conns[i] = NULL; 
    sendstr("Could not bind: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
 
  sendstr("Connection set up, connection identifier is ", com->conn); 
  sprintf((char *)buffer, "%d\n", i); 
  netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY); 
   
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_usnd(struct command *com) 
{ 
  int i; 
  err_t err; 
  struct netbuf *buf; 
  char *mem; 
   
  i = strtol(com->args[0], NULL, 10); 
 
  if (i > NCONNS) { 
    sendstr("Connection identifier too high.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  if (conns[i] == NULL) { 
    sendstr("Connection identifier not in use.\n", com->conn); 
    return ESUCCESS; 
  } 
 
  buf = netbuf_new(); 
  mem = netbuf_alloc(buf, strlen(com->args[1]) + 1); 
  if (mem == NULL) { 
    sendstr("Could not allocate memory for sending.\n", com->conn); 
    return ESUCCESS; 
  } 
  strncpy(mem, com->args[1], strlen(com->args[1]) + 1); 
  err = netconn_send(conns[i], buf); 
  netbuf_delete(buf); 
  if (err != ERR_OK) { 
    sendstr("Could not send data: ", com->conn); 
#ifdef LWIP_DEBUG 
    sendstr(lwip_strerr(err), com->conn); 
#else 
    sendstr("(debugging must be turned on for error message to appear)", com->conn); 
#endif /* LWIP_DEBUG */ 
    sendstr("\n", com->conn); 
    return ESUCCESS; 
  } 
   
  sendstr("Data sent.\n", com->conn); 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
com_help(struct command *com) 
{ 
  sendstr(help_msg, com->conn); 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static s8_t 
parse_command(struct command *com, u32_t len) 
{ 
  u16_t i; 
  u16_t bufp; 
   
  if (strncmp((const char *)buffer, "open", 4) == 0) { 
    com->exec = com_open; 
    com->nargs = 2; 
  } else if (strncmp((const char *)buffer, "lstn", 4) == 0) { 
    com->exec = com_lstn; 
    com->nargs = 1; 
  } else if (strncmp((const char *)buffer, "acpt", 4) == 0) { 
    com->exec = com_acpt; 
    com->nargs = 1; 
  } else if (strncmp((const char *)buffer, "clos", 4) == 0) { 
    com->exec = com_clos; 
    com->nargs = 1; 
#if LWIP_STATS     
  } else if (strncmp((const char *)buffer, "stat", 4) == 0) { 
    com->exec = com_stat; 
    com->nargs = 0; 
#endif     
  } else if (strncmp((const char *)buffer, "send", 4) == 0) { 
    com->exec = com_send; 
    com->nargs = 2; 
  } else if (strncmp((const char *)buffer, "recv", 4) == 0) { 
    com->exec = com_recv; 
    com->nargs = 1; 
  } else if (strncmp((const char *)buffer, "udpc", 4) == 0) { 
    com->exec = com_udpc; 
    com->nargs = 3; 
  } else if (strncmp((const char *)buffer, "udpb", 4) == 0) { 
    com->exec = com_udpb; 
    com->nargs = 2; 
  } else if (strncmp((const char *)buffer, "udpl", 4) == 0) { 
    com->exec = com_udpl; 
    com->nargs = 3; 
  } else if (strncmp((const char *)buffer, "udpn", 4) == 0) { 
    com->exec = com_udpn; 
    com->nargs = 3; 
  } else if (strncmp((const char *)buffer, "usnd", 4) == 0) { 
    com->exec = com_usnd; 
    com->nargs = 2; 
  } else if (strncmp((const char *)buffer, "help", 4) == 0) { 
    com->exec = com_help; 
    com->nargs = 0; 
  } else if (strncmp((const char *)buffer, "quit", 4) == 0) { 
    printf("quit\n"); 
    return ECLOSED; 
  } else { 
    return ESYNTAX; 
  } 
 
  if (com->nargs == 0) { 
    return ESUCCESS; 
  } 
  bufp = 0; 
  for(; bufp < len && buffer[bufp] != ' '; bufp++); 
  for(i = 0; i < 10; i++) { 
    for(; bufp < len && buffer[bufp] == ' '; bufp++); 
    if (buffer[bufp] == '\r' || 
       buffer[bufp] == '\n') { 
      buffer[bufp] = 0; 
      if (i < com->nargs - 1) { 
	return ETOOFEW; 
      } 
      if (i > com->nargs - 1) { 
	return ETOOMANY; 
      } 
      break; 
    }     
    if (bufp > len) { 
      return ETOOFEW; 
    }     
    com->args[i] = (char *)&buffer[bufp]; 
    for(; bufp < len && buffer[bufp] != ' ' && buffer[bufp] != '\r' && 
	  buffer[bufp] != '\n'; bufp++) { 
      if (buffer[bufp] == '\\') { 
	buffer[bufp] = ' '; 
      } 
    } 
    if (bufp > len) { 
      return ESYNTAX; 
    } 
    buffer[bufp] = 0; 
    bufp++; 
    if (i == com->nargs - 1) { 
      break; 
    } 
 
  } 
 
  return ESUCCESS; 
} 
/*-----------------------------------------------------------------------------------*/ 
static void 
error(s8_t err, struct netconn *conn) 
{ 
  switch (err) { 
  case ESYNTAX: 
    sendstr("## Syntax error\n", conn); 
    break; 
  case ETOOFEW: 
    sendstr("## Too few arguments to command given\n", conn); 
    break; 
  case ETOOMANY: 
    sendstr("## Too many arguments to command given\n", conn); 
    break; 
  } 
} 
/*-----------------------------------------------------------------------------------*/ 
static void 
prompt(struct netconn *conn) 
{ 
  sendstr("> ", conn); 
}   
/*-----------------------------------------------------------------------------------*/ 
static void 
shell_main(struct netconn *conn) 
{ 
  struct netbuf *buf; 
  u32_t len; 
  struct command com; 
  s8_t err; 
  int i; 
   
  do { 
    buf = netconn_recv(conn); 
    if (buf != NULL) { 
      netbuf_copy(buf, buffer, 1024); 
      len = netbuf_len(buf); 
      netbuf_delete(buf); 
      if (len >= 4) { 
	if (buffer[0] != 0xff &&  
	   buffer[1] != 0xfe) { 
	  err = parse_command(&com, len); 
	  if (err == ESUCCESS) {	 
	    com.conn = conn; 
	    err = com.exec(&com); 
	  } 
	  if (err != ESUCCESS) { 
	    error(err, conn); 
	  } 
	  if (err == ECLOSED) { 
	    printf("Closed\n"); 
	    error(err, conn); 
	    goto close; 
	  } 
	} else { 
	  sendstr("\n\n" 
	          "lwIP simple interactive shell.\n" 
	          "(c) Copyright 2001, Swedish Institute of Computer Science.\n" 
	          "Written by Adam Dunkels.\n" 
	          "For help, try the \"help\" command.\n", conn); 
	} 
      } 
    } 
    if (buf != NULL) { 
      prompt(conn); 
    } 
  } while (buf != NULL); 
  printf("buf == NULL err %s\n", lwip_strerr(conn->err)); 
 close:   
  netconn_close(conn); 
   
  for(i = 0; i < NCONNS; i++) { 
    if (conns[i] != NULL) { 
      netconn_delete(conns[i]); 
    } 
    conns[i] = NULL; 
  } 
   
} 
/*-----------------------------------------------------------------------------------*/ 
static void  
shell_thread(void *arg) 
{ 
  struct netconn *conn, *newconn; 
   
  conn = netconn_new(NETCONN_TCP); 
  netconn_bind(conn, NULL, 23); 
  netconn_listen(conn); 
 
  while (1) { 
    newconn = netconn_accept(conn); 
    shell_main(newconn); 
    netconn_delete(newconn); 
  } 
} 
/*-----------------------------------------------------------------------------------*/ 
void 
shell_init(void)      
{ 
  sys_thread_new(shell_thread, NULL, DEFAULT_THREAD_PRIO); 
}