diff --git a/CHANGES b/CHANGES index d90ffdb..c944060 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,15 @@ CHANGES ======= +version 8.1.16 (Apr 10, 2007): + - added 'replstring' substitution option - inspired by + conversation with Owen DeLong + - added '^Ecn' option for writing a note to the logfile - patch + by Bryan Schmersal + - fixed leaking file descriptors when 'host' and 'uds' consoles + fail to connect - based on patch by Michael Heironimus + + version 8.1.15 (Dec 31, 2006): - protection again telnet option negotation loops - patch by Robby Griffin @@ -865,5 +874,5 @@ before version 6.05: and enhancements of various types were applied. # -# $Id: CHANGES,v 1.217 2006/12/31 02:04:11 bryan Exp $ +# $Id: CHANGES,v 1.218 2007/04/10 21:35:45 bryan Exp $ # diff --git a/config.guess b/config.guess index 1a69546..0f0fe71 100755 --- a/config.guess +++ b/config.guess @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. -timestamp='2006-12-22' +timestamp='2007-03-06' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -791,12 +791,15 @@ EOF i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - x86:Interix*:[3456]*) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - EM64T:Interix*:[3456]* | authenticamd:Interix*:[3456]*) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; @@ -1218,6 +1221,9 @@ EOF SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; diff --git a/config.sub b/config.sub index 4b8cc7b..5defff6 100755 --- a/config.sub +++ b/config.sub @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. -timestamp='2006-12-08' +timestamp='2007-01-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -250,7 +250,7 @@ case $basic_machine in | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore \ + | maxq | mb | microblaze | mcore | mep \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -1222,7 +1222,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1417,6 +1417,9 @@ case $basic_machine in m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; diff --git a/conserver.cf/conserver.cf.man b/conserver.cf/conserver.cf.man index 431f7f5..e16751f 100644 --- a/conserver.cf/conserver.cf.man +++ b/conserver.cf/conserver.cf.man @@ -1,5 +1,5 @@ -.\" $Id: conserver.cf.man,v 1.77 2006/12/31 02:03:03 bryan Exp $ -.TH CONSERVER.CF 5 "2006/12/31" "conserver-8.1.15" "conserver" +.\" $Id: conserver.cf.man,v 1.78 2007/04/02 17:59:16 bryan Exp $ +.TH CONSERVER.CF 5 "2007/04/02" "conserver-8.1.16" "conserver" .SH NAME conserver.cf \- console configuration file for .BR conserver (8) @@ -500,12 +500,16 @@ fields. .TP String Replacement .TP +.B c +console name +.TP .B h .B host value .TP -.B c -console name +.B r +.B replstring +value .sp .PP Numeric Replacement @@ -979,6 +983,15 @@ The console option still applies when data is read by the server, and if enabled, can impact the encapsulation process. .TP +\f3replstring\fP \f2string\fP +.br +A generic replacement string that can be used by the +.BR devicesubst , +.BR execsubst , +and +.B initsubst +keywords. +.TP \f3ro\fP [\f3!\fP]\f2username\fP[\f3,\fP...]|\f3""\fP .br Define a list of users making up the read-only access list diff --git a/conserver.cf/conserver.passwd.man b/conserver.cf/conserver.passwd.man index ff8f3c5..382ea46 100644 --- a/conserver.cf/conserver.passwd.man +++ b/conserver.cf/conserver.passwd.man @@ -1,5 +1,5 @@ .\" $Id: conserver.passwd.man,v 1.10 2004/01/08 16:12:33 bryan Exp $ -.TH CONSERVER.PASSWD 5 "2004/01/08" "conserver-8.1.15" "conserver" +.TH CONSERVER.PASSWD 5 "2004/01/08" "conserver-8.1.16" "conserver" .SH NAME conserver.passwd \- user access information for .BR conserver (8) diff --git a/conserver.html b/conserver.html index 3e3ae13..37de699 100644 --- a/conserver.html +++ b/conserver.html @@ -41,6 +41,8 @@   Germany   Germany +   Ireland   Russia   US-West @@ -188,11 +190,11 @@

Downloading

-

The current version, released on Dec 31, 2006, is 8.1.15.tar.gz. You can get it +

The current version, released on Apr 10, 2007, is 8.1.16.tar.gz. You can get it via FTP - or HTTP. See the FTP + or HTTP. See the CHANGES file for information on the latest updates.

