How can GCC know argc if we did not specify it? [duplicate] - gcc

Everytime I create a project (standard command line utility) with Xcode, my
main function starts out looking like this:
int main(int argc, const char * argv[])
What's all this in the parenthesis? Why use this rather than just
int main()?

main receives the number of arguments and the arguments passed to it when you start the program, so you can access it.
argc contains the number of arguments, argv contains pointers to the arguments.
argv[argc] is always a NULL pointer. The arguments usually include the program name itself.
Typically if you run your program like ./myprogram
argc is 1;
argv[0] is the string "./myprogram"
argv[1] is a NULL pointer
If you run your program like ./myprogram /tmp/somefile
argc is 2;
argv[0] is the string "./myprogram"
argv[1] is the string "/tmp/somefile"
argv[2] is a NULL pointer

Although not covered by standards, on Windows and most flavours of Unix and Linux, main can have up to three arguments:
int main(int argc, char *argv[], char *envp[])
The last one is similar to argv (which is an array of strings, as described in other answers, specifying arguments to the program passed on the command line.)
But it contains the environment variables, e.g. PATH or anything else you set in your OS shell. It is null terminated so there is no need to provide a count argument.

These are for using the arguments from the command line -
argc contains the number of arguments on
the command line (including the program name), and argv is the list of
actual arguments (represented as character strings).

These are used to pass command line paramters.
For ex: if you want to pass a file name to your process from outside then
myExe.exe "filename.txt"
the command line "filename.txt" will be stored in argv[], and the number of command line parameter ( the count) will be stored in argc.

main() is a function which actually can take maximum three parameters or no parameters.
The following are the parameters that main() can take is as follows:-
1) int argc : It holds the number of arguments passed (from the command prompt) during the execution of program or you can say it is used ot keep a track of the number of variables passed during the execution of program. It cannot hold the negative value. Eg. If you pass your executable file "./a.out" then that will be considered as a parameter and hence argc value will be 0 i.e 1 value is passed.
2) char *argv[] : it is an array of character pointers which holds the address of the strings(array of characters) that are passed from the command prompt during execution of program. Eg. in above example if you wrote argv[argc] i.e argv[0] in cout then it will give ./a.out as output.
3) char*envp[] : it is also an array of character pointer which is used to hold the address of the environments variables being used in the program. Environment variables are the set of dynamic named value that can affect the way the running process will behave on the computer. For example running process want to store temporary files then it will invoke TEMP environment variables to get a suitable location.

Related

How, or in which pattern, are environment variables listed in a shell (bash)?

