So I'm trying to create a C program where you must input the password on the command line, like
./login password1
And if the password is password1, it'll say something. If not, it prints another message. This is the code I have now:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("usage: %s <password>\n", argv[0]);
}
char pass = "password";
if (argc == pass) {
printf("Right\n");
} else {
printf("Wrong\n");
}
}
But it wont work.
char pass = "password";
You're trying to assign a string to a char. That won't work! Instead, you need need to declare pass as a char[] like this:
char pass[] = "password";
Next problem:
if(argc == pass)
argc is the number of command line arguments passed to your program (including the program name as the first). What you want is argv, which contains the actual arguments. Specifically, you probably want argv[1].
You can't just go argv[1] == pass as that compares the location of the two strings. To compare strings, you need to use strcmp(). This function compares two strings and returns 0 if they're equal (there's good reason for that, but leave it for now). The former is like comparing two houses by checking if they have exactly the same street address; the latter is like comparing the houses with each other brick-by-brick. (sniped from #caf)
So the line becomes:
if (strcmp(argv[1], pass) == 0)
Put those fixes together and it should work. Please also work on improving the indentation of your code. It'll make it much easier to read, not only for others but yourself in a few weeks time.
You're comparing argc - the count of command line arguments - with the "password" string pointer.
For a start, you need to use argv[1] instead of argc. You also need to use a suitable strcmp function rather than just comparing the pointers.
Finally, inputting passwords via the command line is usually a bad idea due to security considerations. On many systems the command line may be visible to other users (eg via the "ps" command).
Related
I've been looking every sscanf post here and I can't find an exact solution suitable for my problem. I was implementing my own Shell and one of the characteristics is that if I find the dollar sign $, I got to replace what is exactly behind with the environmental variable:
cd $HOME should actually be replaced by cd /home/user before I even execute the cd.
My question is what is the code to use sscanf to take out the dollar sign and simply get HOME on the same string? I've been struggling with some null pointers trying this:
char * change;
if (strcmp(argv[1][0],'$')==0){
change = malloc(strlen(argv[y]));
sscanf(argv2[y]+1,"%[_a-zA-Z0-9]",change);
argv2[y]=getenv(change);
}
But this seems to be failing, I'm having a segmentation fault core. (If needed i put more code, my question is specially focused on the sscanf).
Quick explanation argv is an array of pointers to the lines entered and parsed, so actually the content of argv[0] = "cd" and argv[1]="$HOME". I also know that the variable I'm going to receive after the $ has the format %[_a-zA-Z0-9].
Please ignore the non failure treatment.
You asked "is malloc() necessary" in your code snipped and the answer was "no", you could use a simple array. In reality, if you are simply making use of the return of getenv() without modification in the same scope without any other calls to getenv(), all you need is a pointer. getenv() will return a pointer to the value part of the name=value pair within the program environment. However the pointer may be a pointer to a statically allocated array, so any other calls to getenv() before you make use of the pointer can cause the text to change. Also, do not modify the string returned by getenv() or you will be modifying the environment of the process.
That said, for your simple case, you could do something similar to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char *envp = NULL, /* pointer for return of getenv() */
buf[MAXC]; /* buffer to parse argv[2] w/sscanf */
if (argc < 3) { /* validate at least 2 program arguments given */
printf ("usage: %s cmd path\n", strrchr (argv[0], '/') + 1);
return 1;
}
if (*argv[2] == '$') /* chest 1st char of argv[2] == '$' */
if (sscanf (argv[2] + 1, "%1023[_a-zA-Z0-9]", buf) != 1) {
fputs ("error: invalid format following '$'.\n", stderr);
return 1;
}
if (!(envp = getenv (buf))) { /* get environment var from name in buf */
fprintf (stderr, "'%s' not found in environment.\n", buf);
return 1;
}
printf ("%s %s\n", argv[1], envp); /* output resulting command line */
}
Right now the program just outputs what the resulting command line would be after retrieving the environment variable. You can adjust and build the array of pointers for execv as needed.
Example Use/Output
$ ./bin/getenvhome "cd" '$HOME'
cd /home/david
Look things over and let me know if you have any further questions.
You don't need sscanf here, you can just slide the pointer.
If argv[1] points to the string "$HOME", then argv[1] + 1 points to "HOME", so your example code would just become:
char * change;
if (argv[y][0] == '$')
{
change = argv[y] + 1;
}
(But in this case your variable should not be named change. Call your variables what they represent, for example in this case variable_name, because it contains the name of the shell variable you will be expanding - remember your code is for communicating to other humans your intent and other helpful information about the code.)
To be clear, whether you do sscanf or this trick, you still have to do error checking to make sure the variable name is actually the right characters.
Remember that sscanf won't tell you if there are wrong characters, it'll just stop - if the user writes a variable like $FO)O (because they made a typo while trying to type $FOO) sscanf will just scan out the first valid characters and ignore the invalid ones, and return FO instead.
In this case ignoring bad data at the end would be bad because user interfaces (that includes shells) should minimize the chances that a user mistake silently does an unintended wrong thing.
I'm trying to input only one filename from command line. Then I want to use an If statement to compare the filename to 4 different names I'm expecting to see. If I don't get one of the 4 expected file names then I need to print it back to the user with what was inputted and then exit the program safely.
int main(int argc, char *argv[])
{
....
}
I've been trying a lot of different methods of getting this done, but I just can't figure it out. I was thinking maybe the way I take the input argument is wrong. Any help would be greatly appreciated.
-edit
I just want to be clear I don't want you to be a leech and solve the question I have for me. Just at least point me in the correct direction. I can't figure how to make a for loop work with the filename.
for(argv == "UnexpectedFile.csv"){
printf("this is an unexpected file: %c", argv[1]);
}
You could use strcmp() from string.h to compare strings like
strcmp(argv[1], "unexpectedfile.csv");
It returns 0 when the strings are equal.
If you have the 4 file names in as an array of strings, say expectedFile, do
for(i=0; i<4 && strcmp(argv[1], expectedFile[i])!=0; ++i);
If the value of i is the total number of file names (ie, 4) after this loop, argv[1] is an unexpected file.
Otherwise, value of i would be the index of the file name string in the expectedFile array.
The command line arguments are stored in the 2-dimensional char array argv.
argv[0] would be the name of the executed file. The arguments you give start only from argv[1] onwards.
argc will have the total number of command line arguments including the file name stored in argc. So if there are 'no' arguments, argc would be 1.
In your case the file name is the only argument, so argc would be 2.
You must check if argc is at least 2 before you access argv[1] to prevent the program from accessing argv[1] when it isn't there.
(You do not ask for complete code solution (and do not provide enough of your code for that). So here are the pointers in the right direction you want.)
The comparison you do with a simple pointer == pointer does not really compare the content of the strings. That is what e.g. strcmp () is for, as proposed by #user3629249.
And in order to print out what was given as commandline argument, you should use "%s\n".
And in order to set up a for loop, you will have to do the syntax right: for(init assignment; condition; step operation).
(If you need more help, you will have to provide more details on what behaviour you get and what you do not like about it. Currently your code looks more like compiler errors, which you did not quote, than a problem with the behaviour goal...)
write c program that accepts one command line argument (your first name) and prompts the user for user input (your last name), then print ""Welcome to operating systems, "" to the screen.
Can anyone help me with this question? I know its using something like this from the below, but I dunno how to print out the thing? Can anyone help by giving the full answer? Thanks in advance.
int main (int argc, int *argv[])
argc is an integer that represents the number of command line arguments passed in to the program. It is the argument count, hence the name. *argv[] (or **argv depending on developer preference) represents the actual arguments. The proper name for argv is argument vector, which makes sense if you're familiar with that particular data type.
The first argument passed in, argc = 1 is the program's name. Argc is always at least one because argv will always contain at a minimum the name of the program.
To answer your question, you need to pass in a second command-line argument, argc = 2, where argv[1] equals the user's first name. We can accomplish that like this:
int main(int argc, char** argv)
{
// This line will print out how many command line arguments were passed in.
// Remember that it will always be at least one because the name of the program
// counts as an argument.
printf("argc: %d", argc);
// Remember that you want the second argument in argv,
// so you have to call argv[1] because arrays in C
// are 0-index based. Think of them as offsets.
printf("\nWelcome, %s", argv[1]);
return 0;
}
This should get you started. All you need to do now is write the code to read the string from the standard input and output it to the console.
Let's say I have a C program whose function declaration is void square(int n), (it's also defined) all it does it printf the squared value of n. I want to be able to run it from bash shell like so: square 5, where 5 is the input to the C program.
How would I go about this? I've looked into using getopt, read, I've read the man pages several times and watched a few getopt tutorials, but I can't seem to figure out a way to do this. I can't find an example of getopt that doesn't use flags in the examples, so I don't know how to apply it to a simple integer input. Could anyone share with me how to do this? I would really appreciate it.
If you don't have any other command line options you need to handle, getopt is probably overkill. All you need is to read the value from argv:
int main(int argc, char *argv[])
{
int n;
// need "2 args" because the program's name counts as 1
if (argc != 2)
{
fprintf(stderr, "usage: square <n>\n");
return -1;
}
// convert the first argument, argv[1], from string to int;
// see note below about using strtol() instead
n = atoi(argv[1]);
square(n);
return 0;
}
A better solution will use strtol() instead of atoi() in order to check if the conversion was valid.
So, I am working on a Linux based command line utility, that has to accept a few flags, and I have noticed some interesting behavior. I will be posting testing code that I was using outside of the main utility. I was using this code, so I did not have to alter the actual utility until I had working code that I could just insert. So here is the code that I have been fiddling with:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
while(--argc && (*++argv)[0] == '-')
putchar('*');
printf("\n%s\n", argv[0]);
}
Please ignore the fact that all this program does is print an asterisk and print its own name when invoked with one argument -b. The printing of the asterik was just to show that the loop ran once. So, I run this in a terminal as "./test -n", and I expected the output to be:
*./test
Much to my surprise, the output was:
*-b
I have a working theory of what the statement
(*++argv)[0] is doing, but I am still a little hazy on it. My assumption is that it steps across the array of pointers looking at the first character in each string pointed to, (*++argv)[0] is now dereferencing *argv[0] or element zero of the first argument string.
So, basically I have three questions:
What exactly is that statement doing?
Why can I not get back to argv[0] or argv[0][0], no matter what I try?
Is storing the value at the address pointed to by argv[0] in another char *, this is the only way that I have been able to access that value at this point, the normal way around this?
I am really confounded by this at the moment and have tried everything that I can think of to work this out. At one point I had a loop that would print the alphabet, I don't know what part of memory the program was accessing. The most interesting permutation was pulling sshid variables from somewhere.
Thank you all in advance for your help with this.
++argv changes argv to point to the next argument.
Try something like
int i = 0;
while(--argc && argv[++i][0] == '-')
Which maintains a separate index, instead of overwriting argv.
Or
char** argp = argv;
while(--argc && (*++argp)[0] == '-')
which works the same as the original, except it changes a copy of argv instead of the original.