From a5599b4610788c17f5166685612f48c71d7537ac Mon Sep 17 00:00:00 2001 From: "Ned T. Crigler" Date: Thu, 24 Jun 2004 01:57:02 +0000 Subject: [PATCH] Allow the redraw method to be chosen by the user, and include the old Ctrl L character method again. --- attach.c | 18 ++++++++++++++---- dtach.h | 19 ++++++++++++++----- main.c | 33 ++++++++++++++++++++++++++++++++ master.c | 58 +++++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 102 insertions(+), 26 deletions(-) diff --git a/attach.c b/attach.c index 26ca9fd..5fe18a2 100644 --- a/attach.c +++ b/attach.c @@ -96,7 +96,7 @@ process_kbd(int s, struct packet *pkt) { /* Tell the master that we are suspending. */ pkt->type = MSG_DETACH; - write(s, pkt, sizeof(*pkt)); + write(s, pkt, sizeof(struct packet)); /* And suspend... */ tcsetattr(0, TCSADRAIN, &orig_term); @@ -106,8 +106,13 @@ process_kbd(int s, struct packet *pkt) /* Tell the master that we are returning. */ pkt->type = MSG_ATTACH; + write(s, pkt, sizeof(struct packet)); + + /* We would like a redraw, too. */ + pkt->type = MSG_REDRAW; + pkt->len = redraw_method; ioctl(0, TIOCGWINSZ, &pkt->u.ws); - write(s, pkt, sizeof(*pkt)); + write(s, pkt, sizeof(struct packet)); return; } /* Detach char? */ @@ -121,7 +126,7 @@ process_kbd(int s, struct packet *pkt) win_changed = 1; /* Push it out */ - write(s, pkt, sizeof(*pkt)); + write(s, pkt, sizeof(struct packet)); } int @@ -176,8 +181,13 @@ attach_main(int noerror) /* Tell the master that we want to attach. */ pkt.type = MSG_ATTACH; + write(s, &pkt, sizeof(struct packet)); + + /* We would like a redraw, too. */ + pkt.type = MSG_REDRAW; + pkt.len = redraw_method; ioctl(0, TIOCGWINSZ, &pkt.u.ws); - write(s, &pkt, sizeof(pkt)); + write(s, &pkt, sizeof(struct packet)); /* Wait for things to happen */ while (1) diff --git a/dtach.h b/dtach.h index 5373404..f28099a 100644 --- a/dtach.h +++ b/dtach.h @@ -74,15 +74,24 @@ #include extern char *progname, *sockname; -extern int detach_char, no_suspend; +extern int detach_char, no_suspend, redraw_method; extern struct termios orig_term; enum { - MSG_PUSH, - MSG_ATTACH, - MSG_DETACH, - MSG_WINCH, + MSG_PUSH = 0, + MSG_ATTACH = 1, + MSG_DETACH = 2, + MSG_WINCH = 3, + MSG_REDRAW = 4, +}; + +enum +{ + REDRAW_UNSPEC = 0, + REDRAW_NONE = 1, + REDRAW_CTRL_L = 2, + REDRAW_WINCH = 3, }; /* The client to master protocol. */ diff --git a/main.c b/main.c index 0835a5e..328a12c 100644 --- a/main.c +++ b/main.c @@ -35,6 +35,8 @@ char *sockname; int detach_char = '\\' - 64; /* 1 if we should not interpret the suspend character. */ int no_suspend; +/* The default redraw method. Initially set to unspecified. */ +int redraw_method = REDRAW_UNSPEC; /* ** The original terminal settings. Shared between the master and attach @@ -63,6 +65,10 @@ usage() " -e \tSet the detach character to , defaults " "to ^\\.\n" " -E\t\tDisable the detach character.\n" + " -r \tUse the specified redraw method when redrawing:\n" + "\t\t none: Don't redraw at all.\n" + "\t\t ctrl_l: Send a Ctrl L character to the program.\n" + "\t\t winch: Send a WINCH signal to the program.\n" " -z\t\tDisable processing of the suspend key.\n" "\nReport any bugs to <" PACKAGE_BUGREPORT ">.\n", PACKAGE_VERSION, __DATE__, __TIME__); @@ -153,6 +159,33 @@ main(int argc, char **argv) detach_char = argv[0][0]; break; } + else if (*p == 'r') + { + ++argv; --argc; + if (argc < 1) + { + printf("%s: No redraw method " + "specified.\n", progname); + printf("Try '%s --help' for more " + "information.\n", progname); + return 1; + } + if (strcmp(argv[0], "none") == 0) + redraw_method = REDRAW_NONE; + else if (strcmp(argv[0], "ctrl_l") == 0) + redraw_method = REDRAW_CTRL_L; + else if (strcmp(argv[0], "winch") == 0) + redraw_method = REDRAW_WINCH; + else + { + printf("%s: Invalid redraw method " + "specified.\n", progname); + printf("Try '%s --help' for more " + "information.\n", progname); + return 1; + } + break; + } else { printf("%s: Invalid option '-%c'\n", diff --git a/master.c b/master.c index 8d31651..612ce2f 100644 --- a/master.c +++ b/master.c @@ -238,7 +238,7 @@ client_activity(struct client *p) struct packet pkt; /* Read the activity. */ - len = read(p->fd, &pkt, sizeof(pkt)); + len = read(p->fd, &pkt, sizeof(struct packet)); /* Close the client on an error. */ if (len <= 0) { @@ -254,24 +254,9 @@ client_activity(struct client *p) if (pkt.type == MSG_PUSH) write(the_pty.fd, pkt.u.buf, pkt.len); - /* When attaching, we set the window size and force a redraw by sending - ** the WINCH signal to the program. - ** - ** XXX: Are there any programs that don't handle the WINCH signal - ** properly? Full-screen programs should fully redraw themselves, and - ** line-oriented programs should redraw the prompt, or do nothing. - */ + /* Attach or detach from the program. */ else if (pkt.type == MSG_ATTACH) - { p->attached = 1; - if (memcmp(&the_pty.ws, &pkt.u.ws, sizeof(struct winsize)) != 0) - { - the_pty.ws = pkt.u.ws; - ioctl(the_pty.fd, TIOCSWINSZ, &the_pty.ws); - } - else - killpty(&the_pty, SIGWINCH); - } else if (pkt.type == MSG_DETACH) p->attached = 0; @@ -281,6 +266,41 @@ client_activity(struct client *p) the_pty.ws = pkt.u.ws; ioctl(the_pty.fd, TIOCSWINSZ, &the_pty.ws); } + + /* Force a redraw using a particular method. */ + else if (pkt.type == MSG_REDRAW) + { + int method = pkt.len; + + /* If the client didn't specify a particular method, use + ** whatever we had on startup. */ + if (method == REDRAW_UNSPEC) + method = redraw_method; + if (method == REDRAW_NONE) + return; + + /* Set the window size. */ + the_pty.ws = pkt.u.ws; + ioctl(the_pty.fd, TIOCSWINSZ, &the_pty.ws); + + /* Send a ^L character if the terminal is in no-echo and + ** character-at-a-time mode. */ + if (method == REDRAW_CTRL_L) + { + char c = '\f'; + + if (((the_pty.term.c_lflag & (ECHO|ICANON)) == 0) && + (the_pty.term.c_cc[VMIN] == 1)) + { + write(the_pty.fd, &c, 1); + } + } + /* Send a WINCH signal to the program. */ + else if (method == REDRAW_WINCH) + { + killpty(&the_pty, SIGWINCH); + } + } } /* The master process - It watches over the pty process and the attached */ @@ -368,6 +388,10 @@ master_main(char **argv) int s; pid_t pid; + /* Use a default redraw method if one hasn't been specified yet. */ + if (redraw_method == REDRAW_UNSPEC) + redraw_method = REDRAW_CTRL_L; + /* Create the unix domain socket. */ s = create_socket(sockname); if (s < 0)