Fix reentrancy problems for serial
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@821 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
7c18bfddad
commit
d72dd985c1
@ -115,27 +115,27 @@ extern const char g_fmtcmdoutofmemory[];
|
||||
|
||||
/* Message handler */
|
||||
|
||||
extern int nsh_parse(FAR void *handle, char *cmdline);
|
||||
extern int nsh_parse(FAR void *handle, char *cmdline);
|
||||
|
||||
/* I/O interfaces */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_NSH_TELNET
|
||||
|
||||
extern int nsh_telnetmain(void);
|
||||
extern int nsh_telnetout(FAR void *handle, const char *fmt, ...);
|
||||
|
||||
# define nsh_main() nsh_telnetmain()
|
||||
# define nsh_output(handle, ...) nsh_telnetout(handle, __VA_ARGS__)
|
||||
extern int nsh_main(void);
|
||||
extern int nsh_output(FAR void *handle, const char *fmt, ...);
|
||||
extern FAR char *nsh_linebuffer(FAR void *handle);
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_TELNET /* Not yet supported on telnetd interface */
|
||||
extern FAR void *nsh_clone(FAR void *handle);
|
||||
extern void nsh_addref(FAR void *handle);
|
||||
extern void nsh_release(FAR void *handle);
|
||||
extern void *nsh_redirect(int fd);
|
||||
extern void nsh_restore(void *direct);
|
||||
#else
|
||||
|
||||
extern int nsh_serialmain(void);
|
||||
|
||||
# define nsh_main() nsh_serialmain()
|
||||
# define nsh_output(handle, ...) printf(__VA_ARGS__)
|
||||
|
||||
# define nsh_clone(handle) (handle)
|
||||
# define nsh_addref(handle)
|
||||
# define nsh_release(handle);
|
||||
# define nsh_redirect(fd) (NULL);
|
||||
# define nsh_restore(direct)
|
||||
#endif
|
||||
extern char *nsh_linebuffer(FAR void *handle);
|
||||
|
||||
/* Shell command handlers */
|
||||
|
||||
|
@ -256,6 +256,7 @@ static int nsh_execute(int argc, char *argv[])
|
||||
}
|
||||
|
||||
handler(handle, argc, &argv[2]);
|
||||
nsh_release(handle);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -361,16 +362,15 @@ int nsh_parse(FAR void *handle, char *cmdline)
|
||||
* in the "background"
|
||||
* argv[1]: This is string version of the handle needed to execute
|
||||
* the command (under telnetd). It is a string because
|
||||
* binary values cannot be provided via char *argv[]
|
||||
* binary values cannot be provided via char *argv[]. NOTE
|
||||
* that this value is filled in later.
|
||||
* argv[2]: The command name. This is argv[0] when the arguments
|
||||
* are, finally, received by the command handler
|
||||
* argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
|
||||
* argv[argc]: NULL terminating pointer
|
||||
*/
|
||||
|
||||
sprintf(strhandle, "%p\n", handle);
|
||||
argv[0] = "nsh_execute";
|
||||
argv[1] = strhandle;
|
||||
argv[2] = cmd;
|
||||
for (argc = 3; argc < NSH_MAX_ARGUMENTS+4; argc++)
|
||||
{
|
||||
@ -400,8 +400,25 @@ int nsh_parse(FAR void *handle, char *cmdline)
|
||||
{
|
||||
struct sched_param param;
|
||||
int priority;
|
||||
void *bkghandle;
|
||||
|
||||
/* Get the execution priority of this task */
|
||||
/* Get a cloned copy of the handle with reference count=1.
|
||||
* after the command has been processed, the nsh_release() call
|
||||
* at the end of nsh_execute() will destroy the clone.
|
||||
*/
|
||||
|
||||
bkghandle = nsh_clone(handle);
|
||||
|
||||
/* Place a string copy of the cloned handle in the argument list */
|
||||
|
||||
sprintf(strhandle, "%p\n", bkghandle);
|
||||
argv[1] = strhandle;
|
||||
|
||||
/* Handle redirection of output via a file descriptor */
|
||||
|
||||
/* (void)nsh_redirect(bkghandle); */
|
||||
|
||||
/* Get the execution priority of this task */
|
||||
|
||||
ret = sched_getparam(0, ¶m);
|
||||
if (ret != 0)
|
||||
@ -455,17 +472,43 @@ int nsh_parse(FAR void *handle, char *cmdline)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* void *save; */
|
||||
|
||||
/* Increment the reference count on the handle. This reference count will
|
||||
* be decremented at the end of nsh_execute() and exists only for compatibility
|
||||
* with the background command logic.
|
||||
*/
|
||||
|
||||
nsh_addref(handle);
|
||||
|
||||
/* Place a string copy of the original handle in the argument list */
|
||||
|
||||
sprintf(strhandle, "%p\n", handle);
|
||||
argv[1] = strhandle;
|
||||
|
||||
/* Handle redirection of output via a file descriptor */
|
||||
/* save = nsh_redirect(fd); */
|
||||
|
||||
/* Then execute the command in "foreground" -- i.e., while the user waits
|
||||
* for the next prompt.
|
||||
*/
|
||||
|
||||
ret = nsh_execute(argc, argv);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Restore the original output */
|
||||
|
||||
/* nsh_undirect(save); */
|
||||
}
|
||||
|
||||
/* Return success if the command succeeded (or at least, starting of the
|
||||
* command task succeeded).
|
||||
*/
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "nsh.h"
|
||||
|
||||
@ -54,13 +55,10 @@
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct cmdmap_s
|
||||
struct serial_s
|
||||
{
|
||||
const char *cmd; /* Name of the command */
|
||||
cmd_t handler; /* Function that handles the command */
|
||||
ubyte minargs; /* Minimum number of arguments (including command) */
|
||||
ubyte maxargs; /* Maximum number of arguments (including command) */
|
||||
const char *usage; /* Usage instructions for 'help' command */
|
||||
int ss_refs; /* Reference counts on the intance */
|
||||
char ss_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -71,8 +69,6 @@ struct cmdmap_s
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
@ -81,6 +77,20 @@ static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_allocstruct
|
||||
****************************************************************************/
|
||||
|
||||
static inline FAR struct serial_s *nsh_allocstruct(void)
|
||||
{
|
||||
struct serial_s *pstate = (struct serial_s *)malloc(sizeof(struct serial_s));
|
||||
if (pstate)
|
||||
{
|
||||
pstate->ss_refs = 1;
|
||||
}
|
||||
return pstate;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -89,8 +99,10 @@ static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
||||
* Name: nsh_main
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_serialmain(void)
|
||||
int nsh_main(void)
|
||||
{
|
||||
FAR struct serial_s *pstate = nsh_allocstruct();
|
||||
|
||||
printf("NuttShell (NSH)\n");
|
||||
fflush(stdout);
|
||||
|
||||
@ -103,16 +115,36 @@ int nsh_serialmain(void)
|
||||
|
||||
/* Get the next line of input */
|
||||
|
||||
if (fgets(g_line, CONFIG_EXAMPLES_NSH_LINELEN, stdin))
|
||||
if (fgets(pstate->ss_line, CONFIG_EXAMPLES_NSH_LINELEN, stdin))
|
||||
{
|
||||
/* Parse process the command */
|
||||
|
||||
(void)nsh_parse(NULL, g_line);
|
||||
(void)nsh_parse(pstate, pstate->ss_line);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_output
|
||||
*
|
||||
* Description:
|
||||
* Print a string to stdout.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_output(FAR void *handle, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vfprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_linebuffer
|
||||
*
|
||||
@ -121,9 +153,59 @@ int nsh_serialmain(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
extern char *nsh_linebuffer(FAR void *handle)
|
||||
FAR char *nsh_linebuffer(FAR void *handle)
|
||||
{
|
||||
return g_line;
|
||||
FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
|
||||
return pstate->ss_line;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_clone
|
||||
*
|
||||
* Description:
|
||||
* Make an independent copy of the handle
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *nsh_clone(FAR void *handle)
|
||||
{
|
||||
return nsh_allocstruct();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_addref
|
||||
*
|
||||
* Description:
|
||||
* Increment the reference count on the handle.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nsh_addref(FAR void *handle)
|
||||
{
|
||||
FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
|
||||
pstate->ss_refs++;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_release
|
||||
*
|
||||
* Description:
|
||||
* Decrement the reference count on the handle, releasing it when the count
|
||||
* decrements to zero.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nsh_release(FAR void *handle)
|
||||
{
|
||||
FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
|
||||
if (pstate->ss_refs > 1)
|
||||
{
|
||||
pstate->ss_refs--;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(handle);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -401,7 +401,7 @@ static void *nsh_connection(void *arg)
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnetmain
|
||||
* Name: nsh_main
|
||||
*
|
||||
* Description:
|
||||
* This is the main processing thread for telnetd. It never returns
|
||||
@ -409,7 +409,7 @@ static void *nsh_connection(void *arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_telnetmain(void)
|
||||
int nsh_main(void)
|
||||
{
|
||||
struct in_addr addr;
|
||||
#if defined(CONFIG_EXAMPLES_NSH_DHCPC) || defined(CONFIG_EXAMPLES_NSH_NOMAC)
|
||||
@ -492,7 +492,7 @@ int nsh_telnetmain(void)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnetout
|
||||
* Name: nsh_output
|
||||
*
|
||||
* Description:
|
||||
* Print a string to the remote shell window.
|
||||
@ -503,7 +503,7 @@ int nsh_telnetmain(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_telnetout(FAR void *handle, const char *fmt, ...)
|
||||
int nsh_output(FAR void *handle, const char *fmt, ...)
|
||||
{
|
||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||
int nbytes = pstate->tn_sndlen;
|
||||
@ -558,7 +558,7 @@ int nsh_telnetout(FAR void *handle, const char *fmt, ...)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
extern char *nsh_linebuffer(FAR void *handle)
|
||||
FAR char *nsh_linebuffer(FAR void *handle)
|
||||
{
|
||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||
return pstate->tn_cmd;
|
||||
|
Loading…
Reference in New Issue
Block a user