--- SOURCES/tcl-snmptools-1.0/generic/util.c 2008-01-29 01:09:38.000000000 -0800 +++ BUILD/tcl-snmptools-1.0/generic/util.c 2009-06-18 21:53:50.000000000 -0700 @@ -23,6 +23,11 @@ #include // errno #include // free +#ifndef WIN32 +#include // dup, dup2, close +#include // fcntl, F_GETFD, F_SETFD +#endif + #include "util.h" #define BUFLEN 500 @@ -55,11 +60,31 @@ * we have many interpreters (with different PID), so the * thread-safe issue doesn't come up as well. */ +/* + * As originally implemented, this technique grossly violates + * the Principle of Least Astonishment on Unix by destroying + * the output redirections of any TCL program that uses tcl-snmptools. + * Therefore we attempt to preserve the original stdout/stderr. + */ +#ifndef WIN32 +static int stdout_fd, stderr_fd; +static fpos_t stdout_pos, stderr_pos; +static long stdout_flags, stderr_flags; +#endif + char *captureOutput(void) { extern char *tempfile; FILE *fd; tempfile = tempnam(TMP, "TEMP"); +#ifndef WIN32 + /* preserve the original stdout */ + fflush(stdout); + fgetpos(stdout, &stdout_pos); + stdout_flags = fcntl(fileno(stdout), F_GETFD); + stdout_fd = dup(fileno(stdout)); +#endif + fd = freopen(tempfile, "a", stdout); if(fd == NULL) { printres("%s", strerror(errno)); @@ -68,6 +93,14 @@ } setvbuf(fd, (char *) NULL, _IONBF, 0); +#ifndef WIN32 + /* preserve the original stderr */ + fflush(stderr); + fgetpos(stderr, &stderr_pos); + stderr_flags = fcntl(fileno(stderr), F_GETFD); + stderr_fd = dup(fileno(stderr)); +#endif + fd = freopen(tempfile, "a", stderr); if(fd == NULL) { printres("%s", strerror(errno)); @@ -83,6 +116,7 @@ int restoreOutput(char *tempfile) { int errors = 0; +#ifdef WIN32 /* Ignore errors but include in the output and return value */ if(freopen(TTY, "w", stdout) == NULL) { errors++; @@ -92,6 +126,24 @@ errors++; printres("%s", strerror(errno)); } +#else + /* restore the original stdout */ + fflush(stdout); + dup2(stdout_fd, fileno(stdout)); + fcntl(fileno(stdout), F_SETFD, stdout_flags); + close(stdout_fd); + clearerr(stdout); + fsetpos(stdout, &stdout_pos); + + + /* restore the original stderr */ + fflush(stderr); + dup2(stderr_fd, fileno(stderr)); + fcntl(fileno(stderr), F_SETFD, stderr_flags); + close(stderr_fd); + clearerr(stderr); + fsetpos(stderr, &stderr_pos); +#endif if(remove(tempfile)) { errors++; @@ -106,6 +158,7 @@ FILE *fd; int errors = 0; +#ifdef WIN32 /* Ignore errors but include in the output and return value */ if(freopen(TTY, "w", stdout) == NULL) { errors++; @@ -115,6 +168,21 @@ errors++; printres("%s", strerror(errno)); } +#else + /* restore the original stdout */ + fflush(stdout); + dup2(stdout_fd, fileno(stdout)); + close(stdout_fd); + clearerr(stdout); + fsetpos(stdout, &stdout_pos); + + /* restore the original stderr */ + fflush(stderr); + dup2(stderr_fd, fileno(stderr)); + close(stderr_fd); + clearerr(stderr); + fsetpos(stderr, &stderr_pos); +#endif fd = fopen(tempfile, "r"); if(fd == NULL) {