diff --git a/network.h b/network.h index 4c0b0332..57e6662d 100644 --- a/network.h +++ b/network.h @@ -397,8 +397,10 @@ void backend_socket_log(Seat *seat, LogContext *logctx, typedef struct ProxyStderrBuf { char buf[8192]; size_t size; + const char *prefix; /* must be statically allocated */ } ProxyStderrBuf; void psb_init(ProxyStderrBuf *psb); +void psb_set_prefix(ProxyStderrBuf *psb, const char *prefix); void log_proxy_stderr( Plug *plug, ProxyStderrBuf *psb, const void *vdata, size_t len); @@ -429,4 +431,6 @@ struct DeferredSocketOpenerVtable { static inline void deferred_socket_opener_free(DeferredSocketOpener *dso) { dso->vt->free(dso); } +DeferredSocketOpener *null_deferred_socket_opener(void); + #endif diff --git a/putty.h b/putty.h index 4cdc9ae8..8f506fb6 100644 --- a/putty.h +++ b/putty.h @@ -2893,6 +2893,16 @@ typedef void (*toplevel_callback_notify_fn_t)(void *ctx); void request_callback_notifications(toplevel_callback_notify_fn_t notify, void *ctx); +/* + * Facility provided by the platform to spawn a parallel subprocess + * and present its stdio via a Socket. + * + * 'prefix' indicates the prefix that should appear on messages passed + * to plug_log to provide stderr output from the process. + */ +Socket *platform_start_subprocess(const char *cmd, Plug *plug, + const char *prefix); + /* * Define no-op macros for the jump list functions, on platforms that * don't support them. (This is a bit of a hack, and it'd be nicer to diff --git a/stubs/CMakeLists.txt b/stubs/CMakeLists.txt index e6b2fc31..dc02aca3 100644 --- a/stubs/CMakeLists.txt +++ b/stubs/CMakeLists.txt @@ -26,5 +26,6 @@ add_sources_from_current_dir(utils null-cipher.c null-key.c null-mac.c + null-opener.c null-plug.c null-seat.c) diff --git a/stubs/null-opener.c b/stubs/null-opener.c new file mode 100644 index 00000000..6fdb7c28 --- /dev/null +++ b/stubs/null-opener.c @@ -0,0 +1,20 @@ +/* + * Null implementation of DeferredSocketOpener. Doesn't even bother to + * allocate and free itself: there's just one static implementation + * which we hand out to any caller. + */ + +#include "putty.h" + +static void null_opener_free(DeferredSocketOpener *opener) {} + +static const DeferredSocketOpenerVtable NullOpener_vt = { + .free = null_opener_free, +}; + +static DeferredSocketOpener null_opener = { .vt = &NullOpener_vt }; + +DeferredSocketOpener *null_deferred_socket_opener(void) +{ + return &null_opener; +} diff --git a/unix/fd-socket.c b/unix/fd-socket.c index 036979d3..9758a17b 100644 --- a/unix/fd-socket.c +++ b/unix/fd-socket.c @@ -371,6 +371,13 @@ void setup_fd_socket(Socket *s, int infd, int outfd, int inerrfd) queue_toplevel_callback(fdsocket_connect_success_callback, fds); } +void fd_socket_set_psb_prefix(Socket *s, const char *prefix) +{ + FdSocket *fds = container_of(s, FdSocket, sock); + assert(fds->sock.vt == &FdSocket_sockvt); + psb_set_prefix(&fds->psb, prefix); +} + static FdSocket *make_fd_socket_internal(SockAddr *addr, int port, Plug *plug) { FdSocket *fds; diff --git a/unix/local-proxy.c b/unix/local-proxy.c index 92f2a501..157f9207 100644 --- a/unix/local-proxy.c +++ b/unix/local-proxy.c @@ -96,3 +96,21 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname, return NULL; } } + +Socket *platform_start_subprocess(const char *cmd, Plug *plug, + const char *prefix) +{ + Socket *socket = make_deferred_fd_socket( + null_deferred_socket_opener(), + sk_nonamelookup(""), 0, plug); + char *err = platform_setup_local_proxy(socket, cmd); + fd_socket_set_psb_prefix(socket, prefix); + + if (err) { + sk_close(socket); + socket = new_error_socket_fmt(plug, "%s", err); + sfree(err); + } + + return socket; +} diff --git a/unix/platform.h b/unix/platform.h index a3cbfd13..3b1db9ba 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -389,6 +389,7 @@ Socket *make_fd_socket(int infd, int outfd, int inerrfd, Socket *make_deferred_fd_socket(DeferredSocketOpener *opener, SockAddr *addr, int port, Plug *plug); void setup_fd_socket(Socket *s, int infd, int outfd, int inerrfd); +void fd_socket_set_psb_prefix(Socket *s, const char *prefix); /* * Default font setting, which can vary depending on NOT_X_WINDOWS. diff --git a/utils/log_proxy_stderr.c b/utils/log_proxy_stderr.c index 90025e08..2a84173a 100644 --- a/utils/log_proxy_stderr.c +++ b/utils/log_proxy_stderr.c @@ -7,6 +7,12 @@ void psb_init(ProxyStderrBuf *psb) { psb->size = 0; + psb->prefix = "proxy"; +} + +void psb_set_prefix(ProxyStderrBuf *psb, const char *prefix) +{ + psb->prefix = prefix; } void log_proxy_stderr(Plug *plug, ProxyStderrBuf *psb, @@ -58,7 +64,7 @@ void log_proxy_stderr(Plug *plug, ProxyStderrBuf *psb, psb->buf[endpos-1] == '\r')) endpos--; char *msg = dupprintf( - "proxy: %.*s", (int)(endpos - pos), psb->buf + pos); + "%s: %.*s", psb->prefix, (int)(endpos - pos), psb->buf + pos); plug_log(plug, PLUGLOG_PROXY_MSG, NULL, 0, msg, 0); sfree(msg); @@ -73,7 +79,8 @@ void log_proxy_stderr(Plug *plug, ProxyStderrBuf *psb, */ if (pos == 0 && psb->size == lenof(psb->buf)) { char *msg = dupprintf( - "proxy (partial line): %.*s", (int)psb->size, psb->buf); + "%s (partial line): %.*s", psb->prefix, (int)psb->size, + psb->buf); plug_log(plug, PLUGLOG_PROXY_MSG, NULL, 0, msg, 0); sfree(msg); diff --git a/windows/handle-socket.c b/windows/handle-socket.c index 0b0e60a9..2820975c 100644 --- a/windows/handle-socket.c +++ b/windows/handle-socket.c @@ -388,6 +388,13 @@ Socket *make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H, return &hs->sock; } +void handle_socket_set_psb_prefix(Socket *s, const char *prefix) +{ + HandleSocket *hs = container_of(s, HandleSocket, sock); + assert(hs->sock.vt == &HandleSocket_sockvt); + psb_set_prefix(&hs->psb, prefix); +} + static void sk_handle_deferred_close(Socket *s) { HandleSocket *hs = container_of(s, HandleSocket, sock); diff --git a/windows/local-proxy.c b/windows/local-proxy.c index 93baad6b..55e9cbf3 100644 --- a/windows/local-proxy.c +++ b/windows/local-proxy.c @@ -98,3 +98,21 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname, local_proxy_opener_set_socket(opener, socket); return socket; } + +Socket *platform_start_subprocess(const char *cmd, Plug *plug, + const char *prefix) +{ + Socket *socket = make_deferred_handle_socket( + null_deferred_socket_opener(), + sk_nonamelookup(""), 0, plug); + char *err = platform_setup_local_proxy(socket, cmd); + handle_socket_set_psb_prefix(socket, prefix); + + if (err) { + sk_close(socket); + socket = new_error_socket_fmt(plug, "%s", err); + sfree(err); + } + + return socket; +} diff --git a/windows/platform.h b/windows/platform.h index 60b8db77..bb190ad2 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -354,6 +354,7 @@ Socket *make_deferred_handle_socket(DeferredSocketOpener *opener, SockAddr *addr, int port, Plug *plug); void setup_handle_socket(Socket *s, HANDLE send_H, HANDLE recv_H, HANDLE stderr_H, bool overlapped); +void handle_socket_set_psb_prefix(Socket *s, const char *prefix); Socket *new_named_pipe_client(const char *pipename, Plug *plug); /* winnpc */ Socket *new_named_pipe_listener(const char *pipename, Plug *plug); /* winnps */