[comp.std.unix] vexec function

rfg@lupine.uucp (Ron Guilmette) (07/24/90)

From:  rfg@lupine.uucp (Ron Guilmette)


Just a trivia question.

On very rare occasions, I have found the family of vprintf functions (i.e.
vprintf, vfprintf, and vsprintf) quite useful.  In certain cases, there
is simply no other way to accomplish quite the same thing (especially
on the newer RISC machines where methods of passing variable numbers of
parameters can get rather complicated).

Now I'm looking at a hunk of non-portable code (written by somebody else
of course :-) that I have to port. and this code involves a call to execvp.
It looks kinda like:

------------------------------------------------------------------------------
different_execvp (a, args)
char    *a;
va_list args;
{
	char **argv;

	argv = (char **) args;		/* YIKES!!! */
	argv[0] = basename(argv[0]);
	execvp(a, argv);
}
------------------------------------------------------------------------------

The line with the comment /* YIKES!!! */ gets errors during compilation due
to a severe type mishmash for the assignment.  That's due to the fact that
(on the machine I am compiling on, the type used for `va_list' is most
definitely *not* a type which can be legally typecast to a pointer.  (Hint:
it is a struct on this type of RISC machine.)

What I appear to need here is either:

	a)  a standard way to convert a va_list into a list of pointers
	    (to argument values), or

	b)  a standard way to modify one element of a va_list *and* a
	    standard function like:

		int vexeclp (char *name, va_list vargs);

None of these things are a part of standard ANSI C (as far as I know).
Are any of them a part of POSIX?  If not, why not?



Volume-Number: Volume 20, Number 138

guy@auspex.uucp (Guy Harris) (07/26/90)

From:  guy@auspex.uucp (Guy Harris)

>What I appear to need here is either:
>
>	a)  a standard way to convert a va_list into a list of pointers
>	    (to argument values), or

I suspect "different_execvp" is misnamed; given the "va_list", it
appears to have a calling sequence more like "execlp" - i.e.,

	different_execlp("/bin/explode", "explode", "bright blue light",
	    (char *)NULL);

Given that, you could scan the argument list twice; the first time,
you'd count the number of arguments, then you'd malloc up an array of
N+1 "char *"s, and scan the argument list a second time filling in that
array.  Now "argv" is a pointer to the first element of that array....

>None of these things are a part of standard ANSI C (as far as I know).

The second isn't; the first can be done in ANSI C, unless I've missed
something subtle in the spec that forbids traversing the argument list
twice (I just checked and didn't see anything obvious).

>Are any of them a part of POSIX?

Nope.

>If not, why not?

Because the first can be done in ANSI C (or pre-ANSI C with <varargs.h>).

Volume-Number: Volume 20, Number 145

mcgrath%tully.Berkeley.EDU@ucbvax.Berkeley.EDU (Roland McGrath) (07/26/90)

From:  mcgrath%tully.Berkeley.EDU@ucbvax.Berkeley.EDU (Roland McGrath)

In article <10461@cs.utexas.edu> rfg@lupine.uucp (Ron Guilmette) writes:
   What I appear to need here is either:

	   a)  a standard way to convert a va_list into a list of pointers
	       (to argument values), or

	   b)  a standard way to modify one element of a va_list *and* a
	       standard function like:

		   int vexeclp (char *name, va_list vargs);

   None of these things are a part of standard ANSI C (as far as I know).
   Are any of them a part of POSIX?  If not, why not?

A would fall under the C standard, and B under 1003.1.  However, neither of
these exist.  I imagine the answer the appropriate committees would give would
be "insufficient utility".

At any rate, you can handle the case in question by doing A manually, since
`execlp' has a defined way of determining its number of arguments:

{
  char **argv[ARG_MAX];
  register unsigned int i = 0;
  va_list args;

  va_start(args, lastarg);

  do
    argv[i] = va_arg(args, char *);
  while (argv[i++] != NULL);
}

(Actually, I would suggest dynamically allocating ARGV to avoid eating all your
memory if ARG_MAX is very large.)
--
	Roland McGrath
	Free Software Foundation, Inc.
roland@ai.mit.edu, uunet!ai.mit.edu!roland

Volume-Number: Volume 20, Number 146