diff --git a/configure.ac b/configure.ac index bbeeaad9..717586cb 100755 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this File with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([gsocket],[1.4.42dev]) +AC_INIT([gsocket],[1.4.42dev2]) AC_CONFIG_AUX_DIR(config) AC_CANONICAL_TARGET diff --git a/lib/event.c b/lib/event.c index 3ff1a53a..6ab8d1e0 100644 --- a/lib/event.c +++ b/lib/event.c @@ -129,7 +129,8 @@ GS_EVENT_execute(GS_EVENT_MGR *mgr) if (ret != 0) { // CB wants this event to be deleted - GS_EVENT_del(event); + if (ret != -2) + GS_EVENT_del(event); return 0; } } else { diff --git a/lib/gsocket-select.c b/lib/gsocket-select.c index bcbec3e9..9d4a06d1 100644 --- a/lib/gsocket-select.c +++ b/lib/gsocket-select.c @@ -252,10 +252,6 @@ GS_select(GS_SELECT_CTX *ctx) ctx->emgr.is_return_to_caller = 0; return 0; } - // if (((ctx->hb_freq > 0) && GS_TV_TO_USEC(ctx->tv_now) > ctx->hb_next)) - // { - // return 0; - // } } /* while (1) */ ERREXIT("NOT REACHED\n"); diff --git a/tools/4_gs-netcat.c b/tools/4_gs-netcat.c index ef45b0e7..2af871a7 100644 --- a/tools/4_gs-netcat.c +++ b/tools/4_gs-netcat.c @@ -168,7 +168,7 @@ peer_free(GS_SELECT_CTX *ctx, struct _peer *p) GS_SELECT_del_cb(ctx, fd); - DEBUGF_Y("free'ing peer on fd = %d\n", fd); + DEBUGF_Y("free'ing peer on fd = %d, size %zd\n", fd, sizeof *p); memset(p, 0, sizeof *p); XFREE(peers[fd]); // FIXME: Eventually GS_shutdown() needs to return ECALLAGAIN and then do 2 things: @@ -266,7 +266,7 @@ cbe_peer_timeout(void *ptr) GS_LOG_TSP(p, "Idle Timeout.\n"); peer_free(p->gs->ctx->gselect_ctx, p); - return -1; // Event manager to free this event. + return -2; // Event manager done & already freed. } /* *********************** FD READ / WRITE ******************************/ @@ -402,7 +402,6 @@ cb_read_fd(GS_SELECT_CTX *ctx, int fd, void *arg, int val) } } else { p->wlen = read(fd, p->wbuf, p->w_max); - // DEBUGF("read(%d)=%zd\n", fd, p->wlen); } if (p->wlen == 0) @@ -423,6 +422,9 @@ cb_read_fd(GS_SELECT_CTX *ctx, int fd, void *arg, int val) * peer might still have data to send (which we can write). */ FD_CLR(fd, ctx->rfd); // Stop reading from fd + if (gopt.is_stdin_ignore_eof) + return GS_SUCCESS; // Ignore EOF on STDIN + ret = GS_shutdown(gs); /* Destroy peer if shutdown failed or we already received a EOF from peer */ if (ret != GS_ERR_FATAL) @@ -599,12 +601,14 @@ cb_read_gs_error(GS_SELECT_CTX *ctx, struct _peer *p, ssize_t len) p->is_received_gs_eof = 1; if (gopt.is_receive_only) peer_free(ctx, p); - - // clients immediately exist if EOF from remote (-iC shell typing 'exit'). - if ((gopt.is_interactive) && (!GS_is_server(p->gs))) + else if ((gopt.is_interactive) && (!GS_is_server(p->gs))) { + // clients immediately exits if EOF from remote (-iC shell typing 'exit'). peer_free(ctx, p); + } - shutdown(p->fd_out, SHUT_WR); + if (!p->is_app_forward) + shutdown(p->fd_out, SHUT_WR); + // For app (bash) do not close stdin yet. Might still have data. Idle timeout will catch this. } else if (len < 0) { /* any ERROR (but EOF) */ DEBUGF_R("Fatal error=%zd in GS_read() (stdin-forward == %d)\n", len, p->is_stdin_forward); GS_shutdown(p->gs); @@ -1414,7 +1418,7 @@ my_usage(int code) ""); #endif - usage("skrlSgvqwCTL"); + usage("skrIlSgvqwCTL"); #ifndef STEALTH fprintf(stderr, "" " -t Check if peer is listening (do not connect)\n" diff --git a/tools/common.h b/tools/common.h index ceb27689..0fa849f6 100644 --- a/tools/common.h +++ b/tools/common.h @@ -173,6 +173,8 @@ struct _gopt int is_greetings; int is_try_server; // Check with GSRN is server is listening. int gs_server_check_sec; + int is_stdin_a_tty; + int is_stdin_ignore_eof; char *prg_name; // argv[0] uint64_t ts_ping_sent; // TimeStamp ping sent fd_set rfd, r; diff --git a/tools/utils.c b/tools/utils.c index 39a7ab80..41d19df1 100644 --- a/tools/utils.c +++ b/tools/utils.c @@ -275,6 +275,11 @@ init_vars(void) GS_LOG_V("=GS Address : %s\n", GS_addr2hex(NULL, gopt.gs_addr.addr)); + gopt.is_stdin_a_tty = isatty(STDIN_FILENO); + // Interactive session but not a TTY: Assume user is piping commands into the shell. + if ((gopt.is_interactive && (!gopt.flags & GSC_FL_IS_SERVER) && !gopt.is_stdin_a_tty)) + gopt.is_stdin_ignore_eof = 1; + signal(SIGTERM, cb_sigterm); } @@ -300,6 +305,9 @@ usage(const char *params) case 'r': fprintf(stderr, " -r Receive-only. Terminate when no more data.\n"); break; + case 'I': + fprintf(stderr, " -I Ignore EOF on stdin.\n"); + break; case 's': fprintf(stderr, " -s Secret (e.g. password).\n"); break; @@ -383,6 +391,9 @@ do_getopt(int argc, char *argv[]) case 'r': gopt.is_receive_only = 1; break; + case 'I': + gopt.is_stdin_ignore_eof = 1; + break; case 'i': gopt.is_interactive = 1; break; @@ -1039,12 +1050,12 @@ pty_cmd(const char *cmd, pid_t *pidptr, int *err) // Sometimes the user has no home directory or there is no .bashrc. // Do the best we can to set a nice prompt and give a hint to the user. + char *str = "\\[\\033[36m\\]\\u\\[\\033[m\\]@\\[\\033[32m\\]\\h:\\[\\033[33;1m\\]\\w\\[\\033[m\\]\\$ "; + snprintf(buf, sizeof buf, "PS1=%s", str); + printf("=Hint : PS1='%s'\n", str); if (GS_getenv("PS1") == NULL) { // Note: This only works for /bin/sh because bash resets this value. - char *str = "\\[\\033[36m\\]\\u\\[\\033[m\\]@\\[\\033[32m\\]\\h:\\[\\033[33;1m\\]\\w\\[\\033[m\\]$ "; - snprintf(buf, sizeof buf, "PS1=%s", str); - printf("=Hint : PS1='%s'\n", str); envp[envplen++] = strdup(buf); envp[envplen++] = "PS2=> "; } @@ -1318,7 +1329,7 @@ fd_kernel_flush(int fd) void cmd_ping(struct _peer *p) { - DEBUGF("Sending PING\n"); + DEBUGF("Sending PING (waiting-for-reply==%d)\n", p->is_want_ping); if (p->is_want_ping != 0) return; diff --git a/tools/utils.h b/tools/utils.h index 33e2fa06..ec70966f 100644 --- a/tools/utils.h +++ b/tools/utils.h @@ -42,6 +42,6 @@ void gs_watchdog(void); /* hack to set rows/columns */ #define GS_STTY_INIT_HACK "stty rows %d columns %d\r" -#define UTILS_GETOPT_STR "3:vigqwACTrlSDL:a:s:k:p:d:e:" +#define UTILS_GETOPT_STR "3:vigqwACTrIlSDL:a:s:k:p:d:e:" -#endif /* !__GSNC_UTILS_H__ */ \ No newline at end of file +#endif /* !__GSNC_UTILS_H__ */