You have two different kinds of "variable" lists of arguments here.
First, you have the arguments passed to the program on the command line, clearly a person could invoke the program from the command line with many arguments
cat file1 file2 file3
and so on. The main() of C programs have since the early days of C given access to the command line arguments in the variables argc and argv, argc is the count of how many arguments (3 + the name of the pogram itself in my example above) and argv is the array of the arguments (actually an array of pointers to strings) So in this case we can access argv[0], argv[1], arv[2] and argv[3], knowing to stop there because argc tells us there are four arguments.
So in your example argc will be 3, argv[0] will point to "cat", argv[1] to "-s" and argv[2] to "a.txt".
Next the function you are looking at itself takes an indefinate number of arguments as indicated by the elipses - the ...
You need to read about variable arguments. This is a language feature that was not in the earliest C language, and is considered to be a little bit advanced, hence some of your books either may not cover it, or leave until late in the book. The key point here though is that we interpretting the variable list we need to know when we have reached the end of the variable list, we don't have an "argc" equivalent. So we put a "this is the last one, stop here" value in the function call, that's the NULL you ask about.