Date: Mon, 24 May 2010 11:41:56 GMT From: Guy Yur <guyyur@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/146916: [patch] sh(1) uses dumb terminal in single-user mode Message-ID: <201005241141.o4OBfusm078825@www.freebsd.org> Resent-Message-ID: <201005241150.o4OBo1pw043981@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 146916 >Category: bin >Synopsis: [patch] sh(1) uses dumb terminal in single-user mode >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon May 24 11:50:01 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Guy Yur >Release: 8.0-RELEASE-p2 >Organization: >Environment: FreeBSD samwise.localdomain 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 #0: Sat Mar 27 00:32:42 IDT 2010 root@samwise.localdomain:/usr/obj/usr/src/sys/SAMWISE i386 >Description: 1. sh doesn't call setenv() for "TERM" so getenv("TERM") will return NULL in single-user mode when used as the first shell. libedit el_init() passes "dumb" to ncurses if getenv("TERM") returns NULL. "dumb" isn't in /usr/src/etc/termcap.small 2. sh doesn't call el_set(el, EL_TERMINAL, term) when TERM changes. so libedit will keep thinking it has a "dumb" terminal. 3. rev 206182 changed 'bin/sh/options.c' to set -o emacs if interactive shell. this is done before /.profile can set TERM= in single-user mode so el_init() is called without TERM env var >How-To-Repeat: create /etc/termcap.small.db taken from /usr/src/etc/termcap.small it should have cons25 (or xterm on CURRENT) it should not have a "dumb" entry in /.profile have export TERM=${TERM:-cons25} # xterm on CURRENT or any terminal found in /etc/termcap.small.db boot into single-user mode and use the default /bin/sh /usr shouldn't be not mounted or have /usr/share/misc/termcap.db not accessible. run `set -o emacs` see Cannot read termcap database; using dumb terminal settings. even though /etc/termcap.small.db is readable and cons25/xterm entry exists >Fix: looking in NetBSD, /bin/sh calls setenv/unsetenv for "TERM" before el_init() and calls el_set(el, EL_TERMINAL, term) when TERM changes. I have made patches using the changes against bin/sh in NetBSD. Only the TERM support changes are included in the patches. The patches are against head, svn revision 208452 cd /usr/src/bin/sh patch < /patch/to/sh.patch possible fixes to revision 206182 'bin/sh/options.c' 1. add the "dumb" entry to etc/termcap.small to silence el_init() 2. instead of enabling -o emacs in 'bin/sh/options.c', create /usr/src/etc/root/dot.shrc with set -o emacs add to /usr/src/etc/root/dot.profile ENV=$HOME/.shrc export ENV this way -o emacs will be called after /.profile has set a valid TERM Patch attached with submission follows: --- histedit.c.orig 2010-05-24 02:43:10.000000000 +0300 +++ histedit.c 2010-05-24 11:55:22.000000000 +0300 @@ -98,6 +98,8 @@ /* * turn editing on */ + char *term; + INTOFF; if (el_in == NULL) el_in = fdopen(0, "r"); @@ -107,6 +109,11 @@ el_out = fdopen(2, "w"); if (el_in == NULL || el_err == NULL || el_out == NULL) goto bad; + term = lookupvar("TERM"); + if (term) + setenv("TERM", term, 1); + else + unsetenv("TERM"); el = el_init(arg0, el_in, el_out, el_err); if (el != NULL) { if (hist) @@ -160,6 +167,13 @@ } } +void +setterm(const char *term) +{ + if (el != NULL && term != NULL) + el_set(el, EL_TERMINAL, term); +} + int histcmd(int argc, char **argv) { --- myhistedit.h.orig 2010-05-24 02:43:10.000000000 +0300 +++ myhistedit.h 2010-05-24 11:55:45.000000000 +0300 @@ -38,6 +38,7 @@ void histedit(void); void sethistsize(const char *); +void setterm(const char *); int histcmd(int, char **); int not_fcnumber(const char *); int str_to_event(const char *, int); --- var.c.orig 2010-05-24 02:43:10.000000000 +0300 +++ var.c 2010-05-24 12:03:07.000000000 +0300 @@ -80,6 +80,7 @@ #ifndef NO_HISTORY struct var vhistsize; +struct var vterm; #endif struct var vifs; struct var vmail; @@ -114,6 +115,10 @@ NULL }, { &vps4, 0, "PS4=+ ", NULL }, +#ifndef NO_HISTORY + { &vterm, VUNSET, "TERM=", + setterm }, +#endif { &voptind, 0, "OPTIND=1", getoptsreset }, { NULL, 0, NULL, --- var.h.orig 2010-05-24 02:43:10.000000000 +0300 +++ var.h 2010-05-24 11:57:07.000000000 +0300 @@ -77,6 +77,7 @@ extern struct var vps4; #ifndef NO_HISTORY extern struct var vhistsize; +extern struct var vterm; #endif /* @@ -96,6 +97,7 @@ #define optindval() (voptind.text + 7) #ifndef NO_HISTORY #define histsizeval() (vhistsize.text + 9) +#define termval() (vterm.text + 5) #endif #define mpathset() ((vmpath.flags & VUNSET) == 0) >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005241141.o4OBfusm078825>