I have a task to implement my own shell in C from scratch for my school.
As a reference, I must take bash.
My question is, how are the environ variables listed when either env or printenv are called?
I've noticed it's neither by creation date nor by alphabetical order.
My shell has its own environment as a char **, and I'm wondering how should I shuffle it after a new variable declared so that it imitates bash correctly.
I tried running export a=aaaa in bash and it appeared in the middle of the list.
how are the environ variables listed when either env or printenv are called?
Both these programs are open source. From coreutlis/env.c:
char *const *e = environ;
while (*e)
printf ("%s%c", *e++, opt_nul_terminate_output ? '\0' : '\n');
From coreutils/printenv:
for (env = environ; *env != NULL; ++env)
printf ("%s%c", *env, opt_nul_terminate_output ? '\0' : '\n');
I've noticed it's neither by creation date nor by alphabetical order.
Inspecting glibc/setenv.c I think it appends the values on the end, and keeps a separate binary search tree (#include <search.h>) with variable names for fast searching.
Posix states from https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html :
There is no meaning associated with the order of strings in the environment.
and I think this is enough to give implementations freedom to use any order they want.
in bash and it appeared in the middle of the list.
There is no reason for Bash to use environ. Bash has its own export_env 2d array, and it keeps variables using its own HASH_TABLE implementation - hashlib.c and also VAR_CONTEXT.

Input stdin of c program using bash

I made a c program which takes two standard inputs automatically and one manually.
#include <stdio.h>
int main()
{
int i, j;
scanf("%d %d", &i, &j);
printf("Automatically entered %d %d\n", i, j);
int k;
scanf("%d", &k);
printf("Manually entered %d", k);
return 0;
}
I want to run this program using bash script which can input first two inputs automatically and leaves one input that is to be entered manually. This is the script I am using.
#!/bin/bash
./test <<EOF
1
2
EOF
The problem is EOF is passed as third input instead of asking for manual input. I cannot change my c program and I cannot input third input before the two inputs, so how can I do this using bash. I am new to bash scripting please help.
I made a c program which takes two standard inputs automatically and one manually.
No, you didn't. You made a program that attempts to read three whitespace-delimited decimal integers from the standard input stream. The program cannot distinguish between different origins of those integers.
The problem is EOF is passed as third input instead of asking for manual input.
No, the problem is that you are redirecting the program's standard input to be a shell here document. The here document provides the whole standard input, similar to if your program were reading a file with the here document's contents. When it reaches the end, it does not fall back to reading anything else.
I cannot change my c program and I cannot input third input before the two inputs
I take those two statements to be redundant: you cannot alter the program so that the input you characterize as "manual" is the first one it attempts to read. Not that that would help, anyway.
What you need to do is prepend the fixed input to the terminal input in the test program's standard input stream. There are many ways to do that, but the cat command (mnemonic for concatenate) seems like a natural choice. That would work together with process substitution to achieve your objective. For example,
#!/bin/bash
cat <(echo 1 2) - | ./test
The <(echo 1 2) part executes echo 1 2 and provides its standard output as if it were a file. The cat command concatenates that with its own standard input (represented by -), emitting its result to its standard output. The result is piped into program ./test.
This provides a means to prepend fixed input under your control to arbitrary data read from the standard input. That is, the wrapper script doesn't need to know what input the program expects after the fixed initial part.
Your problem is not caused by EOF being passed as third argument, but actually because stdin for your command is closed before third call to scanf.
One way how to solve this, is reading the value inside the script and then passing all three of them.
Something like this:
#!/bin/bash
read value
printf '1 2 %s' "$value" | ./test

Override first argument when calling a program

I need to override the first argument when I call a binary.
Since it's the program name I have two solutions:
move the binary and call it with its new name; or
create an alias (if the shell allows it).
However, sometimes I need to completly remove the first parameter.
I wrote a simple program in C that does the job:
#include <unistd.h>
int main(int argc, char **argv)
{
return execve(argv[1], NULL, NULL);
}
I there a built-in way to do it with the shell? A solution for bash would be prefered.
You can override it with exec -a, though you can't make it unset.
For example, to run busybox with argv[0] set to ls:
( exec -a ls busybox )

How to get bash arguments with leading pound-sign (octothorpe)

I need to process an argument to a bash script that might or might not have a leading pound sign (octothorpe). The simplest example is:
echo #1234
which returns nothing
It might be because it processes the text as a command and assumes it is a comment.
$#, $*, etc. do not work. getopts does not seem to address this sort of thing.
Suggestions welcome
This is completely impossible, because the "argument" in question is parsed as a comment and never passed to the command at all.
Keep in mind that programs in C have the following calling convention for their main function:
int main(int argc, char *argv[])
This means that programs are passed a list of individual, separate arguments, not a single string that isn't yet parsed. The original string from which that vector of arguments was parsed is not given to the invoked program at all; often, no "original string" even exists. Consequently, a program that was invoked has no way to "unring the bell" and go back from the parsed list of strings to the original string from which it was generated.
Consequently, if your script is invoked as an external command (as opposed to a shell function), the invocation of the shell that runs it by the operating system will go through the execve syscall, which takes as its arguments (1) the file to execute; (2) the argument vector to pass it (which is to say, the aforementioned list of individual C strings); and (3) a list of environment variables. There is no argument for an unparsed shell command line, so no such content is available to the subprocess.
Train your users to use appropriate quoting. All of the below will have completely indistinguishable behavior, insofar as yourscript is concerned:
yourscript '#1234' # single quotes prevent content from being parsed as shell syntax
yourscript ''#1234 # "#" only begins a comment at the front of a string
yourscript '#'1234 # note that shell quoting is character-by-character
yourscript \#1234 # ...so either quoting or escaping only that single character suffices.
...any of the above will pass an argv containing (in C syntax) char[][]{ "yourscript", "#1234", NULL }

Command line arguments and argc

I was just looking at executing a program with command line arguments. I see that argument count (argc) is implicit and that the computer calculates that by looking at the number of arguments I give.
I just wondered out of curiousity whether or not it is possible or me to explicitly declare the value of argc?
No, argc is passed into the main() method. It is supplied at runtime.

Resources