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.
Related
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.
I am currently writing my own terminal in C.
I found out, that there is multiple variants of the exec() methode, that i can use.
Its simple occurance lead me to use execv():
int main(int argc , char* argv[]){
char* dir = getcwd(NULL, 0);
char* command[] = {"echo", "Hello", "World", "!!!", NULL};
execv(dir, command);
}
From my understanding this should work. It is compiling, but nothing happens.
The path argument to execv is supposed to be the path specification to the executable file you want to run, not just a directory as returned by getcwd. From the manpage:
The initial argument for these functions is the pathname of a file which is to be executed.
In other words, you're looking for something like:
execv ("/bin/echo", command);
The code you currently have is trying to run your current directory, something that's unlikely to end well, and something you may have noticed if you checked the return value from execv along with errno: nudge, nudge, wink, wink :-)
In terms of what to do for other programs, you simply substitute their full path name for /bin/echo.
You should also be aware that exec is a family of functions, each with slight variations.
Some allow environments to be passed, some automatically search the path for your executable (depending on the name given), and some use variable argument lists rather than arrays. If you want to use the automatic path searching, you would look into execvp rather than execv, then you don't have to worry about where the executable file is located.
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;
}
I am very new with c and less experienced with any other language :/
For an assignment at uni, I am a little stuck on this small part. Essentially I am required to write a 'ls' function that has 4 optional arguments, for example:
list [-l] [-f] [pathname] [localfile]
Now, the first two are straight forward. To make things more difficult, the 'localfile' doesn't necessarily exist and the 'pathname'(if given) will be located on the server I'm connecting to through a socket (so checking if it is a file is out and checking the pathname is out). I was thinking, check last 4 chars in the string for a '.txt' or something similar. I'm actually completely stumped and will present this problem to my course conveyor tomorrow, if I can't find a solution.
This is a very small part of what I actually have to do but any push in the right direction would be appreciated.
You will need to process argc and argv to get your command line arguments. That is the first thing to work on, getting the arguments - ensuring they are correct, and determining what is being asked for.
int main(int argc, char *argv[])
Assuming your are on Linux/Unix, you will need to use the directory functions opendir()/readdir()/closedir() - dirent.h. The stat() function will be required to satisfy the -l requirement. access() will determine if a file exists and then stat() will tell you if the file is a regular file or a directory.
I'd make a struct to hold the four optional arguments and return it from a function called "process_arguments" that takes argc and argv as parameters.
struct args {
bool valid;
bool l_option;
bool f_option
char directory[200];
char filename[200];
}
With the requirement for a socket connection you will have to write a "server program" that will be constantly running on the server and a "client program" that it will fork to handle the requests from your local program. Try and locate examples of socket programs.
Another check for whether you have a path string or a filename is to look for the path separator character - '/' if the server is Unix/Linux. This scheme shouldn't have any path separators in filenames, so the presence of one tells you it is a path.
Is there any way in C to remove (using remove()) multiple files using a * (wildcards)?
I have a set of files that all start with Index. For example: Index1.txt, Index-39.txt etc.
They all start with Index but I don't know what text follows. There are also other files in the same directory so deleting all files won't work.
I know you can read the directory, iterate each file name, read the the first 5 chars, compare and if it fits then delete, but, is there an easier way (this is what I currently do by the way)?
This is standard C, since the code runs on Linux and Windows.
As you point out you could use diropen, dirread, dirclose to access the directory contents, a function of your own (or transform the wildcards into a regex and use a regex library) to match, and unlink to delete.
There isn't a standard way to do this easier. There are likely to be libraries, but they won't be more efficient than what you're doing. Typically a file finding function takes a callback where you provide the matching and action part of the code. All you'd be saving is the loop.
If you don't mind being platform-specific, you could use the system() call:
system("del index*.txt"); // DOS
system("rm index*.txt"); // unix
Here is some documentation on the system() call, which is part of the standard C library (cstdlib).
Is this all the program does? If so, let the command line do the wildcard expansion for you:
int main(int argc, char* argv[])
{
while (argc--)
remove(argv[argc]);
}
on Windows, you need to link against 'setargv.obj', included in the VC standard lib directory.