Environment Variables

E

Emmanuel Delahaye

learner wrote on 04/08/04 :
Hi,

What is the difference between accessing environment
variables through

int main(int argc,char *argv[],char *envp[])

and

extern char **environ;
Is there any advantage in any of the above two?

None of them are standard.

The canonical forms of main() are

int main (void)

and

int main (int, char **)

If you want to read an environment variable, you have getenv().
 
E

Emmanuel Delahaye

Ralmin wrote on 05/08/04 :
I get the same error with plain 'gcc' and with 'gcc -ansi -pedantic' as
well.

Perhaps the -ansi and -pedantic options affect only the compiler, not the
linker.

Probably, yes. Chances are that the 'environ' global variable belong to
the C-library (like 'errno' is) and the compiler is not aware of that.
 
E

Emmanuel Delahaye

(supersedes <[email protected]>)

Ralmin wrote on 05/08/04 :
I get the same error with plain 'gcc' and with 'gcc -ansi -pedantic' as
well.

Perhaps the -ansi and -pedantic options affect only the compiler, not the
linker.

Probably, yes. Chances are that the 'environ' global variable belong to
the C-library (like 'errno' does) and that the compiler is not aware of
that.
 
M

Michael Wojcik

That's debatable. While it is arguably "nicer" by definition in the
scope of the immediate interpersonal exchage to avoid offense, it's
conceivable that over a longer term greater benefit may accrue to the
offended party through that offense, so the overall nicer course of
action is to offend. Indeed, a great many social practices are
predicated on this notion, and we see them practiced daily on Usenet.

Further, it's conceivable that by offending one member of the audience,
that member may be driven from the discussion, to the gratification of
several other audience members; and so a net gain in niceness is
achieved through offense. We see this attempted daily on Usenet, with
limited success.
I thought the implication was that Bush could talk better than
Churchill.

Yes, but only when his trainer puts peanut butter in his mouth.
 
C

CBFalconer

Emmanuel said:
Ralmin wrote on 05/08/04 :


Probably, yes. Chances are that the 'environ' global variable
belong to the C-library (like 'errno' does) and that the compiler
is not aware of that.

There are usually many things in the library that are not
specified in the standard, or in the system namespace. However
they should be in modules that do not get loaded unless requested,
and thus should not interfere.
 
C

Chris Torek

[on the name "environ" cluttering up the namespace even under -ansi
mode in various systems]

(This is correct.)

There are usually many things in the library that are not
specified in the standard, or in the system namespace. However
they should be in modules that do not get loaded unless requested,
and thus should not interfere.

Unfortunately, this is "too difficult" (for some value of "too",
or perhaps some definition of "difficult") to achieve on those
systems. The reason is that they use a single startup module
that looks sort of like this (pseudo-C):

void __start(void) {
register struct os_supplied_startup_info *p __asm__("some magic here");
int argc;
char **argv, **envp;
extern char **environ;
int i;

/*
* Often there is actually more than just "argv data" here.
* Some systems provide argc as well, and some provide info
* on loading libraries, O/S version, and/or other special
* stuff.
*/
argv = p->argv_data;
for (i = 0; argv != NULL; i++)
continue; /* nothing else to do here */
argc = i;
environ = envp = &argv;
__more_library_initialization(); /* e.g., stdin/stdout/stderr etc */
exit(main(argc, argv, envp));
__asm__("more magic here if needed, but probably not reachable");
}

Note that this startup module calls main() with three arguments,
rather than the appropriate two-or-zero, and depends on the fact
that the underlying system "just happens" to have that work. (The
system in this case is i386 or SPARC or VAX or MIPS or PowerPC or
ARM or ... well, perhaps I should just say that the list of machines
on which it does NOT work is a LOT shorter :) than the list of
machines where it DOES work. Those of us who write startup code,
however, are prepared to rewrite it when we encounter such machines.
Since the __asm__ contents change from one machine to the next
anyway, and since this code sometimes has to be written in assembly,
it is not that important.)

Unfortunately, this startup module also refers to a global variable
named "environ", because the system-supplied C library does the
same (in getenv()).

The fix (in this case) is not to avoid loading certain modules,
but rather to rename the global variable, e.g., change it to
__environ. For backwards compatibility, these (ELF-based) systems
provide a "weak association" directive under which the "true name"
(now __environ) can be "loosely attached" to the old, intrusive
"environ" name. If the programmer supplies any instance of "environ",
the programmer's version breaks the weak attachment so that the
system's __environ is an entirely separate variable; but if the
program only ever says "extern char **environ;" -- only refers to
it, rather than defining it -- the weak link holds and the old code
continues to compile and link.
 
C

CBFalconer

Chris said:
.... snip ...

Unfortunately, this startup module also refers to a global variable
named "environ", because the system-supplied C library does the
same (in getenv()).

The fix (in this case) is not to avoid loading certain modules,
but rather to rename the global variable, e.g., change it to
__environ. For backwards compatibility, these (ELF-based) systems
provide a "weak association" directive under which the "true name"
(now __environ) can be "loosely attached" to the old, intrusive
"environ" name. If the programmer supplies any instance of "environ",
the programmer's version breaks the weak attachment so that the
system's __environ is an entirely separate variable; but if the
program only ever says "extern char **environ;" -- only refers to
it, rather than defining it -- the weak link holds and the old code
continues to compile and link.

I think the proper thing here is to have the startup module
variable, etc. named __environ (or something else in the system
space). This is used to place the appropriate data in the
appropriate place on the stack (assuming a stack), and is
published in the startup modules exported names.

Now, somewhere in the process of compiler startup, it knows
whether it is an ansi or extended compiler. If extended, it calls
code like:

genline("#define environ __environ\n");

which magically moves the item into the users namespace.

I can see complications because this should probably be local to
main, and I gather from some other posts that "environ" must not
appear in the system headers per POSIX. However I would consider
the first requirement to be "make it C99 compliant", and full
POSIX compliancy is subordinate.

The proper way would be to have an added header for POSIX
standard, which could handle all these silly differences. Just
omit it to strip the POSIX stuff. IMHO.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,372
Latest member
LucretiaFo

Latest Threads

Top