how do I exec() a script

Mike Oliver moliver at pyrshadow
Thu Jun 28 05:57:44 AEST 1990


This really isn't (an answer to) a C question; followups have been
redirected to comp.unix.questions.

In article <661 at kps.UUCP> llj at kps.se (Leif Ljung /DP) writes:
>I have a program that I want to do a general exec(2) sometimes
>executing a binary program, sometimes a shell-script preferably
>using PATH.
>Say I have the program `prog' - if this is a script I add the
>'#! /bin/sh' at the top. Can I exec(2) that? No.

I don't have a problem doing this.  I don't know how you're managing
the PATH variable, but if you provide the coorect relative path of the
target file you can exec() it regardless of whether it's a program or
an interpreter script.

There's a tiny demo program on the end of this post - you might want to
compare it against your code.  My favourite way to get this wrong is to
forget that *argv[0] in the exec() call should be the name of the
executable, usually the same as the path that you supply as the first
parameter to exec().

If you're still stuck after that, mail me your code and I'll see if I
can find what might be causing the problem.

>The system is a Pyramid running BSD4.3.

Meaning that it's running OSx and you're working in the ucb universe ?
If you're building in the att universe you should be aware that the
ability to exec() a script is configurable, and it defaults to being
disabled.  Don't ask me why, I don't know.  This hinges on the universe
that your program was built under, not on the universe in which it
runs.  Check your makefile to make sure the build isn't running under
att.  If that's the case you'll get an "Exec format error" when you try
to exec a script.

Demo program and sample script are below, hit "n" if you've had enough
already.

 --- 8< ------ 8< ------ 8< ------ 8< ------ 8< ------ 8< ------ 8< ---

/*	This program will exec() its first argument, passing any
*	additional arguments to the exec()'d program.
*
*	Try "a.out /bin/ls -l" for starters.  Then try the script
*	below, which will print "hello world" and then print its
*	arguments.
*/

#include <stdio.h>
#include <sys/wait.h>

main( argc, argv )
int	argc;
char	**argv;
{
	extern	char **environ;

	union	wait waitstatus;
	char	*cmdpath;

	if ( argc < 2 )
	{
		/*	Not enough info on the command line.
		*/

		fprintf( stderr, "%s: %s <command> [args ...]\n",
						argv[0], argv[0] );
		exit( -1 );
	}

	switch ( fork() )
	{
		case 0:		/* This is the child */
			cmdpath = *(++argv);
			(void) execve( cmdpath, argv, environ );
			perror( "child ... execve() failed" );
			break;
		case -1:	/* This is the parent, and the fork failed */
			perror( argv[0] );
			break;
		default:	/* This is the parent, the fork() worked */
			fprintf( stdout, "parent ... deceased PID is %d\n", 
							wait( &waitstatus ) );
			fprintf( stdout, "       ... status is %d\n", 
							waitstatus.w_status );
			break;
	}
}

 --- 8< ------ 8< ------ 8< ------ 8< ------ 8< ------ 8< ------ 8< ---

#!	/bin/sh
# Simple script, just says "hello world" and then prints its arguments.

echo "hello world"
echo $*

 --- 8< ------ 8< ------ 8< ------ 8< ------ 8< ------ 8< ------ 8< ---

Cheers, Mike.

moliver at pyramid.com
{allegra,decwrl,hplabs,munnari,sun,utai,uunet}!pyramid!moliver



More information about the Comp.lang.c mailing list