Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior of argv when passing string containing "!!!!"

Tags:

c

bash

quotes

argv

I have written a small program that takes some input parameters from *argv[] and prints them. In almost all use cases my code works perfectly fine. A problem only arises when I use more than one exclamation mark at the end of the string I want to pass as an argument ...

This works:

./program -m "Hello, world!" 

This does NOT work:

./program -m "Hello, world!!!!" 

^^ If I do this, the program output is either twice that string, or the command I entered previous to ./program.

However, what I absolutely don't understand: The following, oddly enough, DOES work:

./program -m 'Hello, world!!!!' 

^^ The output is exactly ...

Hello, world!!!! 

... just as desired.

So, my questions are:

  • Why does this strange behavior occur when using multiple exclamation marks in a string?
  • As far as I know, in C you use "" for strings and '' for single chars. So why do I get the desired result when using '', but not when using "" as I should (in my understanding)?
  • Is there a mistake in my code or what do I need to change to be able to enter any string (no matter if, what, and how many punctuation marks are used) and get exactly that string printed?

The relevant parts of my code:

// this is a simplified example that, in essence, does the same  // as my (significantly longer) code int main(int argc, char* argv[]) {     char *msg = (char *)calloc(1024, sizeof(char));      printf("%s", strcat(msg, argv[2])); // argv[1] is "-m"      free(msg); } 

I already tried copying the content of argv[2] into a char* buffer first and appending a '\0' to it, which didn't change anything.

like image 827
ci7i2en4 Avatar asked Feb 08 '18 13:02

ci7i2en4


People also ask

Is argv a string?

The second argument to main, usually called argv, is an array of strings. A string is just an array of characters, so argv is an array of arrays. There are standard C functions that manipulate strings, so it's not too important to understand the details of argv, as long as you see a few examples of using it.

Is argv 1 a string?

Argc and argv Argv looks weird, but what it is is an array of C-style strings. Sometimes you see it declared as "char *argv[]," which is equivalent to the above. Element argv[i] will be a c style string containing the i-th command line argument. These are defined from 0 through argc-1.

What data type is argv?

argv is of type char ** . It is not an array. It is a pointer to pointer to char . Command line arguments are stored in the memory and the address of each of the memory location is stored in an array. This array is an array of pointers to char .


1 Answers

This is not related to your code but to the shell that starts it.

In most shells, !! is shorthand for the last command that was run. When you use double quotes, the shell allows for history expansion (along with variable substitution, etc.) within the string, so when you put !! inside of a double-quoted string it substitutes the last command run.

What this means for your program is that all this happens before your program is executed, so there's not much the program can do except check if the string that is passed in is valid.

In contrast, when you use single quotes the shell does not do any substitutions and the string is passed to the program unmodified.

So you need to use single quotes to pass this string. Your users would need to know this if they don't want any substitution to happen. The alternative is to create a wrapper shell script that prompts the user for the string to pass in, then the script would subsequently call your program with the proper arguments.

like image 122
dbush Avatar answered Sep 22 '22 08:09

dbush