dyld_insert_libraries ignored when calling application through bash - bash

For my application, I am using DYLD_INSERT_LIBRARIES to switch libraries. I am running Mac OS X, El Capitan.
If I set these environment variables in my shell:
export PYTHONHOME=${HOME}/anaconda
export DYLD_INSERT_LIBRARIES=${HOME}/anaconda/lib/libpython2.7.dylib:${HOME}/anaconda/lib/libmkl_rt.dylib
If I launch my application directly, it works properly. However, if I call it through a bash script I have written, the DYLD_INSERT_LIBRARIES is ignored.
If I add the same 2 lines to my bash script, my application works again.
It looks like DYLD_INSERT_LIBRARIES is being unset when the bash script is called, as proven by this test script.
#!/bin/bash
set -e
echo ${DYLD_INSERT_LIBRARIES}
Is there any way to let the bash script inherit and pass down DYLD_INSERT_LIBRARIES?

This is a security feature of recent macOS versions.
The system bash executable has been marked as "restricted", disabling the DYLD_* features. To work around this, you can make a copy of bash and use that instead.
By looking for the following details in the implementations of dyld, I see that this restriction goes back at least to 10.6.
In the macOS 10.13 dyld implementation this logic is in pruneEnvironmentVariables, with the comment:
// For security, setuid programs ignore DYLD_* environment variables.
// Additionally, the DYLD_* enviroment variables are removed
// from the environment, so that any child processes don't see them.
However the actual logic to set the restriction is in configureProcessRestrictions:
// any processes with setuid or setgid bit set or with __RESTRICT segment is restricted
if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) {
gLinkContext.processIsRestricted = true;
}
...
if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
// On OS X CS_RESTRICT means the program was signed with entitlements
if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && usingSIP ) {
gLinkContext.processIsRestricted = true;
}
// Library Validation loosens searching but requires everything to be code signed
if ( flags & CS_REQUIRE_LV ) {
gLinkContext.processIsRestricted = false;
...
As you can see, it depends on, issetugid, hasRestrictedSegment, and the CS_RESTRICT / SIP entitlements. You might be able to test for restricted status directly, or you could probably construct a function to test for these conditions yourself based on this information.

Related

How to check if a specific program (shell command) is available on a Linux in D?

I am trying to write a script-like D program, that would have different behaviour based on availability of certain tools on user's system.
I'd like to test if a given program is available from command line (in this case it is unison-gtk) or if it is installed (I care only about Ubuntu systems, which use apt)
For the record, there is a walk around using e.g. tryRun:
bool checkIfUnisonGTK()
{
import scriptlike;
return = tryRun("unison-gtk -version")==0;
}
Instead of tryRun, I propose you grab the PATH environment variable, parse it (it is trivial to parse it), and look for specific executable inside those directories:
module which1;
import std.process; // environment
import std.algorithm; // splitter
import std.file; // exists
import std.stdio;
/**
* Use this function to find out whether given executable exists or not.
* It behaves like the `which` command in Linux shell.
* If executable is found, it will return absolute path to it, or an empty string.
*/
string which(string executableName) {
string res = "";
auto path = environment["PATH"];
auto dirs = splitter(path, ":");
foreach (dir; dirs) {
auto tmpPath = dir ~ "/" ~ executableName;
if (exists(tmpPath)) {
return tmpPath;
}
}
return res;
} // which() function
int main(string[] args) {
writeln(which("wget")); // output: /usr/bin/wget
writeln(which("non-existent")); // output:
return 0;
}
A natural improvement to the which() function is to check whether tmpPath is an executable, or not, and return only when it found an executable with given name...
There can't be any «native D solution» because you are trying to detect something in the system environment, not inside your program itself. So no solution will be «native».
By the way, if you are really concerned about Ubuntu only, you can parse output of command dpkg --status unison-gtk. But for me it prints that package 'unison-gtk' is not installed and no information is available (I suppose that I don't have enabled some repo that you have). So I think that C1sc0's answer is the most universal one: you should try to run which unison-gtk (or whatever the command you want to run is) and check if it prints anything. This way will work even if user has installed unison-gtk from anywhere else than a repository, e.g. has built it from source or copied a binary directly into /usr/bin, etc.
Linux command to list all available commands and aliases
In short: run auto r = std.process.executeShell("compgen -c"). Each line in r.output is an available command. Requires bash to be installed.
man which
man whereis
man find
man locate

How to determine if existing bash commands are compatible with new OS

I'm upgrading a mac workstation that we use for some automated data processing. In this processing we call a couple of bash scripts. The work station is currently at 10.7.x and we want to upgrade it to Mavericks.
One of the things I need to determine is if upgrading will break the bash scripts.
Most of the commands are regular /usr/bin commands:
perl
awk
sort
comm
join
uniq
sed
But one in particular is something that was intensionally installed (I thought it was installed via macports, but I don't see it in the installed list).
gjoin
Is there a good way of determining if these commands change in any substantial way between versions before I actually upgrade the workstation?
None of those are "/usr/bin commands". They are binaries that exist on the system. They have nothing to do with your shell, as such.
Most, if not all, of those commands will report their version should you ask them (with --version or similar).
To determine whether things might possibly break you get to find out what has changed between the versions in question and to know whether that matters you need to know what the scripts that call them do and what functionality, from those binaries/languages, they use. That being said I think it very unlikely that updates to those commands will cause your scripts trouble unless your scripts depend on broken behaviour in the given tool or depend on explicit error (or other) messages from the tools for their operation.
Edit: As Pumbaa80 points out in his comment on the OP the only real way to know for sure whether the scripts will work or not is to try them and see. Though obviously testing of non-trivial scripts is certainly complicated and can be very difficult (if not all-but practically impossible depending on the task and script).
By the way...
Amongst the binaries/commands you list, Perl is the odd one out because that typically cannot be considered to have a single version, since it can have a load of additional installed modules which themselves can all be different versions. You may find it useful to run the following on your existing OSX 10.7 to find which modules are installed there so you can grab and install the same ones on Mavericks.
perl -MExtUtils::Installed -MData::Dumper -e '$inst=ExtUtils::Installed->new();print Dumper($inst->modules());'
For example, mine gives this:
$VAR1 = 'Bundle::NetSNMP';
$VAR2 = 'CPAN';
$VAR3 = 'Color::Similarity';
$VAR4 = 'Crypt::RC4';
$VAR5 = 'Devel::NYTProf';
$VAR6 = 'Digest::Perl::MD5';
$VAR7 = 'File::HomeDir';
$VAR8 = 'Graphics::ColorNames';
$VAR9 = 'Graphics::ColorObject';
$VAR10 = 'Image::Magick';
$VAR11 = 'JSON';
$VAR12 = 'JSON::Any';
$VAR13 = 'Mac::SystemDirectory';
$VAR14 = 'Mozilla::CA';
$VAR15 = 'OLE::Storage_Lite';
$VAR16 = 'Perl';
$VAR17 = 'Spreadsheet::ParseExcel';
$VAR18 = 'Spreadsheet::XLSX';
$VAR19 = 'Test::Without::Module';
$VAR20 = 'mod_perl2';

Discover the current user's screensaver timeout either programmatically or via commandline on a mac

Does anyone know how to discover what the timeout is for the screensaver of the current user on a mac. I would prefer a programmatic method if possible but am also happy to parse the output of a command line utility. I am already doing this with pmset to get the sleep times.
The value for screensaver settings for current user in (at least from 10.6.x upwards) stored in a property list file in ~/Library/Preferences/com.apple.screensaver.plist. It is possible that there is no value, in case the user has decided to disable automatic screen blanking/saving.
You can read the value with a command line utility called defaults(1):
defaults read com.apple.screensaver idleTime
defaults -currentHost read com.apple.screensaver idleTime
The former provides access to settings of current user, the latter to system defaults, should one exist.
Reading values with defaults(1) is somewhat complicated as the value may or may not be present. It'd be sane to assume that defaults read com.apple.screensaver idleTime would return zero in case the current user has disabled the screensaver, but that's not the case. Instead defaults(1) will toss an error message on the terminal and return non-zero exit code. Instead of just parsing the output of defaults(1), you'd have to first check the exit code and do parsing only in case it's zero. On the other hand, that might be a sane policy to follow anyway when parsing output of external commands.
Apple provides programming interfaces with their Xcode for reading/writing property lists as well.
As a follow-up to the correct original answer (in a response to the comments on that answer about El Capitan), it seems that the above property does not exist in 10.11 for the set of default values, but it does exist for currentHost:
$ defaults read com.apple.screensaver
{
askForPassword = 1;
askForPasswordDelay = 5;
tokenRemovalAction = 0;
}
and then for currentHost:
$ defaults -currentHost write com.apple.screensaver idleTime 60
$ defaults -currentHost read com.apple.screensaver
{
PrefsVersion = 100;
idleTime = 60;
moduleDict = {
moduleName = iLifeSlideshows;
path = "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver";
type = 0;
};
showClock = 0;
tokenRemovalAction = 0;
}
The above write command sets the idle time for my user, which is what I was looking for. Hope this helps!

Uncaught Throw generated by JLink or UseFrontEnd

This example routine generates two Throw::nocatch warning messages in the kernel window. Can they be handled somehow?
The example consists of this code in a file "test.m" created in C:\Temp:
Needs["JLink`"];
$FrontEndLaunchCommand = "Mathematica.exe";
UseFrontEnd[NotebookWrite[CreateDocument[], "Testing"]];
Then these commands pasted and run at the Windows Command Prompt:
PATH = C:\Program Files\Wolfram Research\Mathematica\8.0\;%PATH%
start MathKernel -noprompt -initfile "C:\Temp\test.m"
Addendum
The reason for using UseFrontEnd as opposed to UsingFrontEnd is that an interactive front end may be required to preserve output and messages from notebooks that are usually run interactively. For example, with C:\Temp\test.m modified like so:
Needs["JLink`"];
$FrontEndLaunchCommand="Mathematica.exe";
UseFrontEnd[
nb = NotebookOpen["C:\\Temp\\run.nb"];
SelectionMove[nb, Next, Cell];
SelectionEvaluate[nb];
];
Pause[10];
CloseFrontEnd[];
and a notebook C:\Temp\run.nb created with a single cell containing:
x1 = 0; While[x1 < 1000000,
If[Mod[x1, 100000] == 0,
Print["x1=" <> ToString[x1]]]; x1++];
NotebookSave[EvaluationNotebook[]];
NotebookClose[EvaluationNotebook[]];
this code, launched from a Windows Command Prompt, will run interactively and save its output. This is not possible to achieve using UsingFrontEnd or MathKernel -script "C:\Temp\test.m".
During the initialization, the kernel code is in a mode which prevents aborts.
Throw/Catch are implemented with Abort, therefore they do not work during initialization.
A simple example that shows the problem is to put this in your test.m file:
Catch[Throw[test]];
Similarly, functions like TimeConstrained, MemoryConstrained, Break, the Trace family, Abort and those that depend upon it (like certain data paclets) will have problems like this during initialization.
A possible solution to your problem might be to consider the -script option:
math.exe -script test.m
Also, note that in version 8 there is a documented function called UsingFrontEnd, which does what UseFrontEnd did, but is auto-configured, so this:
Needs["JLink`"];
UsingFrontEnd[NotebookWrite[CreateDocument[], "Testing"]];
should be all you need in your test.m file.
See also: Mathematica Scripts
Addendum
One possible solution to use the -script and UsingFrontEnd is to use the 'run.m script
included below. This does require setting up a 'Test' kernel in the kernel configuration options (basically a clone of the 'Local' kernel settings).
The script includes two utility functions, NotebookEvaluatingQ and NotebookPauseForEvaluation, which help the script to wait for the client notebook to finish evaluating before saving it. The upside of this approach is that all the evaluation control code is in the 'run.m' script, so the client notebook does not need to have a NotebookSave[EvaluationNotebook[]] statement at the end.
NotebookPauseForEvaluation[nb_] := Module[{},While[NotebookEvaluatingQ[nb],Pause[.25]]]
NotebookEvaluatingQ[nb_]:=Module[{},
SelectionMove[nb,All,Notebook];
Or##Map["Evaluating"/.#&,Developer`CellInformation[nb]]
]
UsingFrontEnd[
nb = NotebookOpen["c:\\users\\arnoudb\\run.nb"];
SetOptions[nb,Evaluator->"Test"];
SelectionMove[nb,All,Notebook];
SelectionEvaluate[nb];
NotebookPauseForEvaluation[nb];
NotebookSave[nb];
]
I hope this is useful in some way to you. It could use a few more improvements like resetting the notebook's kernel to its original and closing the notebook after saving it,
but this code should work for this particular purpose.
On a side note, I tried one other approach, using this:
UsingFrontEnd[ NotebookEvaluate[ "c:\\users\\arnoudb\\run.nb", InsertResults->True ] ]
But this is kicking the kernel terminal session into a dialog mode, which seems like a bug
to me (I'll check into this and get this reported if this is a valid issue).

Startup Items - Creating a basic one

Please save me from a potential nervous breakdown!
I've been following Apples documentation (see below) on how to create a Startup Item. Currently I'm just trying to get my script to print something to the console, much less actually run my app.
Here are my two scripts, one is the startup executable, the other is the plist:
#!/bin/sh
. /etc/rc.common
# The start subroutine
StartService() {
# Insert your start command below. For example:
echo "hey Eric we've started"
# End example.
}
# The stop subroutine
StopService() {
# Insert your stop command(s) below. For example:
echo "STOPPED ERIC"
# End example.
}
# The restart subroutine
RestartService() {
# Insert your start command below. For example:
echo "RESTART ERIC"
# End example.
}
RunService "$1"
{
Description = "Software Update service";
Provides = ("SoftwareUpdateServer");
Requires = ("Network");
Uses = ("Network");
OrderPreference = "Late";
Messages =
{
start = "Starting Software Update service";
stop = "Stopping Software Update service";
};
}
Using terminal I tried to set the permissions as closely as possible as to how it is documented in the example in the link below. The odd thing was that the files didn't show the 'root' aspect to their ownership.
I then ran SystemStarter start theApp and nothing happens. Absolutely nothing.
Any help?
http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/StartupItems.html
You should not create a Startup Item any more. It's a legacy mechanism and superseded by launchd. Write a plist for launchd instead. I know this is not the help you wanted, but sadly with Apple, you need to follow the mothership...
Read this section of the same document instead.
See the document just you quoted yourself:
Note: The launchd facility is he preferred mechanism for launching daemons in Mac OS X v10.4 and higher. Unless your software requires compatibility with Mac OS X v10.3 or earlier, you should use the launchd facility instead of writing a startup item. For more information, see “Guidelines for Creating and Launching Daemons.”
Note that v10.4 become available in 2005.

Resources