jian@kuhub.cc.ukans.edu (08/15/90)
Yesterday I asked for help about how to issue a C-SHELL command within a C program. I was lucky: serveral people came up with immediate answers. I very much appreciate those answers. According to the answers and what I read from the menu, system() and execlp() should work without any doubts. However, I can't make it. What I want to do is to issue a csh command to change terminal type within a C program. I did try: system("csh -cf \"setenv TERM adm3a"); and system("/bin/csh -c 'setenv TERM adm3a"); and execlp("/bin/csh", "csh", "-c", "setenv TERM adm3a", (char *) 0); There was not any runtime errors if I embeded one of above statements into my C program. But none of them can change the terminal type. I don't know why. Would someone point me another way to change terminal type within a C program or give me some hints what I did wrong. I would appreciate any helps. Jian Q. Li jian@kuhub.cc.ukans.edu
merlyn@iwarp.intel.com (Randal Schwartz) (08/16/90)
In article <25285.26c9113d@kuhub.cc.ukans.edu>, jian@kuhub writes: | Yesterday I asked for help about how to issue a C-SHELL command within a C | program. I was lucky: serveral people came up with immediate answers. I very | much appreciate those answers. | | According to the answers and what I read from the menu, system() and execlp() | should work without any doubts. However, I can't make it. What I want to do | is to issue a csh command to change terminal type within a C program. I did | try: | system("csh -cf \"setenv TERM adm3a"); | and | system("/bin/csh -c 'setenv TERM adm3a"); | | and | execlp("/bin/csh", "csh", "-c", "setenv TERM adm3a", (char *) 0); | | There was not any runtime errors if I embeded one of above statements into my | C program. But none of them can change the terminal type. I don't know why. | Would someone point me another way to change terminal type within a C program | or give me some hints what I did wrong. I would appreciate any helps. Aha. As I said in my private mail, *why* would you want to execute a csh command? Now I can see. The short answer: You *cannot* change an environment variable (such as TERM) from a child process. The shell provides a *copy* of its environment to the children processes (such as your C program), so changes to that copy (or in your case, using a further csh which has its *own* copy), will not affect the parent shell. This is by design, so don't ask "Well, are they going to fix this some day?" The longer answer: If you invoke a program from the shell in such a way that the shell is going to expect an answer back and take action on that, you can get away with it. For example, if your program "pickterm" is invoked from the csh as: setenv TERM `pickterm` then all "pickterm" has to do is output the desired term-type on stdout. If you need interaction, you may need to arrange for the csh to get it from a file. For example, pickterm /tmp/$$ && setenv TERM `cat /tmp/$$` rm /tmp/$$ in which case pickterm would open /tmp/$$ for output, put the desired termtype into it after interacting with the user, and then exit successfully. Either of these solutions could be wrapped up inside an alias to prevent the nitty gritties from being exposed to the poor user. Just another Unix hacker, -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
fpb@ittc.wec.com (Frank P. Bresz) (08/16/90)
In article <1990Aug15.221504.348@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes: >In article <25285.26c9113d@kuhub.cc.ukans.edu>, jian@kuhub writes: [ Stuff deleted ] >| execlp("/bin/csh", "csh", "-c", "setenv TERM adm3a", (char *) 0); >| >| There was not any runtime errors if I embeded one of above statements into my >| C program. But none of them can change the terminal type. I don't know why. >| Would someone point me another way to change terminal type within a C program >| or give me some hints what I did wrong. I would appreciate any helps. >The short answer: >You *cannot* change an environment variable (such as TERM) from a >child process. The shell provides a *copy* of its environment to the >children processes (such as your C program), so changes to that copy >(or in your case, using a further csh which has its *own* copy), will >not affect the parent shell. This is by design, so don't ask "Well, >are they going to fix this some day?" Why not just use the putenv system call with something akin to: putenv("TERM=adm3a"); /* notify subprocess that it is an adm3a terminal */ -- +--------------------+ |fbresz@ittc.wec.com | My opinions are my own, I'm not paid |uunet!ittc!fbresz | enough to make an official statement |(412)733-6749 | +-----------------------------------+ |Fax: (412)733-6444 | | THIS SPACE FOR SALE!!! | +--------------------+ +-----------------------------------+
merlyn@iwarp.intel.com (Randal Schwartz) (08/16/90)
In article <FPB.90Aug16004855@ittc.ittc.wec.com>, fpb@ittc (Frank P. Bresz) writes: | Why not just use the putenv system call with something akin to: | | putenv("TERM=adm3a"); /* notify subprocess that it is an adm3a terminal */ Nope. That changes the *current* process (the C program), not the parent process (the parent shell). You *must* involve the parent process if you want programs invoked after the C program to see the change (unless you intend the C program to perform all the future invocations... yuck). Just another UNIX hacker, -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/16/90)
In article <25285.26c9113d@kuhub.cc.ukans.edu> jian@kuhub.cc.ukans.edu writes: > system("/bin/csh -c 'setenv TERM adm3a"); (You're missing a quote ') >But none of them can change the terminal type. I don't know why. Your problem is that no change made to the environment variables of a subprocess can affect the environment variables of an ancestor process. This is why most of us make sure our TERM environment variable is properly set up by a file that is SOURCED, not executed in a subprocess, when our shell starts up (e.g. .profile or .login).
guy@auspex.auspex.com (Guy Harris) (08/17/90)
>Would someone point me another way to change terminal type within a C program >or give me some hints what I did wrong. I would appreciate any helps. As noted, the environment isn't "global", so setting an environment variable such as TERM in one process won't affect its value in any other existing processes; it'll only affect its initial value in processes forked from that process. If you want to change the value of an environment variable in a process running some arbitrary C program, check whether your system has the "putenv" routine (look for PUTENV(3) in the manual - unless you have some SCO system wherein they "improved" the manuals by changing the names of the sections, in which case I've no idea what the name would be). If not, see whether it has the "setenv" routine. If it has one or the other of those routines, the manual page should show you how to set an environment variable using the routine. Why do you need to change the setting of TERM within a program? The ultimate problem may lie deeper. (Also bear in mind that you should set TERM *before* you call *any* "curses" or "termcap" routines; otherwise, "curses" or "termcap" will start out using the old value of TERM, not the new value.)
peter@ficc.ferranti.com (Peter da Silva) (08/17/90)
In article <25285.26c9113d@kuhub.cc.ukans.edu>, jian@kuhub.cc.ukans.edu writes: > execlp("/bin/csh", "csh", "-c", "setenv TERM adm3a", (char *) 0); You can't set your environment from a subshell. An environment is owned by a process and inherited by its children, but never passed back. You need to do something like print the commands on standard output, the way "tset" does: 47 % tset -s set noglob; setenv TERM at/386 console ; setenv TERMCAP 'at386:am:bw:eo:xo:xt:bs:co#80:li#25:kn#4:ae=^P:al=\E[1L:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[H:cm=\E[%i%2;%2H:ct=\E[3g:dc=\E[1P:dl=\E[1M:ho=\E[H:ic=\E[1@:K1=\EOp:K2=\EOq:K3=\EOr:K4=\EOs:K5=\EOt:K6=\EOu:K7=\EOv:K8=\EOw:K9=\EOx:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:k9=\EOX:kb=\b:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:nd=\E[C:se=\E[m:so=\E[7m:st=\EH:ue=\E[m:up=\E[A:us=\E[4m:ko=do,nd,up,ho'; unset noglob; 48 % grep tset .login tset -s ... >/tmp/tset$$ source /tmp/tset$$ rm /tmp/tset$$ 49 % This way the variables get set in the parent shell and so stick around after the subshell or your C program (which is also a child of the shell) exits. If you just want to set variables for programs you call, try "putenv". -- Peter da Silva. `-_-' +1 713 274 5180. 'U` peter@ferranti.com (currently not working) peter@hackercorp.com