From 6ffbd82a64d472d700d97d6266ba6dc2b6bbc162 Mon Sep 17 00:00:00 2001 From: "Ned T. Crigler" Date: Fri, 28 Sep 2001 00:50:56 +0000 Subject: initial import to sourceforge --- attach.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 attach.c (limited to 'attach.c') diff --git a/attach.c b/attach.c new file mode 100644 index 0000000..c5fb412 --- /dev/null +++ b/attach.c @@ -0,0 +1,250 @@ +/* + dtach - A simple program that emulates the detach feature of screen. + Copyright (C) 2001 Ned T. Crigler + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "detach.h" + +#ifndef VDISABLE +#ifdef _POSIX_VDISABLE +#define VDISABLE _POSIX_VDISABLE +#else +#define VDISABLE 0377 +#endif +#endif + +// The current terminal settings. After coming back from a suspend, we +// restore this. +static struct termios cur_term; +// 1 if the window size changed +static int win_changed; +// 1 if we want a redraw +static int want_redraw; + +// This hopefully moves to the bottom of the screen +#define EOS "\033[999H" + +// Restores the original terminal settings. +static void +restore_term(void) +{ + tcsetattr(0, TCSADRAIN, &orig_term); + // Make cursor visible. Assumes VT100. + printf("\033[?25h\033[?0c"); + fflush(stdout); +} + +// Connects to a unix domain socket +static int +connect_socket(char *name) +{ + int s; + struct sockaddr_un sun; + + s = socket(PF_UNIX, SOCK_STREAM, 0); + if (s < 0) + return -1; + sun.sun_family = AF_UNIX; + strcpy(sun.sun_path, name); + if (connect(s, (struct sockaddr*)&sun, sizeof(sun)) < 0) + return -1; + return s; +} + +// Signal +static RETSIGTYPE +die(int sig) +{ + // Print a nice pretty message for some things. + if (sig == SIGHUP || sig == SIGINT) + printf(EOS "\r\n[detached]\r\n"); + else + printf(EOS "\r\n[got signal %d - dying]\r\n", sig); + exit(1); +} + +// Window size change. +static RETSIGTYPE +win_change() +{ + win_changed = 1; +} + +// Handles input from the keyboard. +static void +process_kbd(int s, struct packet *pkt) +{ + // Suspend? + if (!no_suspend && (pkt->u.buf[0] == cur_term.c_cc[VSUSP])) + { + // Tell the master that we are suspending. + pkt->type = MSG_DETACH; + write(s, pkt, sizeof(*pkt)); + + // And suspend... + tcsetattr(0, TCSADRAIN, &orig_term); + kill(getpid(), SIGTSTP); + tcsetattr(0, TCSADRAIN, &cur_term); + + // Tell the master that we are returning. + pkt->type = MSG_ATTACH; + write(s, pkt, sizeof(*pkt)); + + // The window size might have changed, and we definately want + // a redraw. We don't want to pass the suspend, though. + win_changed = 1; + want_redraw = 1; + return; + } + // Detach char? + else if (pkt->u.buf[0] == detach_char) + { + printf(EOS "\r\n[detached]\r\n"); + exit(1); + } + // Just in case something pukes out. + else if (pkt->u.buf[0] == '\f') + win_changed = 1; + + // Push it out + write(s, pkt, sizeof(*pkt)); +} + +int +attach_main(int noerror) +{ + int s; + struct pollfd polls[2]; + struct packet pkt; + unsigned char buf[BUFSIZE]; + + // The current terminal settings are equal to the original terminal + // settings at this point. + cur_term = orig_term; + + // Set a trap to restore the terminal when we die. + atexit(restore_term); + + // Set some signals. + signal(SIGPIPE, SIG_IGN); + signal(SIGXFSZ, SIG_IGN); + signal(SIGHUP, die); + signal(SIGTERM, die); + signal(SIGINT, die); + signal(SIGQUIT, die); + signal(SIGWINCH, win_change); + + // Attempt to open the socket. Don't display an error if noerror is + // set. + s = connect_socket(sockname); + if (s < 0) + { + if (!noerror) + printf("%s: %s: %s\n", progname, sockname, + strerror(errno)); + return 1; + } + + // Set raw mode, almost. We allow flow control to work, for instance. + cur_term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); + cur_term.c_oflag &= ~(OPOST); + cur_term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + cur_term.c_cflag &= ~(CSIZE|PARENB); + cur_term.c_cflag |= CS8; + cur_term.c_cc[VLNEXT] = VDISABLE; + + tcsetattr(0, TCSADRAIN, &cur_term); + + // Clear the screen. This assumes VT100. + write(1, "\33[H\33[J", 6); + + // Set up the poll structures + polls[0].fd = 0; + polls[0].events = POLLIN; + polls[0].revents = 0; + polls[1].fd = s; + polls[1].events = POLLIN; + polls[1].revents = 0; + + // Send our window size. + pkt.type = MSG_WINCH; + ioctl(0, TIOCGWINSZ, &pkt.u.ws); + write(s, &pkt, sizeof(pkt)); + // We would like a redraw, too. + pkt.type = MSG_REDRAW; + write(s, &pkt, sizeof(pkt)); + + // Wait for things to happen + while (1) + { + if (poll(polls, 2, -1) < 0) + { + if (errno != EINTR && errno != EAGAIN) + { + printf(EOS "\r\n[poll failed]\r\n"); + exit(1); + } + } + // Pty activity + if (polls[1].revents != 0) + { + int len = read(s, buf, sizeof(buf)); + + if (len == 0) + { + printf(EOS "\r\n[EOF - dtach terminating]" + "\r\n"); + exit(1); + } + else if (len < 0) + { + printf(EOS "\r\n[read returned an error]\r\n"); + exit(1); + } + // Send the data to the terminal. + write(1, buf, len); + } + // stdin activity + if (polls[0].revents != 0) + { + pkt.type = MSG_PUSH; + memset(pkt.u.buf, 0, sizeof(pkt.u.buf)); + pkt.len = read(0, pkt.u.buf, sizeof(pkt.u.buf)); + + if (pkt.len <= 0) + exit(1); + process_kbd(s, &pkt); + } + // Window size changed? + if (win_changed) + { + win_changed = 0; + + pkt.type = MSG_WINCH; + ioctl(0, TIOCGWINSZ, &pkt.u.ws); + write(s, &pkt, sizeof(pkt)); + } + // Want a redraw? + if (want_redraw) + { + want_redraw = 0; + + pkt.type = MSG_REDRAW; + write(s, &pkt, sizeof(pkt)); + } + } + return 0; +} -- cgit v1.2.3