Discussion:
USS assembler program and envars
(too old to reply)
Frank Chu
2018-03-12 21:11:45 UTC
Permalink
Hi,

Does anybody know if there is a control block chain that I can walk to
find all of the envars that are define?  I know there is a LE C function
that can query for a specified envar but I can't use LE C. And there are
circumstances where I do not have access to the parm list pointer that
is passed to the executing program, so I can't rely on that guy to find
the envars.  I've also gone through the USS Callable Assembler Services
Guide and it doesn't look like there is a service for this either.

Thanks in advance.
Frank
--
Development Programmer
ColeSoft Marketing
www.colesoft.com
Phone : 540.456.6164
Email : ***@colesoft.com

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Kirk Wolf
2018-03-12 21:53:52 UTC
Permalink
Seems like a really good question... you would think that there would be a
pointer somewhere.

This is kind of a hack, but you could spawn /bin/env with no arguments and
redirect the output to an anonymous pipe and then read that into a buffer.
The output with be a repeated stream of "KEY=VALUE\n"

The services would be:

BPX1PIP - pipe() to create an unnamed pipe
BPX1SPN - spawn("/bin/env"....) direct stout to pipe write fd, stdin and
stderr to nothing (SPAWN_FDCLOSED).
BPX1OPN - open the input side of the pipe
BPX1RED* - repeatedly read the pipe until eof
BPX1CLO - close

Assuming that your program is not authorized, I suggest you
set INHEMUSTBELOCAL in the inheritance structure for BPX1SPN so that
/bin/env will be run in the same address space, which will be a little
cheaper/quicker.

You might also want to ask this on mvs-asm370. There are some guys there
that think that assembler is better than C for everything. They may have a
better answer than this :-)



Kirk Wolf
Dovetailed Technologies
http://dovetail.com
Post by Frank Chu
Hi,
Does anybody know if there is a control block chain that I can walk to
find all of the envars that are define? I know there is a LE C function
that can query for a specified envar but I can't use LE C. And there are
circumstances where I do not have access to the parm list pointer that is
passed to the executing program, so I can't rely on that guy to find the
envars. I've also gone through the USS Callable Assembler Services Guide
and it doesn't look like there is a service for this either.
Thanks in advance.
Frank
--
Development Programmer
ColeSoft Marketing
www.colesoft.com
Phone : 540.456.6164
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Kirk Wolf
2018-03-12 21:55:05 UTC
Permalink
Be sure to ask this on the mvs-oe list, since an IBM Unix guy might see it
there and give a better answer.

Kirk Wolf
Dovetailed Technologies
http://dovetail.com
Post by Kirk Wolf
Seems like a really good question... you would think that there would be a
pointer somewhere.
This is kind of a hack, but you could spawn /bin/env with no arguments and
redirect the output to an anonymous pipe and then read that into a buffer.
The output with be a repeated stream of "KEY=VALUE\n"
BPX1PIP - pipe() to create an unnamed pipe
BPX1SPN - spawn("/bin/env"....) direct stout to pipe write fd, stdin and
stderr to nothing (SPAWN_FDCLOSED).
BPX1OPN - open the input side of the pipe
BPX1RED* - repeatedly read the pipe until eof
BPX1CLO - close
Assuming that your program is not authorized, I suggest you
set INHEMUSTBELOCAL in the inheritance structure for BPX1SPN so that
/bin/env will be run in the same address space, which will be a little
cheaper/quicker.
You might also want to ask this on mvs-asm370. There are some guys there
that think that assembler is better than C for everything. They may have a
better answer than this :-)
Kirk Wolf
Dovetailed Technologies
http://dovetail.com
Post by Frank Chu
Hi,
Does anybody know if there is a control block chain that I can walk to
find all of the envars that are define? I know there is a LE C function
that can query for a specified envar but I can't use LE C. And there are
circumstances where I do not have access to the parm list pointer that is
passed to the executing program, so I can't rely on that guy to find the
envars. I've also gone through the USS Callable Assembler Services Guide
and it doesn't look like there is a service for this either.
Thanks in advance.
Frank
--
Development Programmer
ColeSoft Marketing
www.colesoft.com
Phone : 540.456.6164
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Don Poitras
2018-03-12 21:58:16 UTC
Permalink
Frank,
Try:

