Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Apr 1996 15:44:24 -0700 (PDT)
From:      "JULIAN Elischer" <julian@ref.tfs.com>
To:        jraynard@dial.pipex.com (James Raynard)
Cc:        hackers@freebsd.org
Subject:   Re: Flaws in system() implementation?
Message-ID:  <199604222244.PAA20222@ref.tfs.com>
In-Reply-To: <199604222142.VAA00923@dial.pipex.com> from "James Raynard" at Apr 22, 96 09:42:43 pm

next in thread | previous in thread | raw e-mail | index | archive | help
> 
> 
> Inspired by Rich Stevens' implementation of system() in his book
> "Advanced Programming in the Unix Environment", I've been looking at
> the FreeBSD implementation and was struck by the following points:-
> 
> 1. Use of a wait union when an int would do.
This is the correct POSIX thing to do..
check the man page for wait.
> 
> 
> 3. Returns 0 if fork() fails, when -1 seems more appropriate.
 POSIX says:
 If "command" is a null pointer, the system() function returns non-zero
 only if a command processor is available.

 If "command" is a nin null pointer the system() function returnsa
 the termination status of the command language interpretter in the
 format specified by the waitpid() function.
 [...]
 If a child process cannot be  created,
 or if the termination status of hte command interpretter cannot be obtained
 system() returns -1
 and sets errno to indicate the error.

> 
> 4. The SIGINT and SIGQUIT are not ignored until after the fork().
>    If the child runs first, one of these signals could in theory be
the child MUST run first in vfork()

>    generated before the parent gets around to ignoring it. Hence the
>    dispositions should be changed before the fork().
> 
> Here's an untested patch which addresses these points.
> Comments/corrections welcomed!
> 
> (In /usr/src/lib/libc/stdlib)
> *** system.c~	Mon Apr 22 21:04:59 1996
> --- system.c	Mon Apr 22 21:20:18 1996
> ***************
> *** 46,76 ****
>   system(command)
>   	const char *command;
>   {
> - 	union wait pstat;
>   	pid_t pid;
> ! 	int omask;
>   	sig_t intsave, quitsave;
>   
>   	if (!command)		/* just checking... */
>   		return(1);
>   
>   	omask = sigblock(sigmask(SIGCHLD));
> ! 	switch(pid = vfork()) {
>   	case -1:			/* error */
> ! 		(void)sigsetmask(omask);
> ! 		pstat.w_status = 0;
> ! 		pstat.w_retcode = 127;
> ! 		return(pstat.w_status);
>   	case 0:				/* child */
>   		(void)sigsetmask(omask);
>   		execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
>   		_exit(127);
>   	}
> - 	intsave = signal(SIGINT, SIG_IGN);
> - 	quitsave = signal(SIGQUIT, SIG_IGN);
> - 	pid = waitpid(pid, (int *)&pstat, 0);
>   	(void)sigsetmask(omask);
>   	(void)signal(SIGINT, intsave);
>   	(void)signal(SIGQUIT, quitsave);
> ! 	return(pid == -1 ? -1 : pstat.w_status);
>   }
> --- 46,77 ----
>   system(command)
>   	const char *command;
>   {
>   	pid_t pid;
> ! 	int omask, pstat;
>   	sig_t intsave, quitsave;
>   
>   	if (!command)		/* just checking... */
>   		return(1);
>   
> + 	intsave = signal(SIGINT, SIG_IGN);
> + 	quitsave = signal(SIGQUIT, SIG_IGN);
>   	omask = sigblock(sigmask(SIGCHLD));
> ! 	switch(pid = fork()) {
>   	case -1:			/* error */
> ! 		break;
>   	case 0:				/* child */
>   		(void)sigsetmask(omask);
> + 		(void)signal(SIGINT, intsave);
> + 		(void)signal(SIGQUIT, quitsave);
>   		execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
>   		_exit(127);
> + 	default:			/* parent */
> + 		pid = waitpid(pid, &pstat, 0);
> + 		break;
>   	}
>   	(void)sigsetmask(omask);
>   	(void)signal(SIGINT, intsave);
>   	(void)signal(SIGQUIT, quitsave);
> ! 	return(pid == -1 ? -1 : pstat);
>   }
> 




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199604222244.PAA20222>