Program parameters to main in c - ./dev --print - c

I am trying to make a program check whether the user is passing a program parameter when running the program. fx:
./dev --print
I came up with the following:
int main(int argc, char *argv[]) {
char print[] = "--print";
if(strcmp(argv[1], print) == 0) {
solve_a_bunch_of_functions_and_print_without_user_input();
}
else {
ask_for_user_input();
then_solve_bunch_of_functions();
}
}
Is this the correct / smartest way to do so?
Currently I am experiencing issues with seg-faults after this implementation for everytime i get into the else statement. Not sure my implementation here has anything to do with it.

Yes, that's one way although I think most C programmers wouldn't bother with the separate variable, and just do:
if(strcmp(argv[1], "--print") == 0)
Of course, you should first validate that there is an argument in argv[1], by checking argc, too. Otherwise you're passing NULL to strcmp(), which is a bad idea.
if(argc > 1 && strcmp(argv[1], "--print") == 0)
{
}

Related

basic CLI program in C

Okay so overall im trying to complete a basic CLI C program which will complete functions such as clear, quit, cd, ls, help (bring up the unix man) etc.. i altered my code and so far i have this, im getting segmination error when trying to execute the cd command part of the program, (im very new to c btw);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main (int argc, char *argv[])
{
char input[] = " ";
char *argument;
while(strcmp(input, "quit")!= 0)
{
printf("$");
scanf ("%s", input);
if(strcmp(input,"clear") == 0)
{
printf("\e[1;1H\e[2J");
}
else if(strcmp(argv[1],"cd") == 0)
{
if(chdir(argv[2]) == -1)
{
printf("\n directory does not exists");
}
}
else if(strcmp(input, "echo") == 0)
{
char str[50];
scanf("%[^\n]+", str);
printf(" %s", str);
}
}
}
input is declared as a ' ' (space) character. It will never match 'cd'.
This is probably more along the lines of what you want to achieve, where the first parameter is the command (cd), and the second will be the directory:
int main (int argc, char *argv[])
{
char *argument;
if(strcmp(argv[1],"cd") == 0)
{
if(chdir(argv[2]) == -1)
{
printf("\n directory does not exists");
}
}
Edit Also please note that there is no need for the else satement. If chdir does not return an error, it will change the directory, thus no need to call it again in an else.
Additionally, another tip for using system calls in general, it would be of great help if you print the error number returned by the system upon a failure in system call. This will make things easier when things start going wrong. To do this simply include <errno.h>' and modify the printf to printerrno` which gives specific details about the error:
printf("Chdir error: %d", errno);
For instance chdir() does not only return an error when the directory does not exist, but also for example if you do not have permissions to view the contents of the directory. See the man page for a list of possible errors.
To implement your own shell, you need to take input directly from stdin, not from command-line arguments (argv) from another shell. The basic pattern is like this:
Read input
Execute command
Print results
Loop back to step 1

Checking for command line arguments in C

I wrote this code to take input from the command line, and depending on the input, will perform a set of actions, or if the input is incorrect, throws an error. However, I also need to check if no arguments are supplied, which I try to account for in my else statement.
if(strcmp(argv[1], "-L") == 0)
{
//does stuff
}
else if(strcmp(argv[1], "-W") == 0)
{
//does stuff
}
else if (*(argv[1]) != 1)
{
puts("error: invalid input");
}
else //should check if no arguments
{
puts("error: expected command line argument");
return 1;
}
I am getting a segmentation fault whenever there are no arguments from the command line, and I'm not sure how to fix it. I have also tried to write the else statement this way:
else if(argc < 2)
{
puts("error: expected command line argument");
return 1;
}
This was based on my previous research on here where I found "C produce error if no argument is given in command line," but it won't work either. I am a beginner in C and do not fully understand argc and argv, so if anyone has any suggestions or logic I'm completely overlooking, please let me know.
You need to check if argc < 2 before anything else.
Else you get segmentation fault because argv[index] could be something you have not privileges to access.
Whatever you do, make sure you never try to access an index of argv that is greater or equal to argc. In your case, you are accessing index 1 when the last available index is 0 (argc is 1), that's why the segmentation fault. See this post for more info: What does int argc, char *argv[] mean?

Using an if/else statment to check that enum arguments exist

I'm having a slight issue with my current piece of code and trying to check that arguments have been passed to enum before trying to continue with the program;
enum arg {argName, sineArg, sampleArg, argC}eargs;
int main(int argc, char *argv[]){
long samplingRate = atol(argv[sampleArg]);
float sineFreq = atof(argv[sineArg]);
if (argC < eargs ){
printf("Usage: sineFreq\tsamplingRate\n");
}else{}
}
The code compiles fine, although when run without arguments the program returns "Segmentation fault: 11" instead of the usage message that I want to print to console.
you have to do the check before accessing argv[...]
EDIT: the check itself is wrong too (eargs is undefined; you should write
int main(int argc, char *argv[]) {
if (argc < argC) /* --> you should change you naming conventions! */
return EXIT_FAILURE;
long samplingRate = atol(argv[sampleArg]);
Your usage check is against eargs that has nothing to with the number of command line arguments passed. No matter how many arguments you pass, eargs is always going to be 0.
Also you should do the check before using any of the command line arguments. Place the condition at the start of main():
#include<stdio.h>
#include <stdlib.h>
enum arg {argName, sineArg, sampleArg, argC}eargs;
int main(int argc, char *argv[]) {
/* if ( argc < 3) would be explicit and clear here */
if (argc < argC ) { /* You expect at least two arguments */
printf("Usage: sineFreq\tsamplingRate\n");
return 1; // return from main on failure
}
long samplingRate = atol(argv[sampleArg]);
float sineFreq = atof(argv[sineArg]);
....
}
I have also included standard headers as you are using printf() and atol()
you need to change argC to argc, in the if statement...c is case-sensitive!!!
When you run the code without arguments, this
long samplingRate = atol(argv[sampleArg]);
accesses argv[2], which is undefined behavior, since you don't provide enough args (there are only argv[0] = program name and argv[1] = NULL indicating the end of the argv[]).

Compare string literal command line parameters in C

I need my program to run this way ./src c 2345 or ./src s 345, whereby the first character hs to be either c or s and second an integer. The program should throw an usage error if there's any less parameters and also any charcter other than c or s. Here's my code
int main(int argc, char **argv) {
int num_of_connections = 0, client_sockfd;
int max_sockfd, master_socket;
fd_set socket_collection, read_collection;
// Check validity of the user input
if(argc < 3) {
if((strcmp(argv[2], "s") != 0) || (strcmp(argv[2], "c") != 0)){
fprintf(stderr, "Usage: ./src <s/c> <port>\n");
exit(EXIT_FAILURE);
}
}
When I enter one argument I get a segmentation fault. Also it doesnt identify the C or S parameter. Any help will be appreciated.
Notice that main has a very specific convention: the argv array has argc+1 members, with the last being NULL and the others being non-null distinct pointers to zero-terminated strings.
So if argc is 1 (e.g. if your run ./src alone) or 2, argv[2] is NULL and you cannot pass it to  strcmp
You can call strcmp(argv[2],"s") only when argc>=3
BTW, I would suggest to use getopt(3) or preferably (on Linux only) getopt_long and to accept the --help and --version arguments, per GNU conventions.
Also, compile with all warnings and debug info (gcc -Wall -g) and use the gdb debugger. It would be faster for you to use gdb than to ask here and wait for replies.
if(argc < 3) { does not make sense if you want exactly two parameters. In the inner if block you are confusion || (logical or) with && (logical and).
In your invocation example ./src s 345 the character is the first argument, so probably argv[2] should read argv[1].
if ((argc != 3) || ((strcmp(argv[1], "s") != 0) &&
(strcmp(argv[1], "c") != 0))) {
fprintf(…);
return EXIT_FAILURE;
}
Note: all parentheses in this if (…) condition are optional, because of C's operator precedence. I put them for readability.

Real time input/output (chat-like)

I'm trying to make a little chat program after reading Beej's guide to programming.
And then I was thinking about the basics of the program itself, and I don't know how to print output of recv() and get input for send() at the same time, because the client can always write something and send, but how is it possible to also print something while he's trying to input ?
I thought about threads, and I learned a little bit about them, and I created 2 simple threads: The first one, prints a sentence every 3 seconds, and the second one get input, this little program of-course had a lot of issues, for ex. if you started typing, and the other thread needs to print something, it will simply take what you wrote, and print it with itself output.
Here is the code, I tried to recreate it, I hope you guys can help me ..
pthread_t tid[2];
void* printse();
void* getinput();
int main(int argc, char *argv[])
{
int error;
error = pthread_create(&(tid[1]), NULL, &getinput, NULL);
if(error != 0)
{
printf("ERROR\n");
} else {
printf("NOERROR\n");
}
error = pthread_create(&(tid[2]), NULL, &printse, NULL);
if(error != 0)
{
printf("ERROR\n");
} else {
printf("NOERROR\n");
}
sleep(5000);
return 0;
}
void* printse()
{
while(1)
{
printf("POTATO\n");
sleep(3);
}
return NULL;
}
void* getinput()
{
char *input;
while(scanf("%s", input) != EOF)
{
printf("-%s\n", input);
}
return NULL;
}
You have undefined behavior in your code: You haven an uninitialized pointer input in getinput.
Uninitialized (non-static) local variables have an indeterminate value, and it will seem to be random. As the value is indeterminate (and seemingly random) the scanf call will write to some unknown place in memory, overwriting whatever was there.
You could easily solve this by making input an array.

Resources