Passing a termcap entry into a program

Hello. I'm trying to run a program like this:

TERM=pcansi-25 cp437 ./myprogram

My question is, can I include this in the program source code, and have it execute within the code? I've tried putenv(), setenv() all of which don't seem to work.

Thank you.

cp437 is a program to display a program with ANSI graphics. myprogram isn't reliant on this.

Hi @ignatius,

i had just started writing some text when the thread closed :slight_smile:

Unfortunately, I don't quite understand the command TERM=pcansi-25 cp437 ./myprogram. Do you want the content, i.e. show the hexdump of your compiled program or the output of your program? It is not clear to me which of the two programs should process the new TERM value.

The shell passes TERM in your command only to cp437, where ./myprogram is an argument of cp437, the former is therefore not started by the shell. But it could very well be started by cp437.

Ok.. TERM=pcansi-25 ./myprogram is how the program is executed. The cp437 isn't needed. I shouldn't have insinuated that. What i'd like to do, ultimately, is write some code in the source, and have it display the pcansi-25 termcap entry upon execution.. Like I said, i've tried putenv(), setenv()... none of which seem to work.

So, how would I write what i'd like it to do in the source code? TERM=pcansi-25 ./myprogram just passes the TERM environment variable on the command line, to myprogram and executes it.

Thank you.

Hello,

You've not stated which programming language you're using here - I'm going to assume it's C, given that you're talking about getenv and setenv. Now I'm not an expert in C by any means, but in days long gone by I do remember using getenv, as you say, to do this.

Here's a quick-and-dirty C programme to get and display the contents of the TERM environment variable.

#include <stdio.h>
#include <stdlib.h>

int main()
{
const char* s = getenv("TERM");
printf("TERM: %s\n",s);
}

Here's what we get when we compile and run this, a CentOS 7 test system.

# gcc -o getterm getterm.c
# ./getterm
TERM: xterm-256color
# export TERM=vt100
# ./getterm
TERM: vt100
# export TERM=xterm
# ./getterm
TERM: xterm
#

And so on in that style.

So if this is what you're after, I hope this helps you to see how getenv can be used to get the variable(s) you need. If not, then if you can explain a bit more about why this doesn't work, including what language you're writing in, and showing what you've tried so far and what happened when you ran your code, then we can take things from there.

That is all nice, but what I'd like to do, is "export TERM=..." within the source code. Or, within the program, however you see it. And this is written in C, BTW.

Thank you for your time.

Hi,

Ah, OK. I suspect that what's happening here is that you are, in fact, successfully setting environment variables when you set them with putenv. However, environment variables are only set for the process that sets them. So when your process exits and returns to the shell, the shell still has its own environment variables, which cannot be modified by your programme.

For example:

# cat putterm.c
#include <stdio.h>
#include <stdlib.h>

int main()
{
const char* b = getenv("TERM");
printf("TERM before putenv:%s\n",b);
putenv("TERM=made-up-terminal");
const char* a = getenv("TERM");
printf("TERM after putenv:%s\n",a);
}
# gcc -o putterm putterm.c
# echo $TERM
xterm
# ./putterm 
TERM before putenv:xterm
TERM after putenv:made-up-terminal
# echo $TERM
xterm
#

So even though we can see we successfully modified the value of TERM inside our C programme, this ultimately only effects the process of the binary itself whilst it's running. As soon as it exits, its environment is destroyed along with its image in memory, and we return to the shell, and its own environment.

Does this sound right ? If I'm still not quite grasping what you're trying to do, my apologies - if you could explain a bit more about what it is that's not working (if it's different from what's described above, which is basically what you'd expect to see), we can take it from there.

1 Like

if you set an env var, you just tell a program on the same or less 'level' what the value of the var is. You can set it again in your program, but since the program is a subprogram (child) of the shell, it cannot pass any information 'upwards'. Except the status code and an optional output.

TERM is a variable that tells the shell how it should address the 'printing' terminal, e.g. konsole or xterm. But you want to set in your code which terminal(-capacity) the shell should address, and that is not possible for the above reason. If you want to e.g. restrict your output to a special range of chars, you have to do this in your code by outputting only chars, that the terminal (not the shell) should and is able to display.

See also bash - how to export variables back to the parent process - Super User or bash - Where does the TERM environment variable default get set? - Unix & Linux Stack Exchange.

1 Like

Well,all I can really say that it works. The TERM=pcansi-25 ./myprogram command on the console do in fact work.

Thank you.

I forgot to mention that, it indeed works, but only from the console. Only as already stated so, in my previous posting. I do not in any way say that this issue is solved, because of the fact, I said "it works." I still need to figure out how to automate this process of having the screen set to pcansi-25 while the program is running.

Sorry for the confusion.

Hello,

One thing I would note is that in your C programme, once you set the TERM value, any other processes you spawn (such as sub-shells via the system call and the like) will see the value for TERM that they inherit from your programme.

Again, here's an example:

# cat putterm.c
#include <stdio.h>
#include <stdlib.h>

int main()
{
const char* b = getenv("TERM");
printf("TERM before putenv:%s\n",b);
putenv("TERM=made-up-terminal");
const char* a = getenv("TERM");
printf("TERM after putenv:%s\n",a);
system("/bin/bash -c 'echo Bash here, and I see TERM as: $0' $TERM");
}
# gcc -o putterm putterm.c
# ./putterm
TERM before putenv:xterm-256color
TERM after putenv:made-up-terminal
Bash here, and I see TERM as: made-up-terminal
#

So in this case, the Bash shell that we spawned after using putenv to configure the value of TERM that we wanted does indeed inherit that value of TERM, and not the value that the original shell had set. So you can meaningfully change the value of environment variables - the changes just only apply to your current process, or any child processes that inherit its environment.

If I understand what you're saying correctly, I can do such with the TERM variable. And,
that's perfectly fine if they (child processes) inherit the current TERM variable. I will stay away from system()..

1 Like

Ok. I seem to have fixed it. Thanks to everyone that helped. You can close this thread as "solved".

How did you solve it?

Funny you asked.. I seem have solved it all over again. I had originally added putenv("TERM=pcansi-25"); in the source code, but didn't realize that it worked. I guess I must of removed that line out of frustration, then added it again, and just realized that it works. :slight_smile:

Hi @ignatius,

glad that it works. But it can't be because of your putenv line. As said, your program can pass env vars only on to sub/child processes, aka forked processes. You can see that in this little example, call it via echo $TERM && ./prog & sleep 1 && echo $TERM. The prog is started in background, so you can see after 1s that TERM will not be changed in the shell:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char**argv)
{
    puts("set TERM=foo");
    putenv("TERM=foo");
    sleep(3);
    puts("done");
    return 0;
}

When you start a screen, the shell creates a new child process for it and screen itself creates a new (emulated) text terminal plus a (child) shell in it. TERM is also set anew. You can verify this via

$ echo $TERM && screen
$ echo $TERM # <= in screen

If you want your screen (and thus the shell in it) to have its own value for TERM, you have to call screen -T <term> (TERM=<term> screen doesn't work, cause screen doesn't read TERM). Or pass the value directly to the prog vie TERM=<term> ./prog inside the screen. And when prog doesn't read TERM, i.e. doesn't do any special stuff based on its value, then it doesn't make any sense to set it.
See also https://unix.stackexchange.com/questions/108410/is-it-correct-to-set-the-term-variable-manually.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.