0

I have a c-code written in Xcode 7, and running on my Mac laptop running El Capitain (OSX 10.11.6). The program calls another program, "bertini", using the following lines of code:

eflag = execvp("bertini", "input");

or alternatively

system("bertini input");

Both of these worked just fine before I upgraded my operating system (I was running either Xcode 3 or 4, I don't remember.) Now the program no longer works, because it can't find the program bertini.

I figured out the problem is that bertini is not on the search path, because in El Capitain, I am not allowed to copy executables to /usr/bin/. So, following instructions on this page: http://forums.appleinsider.com/discussion/189702/cant-copy-file-to-usr-bin-even-when-logged-in-as-root,

I moved the bertini executable to a folder of my choice, and changed ~/.bash_profile to point to this folder. Now bertini runs just fine in the terminal, but not when it is called by my program.

How on earth can I get to program, when run in Xcode, to find the current location of bertini? I have tried inputting the full directory (/path/to/directory/containing/bertini/bertini), but this still doesn't work. I have also tried following instructions for previous versions of Xcode (eg as in this question where is $PATH set in xcode?) but it seems that the versions of Xcode are pretty different and I don't understand how to adapt these instructions. Also, the link in the response about setting ~/.MacOSX/environment.plist is broken, and I'm nervous about changing files starting with a "." without knowing what I'm doing (I don't know much about this).

Note that this is for academic research, not for general use, so if I can get it to work on my machine only (well, two machines), that is fine.

Community
  • 1
  • 1

1 Answers1

0

I need to start by saying that your code sample using execvp does not look right, and in fact should not compile. You may mean something like either

char *const argvector[] = { (char *const)"bertini", (char *const)"input", NULL };
eflag = execvp("bertini", argvector);

or

eflag = execlp("bertini", "bertini", "input", (char *)0);

OK, now on to solving your problem. There are at least two basic approaches to simply make things work. One is to specify a full path to wherever you put "bertini" in your exec call, as in the following example using execvp:

char *const argvector[] = { (char *const)"bertini", (char *const)"input", NULL };
eflag = execvp("/full/path/to/bertini", argvector);

The man page for the exec functions (man 3 exec) specifies that the path is only searched if the string passed in as the "file" parameter does not have any "/" characters in it. Thus the above ignores the path and launches "bertini" if it exists at the full path specified. That might be the easiest way forward, and it will work in older versions of MacOS as well.

But if for some reason you would prefer to have a search path involved, you can can ensure that the path for an app launched from Finder uses a specific search path by using the launchctl shell command, as explained in the following article -

Environment variables in Mac OS X

Just place the command

launchctl setenv PATH $PATH

in ~/.bash_profile, after wherever you update your path to include your new location for "bertini" and then (this is important) you need to reset Finder to absorb this new information. I think logging out and in again will do it, but if I'm wrong, try rebooting. Now all apps launched from the command line will use your updated path and the original "system" call should work.

Just a parting comment. /usr/local/bin is a good place to put things on the later MacOS versions (the ones that don't allow changes to /usr/bin). It may even be on the default path that Finder-launched apps use. Just one more thing to try.

Community
  • 1
  • 1