Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bash unable to reference "${PROGRAMFILES(X86)}" #43

Closed
dgtlrift opened this issue Sep 29, 2015 · 13 comments
Closed

bash unable to reference "${PROGRAMFILES(X86)}" #43

dgtlrift opened this issue Sep 29, 2015 · 13 comments

Comments

@dgtlrift
Copy link

I'm not sure if this is an escaping issue, but I'm unable to check this string in the inherited environment from windows.
I keep getting:

C:\P\foo.bash: line 45: syntax error: bad substitution

right now the offending line looks like:

for PF in "${PROGRAMFILES}" "${PROGRAMFILES(X86)}" ; do
log_trace "${PF}"
done
@rmyorston
Copy link
Owner

I'm not entirely sure what you're doing there. Maybe you want:

for PF in "${PROGRAMFILES}" "${PROGRAMFILES} (X86)"

That does something.

@dgtlrift
Copy link
Author

Thanks, but that will expand to the same string - to give the background on these two variables:

On a 64-bit machine running in 64-bit mode
the variable %programfiles% is (typically) "C:\Program Files"
the variable %programfiles(x86)% is (typically) "C:\Program Files (x86)"
On a 64-bit machine running in 32-bit (WoW64) mode:
the variable %programfiles%  is (typically) "C:\Program Files (x86)"
the variable %programfiles(x86)%  is (typically) "C:\Program Files (x86)"
On an XP Machine
the variable %programfiles% is (typically) "C:\Program Files"
the variable %programfiles(x86)% is unset

The reason I say typically, is that there could be some strange virtual instance that has the registry configured for those variables to point to "D:\Program Files" or "K:\Program Files"

I'm trying to pragmatically discover where a specific application is installed regardless if it is XP, or WOW64 or 64/64 mode. By expanding "${PROGRAMFILES}" "${PROGRAMFILES(X86)}" it will allow me to search the Install location regardless of what Windows version the user installed and regardless of the application installed being 32bit or 64bit version.

As a side - I've tried "${PROGRAMFILES(X86)}" and "${PROGRAMFILES(X86)}" and "${PROGRAMFILES(X86)}" - one idea I can try in the morning is "${'PROGRAMFILES(X86)'}"

@rmyorston
Copy link
Owner

I see, the environment variable name contains brackets. Unfortunately both POSIX and bash only allow letters, digits or underscores in shell variable names. I think this means that it isn't possible to reference an environment variable containing special characters no matter how you escape it.

Perhaps the busybox-w32 shell should turn special characters into underscores when it imports the environment.

@rmyorston
Copy link
Owner

The latest busybox-32 build replaces invalid characters in shell variable names with underscores. Thus PROGRAMFILES(X86) becomes PROGRAMFILES_X86_.

@dgtlrift
Copy link
Author

That will work for all the applets inside busybox - what about when ash et al execute a batch/command script or other win32 application - will it restore the original environment variable name?

@rmyorston
Copy link
Owner

No, the original name won't be restored; yes, that's probably a bad thing.

So, we could retain the original environment variable but make a copy for the shell with the invalid characters substituted. Then everyone would be happy.

@dgtlrift
Copy link
Author

dgtlrift commented Oct 1, 2015

Yes - I think that works - I don't picture the values changing by the user, only to be referenced.... so making a copy with a referable variable name so that the original gets preserved for BB to spawn windows binaries that use those original names will work.
Make it so, please.

@rmyorston
Copy link
Owner

Right, the latest binary preserves PROGRAMFILES(X86) but also make a copy named PROGRAMFILES_X86_.

@dgtlrift
Copy link
Author

Now works as I would expect - I call it done.

@rmyorston
Copy link
Owner

A change to upstream BusyBox about a year ago resulted in variables with invalid names being stripped out. busybox-w32 since FRP-671-ge135a80 was therefore unable to preserve names like PROGRAMFILES(X86).

This has now been fixed and busybox-w32 from FRP-1709-g65e9c0ad9 works again.

@ale5000-git
Copy link

ale5000-git commented Nov 5, 2017

@rmyorston

When executing:
echo "${PROGRAMFILES(X86)}"
I still get:
bash: syntax error: bad substitution

@rmyorston
Copy link
Owner

That's correct: PROGRAMFILES(X86) is still an invalid name for a shell variable. You need to access it as PROGRAMFILES_X86_.

That's the tl;dr. Here's the long version:

Environment variable names can contain just about any character: the equals sign isn't allowed and using a null character would be unwise but anything else is possible. Shell variables are much more restricted: they can only have alphabetic or numeric characters plus underscore (and they can't start with a digit).

When the shell starts it initiialises its variables from the environment. Environment variables with names that are invalid to the shell are excluded. This isn't a problem on Unix because everyone performs self-censorship and only uses environment variable names that are also valid in the shell.

Unfortunately nobody told Microsoft that, so they sometimes use names (like PROGRAMFILES(X86)) that are valid in the environment and in cmd.exe but not a POSIX shell. (They also foolishly made names case-insensitive, but that's another story.)

To support the use of variables like PROGRAMFILES(X86) I made two changes:

  1. To allow the shell to access environment variables with invalid names they're imported with all invalid characters changed to underscores. So PROGRAMFILES(X86) is imported as PROGRAMFILES_X86_.

  2. The shell remembers the invalid version of the name so it can pass it to the environment of programs it runs. Otherwise if you run cmd.exe from the shell it wouldn't get the PROGRAMFILES(X86) variable. This would break native Windows program that need such variables.

This still doesn't allow the shell to change the value of an environment variable with an invalid name. It would be possible to do that too, but it seemed an unnecessary complication.

@ale5000-git
Copy link

ale5000-git commented Nov 5, 2017

It seems fine but the problem is that it can be overridden.

If I set ProgramFiles_x86_ from a .bat file before running bash then I can no longer see PROGRAMFILES(X86).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants