Distinguish between optional arguments, pathname or file? c language - c

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.

Related

How to fix "too few arguments to function mkdir"

Im a coding noob. I have to compile some codes for my project in a HPC server. I can compile the codes in my laptop but when i run it on the HPC i get the error message
"too few arguments to function mkdir".
I have tried to print the output in the cwd and not in the output directory but it still didnt fix the problem. If i use the check command declared as a comment (which one of my instructors advised), I get the error check undeclared first use in the function.
void write_collection_pvd(int time_total, int time_save, char *directory, char *filename)
{
int x;
char dataFileName[255];
FILE *dataFile;
//#ifdef WIN32
mkdir(directory);
//#else
// check = mkdir(directory,0777);
//#endif
sprintf(dataFileName, "%s/%s.pvd", directory, filename);
}
i expect the pvd file to be written in the ouput directory. Thanks in advanceenter code here
In C, the mkdir function accepts two parameters: the name of the directory to create and the (typically octal) permission mode to give it. So instead of calling
mkdir(directory);
you should call something like
mkdir(directory, 0777);
That will give the new directory permissions of read, write, and search (execute) by the owner, group, and everybody else. But (at least under Unix and Linux) these permissions will be adjusted downward by your process's default permissions, which will typically turn off writability by world and often group.

What is the entry point for git?

I was browsing through the git source code, and I was wondering where the entry point file is? I have gone through a couple files, that I thought would be it but could not find a main function.
I could be wrong, but I believe the entrypoint is main() in common-main.c.
int main(int argc, const char **argv)
{
/*
* Always open file descriptors 0/1/2 to avoid clobbering files
* in die(). It also avoids messing up when the pipes are dup'ed
* onto stdin/stdout/stderr in the child processes we spawn.
*/
sanitize_stdfds();
git_setup_gettext();
git_extract_argv0_path(argv[0]);
restore_sigpipe_to_default();
return cmd_main(argc, argv);
}
At the end you can see it returns cmd_main(argc, argv). There are a number of definitions of cmd_main(), but I believe the one returned here is the one defined in git.c, which is a bit long to post here in its entirety, but is excerpted below:
int cmd_main(int argc, const char **argv)
{
const char *cmd;
cmd = argv[0];
if (!cmd)
cmd = "git-help";
else {
const char *slash = find_last_dir_sep(cmd);
if (slash)
cmd = slash + 1;
}
/*
* "git-xxxx" is the same as "git xxxx", but we obviously:
*
* - cannot take flags in between the "git" and the "xxxx".
* - cannot execute it externally (since it would just do
* the same thing over again)
*
* So we just directly call the builtin handler, and die if
* that one cannot handle it.
*/
if (skip_prefix(cmd, "git-", &cmd)) {
argv[0] = cmd;
handle_builtin(argc, argv);
die("cannot handle %s as a builtin", cmd);
}
handle_builtin() is also defined in git.c.
Perhaps it's best to address the misunderstanding. Git is a way of collecting, recording, and archiving changes to a project directory. This is the purpose of a Version Control System, and git is perhaps one of the more recognizable ones.
Sometimes they also provide build automation, but often the best tools focus on the fewest responsibilities. In the case of git, it mostly focuses on commits to a repository in order to preserve different states of the directory it is initialized to. It doesn't build the program, so the entry points are unaffected.
For C projects, the entry point will always be the same one defined by the compiler. Generally this is a function called main, but there are ways to redefine or hide this entry point. Arduino, for example, uses setup as the entry point and then calls loop.
The comment left by #larks is an easy way to find the entry point when you're not sure. Using a simple recursive search from a git repo's root directory can hunt for the word main in any included file:
grep main *.c
The Windows equivalent is FINDSTR, but recent updates to Windows 10 have greatly improved compatibility with Bash commands. grep is usable in the version I'm running. So is ls, though I'm not sure whether it has been there all along.
Some git projects include multiple languages, and many languages related to C (and predecessors) use the same entry point name. Looking only in file extensions of .c is a good way to find the entry point of the C components, assuming the code is of high enough quality that you'd want to run it in the first place.
There are definitely ways to interfere with how well the extension filters out other languages, but their use implies very haphazard coding practice.

Command line arguments without the hyphen

How can I parse arguments without the hyphen in C?
I.e. virsh install vm
or
git pull origin master
When I tried it out, if there is no - prefix, everything just gets ignored and argc returns 1 (argv[0] is the program call).
I'm using Linux, but it would be nice if there was a cross platform method to achieve this.
UPDATE: the problem was me using a # in front of the first argument, I was trying to pass in #XX eg number_program #12. Needless to say this doesn't work.
Are you using some library to parse the arguments for you? There is no special 'hyphen' arguments when passing in parameters to a C program specifically. Parse argv however you like.
For example:
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
for(i=0; i<argc; i++) {
//dont do this without proper input validation
printf("%s\n", argv[i]);
}
return 0;
}
Example run:
$ ./a.out test test test -hyphen
./a.out
test
test
test
-hyphen
argv contains the program name and the arguments to the program, in the order they were given in the command line.* Hyphens aren't special; they just make it easy for both people and computers to separate options from other args.
If you want to interpret args a certain way, that's your prerogative. That's what git does, basically interpreting argv[1] (if it exists, of course) as the name of a subcommand. And you don't need any libraries in order to do that. You just need to decide how you want the args interpreted.
* Modulo some cross-platform differences in how args are parsed; *nix typically does some pre-parsing for you and expands wildcard patterns, for example. You won't have 100% cross-platform compatibility unless you understand those differences and are ready for them.

Execv for own terminal

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.

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.

Resources