LAA (PSA+0x4B8)->LCA->CAA->EDB->env var ptr array, ends with null ptr.
Post by Frank Chu
Hi,
Does anybody know if there is a control block chain that I can walk to
find all of the envars that are define??? I know there is a LE C function
that can query for a specified envar but I can't use LE C. And there are
circumstances where I do not have access to the parm list pointer that
is passed to the executing program, so I can't rely on that guy to find
the envars.?? I've also gone through the USS Callable Assembler Services
Guide and it doesn't look like there is a service for this either.
Thanks in advance.
Frank
--
Development Programmer
ColeSoft Marketing
www.colesoft.com
Phone : 540.456.6164
--
Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive
***@sas.com (919) 531-5637 Cary, NC 27513

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Paul Gilmartin
2018-03-13 00:24:45 UTC
Permalink
Post by Don Poitras
LAA (PSA+0x4B8)->LCA->CAA->EDB->env var ptr array, ends with null ptr.
Since different processes spawned with _BPX_SHAREAS=YES may be executing
concurrently in the same address space, but with different environment variables,
how does this keep the env var ptr arrays separate.

I have come to believe that "environment variables" is a misnomer; the array is
just another array of pointers passed to exec()/spawn().

It appears that if a program is compile/linked in Enhanced ASCII mode, the
environment variable array is translated (by spawn()/exec()?) to ASCII.

-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Frank
2018-03-13 13:32:24 UTC
Permalink
Thank Kirk.

The spawn and pipe was where I was heading down but I thought there must be a better way to get what I need. That will probably end up being the method of last resort.

I'll give the mvs-oe list a try.


Frank

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Frank
2018-03-13 13:47:42 UTC
Permalink
Hi Don,

Thanks for the info but that looks like it will only work with LE programs. The LCA and everything behind it are created when LE is first initialized. Unfortunately, I cannot use LE.


Frank

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
John McKown
2018-03-13 14:23:54 UTC
Permalink
Post by Frank
Hi Don,
Thanks for the info but that looks like it will only work with LE
programs. The LCA and everything behind it are created when LE is first
initialized. Unfortunately, I cannot use LE.
​I think that there are two sets of "environment variables" in this
situation. There are the UNIX shell environment variables, which is what I
think you are asking about. And there are the Language Environment
environment variables. I am not certain, but I think that these are really
separate things, but sometime appear to be the same because the standard
IBM UNIX shell (/bin/sh), which is a LE program,​ initialises the shell's
environment variables from the LE environment variables. If you will look
at the UNIX exec() function, BPX1EXC, you will see that the invoker _must_
set up the environment variables to be passed to the executed program.
Exactly where this data area resides is not specified. That is, it could be
"hard coded" in the executable, or in dynamic storage. And, for all that I
know, the BPX1EXC processing could copy this data into an entirely
different area. The C language has a number of exec...() variants. Some of
which are explicitly passed the environment variables and other optionally
pass the environment variable.

What I'm getting at is that I am fairly sure that _UNIX_ shell environment
variables may not be generally accessible in all situations. I have not
done so, but I would likely try to see if my code could find the external
variable "environ". But this may be LE only also. In addition, I really
don't know what your code is doing and how it is being invoked. And, since
I'm blathering on, I will also mention that not all UNIX processes have
UNIX shell environment variables. If a non-UNIX program does a UNIX request
and is dynamically "dubbed" as a UNIX process, then it will not have any
non-LE environment variables. And, if not LE, it won't have any LE
environment variables either.


ref:
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.bpxb100/exc.htm
UNIX exec() callable service
​ref:
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.bpxbd00/rtexe.htm​
C language exec...()
Post by Frank
Frank
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
--
I have a theory that it's impossible to prove anything, but I can't prove
it.

Maranatha! <><
John McKown

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Peter Hunkeler
2018-03-14 07:12:56 UTC
Permalink
​>I think that there are two sets of "environment variables" in this
situation. There are the UNIX shell environment variables, which is what I
think you are asking about. And there are the Language Environment
environment variables.



I have not done an in-depth analysis on this but I don't think there are two sets of environment variables. The shell is just an LE UNIX program. It works with the environment variables of its process. However, the shell will *not* forward environment variables to its child processes, unless they have been flagged via shell built-in command "export".


o The /bin/env command displays only those variables which have been exported.
o The set shell built-in command display all variables, whether exported or not.




