On Thu, Apr 26, 2007 at 05:36:18PM +0200, Josip Rodin wrote:
> Even if I run it with another COLUMNS environment variable, this doesn't
> change.
Searching the bugs and reading the code, I stumbled upon this:
def get_terminal_width():
"""
this does not work:
if os.environ.has_key('COLUMNS'):
return int(os.environ['COLUMNS'])
else:
return 80
"""
c = commands.getoutput('resize').split('\n')
First of all, this doesn't work out because I don't have the program
resize(1). pydf also didn't help me get it, because it no longer resides in
the xutils package - it is now part of the xterm package.
Secondly, you *really* should be able to fetch environment variables
somehow other than invoking an unrelated binary program that does it for you.
Someone who knows Python could contribute a working method.
Google indicates that os.getenv() or os.environ.get() might be it, but
upon testing, I see that I can get variables such as USER or PATH, but not
COLUMNS. Running env(1) doesn't show the variables COLUMNS and LINES,
so I guess that's the reason.
Yet, there are other simple ways to get it from the shell. This works from
bash and zsh:
% set | grep ^COLUMNS
COLUMNS=94
I tried to find it in tcsh, but it's not there like that :(
One could also dissect resize(1) and replicate the same in Python.
I've attached the extracted version of all that is needed from resize(1).
It's possible that more stuff can be weeded out of it, I didn't read too
much into it.
(The attachment carries the same copyright and license as
xterm-225/resize.c, obviously.)
--
2. That which causes joy or happiness.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <term.h>
#include <sys/ioctl.h>
#define ESCAPE(string) "\033" string
#define EMULATIONS 2
#define VT100 0
#define TIMEOUT 10
static struct termio tioorig;
static char *getsize[EMULATIONS] =
{
ESCAPE("7") ESCAPE("[r") ESCAPE("[999;999H") ESCAPE("[6n"),
ESCAPE("[18t"),
};
static char *restore[EMULATIONS] =
{
ESCAPE("8"),
0,
};
static char *size[EMULATIONS] =
{
ESCAPE("[%d;%dR"),
ESCAPE("[8;%d;%dt"),
};
static int tty;
static FILE *ttyfp;
static void onintr(int sig)
{
ioctl(tty, TCSETAW, &tioorig);
exit(1);
}
static void resize_timeout(int sig)
{
fprintf(stderr, "\nTime out occurred\r\n");
onintr(sig);
}
static void readstring(register FILE *fp, register char *buf, char *str)
{
register int last, c;
/* What is the advantage of setitimer() over alarm()? */
struct itimerval it;
signal(SIGALRM, resize_timeout);
bzero((char *) &it, sizeof(struct itimerval));
it.it_value.tv_sec = TIMEOUT;
setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
if ((c = getc(fp)) == 0233) { /* meta-escape, CSI */
*buf++ = c = ESCAPE("")[0];
*buf++ = '[';
} else {
*buf++ = c;
}
if (c != *str) {
fprintf(stderr, "unknown character, exiting.\r\n");
onintr(0);
}
last = str[strlen(str) - 1];
while ((*buf++ = getc(fp)) != last) ;
bzero((char *) &it, sizeof(struct itimerval));
setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
*buf = 0;
}
int main() {
register int emu = VT100;
int rows, cols;
struct termio tio;
char buf[BUFSIZ];
char *name_of_tty = "/dev/tty";
if ((ttyfp = fopen(name_of_tty, "r+")) == NULL) {
fprintf(stderr, "can't open terminal %s\n", name_of_tty);
exit(1);
}
tty = fileno(ttyfp);
ioctl(tty, TCGETA, &tioorig);
tio = tioorig;
tio.c_iflag &= ~(ICRNL | IUCLC);
tio.c_lflag &= ~(ICANON | ECHO);
tio.c_cflag |= CS8;
tio.c_cc[VMIN] = 6;
tio.c_cc[VTIME] = 1;
signal(SIGINT, onintr);
signal(SIGQUIT, onintr);
signal(SIGTERM, onintr);
ioctl(tty, TCSETAW, &tio);
write(tty, getsize[emu], strlen(getsize[emu]));
readstring(ttyfp, buf, size[emu]);
if (sscanf(buf, size[emu], &rows, &cols) != 2) {
fprintf(stderr, "Can't get rows and columns\r\n");
onintr(0);
}
if (restore[emu])
write(tty, restore[emu], strlen(restore[emu]));
ioctl(tty, TCSETAW, &tioorig);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
printf("COLUMNS=%d\n", cols);
return 0;
}