diff --git a/conserver/client.c b/conserver/client.c index fc025c9..3f5446f 100644 --- a/conserver/client.c +++ b/conserver/client.c @@ -1,5 +1,5 @@ /* - * $Id: client.c,v 5.90 2006/04/03 13:32:08 bryan Exp $ + * $Id: client.c,v 5.91 2007/04/02 18:18:58 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -399,6 +399,7 @@ static HELP aHLTable[] = { {WHEN_ATTACH, "l0 send break per config file"}, {WHEN_ATTACH, "l1-9 send specific break sequence"}, {WHEN_ALWAYS, "m display the message of the day"}, + {WHEN_ALWAYS, "n write a note to the logfile"}, {WHEN_ALWAYS, "o (re)open the tty and log file"}, {WHEN_ALWAYS, "p playback the last %hu lines"}, {WHEN_ALWAYS, "P set number of playback lines"}, diff --git a/conserver/client.h b/conserver/client.h index 257be9e..705ea9b 100644 --- a/conserver/client.h +++ b/conserver/client.h @@ -1,5 +1,5 @@ /* - * $Id: client.h,v 5.41 2006/04/03 13:32:08 bryan Exp $ + * $Id: client.h,v 5.42 2007/04/02 18:18:59 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -50,7 +50,8 @@ typedef enum clientState { S_CWAIT, /* wait for client */ S_CEXEC, /* client execing a program */ S_REPLAY, /* set replay length for 'r' */ - S_PLAYBACK /* set replay length for 'p' */ + S_PLAYBACK, /* set replay length for 'p' */ + S_NOTE /* send a note to the logfile */ } CLIENTSTATE; typedef struct client { /* Connection Information: */ diff --git a/conserver/consent.c b/conserver/consent.c index 131a630..ca3161d 100644 --- a/conserver/consent.c +++ b/conserver/consent.c @@ -1,5 +1,5 @@ /* - * $Id: consent.c,v 5.150 2006/06/17 02:03:15 bryan Exp $ + * $Id: consent.c,v 5.151 2007/04/09 15:52:28 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -896,12 +896,14 @@ ConsInit(pCE) ("[%s] setsockopt(%u,SO_KEEPALIVE): %s: forcing down", pCE->server, cofile, strerror(errno)); ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } #endif if (!SetFlags(cofile, O_NONBLOCK, 0)) { ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } @@ -913,6 +915,7 @@ ConsInit(pCE) Error("[%s] connect(%u): %s: forcing down", pCE->server, cofile, strerror(errno)); ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } } @@ -923,6 +926,7 @@ ConsInit(pCE) ("[%s] FileOpenFD(%d,simpleSocket) failed: forcing down", pCE->server, cofile); ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } if (ret == 0) { @@ -971,6 +975,7 @@ ConsInit(pCE) if (!SetFlags(cofile, O_NONBLOCK, 0)) { ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } @@ -981,6 +986,7 @@ ConsInit(pCE) Error("[%s] connect(%u): %s: forcing down", pCE->server, cofile, strerror(errno)); ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } } @@ -991,6 +997,7 @@ ConsInit(pCE) ("[%s] FileOpenFD(%d,simpleSocket) failed: forcing down", pCE->server, cofile); ConsDown(pCE, FLAGTRUE, FLAGTRUE); + close(cofile); return; } if (ret == 0) { diff --git a/conserver/consent.h b/conserver/consent.h index c097204..dec5f52 100644 --- a/conserver/consent.h +++ b/conserver/consent.h @@ -1,5 +1,5 @@ /* - * $Id: consent.h,v 5.67 2006/05/28 17:27:14 bryan Exp $ + * $Id: consent.h,v 5.68 2007/04/02 17:59:16 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -121,6 +121,7 @@ typedef struct consent { /* console information */ char *idlestring; /* string to print when idle */ unsigned short spinmax; /* initialization spin maximum */ unsigned short spintimer; /* initialization spin timer */ + char *replstring; /* generic string for replacements */ /* timestamp stuff */ int mark; /* Mark (chime) interval */ long nextMark; /* Next mark (chime) time */ diff --git a/conserver/conserver.man b/conserver/conserver.man index 36da1a2..0f33d2c 100644 --- a/conserver/conserver.man +++ b/conserver/conserver.man @@ -1,6 +1,6 @@ .\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine .\" $Id: conserver.man,v 1.54 2006/12/31 02:02:48 bryan Exp $ -.TH CONSERVER 8 "2006/12/31" "conserver-8.1.15" "conserver" +.TH CONSERVER 8 "2006/12/31" "conserver-8.1.16" "conserver" .SH NAME conserver \- console server daemon .SH SYNOPSIS diff --git a/conserver/group.c b/conserver/group.c index b1ad0ae..ea6bd76 100644 --- a/conserver/group.c +++ b/conserver/group.c @@ -1,5 +1,5 @@ /* - * $Id: group.c,v 5.327 2006/06/17 02:02:00 bryan Exp $ + * $Id: group.c,v 5.329 2007/04/02 18:18:59 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -622,6 +622,8 @@ DestroyConsent(pGE, pCE) free(pCE->motd); if (pCE->idlestring != (char *)0) free(pCE->idlestring); + if (pCE->replstring != (char *)0) + free(pCE->replstring); if (pCE->execSlave != (char *)0) free(pCE->execSlave); while (pCE->aliases != (NAMES *)0) { @@ -3274,6 +3276,21 @@ DoClientRead(pGE, pCLServing) /* these are not used in this mode */ break; + case S_NOTE: + if (GatherLine(acIn[i], 0, G_TEXT, pCLServing)) { + FileWrite(pCLServing->fd, FLAGFALSE, "]\r\n", + 3); + BuildString((char *)0, bcast); + BuildString("NOTE -- ", bcast); + BuildString(pCLServing->acid->string, bcast); + BuildString(": ", bcast); + BuildString(pCLServing->accmd->string, bcast); + TagLogfile(pCEServing, bcast->string); + BuildString((char *)0, pCLServing->accmd); + pCLServing->iState = S_NORMAL; + } + continue; + case S_BCAST: if (GatherLine(acIn[i], 0, G_TEXT, pCLServing)) { FileWrite(pCLServing->fd, FLAGFALSE, "]\r\n", @@ -3663,6 +3680,18 @@ DoClientRead(pGE, pCLServing) pCEServing->motd); break; + case 'n': /* note message to log file */ + if (pCEServing->fdlog == (CONSFILE *)0) { + FileWrite(pCLServing->fd, FLAGFALSE, + "no log file on this console]\r\n", -1); + } else { + FileWrite(pCLServing->fd, FLAGFALSE, + "Enter note: ", -1); + BuildString((char *)0, pCLServing->accmd); + pCLServing->iState = S_NOTE; + } + break; + case 'o': /* close and re-open line */ CommandOpen(pGE, pCLServing, pCEServing, tyme); diff --git a/conserver/main.c b/conserver/main.c index b37e824..38b66dd 100644 --- a/conserver/main.c +++ b/conserver/main.c @@ -1,5 +1,5 @@ /* - * $Id: main.c,v 5.200 2006/04/03 13:32:08 bryan Exp $ + * $Id: main.c,v 5.201 2007/04/02 17:59:16 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -783,6 +783,8 @@ SummarizeDataStructures() size += strlen(pCE->motd); if (pCE->idlestring != (char *)0) size += strlen(pCE->idlestring); + if (pCE->replstring != (char *)0) + size += strlen(pCE->replstring); if (pCE->fdlog != (CONSFILE *)0) size += sizeof(CONSFILE); if (pCE->cofile != (CONSFILE *)0) @@ -974,9 +976,10 @@ DumpDataStructures() CONDDEBUG((1, "DumpDataStructures(): inituid=%d, initgid=%d", pCE->inituid, pCE->initgid)); CONDDEBUG((1, - "DumpDataStructures(): motd=%s, idletimeout=%d, idlestring=%s", + "DumpDataStructures(): motd=%s, idletimeout=%d, idlestring=%s, replstring=%s", EMPTYSTR(pCE->motd), pCE->idletimeout, - EMPTYSTR(pCE->idlestring))); + EMPTYSTR(pCE->idlestring), + EMPTYSTR(pCE->replstring))); if (pCE->ro) { CONSENTUSERS *u; for (u = pCE->ro; u != (CONSENTUSERS *)0; u = u->next) { diff --git a/conserver/readcfg.c b/conserver/readcfg.c index f739857..f4e8347 100644 --- a/conserver/readcfg.c +++ b/conserver/readcfg.c @@ -1,5 +1,5 @@ /* - * $Id: readcfg.c,v 5.192 2006/03/20 16:47:03 bryan Exp $ + * $Id: readcfg.c,v 5.193 2007/04/02 17:59:16 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -591,6 +591,8 @@ DestroyParserDefaultOrConsole(c, ph, pt) free(c->motd); if (c->idlestring != (char *)0) free(c->idlestring); + if (c->replstring != (char *)0) + free(c->replstring); if (c->execSlave != (char *)0) free(c->execSlave); while (c->aliases != (NAMES *)0) { @@ -777,6 +779,12 @@ ApplyDefault(d, c) if ((c->idlestring = StrDup(d->idlestring)) == (char *)0) OutOfMem(); } + if (d->replstring != (char *)0) { + if (c->replstring != (char *)0) + free(c->replstring); + if ((c->replstring = StrDup(d->replstring)) == (char *)0) + OutOfMem(); + } CopyConsentUserList(d->ro, &(c->ro)); CopyConsentUserList(d->rw, &(c->rw)); } @@ -980,27 +988,31 @@ SubstValue(c, s, i) #endif { int retval = 0; + CONSENT *pCE; + static char *empty = ""; + + if (substData->data == (void *)0) + return 0; + pCE = (CONSENT *)(substData->data); if (s != (char **)0) { - CONSENT *pCE; - if (substData->data == (void *)0) - return 0; - - pCE = (CONSENT *)(substData->data); if (c == 'h') { (*s) = pCE->host; retval = 1; } else if (c == 'c') { (*s) = pCE->server; retval = 1; + } else if (c == 'r') { + if (pCE->replstring == (char *)0) { + (*s) = empty; + } else { + (*s) = pCE->replstring; + } + retval = 1; } } if (i != (int *)0) { - CONSENT *pCE; - if (substData->data == (void *)0) - return 0; - pCE = (CONSENT *)(substData->data); if (c == 'p') { (*i) = pCE->port; retval = 1; @@ -1055,6 +1067,7 @@ SubstToken(c) return ISNUMBER; case 'h': case 'c': + case 'r': substTokenCount[(unsigned)c]++; return ISSTRING; default: @@ -2011,6 +2024,38 @@ DefaultItemProtocol(id) ProcessProtocol(parserDefaultTemp, id); } +void +#if PROTOTYPES +ProcessReplstring(CONSENT *c, char *id) +#else +ProcessReplstring(c, id) + CONSENT *c; + char *id; +#endif +{ + if (c->replstring != (char *)0) { + free(c->replstring); + c->replstring = (char *)0; + } + if ((id == (char *)0) || (*id == '\000')) + return; + if ((c->replstring = StrDup(id)) + == (char *)0) + OutOfMem(); +} + +void +#if PROTOTYPES +DefaultItemReplstring(char *id) +#else +DefaultItemReplstring(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemReplstring(%s) [%s:%d]", id, file, line)); + ProcessReplstring(parserDefaultTemp, id); +} + void #if PROTOTYPES ProcessIdletimeout(CONSENT *c, char *id) @@ -2991,6 +3036,7 @@ ConsoleAdd(c) SwapStr(&pCEmatch->motd, &c->motd); SwapStr(&pCEmatch->idlestring, &c->idlestring); + SwapStr(&pCEmatch->replstring, &c->replstring); pCEmatch->portinc = c->portinc; pCEmatch->portbase = c->portbase; pCEmatch->spinmax = c->spinmax; @@ -3766,6 +3812,18 @@ ConsoleItemProtocol(id) ProcessProtocol(parserConsoleTemp, id); } +void +#if PROTOTYPES +ConsoleItemReplstring(char *id) +#else +ConsoleItemReplstring(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemReplstring(%s) [%s:%d]", id, file, line)); + ProcessReplstring(parserConsoleTemp, id); +} + void #if PROTOTYPES ConsoleItemIdletimeout(char *id) @@ -4831,6 +4889,7 @@ ITEM keyDefault[] = { {"portbase", DefaultItemPortbase}, {"portinc", DefaultItemPortinc}, {"protocol", DefaultItemProtocol}, + {"replstring", DefaultItemReplstring}, {"ro", DefaultItemRo}, {"rw", DefaultItemRw}, {"timestamp", DefaultItemTimestamp}, @@ -4869,6 +4928,7 @@ ITEM keyConsole[] = { {"portbase", ConsoleItemPortbase}, {"portinc", ConsoleItemPortinc}, {"protocol", ConsoleItemProtocol}, + {"replstring", ConsoleItemReplstring}, {"ro", ConsoleItemRo}, {"rw", ConsoleItemRw}, {"timestamp", ConsoleItemTimestamp}, diff --git a/conserver/version.h b/conserver/version.h index 29f544c..8a0ddf6 100644 --- a/conserver/version.h +++ b/conserver/version.h @@ -1,5 +1,5 @@ /* - * $Id: version.h,v 1.74 2007/01/01 04:41:08 bryan Exp $ + * $Id: version.h,v 1.75 2007/04/10 21:36:34 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -16,6 +16,6 @@ All rights reserved.\n" #define VERSION_MAJOR 8 #define VERSION_MINOR 1 -#define VERSION_REV 15 +#define VERSION_REV 16 #define VERSION_TEXT "conserver.com version" #define VERSION_UINT (VERSION_MAJOR * 1000000 + VERSION_MINOR * 1000 + VERSION_REV) diff --git a/console/console.man b/console/console.man index cf0b1cc..f05b0e1 100644 --- a/console/console.man +++ b/console/console.man @@ -1,5 +1,5 @@ .\" $Id: console.man,v 1.61 2006/04/03 13:32:12 bryan Exp $ -.TH CONSOLE 1 "2006/04/03" "conserver-8.1.15" "conserver" +.TH CONSOLE 1 "2006/04/03" "conserver-8.1.16" "conserver" .SH NAME console \- console server client program .SH SYNOPSIS diff --git a/contrib/redhat-rpm/conserver.spec b/contrib/redhat-rpm/conserver.spec index 352e50f..08bb0f7 100644 --- a/contrib/redhat-rpm/conserver.spec +++ b/contrib/redhat-rpm/conserver.spec @@ -4,7 +4,7 @@ # %define pkg conserver -%define ver 8.1.15 +%define ver 8.1.16 # define the name of the machine on which the main conserver # daemon will be running if you don't want to use the default diff --git a/contrib/solaris-package/pkginfo b/contrib/solaris-package/pkginfo index 447fc2c..32e6bb9 100644 --- a/contrib/solaris-package/pkginfo +++ b/contrib/solaris-package/pkginfo @@ -1,7 +1,7 @@ PKG="conserver" NAME="Console server and client" CATEGORY="system" -VERSION="8.1.15" +VERSION="8.1.16" DESC="Console server and client" CLASSES=none ARCH=sparc diff --git a/test/results/test2 b/test/results/test2 index 031479a..8cc7064 100644 --- a/test/results/test2 +++ b/test/results/test2 @@ -7,13 +7,13 @@ g group info i information dump L toggle logging on/off l? break sequence list l0 send break per config file l1-9 send specific break sequence - m display the message of the day o (re)open the tty and log file - p playback the last 60 lines P set number of playback lines - r replay the last 20 lines R set number of replay lines - s spy mode (read only) u show host status - v show version info w who is on this console - x show console baud info z suspend the connection - | attach local command ? print this message - ignore/abort command ^R replay the last line - \ooo send character by octal code + m display the message of the day n write a note to the logfile + o (re)open the tty and log file p playback the last 60 lines + P set number of playback lines r replay the last 20 lines + R set number of replay lines s spy mode (read only) + u show host status v show version info + w who is on this console x show console baud info + z suspend the connection | attach local command + ? print this message ignore/abort command + ^R replay the last line \ooo send character by octal code [disconnect] diff --git a/test/results/test7 b/test/results/test7 index 031479a..8cc7064 100644 --- a/test/results/test7 +++ b/test/results/test7 @@ -7,13 +7,13 @@ g group info i information dump L toggle logging on/off l? break sequence list l0 send break per config file l1-9 send specific break sequence - m display the message of the day o (re)open the tty and log file - p playback the last 60 lines P set number of playback lines - r replay the last 20 lines R set number of replay lines - s spy mode (read only) u show host status - v show version info w who is on this console - x show console baud info z suspend the connection - | attach local command ? print this message - ignore/abort command ^R replay the last line - \ooo send character by octal code + m display the message of the day n write a note to the logfile + o (re)open the tty and log file p playback the last 60 lines + P set number of playback lines r replay the last 20 lines + R set number of replay lines s spy mode (read only) + u show host status v show version info + w who is on this console x show console baud info + z suspend the connection | attach local command + ? print this message ignore/abort command + ^R replay the last line \ooo send character by octal code [disconnect]