From 087e89f7a8fecba3e8d276ab9808f10e6077784b Mon Sep 17 00:00:00 2001 From: "Ned T. Crigler" Date: Sat, 18 Jul 2015 13:13:09 -0700 Subject: [PATCH] Add dtach -p. dtach -p copies the contents of standard input to a session. Based on an initial patch by @johnlane. --- README | 9 ++++++++ attach.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dtach.1 | 11 ++++++++++ dtach.h | 1 + main.c | 18 ++++++++++++++- 5 files changed, 105 insertions(+), 1 deletion(-) diff --git a/README b/README index fc3dc08..f732b8b 100644 --- a/README +++ b/README @@ -66,6 +66,15 @@ will likely encounter problems if your terminals have different window sizes. Pressing ^L (Ctrl-L) will reset the window size of the program to match the current terminal. +dtach also has a mode that copies the contents of standard input to a session. +For example: + + $ echo -ne 'cd /var/log\nls -l\n' | dtach -p /tmp/foozle + +The contents are sent verbatim including any embedded control characters (e.g. +the newline characters in the above example), and dtach will not scan the +input for a detach character. + 3. DETACHING FROM THE SESSION By default, dtach scans the keyboard input looking for the detach character. diff --git a/attach.c b/attach.c index 45788e2..c01e86d 100644 --- a/attach.c +++ b/attach.c @@ -292,3 +292,70 @@ attach_main(int noerror) } return 0; } + +int +push_main() +{ + struct packet pkt; + int s; + + /* Attempt to open the socket. */ + s = connect_socket(sockname); + if (s < 0 && errno == ENAMETOOLONG) + { + char *slash = strrchr(sockname, '/'); + + /* Try to shorten the socket's path name by using chdir. */ + if (slash) + { + int dirfd = open(".", O_RDONLY); + + if (dirfd >= 0) + { + *slash = '\0'; + if (chdir(sockname) >= 0) + { + s = connect_socket(slash + 1); + fchdir(dirfd); + } + *slash = '/'; + close(dirfd); + } + } + } + if (s < 0) + { + printf("%s: %s: %s\n", progname, sockname, strerror(errno)); + return 1; + } + + /* Set some signals. */ + signal(SIGPIPE, SIG_IGN); + + /* Push the contents of standard input to the socket. */ + pkt.type = MSG_PUSH; + for (;;) + { + ssize_t len; + + memset(pkt.u.buf, 0, sizeof(pkt.u.buf)); + len = read(0, pkt.u.buf, sizeof(pkt.u.buf)); + + if (len == 0) + return 0; + else if (len < 0) + { + printf("%s: %s: %s\n", progname, sockname, + strerror(errno)); + return 1; + } + + pkt.len = len; + if (write(s, &pkt, sizeof(struct packet)) < 0) + { + printf("%s: %s: %s\n", progname, sockname, + strerror(errno)); + return 1; + } + } +} diff --git a/dtach.1 b/dtach.1 index abc700e..6819358 100644 --- a/dtach.1 +++ b/dtach.1 @@ -16,6 +16,9 @@ dtach \- simple program that emulates the detach feature of screen. .br .B dtach \-N .I +.br +.B dtach \-p +.I .SH DESCRIPTION .B dtach @@ -103,6 +106,14 @@ created in which the specified program is executed. .B dtach does not try to attach to the newly created session, however, and will stay in the foreground until the program exits. +.TP +.B \-p +Copies the contents of standard input to a session. +.B dtach +connects to the session specified by +.IR , +copies the contents of standard input to the session, and then exits. dtach +will not scan the input for a detach character. .PP .SS OPTIONS diff --git a/dtach.h b/dtach.h index 059278e..88946a0 100644 --- a/dtach.h +++ b/dtach.h @@ -129,6 +129,7 @@ struct packet int attach_main(int noerror); int master_main(char **argv, int waitattach, int dontfork); +int push_main(void); #ifdef sun #define BROKEN_MASTER diff --git a/main.c b/main.c index 4bd55c3..0f9f459 100644 --- a/main.c +++ b/main.c @@ -56,6 +56,7 @@ usage() " dtach -c \n" " dtach -n \n" " dtach -N \n" + " dtach -p \n" "Modes:\n" " -a\t\tAttach to the specified socket.\n" " -A\t\tAttach to the specified socket, or create it if it\n" @@ -66,6 +67,8 @@ usage() " -N\t\tCreate a new socket and run the specified command " "detached,\n" "\t\t and have dtach run in the foreground.\n" + " -p\t\tCopy the contents of standard input to the specified\n" + "\t\t socket.\n" "Options:\n" " -e \tSet the detach character to , defaults " "to ^\\.\n" @@ -106,7 +109,7 @@ main(int argc, char **argv) if (mode == '?') usage(); else if (mode != 'a' && mode != 'c' && mode != 'n' && - mode != 'A' && mode != 'N') + mode != 'A' && mode != 'N' && mode != 'p') { printf("%s: Invalid mode '-%c'\n", progname, mode); printf("Try '%s --help' for more information.\n", @@ -133,6 +136,19 @@ main(int argc, char **argv) sockname = *argv; ++argv; --argc; + if (mode == 'p') + { + if (argc > 0) + { + printf("%s: Invalid number of arguments.\n", + progname); + printf("Try '%s --help' for more information.\n", + progname); + return 1; + } + return push_main(); + } + while (argc >= 1 && **argv == '-') { char *p;