summaryrefslogtreecommitdiff
path: root/nuttx/examples/nsh
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-01 02:32:50 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-01 02:32:50 +0000
commitb9fd3d2acfda5074d62e671c6edcdaed9fdc40c9 (patch)
tree9488da6f278c95fd921b2e552334be87a869b79d /nuttx/examples/nsh
parent587a5b65f3f48805150f8a0d8db9ce34f9cabfda (diff)
downloadpx4-nuttx-b9fd3d2acfda5074d62e671c6edcdaed9fdc40c9.tar.gz
px4-nuttx-b9fd3d2acfda5074d62e671c6edcdaed9fdc40c9.tar.bz2
px4-nuttx-b9fd3d2acfda5074d62e671c6edcdaed9fdc40c9.zip
Fix NSH redirection hang
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3326 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/examples/nsh')
-rw-r--r--nuttx/examples/nsh/nsh.h2
-rw-r--r--nuttx/examples/nsh/nsh_fscmds.c2
-rw-r--r--nuttx/examples/nsh/nsh_serial.c92
-rw-r--r--nuttx/examples/nsh/nsh_telnetd.c63
4 files changed, 151 insertions, 8 deletions
diff --git a/nuttx/examples/nsh/nsh.h b/nuttx/examples/nsh/nsh.h
index ef03ddc9d..a7a04a908 100644
--- a/nuttx/examples/nsh/nsh.h
+++ b/nuttx/examples/nsh/nsh.h
@@ -177,6 +177,7 @@
#define nsh_clone(v) (v)->clone(v)
#define nsh_release(v) (v)->release(v)
+#define nsh_write(v,b,n) (v)->write(v,b,n)
#define nsh_linebuffer(v) (v)->linebuffer(v)
#define nsh_redirect(v,f,s) (v)->redirect(v,f,s)
#define nsh_undirect(v,s) (v)->undirect(v,s)
@@ -255,6 +256,7 @@ struct nsh_vtbl_s
void (*addref)(FAR struct nsh_vtbl_s *vtbl);
void (*release)(FAR struct nsh_vtbl_s *vtbl);
#endif
+ ssize_t (*write)(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes);
int (*output)(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl);
void (*redirect)(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save);
diff --git a/nuttx/examples/nsh/nsh_fscmds.c b/nuttx/examples/nsh/nsh_fscmds.c
index eb43ed23c..40f894ec8 100644
--- a/nuttx/examples/nsh/nsh_fscmds.c
+++ b/nuttx/examples/nsh/nsh_fscmds.c
@@ -457,7 +457,7 @@ int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
while (nbyteswritten < nbytesread)
{
- int n = write(1, buffer, nbytesread);
+ ssize_t n = nsh_write(vtbl, buffer, nbytesread);
if (n < 0)
{
/* EINTR is not an error (but will stop stop the cat) */
diff --git a/nuttx/examples/nsh/nsh_serial.c b/nuttx/examples/nsh/nsh_serial.c
index 1f76de533..0704cf080 100644
--- a/nuttx/examples/nsh/nsh_serial.c
+++ b/nuttx/examples/nsh/nsh_serial.c
@@ -1,7 +1,7 @@
/****************************************************************************
* examples/nsh/nsh_serial.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,8 @@
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
+#include <errno.h>
+#include <debug.h>
#include "nsh.h"
@@ -78,6 +80,7 @@ struct serialsave_s
static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl);
static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl);
#endif
+static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes);
static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl);
static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save);
@@ -109,6 +112,7 @@ static inline FAR struct serial_s *nsh_allocstruct(void)
pstate->ss_vtbl.clone = nsh_consoleclone;
pstate->ss_vtbl.release = nsh_consolerelease;
#endif
+ pstate->ss_vtbl.write = nsh_consolewrite;
pstate->ss_vtbl.output = nsh_consoleoutput;
pstate->ss_vtbl.linebuffer = nsh_consolelinebuffer;
pstate->ss_vtbl.redirect = nsh_consoleredirect;
@@ -171,6 +175,41 @@ static void nsh_closeifnotclosed(struct serial_s *pstate)
}
/****************************************************************************
+ * Name: nsh_consolewrite
+ *
+ * Description:
+ * write a buffer to the remote shell window.
+ *
+ * Currently only used by cat.
+ *
+ ****************************************************************************/
+
+static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes)
+{
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
+ ssize_t ret;
+
+ /* The stream is open in a lazy fashion. This is done because the file
+ * descriptor may be opened on a different task than the stream. The
+ * actual open will then occur with the first output from the new task.
+ */
+
+ if (nsh_openifnotopen(pstate) != 0)
+ {
+ return (ssize_t)ERROR;
+ }
+
+ /* Write the data to the output stream */
+
+ ret = fwrite(buffer, 1, nbytes, pstate->ss_stream);
+ if (ret < 0)
+ {
+ dbg("[%d] Failed to send buffer: %d\n", pstate->ss_fd, errno);
+ }
+ return ret;
+}
+
+/****************************************************************************
* Name: nsh_consoleoutput
*
* Description:
@@ -265,7 +304,29 @@ static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl)
* Name: nsh_consoleredirect
*
* Description:
- * Set up for redirected output
+ * Set up for redirected output. This function is called from nsh_parse()
+ * in two different contexts:
+ *
+ * 1) Redirected background commands of the form: command > xyz.text &
+ *
+ * In this case:
+ * - vtbl: A newly allocated and initialized instance created by
+ * nsh_consoleclone,
+ * - fd:- The file descriptor of the redirected output
+ * - save: NULL
+ *
+ * nsh_consolerelease() will perform the clean-up when the clone is
+ * destroyed.
+ *
+ * 2) Redirected foreground commands of the form: command > xyz.txt
+ *
+ * In this case:
+ * - vtbl: The current state structure,
+ * - fd: The file descriptor of the redirected output
+ * - save: Where to save the re-directed registers.
+ *
+ * nsh_consoleundirect() will perform the clean-up after the redirected
+ * command completes.
*
****************************************************************************/
@@ -274,18 +335,39 @@ static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t
FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
FAR struct serialsave_s *ssave = (FAR struct serialsave_s *)save;
- (void)nsh_openifnotopen(pstate);
- fflush(pstate->ss_stream);
+ /* Case 1: Redirected foreground commands */
+
if (ssave)
{
+ /* pstate->ss_stream and ss_fd refer refer to the
+ * currently opened output stream. If the console is open, flush
+ * any pending output.
+ */
+
+ if (pstate->ss_stream)
+ {
+ fflush(pstate->ss_stream);
+ }
+
+ /* Save the current fd and stream values. These will be restored
+ * when nsh_consoleundirect() is called.
+ */
+
ssave->ss_fd = pstate->ss_fd;
ssave->ss_stream = pstate->ss_stream;
}
else
{
- fclose(pstate->ss_stream);
+ /* nsh_consoleclone() set pstate->ss_fd and ss_stream to refer
+ * to standard out. We just want to leave these alone and overwrite
+ * them with the fd for the re-directed stream.
+ */
}
+ /* In either case, set the fd of the new, re-directed output and nullify
+ * the output stream (it will be fdopen'ed if it is used).
+ */
+
pstate->ss_fd = fd;
pstate->ss_stream = NULL;
}
diff --git a/nuttx/examples/nsh/nsh_telnetd.c b/nuttx/examples/nsh/nsh_telnetd.c
index 42eb5a9e9..9776124f6 100644
--- a/nuttx/examples/nsh/nsh_telnetd.c
+++ b/nuttx/examples/nsh/nsh_telnetd.c
@@ -1,7 +1,7 @@
/****************************************************************************
* examples/nsh/nsh_telnetd.c
*
- * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* This is a leverage of similar logic from uIP:
@@ -147,6 +147,7 @@ static void tio_semtake(struct telnetio_s *tio);
static FAR struct nsh_vtbl_s *nsh_telnetclone(FAR struct nsh_vtbl_s *vtbl);
#endif
static void nsh_telnetrelease(FAR struct nsh_vtbl_s *vtbl);
+static ssize_t nsh_telnetwrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes);
static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
static int nsh_redirectoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
static FAR char *nsh_telnetlinebuffer(FAR struct nsh_vtbl_s *vtbl);
@@ -195,6 +196,7 @@ static FAR struct telnetd_s *nsh_allocstruct(void)
pstate->tn_vtbl.clone = nsh_telnetclone;
pstate->tn_vtbl.release = nsh_telnetrelease;
#endif
+ pstate->tn_vtbl.write = nsh_telnetwrite;
pstate->tn_vtbl.output = nsh_telnetoutput;
pstate->tn_vtbl.linebuffer = nsh_telnetlinebuffer;
pstate->tn_vtbl.redirect = nsh_telnetredirect;
@@ -538,6 +540,41 @@ static void *nsh_connection(void *arg)
}
/****************************************************************************
+ * Name: nsh_telnetwrite
+ *
+ * Description:
+ * write a buffer to the remote shell window.
+ *
+ * Currently only used by cat.
+ *
+ ****************************************************************************/
+
+static ssize_t nsh_telnetwrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes)
+{
+ struct telnetd_s *pstate = (struct telnetd_s *)vtbl;
+ struct telnetio_s *tio = pstate->u.tn;
+ ssize_t ret = nbytes;
+
+ /* Flush anything already in the output buffer */
+
+ nsh_flush(pstate);
+
+ /* Then write the user buffer */
+
+ nsh_telnetdump(&pstate->tn_vtbl, "Buffer output",(uint8_t*)buffer, nbytes);
+
+ tio_semtake(tio); /* Only one call to send at a time */
+ ret = send(tio->tio_sockfd, buffer, nbytes, 0);
+ if (ret < 0)
+ {
+ dbg("[%d] Failed to send buffer: %d\n", tio->tio_sockfd, errno);
+ }
+
+ tio_semgive(tio);
+ return ret;
+}
+
+/****************************************************************************
* Name: nsh_telnetoutput
*
* Description:
@@ -704,7 +741,29 @@ static void nsh_telnetrelease(FAR struct nsh_vtbl_s *vtbl)
* Name: nsh_telnetredirect
*
* Description:
- * Set up for redirected output
+ * Set up for redirected output. This function is called from nsh_parse()
+ * in two different contexts:
+ *
+ * 1) Redirected background commands of the form: command > xyz.text &
+ *
+ * In this case:
+ * - vtbl: A newly allocated and initialized instance created by
+ * nsh_telnetclone,
+ * - fd:- The file descriptor of the redirected output
+ * - save: NULL
+ *
+ * nsh_telnetrelease() will perform the clean-up when the clone is
+ * destroyed.
+ *
+ * 2) Redirected foreground commands of the form: command > xyz.txt
+ *
+ * In this case:
+ * - vtbl: The current state structure,
+ * - fd: The file descriptor of the redirected output
+ * - save: Where to save the re-directed registers.
+ *
+ * nsh_telnetundirect() will perform the clean-up after the redirected
+ * command completes.
*
****************************************************************************/