The shell will have to built the array of environment variables to be passed when exec()ing or spawn()ing. Only exported environment variables will make it into that array.
--
Peter Hunkeler

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Don Poitras
2018-03-13 17:51:40 UTC
Permalink
There's an undocumented BPX function to get and set environment
variables. The "OpenMVS extension" to the TCB has a non-gupi pointer
that appears to be used. See SYS1.MACLIB(BPXZOTCB).
Post by Frank
Hi Don,
Thanks for the info but that looks like it will only work with LE programs. The LCA and everything behind it are created when LE is first initialized. Unfortunately, I cannot use LE.
Frank
--
Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive
***@sas.com (919) 531-5637 Cary, NC 27513

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Thomas David Rivers
2018-03-13 15:33:06 UTC
Permalink
Post by Frank Chu
Hi,
Does anybody know if there is a control block chain that I can walk to
find all of the envars that are define? I know there is a LE C
function that can query for a specified envar but I can't use LE C.
And there are circumstances where I do not have access to the parm
list pointer that is passed to the executing program, so I can't rely
on that guy to find the envars. I've also gone through the USS
Callable Assembler Services Guide and it doesn't look like there is a
service for this either.
Thanks in advance.
Frank
Just FYI - in a UNIX environment the address of the incoming environment
variable array
is stuffed away in an external variable named "environ":

extern char **environ;

The Dignus C runtime (also non-LE) makes that available... basically at
the start-up of an
exec'd program you have to copy the incoming variables into a blob of memory
and point 'environ' to the blob... (because the format from IBM doesn't
match
the UNIXy way of doing it.)

Then, your program can merrily reference 'environ' (getenv/setenv,
etc... also
just reference 'environ'.)

If you are a non-LE program that has been exec'd; you probably want to take
the same approach and make those copies when you start execution; then
provide
functions that can reference the copies (e.g. your own getenv/setenv
functions.)

There is no "magic" to these environment variables - they are simply passed
on the exec() call... that's how they pass from parent-to-child in the
UNIX environmnt.
No need for a defined location beyond the per-program copy (and that
copy is up to
the program.)

- Dave R. -
--
***@dignus.com Work: (919) 676-0847
Get your mainframe programming tools at http://www.dignus.com
Seymour J Metz
2018-03-13 17:03:12 UTC
Permalink
When you write "Unix" do mean a particular set of Unix implementations, or do you mean that certification by The Open Group <http://www.opengroup.org/> requires it? If the later, shouldn't there be an APAR on this?


--
Shmuel (Seymour J.) Metz
http://mason.gmu.edu/~smetz3

________________________________________
From: IBM Mainframe Discussion List <IBM-***@listserv.ua.edu> on behalf of Thomas David Rivers <***@DIGNUS.COM>
Sent: Tuesday, March 13, 2018 11:33 AM
To: IBM-***@listserv.ua.edu
Subject: Re: USS assembler program and envars
Post by Frank Chu
Hi,
Does anybody know if there is a control block chain that I can walk to
find all of the envars that are define? I know there is a LE C
function that can query for a specified envar but I can't use LE C.
And there are circumstances where I do not have access to the parm
list pointer that is passed to the executing program, so I can't rely
on that guy to find the envars. I've also gone through the USS
Callable Assembler Services Guide and it doesn't look like there is a
service for this either.
Thanks in advance.
Frank
Just FYI - in a UNIX environment the address of the incoming environment
variable array
is stuffed away in an external variable named "environ":

extern char **environ;

The Dignus C runtime (also non-LE) makes that available... basically at
the start-up of an
exec'd program you have to copy the incoming variables into a blob of memory
and point 'environ' to the blob... (because the format from IBM doesn't
match
the UNIXy way of doing it.)

Then, your program can merrily reference 'environ' (getenv/setenv,
etc... also
just reference 'environ'.)

If you are a non-LE program that has been exec'd; you probably want to take
the same approach and make those copies when you start execution; then
provide
functions that can reference the copies (e.g. your own getenv/setenv
functions.)

There is no "magic" to these environment variables - they are simply passed
on the exec() call... that's how they pass from parent-to-child in the
UNIX environmnt.
No need for a defined location beyond the per-program copy (and that
copy is up to
the program.)

- Dave R. -

