Added a terminal-creation capability.
--- a/app_control.c Mon Oct 08 13:08:09 2007 +0200
+++ b/app_control.c Wed Jan 02 15:15:11 2008 +0100
@@ -50,16 +50,16 @@
void app_control_prepare_read_fdset(fd_set *read_set, int *maxfd)
{
- assert(app_stdout != -1 || app_stderr != -1);
-
if (app_stdout != -1)
{
+ debugmsg("Considering app_stdout %i", app_stdout);
FD_SET(app_stdout, read_set);
*maxfd = max(*maxfd, app_stdout);
}
if (app_stderr != -1 && app_stdout != app_stderr)
{
+ debugmsg("Considering app_stderr %i", app_stderr);
FD_SET(app_stderr, read_set);
*maxfd = max(*maxfd, app_stderr);
}
@@ -71,6 +71,7 @@
if (app_stdout != -1 && FD_ISSET(app_stdout, read_set))
{
int res;
+ debugmsg("Read app_stdout %i", app_stdout);
res = read(app_stdout, stream_buffer, stream_buffer_size);
if (res == -1 && errno == EIO)
{
@@ -83,12 +84,16 @@
error("Error reading from app.");
if (res == 0)
{
+ debugmsg("Closing app_stdout %i", app_stdout);
close(app_stdout);
if (!command_line.s_param.nohup)
close(1);
+ app_stdout = -1;
if (app_stdout == app_stderr || app_stderr == -1)
+ {
+ app_stderr = -1;
return -1;
- app_stdout = -1;
+ }
} else
{
hex_dump("from app", stream_buffer, res);
@@ -108,9 +113,11 @@
FD_ISSET(app_stderr, read_set))
{
int res;
+ debugmsg("Read app_stderr %i", app_stdout);
res = read(app_stderr, stream_buffer, stream_buffer_size);
if (res == 0)
{
+ debugmsg("Closing app_stderr %i", app_stderr);
close(app_stderr);
close(2); /* MOVE */
app_stderr = -1;
@@ -137,7 +144,13 @@
void app_control_local_send_to_stdin(const char *buffer, size_t size)
{
if (size == 0)
+ {
close(app_stdin);
+ if (app_stdout == app_stdin)
+ app_stdout = -1;
+ if (app_stderr == app_stdin)
+ app_stderr = -1;
+ }
else
{
hex_dump("from local to app", buffer, size);
@@ -177,7 +190,13 @@
}
if (size == 0 && command_line.s_param.client_may_close_app_stdin)
+ {
close(app_stdin);
+ if (app_stdout == app_stdin)
+ app_stdout = -1;
+ if (app_stderr == app_stdin)
+ app_stderr = -1;
+ }
}
}
--- a/app_term.c Mon Oct 08 13:08:09 2007 +0200
+++ b/app_term.c Wed Jan 02 15:15:11 2008 +0100
@@ -46,6 +46,37 @@
ioctl(app_stdin, TIOCSWINSZ, (char *) &app_winsize);
}
+void get_term_options(struct termios *tios, struct winsize *wsize)
+{
+ int res;
+
+ /* Try to get the config from the actual terminal's stdout */
+ res = tcgetattr(1, tios);
+ if (res == -1)
+ {
+ /* Create the termios structure from scratch */
+ memset(tios, 0, sizeof(*tios));
+ cfmakeraw(tios);
+ }
+
+ /* if starting using shells' &, it doesn't get ECHO set.
+ * Let's force it. */
+ tios->c_lflag |= ECHO | ECHOE | ECHOK | ECHONL;
+ /* Try to emulate something compatible with xterm */
+ tios->c_oflag |= OPOST | ONLCR;
+ tios->c_lflag |= ISIG | ICANON | ECHOCTL | ECHOKE;
+ tios->c_iflag |= BRKINT | IGNPAR | IMAXBEL;
+
+ /* Get the original term's winsize */
+ res = ioctl(1, TIOCGWINSZ, wsize);
+ if (res == -1)
+ {
+ /* If we don't have original term, create an arbitrary winsize */
+ wsize->ws_row = 25;
+ wsize->ws_col = 80;
+ }
+}
+
static void give_terminal(int parent[], int child[])
{
struct termios tios;
@@ -53,17 +84,7 @@
int res;
int master, slave;
- res = tcgetattr(1, &tios);
- if (res == -1)
- error("tcgetatttr");
-
- /* if starting using shells' &, it doesn't get ECHO set.
- * Let's force it. */
- tios.c_lflag |= ECHO | ECHOE | ECHOK | ECHONL;
-
- res = ioctl(1, TIOCGWINSZ, &wsize);
- if (res == -1)
- error("ioctl TIOCGWINSZ");
+ get_term_options(&tios, &wsize);
app_winsize = wsize;
--- a/dump.c Mon Oct 08 13:08:09 2007 +0200
+++ b/dump.c Wed Jan 02 15:15:11 2008 +0100
@@ -5,6 +5,7 @@
Please find the license in the provided COPYING file.
*/
#include <stdio.h>
+#include <sys/select.h>
#include <stdarg.h>
#include "main.h"
@@ -51,3 +52,14 @@
fprintf(f, "\"\n");
fclose(f);
}
+
+void fdset_dump(fd_set *set, int maxfd)
+{
+ int i;
+
+ fprintf(stderr, "fdset:");
+ for (i=0; i <= maxfd; ++i)
+ if (FD_ISSET(i, set))
+ fprintf(stderr, " %i", i);
+ fprintf(stderr, "\n");
+}
--- a/error.c Mon Oct 08 13:08:09 2007 +0200
+++ b/error.c Wed Jan 02 15:15:11 2008 +0100
@@ -23,6 +23,27 @@
finish(-1);
}
+void warning(const char *msg, ...)
+{
+ va_list v;
+
+ va_start(v, msg);
+ vfprintf(stderr, msg, v);
+ putc('\n', stderr);
+}
+
+void debugmsg(const char *msg, ...)
+{
+ va_list v;
+
+ va_start(v, msg);
+ if (0)
+ {
+ vfprintf(stderr, msg, v);
+ putc('\n', stderr);
+ }
+}
+
void not_implemented(const char *msg, ...)
{
va_list v;
--- a/main.h Mon Oct 08 13:08:09 2007 +0200
+++ b/main.h Wed Jan 02 15:15:11 2008 +0100
@@ -37,6 +37,8 @@
/* error.c */
void not_implemented(const char *msg, ...);
void error(const char *msg, ...);
+void warning(const char *msg, ...);
+void debugmsg(const char *msg, ...);
void finish(int ret);
/* signals.c */
--- a/server.c Mon Oct 08 13:08:09 2007 +0200
+++ b/server.c Wed Jan 02 15:15:11 2008 +0100
@@ -16,6 +16,12 @@
#include "main.h"
#include "handlers.h"
+/* signals.c */
+extern int child_died;
+
+/*extern*/
+void fdset_dump(fd_set *set, int maxfd);
+
static void loop()
{
fd_set read_set;
@@ -37,9 +43,12 @@
{
FD_ZERO(&read_set);
+ maxfd = -1;
if (stdin_opened)
+ {
FD_SET(0, &read_set);
- maxfd = 0;
+ maxfd = 0;
+ }
app_control_prepare_read_fdset(&read_set, &maxfd);
if (command_line.s_param.serve_unix)
@@ -61,6 +70,13 @@
eth_proto_process_timeouts();
#endif
+ if (maxfd == -1)
+ error("No fds in select");
+
+ debugmsg("Blocking in pselect");
+ if (child_died == 1)
+ break;
+
/* Will block */
res = pselect(maxfd + 1, &read_set, 0, 0, 0, &sigold);
#ifdef linux
@@ -85,7 +101,10 @@
/* if res is 0, the fcall will close app_stdin */
app_control_local_send_to_stdin(stream_buffer, res);
if (res == 0)
+ {
+ debugmsg("Closing stdin\n");
stdin_opened = 0;
+ }
}
if (command_line.s_param.serve_unix)
--- a/signals.c Mon Oct 08 13:08:09 2007 +0200
+++ b/signals.c Wed Jan 02 15:15:11 2008 +0100
@@ -8,11 +8,14 @@
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/wait.h>
+#include <assert.h>
#include "main.h"
#include "handlers.h"
static int child;
+int child_died;
static char old_alarm_handler_set;
static struct sigaction old_alarm_handler;
@@ -23,6 +26,23 @@
kill(child, val);
}
+static void sig_child_died(int val)
+{
+ int status;
+ int res;
+
+ assert(child_died == 0);
+
+ res = wait(&status);
+
+ if (WIFEXITED(status) || WIFSIGNALED(status))
+ {
+ debugmsg("Child exited");
+ child_died = 1;
+ }
+ debugmsg("Child handler");
+}
+
static void update_window_size(int val)
{
char *xterm_str;
@@ -60,6 +80,10 @@
act.sa_handler = update_window_size;
sigaction(SIGWINCH, &act, 0);
+
+ act.sa_handler = sig_child_died;
+ act.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGCHLD, &act, 0);
}
static void alarm_handler(int x)
--- a/user_term.c Mon Oct 08 13:08:09 2007 +0200
+++ b/user_term.c Wed Jan 02 15:15:11 2008 +0100
@@ -26,7 +26,10 @@
res = tcgetattr(1, &tios);
if (res == -1)
- error("tcgetatttr");
+ {
+ debugmsg("tcgetattr(1) failed - not a terminal");
+ return;
+ }
memcpy(&saved_tios, &tios, sizeof(struct termios));
is_tios_saved = 1;
@@ -34,22 +37,17 @@
cfmakeraw(&tios);
tios.c_lflag &= ~ECHO;
- res = tcsetattr(0, TCSANOW, &tios);
+ res = tcsetattr(1, TCSANOW, &tios);
if (res == -1)
- error("tcsetatttr");
+ debugmsg("tcsetattr(1) failed - not a terminal");
}
void restore_user_terminal()
{
int res;
- res = tcsetattr(0, TCSANOW, &saved_tios);
+ res = tcsetattr(1, TCSANOW, &saved_tios);
if (res == -1)
- {
- /* cannot call error(), because it calls finish(), then
- * restore_user_terminal() */
- fprintf(stderr,"tcsetatttr failed: %s", strerror(errno));
- exit(-1);
- }
+ debugmsg("tcsetatttr failed: %s", strerror(errno));
}
void finish(int ret)