Subject: Re: setting and using progname.
To: None <tech-userlevel@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: tech-userlevel
Date: 09/30/2000 20:42:15
[ On , September 30, 2000 at 15:23:31 (-0700), Chris G. Demetriou wrote: ]
> Subject: setting and using progname.
>
> The right thing to do is have a function to set the 'program name' if
> it's not already been set, for use by functions like err(), etc., and
> a function to get the program name (for use by programs bodies), where
> the information may not be as easily accessible.

THANK YOU!  (for saying that)

> /*
>  * __progname declared in library or crt0, kept private, but existing
>  * uses still allowed to avoid breaking things.
>  */
> const char *__progname;
> 
> /*
>  * Set program name if it's not already set.  Memory pointed to by
>  * arg0 must be valid until program termination.
>  */
> void
> setprogname(const char *arg0)
> {
> 
> 	if (__progname != NULL)
> 		return;

Is this a good/necessary idea?  I'd rather be able to reset the value.

> 	__progname = strrchr(arg0, '/');
> 	if (__progname == NULL)
> 		__progname = arg0;
> 	else
> 	    __progname++;

Style-wise I personally would just use this much more concise statement:

	__progname = basename(arg0);	/* a SUSv2 compatible function */

> }

I'm not terribly comfortable at modifying argv[0] though, at least not
in this kind of context (nor about basename doing this either, though
when I do the equivalent in my own programs I don't worry about whacking
it).

Perhaps it should really be something like this instead:

	const char __progname[PATH_MAX];
	
	void
	setprogname(argv0)
		char *argv0;
	{
		char *p;
		char *q;
	
		p = (q = strrchr(argv0, '/')) ? q + 1 : argv0;
		strncpy(__progname, p, sizeof(__progname)-1);
		__progname[sizeof(__progname)-1] = '\0';
		if (q)
			*q = '/';
		return;
	}

Of course if you really do want to keep __progname's definition in crt0.o
then I suppose you have to avoid sizeof() and use PATH_MAX instead.

I thought of using malloc() instead of a static array (perhaps in the
guise of the currently missing strsave() function), but that probably
raises more problems and complications than it is worth in terms of the
storage savings.


>  I think this is long overdue...

That's for sure!

> any thoughts or comments?

I'm not sure any or all of this is necessary except for the fact that if
system library functions indeed do want to make use of basename(argv[0])
then it needs to be privately defined.

My current practice is always to just declare my own global:

	const char *argv0 = PACKAGE;

(where PACKAGE is #define PACKAGE "progname" just to be 100% safe)

Of course err() and friends are a bit of a pain for porting too -- I'd
much rather NetBSD source stick to POSIX/SUSv2 stuff internally too.
Yes it's possible to cart off some of these functions and make a
lib44bsd or similar but it's a bit of a pain; and at least for err() and
friends it's not really all that much harder to write code using
standard portable functionality that's much clearer for any outsider to
read....  (Besides, what's good for the goose... and all that! :-)


-- 
							Greg A. Woods

+1 416 218-0098      VE3TCP      <gwoods@acm.org>      <robohack!woods>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>