Now, if I log onto my machine with a non-UTF-8 terminal program, is it possible to detect if the terminal emulator understands UTF-8 and eventually can tell the script (by setting an environment variable) to convert the output to plain old latin1 instead?
attached you find a program by Gerd Krorr, which does this and an example how to use this in your shell init scripts.
Bjoern
/* * small tool to figure whenever a tty runs in utf8 mode or not. * writes a utf-8 multibyte sequence and then checks how far the * cursor has been moved. * * return codes: * 0 - don't know (stdin isn't a terminal, timeout, some error, ...) * 1 - not in utf8 * 2 - utf-8 * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <termios.h>
struct termios saved_attributes;
int saved_fl;
void
tty_raw()
{
struct termios tattr;
fcntl(0,F_GETFL,&saved_fl);
tcgetattr (0, &saved_attributes);
fcntl(0,F_SETFL,O_NONBLOCK);
memcpy(&tattr,&saved_attributes,sizeof(struct termios));
tattr.c_lflag &= ~(ICANON|ECHO);
tattr.c_cc[VMIN] = 1;
tattr.c_cc[VTIME] = 0;
tcsetattr (0, TCSAFLUSH, &tattr);
}
void
tty_restore()
{
fcntl(0,F_SETFL,saved_fl);
tcsetattr (0, TCSANOW, &saved_attributes);
}
int
select_wait()
{
struct timeval tv;
fd_set se;
FD_ZERO(&se);
FD_SET(0,&se);
tv.tv_sec = 3;
tv.tv_usec = 0;
return select(1,&se,NULL,NULL,&tv);
}
int
main(int argc, char **argv)
{
static char *teststr = "\r\xc3\xb6";
static char *cleanup = "\r \r";
static char *getpos = "\033[6n";
char retstr[16];
int pos,rc,row,col;
if (!isatty(0))
exit(0);
tty_raw();
write(1,teststr,strlen(teststr));
write(1,getpos,strlen(getpos));
for (pos = 0; pos < sizeof(retstr)-1;) {
if (0 == select_wait())
break;
if (-1 == (rc = read(0,retstr+pos,sizeof(retstr)-1-pos))) {
perror("read");
exit(0);
}
pos += rc;
if (retstr[pos-1] == 'R')
break;
}
retstr[pos] = 0;
write(1,cleanup,strlen(cleanup));
tty_restore();
rc = sscanf(retstr,"\033[%d;%dR",&row,&col);
if (2 == rc && 2 == col) {
//fprintf(stderr,"Terminal is in UTF-8 mode.\n");
exit(2);
}
exit(1);
}
########################################################################
# locale setup
# set the LC_* stuff the way we want it ...
unset `set | grep "^LC_" | cut -d= -f1`
export LC_COLLATE=POSIX
export LC_TIME=POSIX
# figure whenever the term is utf-8 or not, fixup the LANG variable
# to match the current tty settings if needed
${HOME}/bin/`uname -m`/utf8
case "$?" in
0)
# not a tty
unset LANG
;;
1)
# not utf-8
if test "`locale charmap`" == "UTF-8"; then
echo "setting LANG=en_GB [non-utf8 fixup]"
export LANG="en_GB"
fi
if test "$LANG" = ""; then
echo "setting LANG=en_GB [was unset]"
export LANG="en_GB"
fi
;;
2)
# utf-8
if test "`locale charmap`" != "UTF-8"; then
echo "setting LANG=en_GB.UTF-8 [utf8 fixup]"
export LANG="en_GB.UTF-8"
fi
;;
esac
pgp00000.pgp
Description: PGP signature