--
***@dignus.com Work: (919) 676-0847
Get your mainframe programming tools at http://secure-web.cisco.com/1yv1SBdrUxM_Et9wyycsLgdZSNj8tm0S1ueixX8COmlgQ952gVClA4cAebBGU-DHHGU6IbHUM0UOIt7zxQvGStv26OAGg76O5hrGMxgnryQLoDWUXIzQEUEN5BPUJt9oSrGawSWUV2cLvTaL24xYAT24IQPlRoZ3IJuhRikp_UHJI4dUijGAz7KV7kuM6Idh22HGogg-dvMrT9kE5Q_fvkiQPPDXsF0Ft1Rs1ipL9kt2H5CJcdjo69EvWiAqjvU4oDSW3RyVlca5pwIRVCDXDcdDhZJZLSF-F7acuBdpyQNMEViXE9V3PzE3PirU5BkR84kn0jQ1CFwdQ2wItRRhobAhCLIAV4SPz57nzIklS2tsOoJHBlQpUKKNAkjlAEpDXMDBkAZX2sXQSAOfRa5ec3PGwfkYn2k1Z_jZGfY-6kbninNGr6ArS9eCDHvPaLHSx/http%3A%2F%2Fwww.dignus.com

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Paul Gilmartin
2018-03-13 15:34:11 UTC
Permalink
Post by Paul Gilmartin
Post by Don Poitras
LAA (PSA+0x4B8)->LCA->CAA->EDB->env var ptr array, ends with null ptr.
Since different processes spawned with _BPX_SHAREAS=YES may be executing
concurrently in the same address space, but with different environment variables,
how does this keep the env var ptr arrays separate.
I believe I need to correct myself here. I forgot that PSA is processor-specific,
so two processors, even executing in the same address space can access different
structures anchored in PSA. And something along the chain must be updated
when a processor switches context.
Post by Paul Gilmartin
​ ... If you will look
at the UNIX exec() function, BPX1EXC, you will see that the invoker _must_
set up the environment variables to be passed to the executed program.
Exactly where this data area resides is not specified. That is, it could be
"hard coded" in the executable, or in dynamic storage. And, for all that I
know, the BPX1EXC processing could copy this data into an entirely
different area. ...
Or even perform EBCDIC<==>ASCII translation depending on characteristics
of the invoked program?

-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
John McKown
2018-03-13 17:11:13 UTC
Permalink
On Tue, Mar 13, 2018 at 10:35 AM, Paul Gilmartin <
​<snip>
Post by Paul Gilmartin
​ ... If you will look
at the UNIX exec() function, BPX1EXC, you will see that the invoker _must_
set up the environment variables to be passed to the executed program.
Exactly where this data area resides is not specified. That is, it could
be
Post by Paul Gilmartin
"hard coded" in the executable, or in dynamic storage. And, for all that I
know, the BPX1EXC processing could copy this data into an entirely
different area. ...
Or even perform EBCDIC<==>ASCII translation depending on characteristics
of the invoked program?
​The ASCII support, as best as I can tell, is strictly a C language
invention. I.e. there is nothing similar for Fortran, PL/I, or COBOL. So I
would bet that the C run time initialisation ​logic creates the ASCII
environment variables from the ones passed into the exec() function. But
that is strictly a guess. IMO, use of C language ASCII support is the lazy
man's way to "port" existing UNIX programs to z/OS. Not that I have
anything against "lazy".
-- gil
--
I have a theory that it's impossible to prove anything, but I can't prove
it.

Maranatha! <><
John McKown

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Tom Marchant
2018-03-13 18:25:47 UTC
Permalink
If you are a non-LE program that has been exec'd....
Given that Frank's email is Colesoft, I suspect that his requirement
is not that of a normal program, but a debugger or a monitor.
--
Tom Marchant

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Binyamin Dissen
2018-03-14 09:37:27 UTC
Permalink
You would need to follow the CAA chain. For a standard LE task you would find
the anchor in the TCB. CICS would have it in its control blocks.

If you need it to be super clean, i.e., avoiding walking control blocks, you
could probably fake a call to your routine with NAB=NO and then use the
standard services.


On Mon, 12 Mar 2018 17:13:03 -0400 Frank Chu <***@COLESOFT.COM> wrote:

:>Hi,
:>
:>Does anybody know if there is a control block chain that I can walk to
:>find all of the envars that are define?  I know there is a LE C function
:>that can query for a specified envar but I can't use LE C. And there are
:>circumstances where I do not have access to the parm list pointer that
:>is passed to the executing program, so I can't rely on that guy to find
:>the envars.  I've also gone through the USS Callable Assembler Services
:>Guide and it doesn't look like there is a service for this either.
:>
:>Thanks in advance.
:>Frank

--
Binyamin Dissen <***@dissensoftware.com>
http://www.dissensoftware.com

Director, Dissen Software, Bar & Grill - Israel


Should you use the mailblocks package and expect a response from me,
you should preauthorize the dissensoftware.com domain.

I very rarely bother responding to challenge/response systems,
especially those from irresponsible companies.

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Paul Gilmartin
2018-03-16 16:52:18 UTC
Permalink
Post by Kirk Wolf
This is kind of a hack, but you could spawn /bin/env with no arguments and
redirect the output to an anonymous pipe and then read that into a buffer.
The output with be a repeated stream of "KEY=VALUE\n"
But be careful. If a programmer has been mischievous enough to do such as:
wombat="xyzzy
foo=bar" export wombat

env will show:
...
wombat=xyzzy
foo=bar
....

Better:
sh -c "export -p"
...
export wombat='xyzzy
foo=bar'
...
which is parseable.

-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Loading...