Passing relative path on OSX in C - c

I'm trying to make a program which runs an executable in its folder on my Mac.
Considering that my program is compiled in the same folder as the source (/Users/Marcello/Documents/C/Test/Test/Test.c), the program would look something like this:
int main(int argc, const char * argv[])
{
printf("Hello, world!\n");
if(execl("/Users/Marcello/Documents/C/Test/Test/HelloWorld", "HelloWorld", NULL))
printf("ERROR\n");
return 0;
}
Everything works fine if I give the absolute path, but it won't work anymore when I try to pass the relative path to the folder (passing "HelloWorld" instead of "/Users/Marcello/Documents/C/Test/Test/HelloWorld").
I noticed this happens because, without other indications, the program will try to search for HelloWorld in the shell's folder instead of the project's folder. This happens as well with functions such as fopen(), so I tried thinking of solutions; the problem is, I want to get this code into a program that everybody could download and install wherever they like, an I would like it to be cross-platform too, but all the solutions I found, such as chdir(), somehow reference to the absolute path of the program, which I shouldn't know in advance.
Can anybody help me find a long-term solution?

The first element of argv contain the relative to path to your program.

Related

How to find current directory in C inside an application bundle [macOS]

We have an application bundle whose main executable has been written in Perl and packaged with pp. Unfortunately, this executable prevents us to codesign the .app. Apparently executables created with pp cannot be codesigned. To allow codesigning we want to move the main executable from its default folder "MacOS" to the "Resources" folder, as this folder seems to be okay to host the executable for codesigning and create a launcher that will run this executable. We do not know if this will work, but we want to give it a try.
We need to create a launcher to put in the "MacOS" folder that will launch our main executable. I have worked out a small C program that launches an executable in another folder. It works fine in Finder, however it fails if in the .app structure. Apparently it has to do with the relative path being different inside a .app. My hope is to add to the following C program a way to get the current directory of the .app and construct the relative path to the executable to be opened. Being the first time I write something in C, I need your help to make this adaptation.
#include<stdlib.h>
#include<stdio.h>
int main( void ){
int result ;
result=system("../Resources/MyApp");
printf("%d", result);
return 0;
}
I'm not quite sure what do you want to do but pwd is something that you looking for. In first block of code you will receive full path of the working directory and in second with int result you can know is operation done sucessfully (if result = 0 than is OK)
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char* dir= malloc (50);
dir = getenv("pwd");
printf("Workdir: %s\n", dir);
free(dir);
int result;
result = system("pwd");
printf("%d", result);
return 0;
}
then you can edit the full path and create relative.

Accessing Local Application Files In CLI Enviroment?

I'm not sure how to ask this, but I'll do my best. Anyway, my situation is this: I have files that I want my app/executable to be able to access at all times that are relative to the executable's path or in the same directory as the program. Since I want my program to be able to run in any CWD and still get everything it needs. I want to know what's the best way or method to get a file that's relative to my executable, that won't mess up the user's CWD?
The approach I had in my head is this:
Get program's directory using OS dependent function.
Use some string manipulation to get the program's home directory.
Append to the string the file I require during run time without having to use any hat trick CWD commands.
Not sure if Windows/Linux already has something up it's sleeves to deal with this, but I thought I should know if there is a better alternative.
Thank you!
If the files, that you want to access from your C binary, are in the same directory or subdirectory, you can access directly by using ".", this is the current directory.
or you can simply use the getwd function.
char *getwd(char *buf);
Typically, you can use like this (this snippet will print you, the current directory of the C binary):
int main()
{
char buf[4096];
getwd(buf);
printf(but);
}

List a target directory in C

So I am tasked with creating a shell. I have the functions working correctly (e.g. dir, clear, quit, etc.), but I have a question about the 'dir' function. Currently 'dir' works fine. It lists the files of the directory that the program is located in. What I want to do is list the directory of another location. Is there a way to that?
I have yet to create the change directory command. I was wondering if my problem would be solved through that instead. Any help is appreciated.
Side note: The instructions state that I "will need to provide some command line parsing capability to extract the target directory for listing." I have no idea what that is, but maybe someone could enlighten me.
Take a look at GNU's Simple Directory Lister example code, which uses opendir().
To parse command line arguments, take a look at your main() function:
int main(int argc, char* argv[])
{
...
return 0;
}
Use the argv[] pointer and argc integer value to determine the number of and character pointers of arguments.

Relative paths in C

I have a C program that uses some resources located in the same directory as the executable. When I execute the program from a random working directory (not the directory where the program is located) the resources don't load, because the relative path I use in the code is not the path where the executable is. How can I solve this nicely?
Pass the path of the directory that contains the resources to the program as an argument and either:
change the current directory of the process to the directory (chdir() on Unix and SetCurrentDirectory() on Windows), or
construct absolute paths to the resources
If it is Windows, as the comment on the question suggests, you can obtain the path of the exe using GetModuleFileName(), extract the directory from it and avoid having to provide an argument to the program. Then either of two options listed would allow the program to be executed from anywhere and still locate its resources.
For anyone happening upon this old question in the future as I just did:
The program (at least in linux) keeps the command it was called by as the first argument of int main argument list.
e.g.
In this example we will drill down a couple of directories to get to our program, resulting in the following call command user#PC:~$ ./foo/bar/awesome_program.x86_64.
The program (code below) will print ./foo/bar/awesome_program.x86_64.
Since we have that string as a variable, it should be rather simple to construct relative paths from it, only replacing the end of that string with paths relative to the executable.
working code:
#include <stdio.h>
int main (int argc, char **argv)
{
printf("calling path: %s\n", argv[0]);
return 0;
}

How to use chroot function in C programming?

I know that use the command "chroot" in linux need some files or directories such as usr, bin and so on. But when I use the function chroot() in C, do I need these files?
Here is my code, which "hw.out" is a binary file which just print "Hello, world". I compiled it and run it as root, but it was failed to print "Hello, world". What else should I do? Thank you!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int result = chroot(".");
if(result == 0)
printf("Chroot Succese.\n");
char *arrays[]={"./hw.out",NULL};
execvp("./hw.out", arrays);
return 0;
}
execvp is most likely failing, probably with ENOENT: no such file or directory, if hw.out is a dynamically linked executable.
For that to work, all the libraries required by hw.out need to be findable in the chrooted environment.
Try linking hw.out statically, and it should work. (And add error checking after execvp to see what errno is set to after the call if it returns.)
Please test that your hw.out works with command line chroot.
Perhaps hw.out is dynamically linked and is missing some libraries or ld-linux.so in the chroot directory.
Nitpicks 1, what's the point of return 0 after execvp? it never gets executed unless there is an error. I would rather have perror("can't exec"); return 1;
Nitpick 2, chroot() doesn't change working directory, although it works in your case, as you are chrooting to ".", it won't work as you expect if you later change it to chroot("somedir").
Make sure that hw.out is in the correct direct. Perhaps it is easier to have it statically linked if it is using libraries. Otherwise need to enable after chroot that it can access the dynamic libraries.

Resources