views:

209

answers:

7

what is considered best practice when referring to a program's name? i've seen

#define PROGRAM_NAME "myprog"
printf("this is %s\n", PROGRAM_NAME);

as well as

printf("this is %s\n", argv[0]);

i know, that the second approach will give me ./myprog rather than myprog when the program is not called from $PATH and that the first approach will guarantee consistence regarding the program's name.

but is there anything else, that makes one approach superior to the other?

A: 

The former is superior to the later when your don't have argv at hand.

#define PROGRAM_NAME "myprog"

void salute()
{
     // no argv available 

     printf("Hello from %s\n", PROGRAM_NAME );
}

void main( int argc, char** argv ) 
{
     salute();
}
OscarRyz
does that make such a big difference? i don't think `argc` and `argv` cost too much
guest
ah. i see what you mean now. yeah, makes perfect sense
guest
I get your point, but in your example you are basically creating a global variable. If you need program_name, then pass it (argv) as a parameter to salute() and your problem is solved.
MJB
Well yes, works for a couple of methods, if the name is needed in several places and most functions already have a large list of parameter, using one more is ridiculous when the global constant is available. In either case I think jonhcatfish is a better alternative.
OscarRyz
@Support: if the name is needed in several places, possibly what you should be passing about (or making global if absolutely necessary) is some kind of logger object, rather than just the program name.
Steve Jessop
I get it. I have never had to do that, but I do understand. I hate really long arg lists, since I always end up typo'ing somewhere and sending the wrong order.
MJB
A: 

Depends whether argv is in scope or not...

Jaymz
+4  A: 

The second approach is superior when you have multiple links. In *nix systems, sometimes behavior depends on how you call a program. So hard coding the program name would clearly be a problem -- it could never check that.

MJB
what does this mean "behavior depends on how you call a program"? i can't really make sense out of it.
guest
@guest: for example, `gcc` and `g++` might be the same executable, which checks the name it was called with and modifies the linker options accordingly. Can't remember whether it actually is or not.
Steve Jessop
Example: By default, grep prints the matching lines. In addition, three variant programs egrep, fgrep and rgrep are available. egrep is the same as grep -E. fgrep is the same as grep -F. rgrep is the same as grep -r.
Jurily
ah. never heard of that concept before, makes sense, though
guest
Some programs examine argv[0] to determine how they should behave. For example, BusyBox implements a host of Unix utilities, and it's normally installed as /bin/BusyBox, with many symbolic links pointing to it: /bin/ls, for example, would point to /bin/BusyBox, and when you run 'ls' it runs BusyBox which then determines it needs to behave like ls.
Ori Pessach
Another example is *vi* and *view*, which is the read only version of *vi*, but which is the exact same code and exact same executable. Calling it *view* just opens the file read-only.
MJB
+3  A: 

I tried to take the best of both worlds:

char const * program_name;

int main(int argc, char **argv) {
   program_name = argv[0];
   //...
}

If you need program_name to be available in some other file you can declare it like this:

extern char const * program_name;

I declare "char const *" because I want it to be a pointer which points to const data. I'm not sure if I did right this part.

Not bad. Sidesteps the question of which is better by answering "both," but not bad.
MJB
+1  A: 

The second approach could give you also strings like /usr/bin/myprog if you executed it that way; basename should give the name of the executable (that you could think of as the name of your program)... unless it is symlinked... (in that case, you have the name of the link... that could be used to do choices of some kind in the program behaviour).

The first approach "fixes" the program name to what the programmer wanted, no matter how the user renamed the executable file or symlinked (or even hardlinked)

ShinTakezou
Yes, I have used products where it looks like you have several executables, but actually it is only one with multiple links to it. This may seem crazy, but it is a good way to keep multiple tools in sync through multiple revisions.
Jim Tshr
+1  A: 

I usually use argv[0], or basename(argv[0]) if possible. From the user's POV, I think if they rename or hardlink an executable (or somebody else does that for them), then they want messages from it to appear under the name they're using, not under some other name it was compiled as, that they may or may not know about.

Similarly if you discover in future that you want to compile your program under different names with different options, to give different versions, do you want to wrap an #ifndef around that #define and make sure that it's defined via the compiler command line: -DPROGRAM_NAME=myprog_demo, or do you just want to do it and it works?

The exception might be that if your usage instructions are an extract from a manpage or other documentation, then possibly you do want to hardwire the program name into that. But then you probably wouldn't use the #define either.

Implementations needn't provide argv[0], though, so for best portable practices handle that case too. Then again, if your system doesn't provide it then probably the user isn't actually going to see messages on any kind of terminal, either.

By the way:

#define PROGRAM_NAME "myprog"
puts("this is " PROGRAM_NAME);
Steve Jessop
+1  A: 

It doesn't exactly answer your question for programming best practices, but I think you should also keep in mind what's best for the user. I personally prefer programs refering to themselves using argv[0], i.e. the command I was calling, and not some random name that the coder hardcoded in the program. A few examples where a hardcoded name is annoying or at least not helpful:

  • I've created a link to a program
  • I've renamed the binary for some reason
  • I have multiple executables with the same basenames in different directories in my $PATH
  • A program gives me hints about other ways to call it, e.g. in "usage" messages

The only situation where I'd prefer a hardcoded program name is when I'm using GUI applications. I wouldn't want to see "~/foo/bar.pl" as a window title.

jkramer