Re: setting unix environment variables for debugging
Re: setting unix environment variables for debugging
- Subject: Re: setting unix environment variables for debugging
- From: Chad Jones <email@hidden>
- Date: Thu, 07 Feb 2008 17:29:17 -0600
One time years ago I had to return the absolute path to certain files. I remember that I used a unix call called realpath "man realpath".
Aside from that I believe I had to get the value of '~' separately. Actually you are in luck (or maybe not) as I found the code I worked
on. Its insanely ugly code but it does do what its supposed to.
Basically the short answer is use getenv("HOME") and where MAXPATHLEN below is defined in the system headers. I should also
note that this just gets you the value of HOME variable and may not always be the user's home directory. But for your
testing purposes that should be all you need. If you want to get the user's home directory reliably regardless of what $HOME
is set to then you need to use directory services matched with the system configuration framework. The code to do that is much more
complicated but turns out I also have code to do that as well. But its far too long to post into an email. But in any case I think the below
should answer your question. :)
Chad.
----
#include <stdio.h>
#include <sys/param.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
char FullPathCString[MAXPATHLEN]; //the Maxpathlength is actually returned on completion of this routine.
char* GetRealPath(char* PathToItem)
{
char HomePath[MAXPATHLEN];
char RealPath[MAXPATHLEN];
int counter, RealPathStart;
int PathLength = strlen(PathToItem);
//Checking path to ensure that it is a valid string.
if (PathLength < 0)
{
return(NULL);
}
//If there is a ~ at the beginning of the path then we resolve it to the User's home directory.
if ((PathToItem[0] == '~')) //this code takes care of resolving the '~' in the path.
{
//To resolve ~ we need to know what it's value resolves to. This is the home directory path which is stored in the environment variable "HOME" and is even what "cd" depends on within terminal. After this HomePath holds the users home directory as a path.
strncpy(HomePath, getenv("HOME"), MAXPATHLEN);
//Next we need to concatinate the home path we obtained with the original path passed in (minus the ~ of course). However first we need to check there is enough space available to store the string. If there isn't we fail. MAXPATHLEN is a global system variable which determines the maximum lenght a path can have. Typically this is 1024.
if ((strlen(HomePath) + strlen(PathToItem) - 1) > MAXPATHLEN)
{
return(NULL);
}
//now that we have the home path we will append it to the path we already have to get a new path to the item.
strncpy(RealPath, HomePath, MAXPATHLEN);
//we are going to copy character by character the path to the new complete path (without the ~). We do character by character because for such a small number of characters (typically 1024) this is acceptable and easy to understand.
RealPathStart = strlen(RealPath);
for (counter = 1; counter < PathLength ; counter++)
{
if (counter > MAXPATHLEN)
{
return(NULL); //if this is true something went terribly wrong and we fail.
}
RealPath[RealPathStart + counter - 1] = PathToItem[counter]; //copying character by character adding the two paths together
}
}//end resolving ~ section
else //if we don't have a ~.
{
//if there is a null string passed in it is treated as if ~ was passed in. This is the behaviour of cd and other commands.
if (strcmp(PathToItem, "") == 0)
{
strncpy(RealPath, getenv("HOME"), MAXPATHLEN);
}
else //we just stick with what is passed in.
{
strncpy(RealPath, PathToItem, MAXPATHLEN);
}
}
//Now we remove/resolve symbols "./", "../". Much easier than resolving the ~ this can be done with a standard system call to the POSIX function "realpath".
if (realpath(RealPath, FullPathCString) == NULL)
{
return(NULL); //if realpath returns null then we had a bad error. Then we quit.
}
//if we got this far we were successful.
return(FullPathCString);
}
int main (int argc, const char * argv[])
{
#pragma unused( argc, argv )
// insert code here...
printf(GetRealPath("~"));
return 0;
}
Joe Harris wrote:
Thanks, you've given me some excellent ideas. I like the idea of
launching xcode from a terminal and it appears that environment
variables are inherited by xcode and the debugger. (I inserted a
printenv in the code and the output was sent to gdb console). I'm not
quite ready to pull out the symbolic links from the code but may have
to. I'm still not able to use the environment variables in my code. Even
a simple one like home; in the code I use it as '$HOME/some/more/path/'
and it still is not recognized. Any thoughts?
Thanks,
Joe
On Feb 6, 2008, at 11:04 PM, Chad Jones wrote:
Not positive what you mean here. But from what I understand I'd
probably add some UNIX calls to my code to control the creation
of symbolic links. First I would add some code to my main project
which would be activated by a debugger flag.
The debugger flag I would define under "Other Warning Flags" using "-D
AddSyms" but of course any name could be chosen. The
debugger flags allows your configuration to be easily configured for
your test environment. :) This code when activated would use
popen to get a list of the symbolic links or (alternatively system()
could be used to create your symbolic links) see man popen, man system
in terminal for more information. Other UNIX commands for creating
symbolic links can likewise be used. Here's some test code
below that uses the debugger flag and popen to print out a list of the
files in "/". I imagine you could use something like the following
to even create or analyze symlinks using UNIX calls readlink, symlink
or unlink and the like matched with the appropriate popen/system call.
Note the below code will only do anything if you have AddSyms defined.
#include <stdio.h>
int main (int argc, const char * argv[])
{
#pragma unused( argc, argv )
#if defined( AddSyms )
FILE *fp;
int status;
char path[1024];
fp = popen("ls /", "r");
if (fp == NULL)
{ /* Handle error */ }
while (fgets(path, 1024, fp) != NULL)
printf("%s", path);
status = pclose(fp);
if (status != -1)
{ printf( "Success\n" ); }
else
{ printf( "Failure\n" ); }
#endif
return 0;
}
So I guess I'm saying that you maybe shouldn't be using environment
variables at all but instead use debugger flags. :) But if you
really want to use environment variables off the top of my head if you
use "open /Developer/Applications/Xcode.app"
from terminal it will launch XCode and then I believe XCode will
inherit the environment variables you set in terminal using setenv and
the like.
>Does someone have an
>example for setting a symbolic link?
see "man symlink" in terminal? Also google. :)
> A related question is how do I verify the env var are set correctly
> before debugging?
For this I'd use UNIX popen() similar to above and check the output
is what you expect. There may be other file system calls which
are more appropriate for this as well.
email@hidden wrote:
The issue of setting environment variables has come up before but I
don't think in this context. I have an application that must have
symbolic links defined for 30 files before it can be tested. How do I
set these variables before debugging in Xcode? I know about the
environment.plist and setting env var in Executable Info. The .plist
option is not very useful because the variables will change with
different test configurations. The arguments/variables panel under
Executable Info potentially may work but it has not worked in the
case I've tried - perhaps I don't have the format right. Does someone
have an example for setting a symbolic link?
A related question is how do I verify the env var are set correctly
before debugging?
Joe
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden