Ejemplo n.º 1
0
static int ast_forall_execute( struct ast_forloop *f, time_t stoptime, const char *name, int argc, char **argv )
{
	int i;
	int pid;
	int result;
	struct multi_fork_status *s;

	s = xxmalloc(sizeof(*s)*argc);

	pid = multi_fork(argc,s,stoptime,f->for_line);
	if(pid>=0) {
		random_init();
		if(stoptime && (time(0)>stoptime)) _exit(1);

		ftsh_error(FTSH_ERROR_STRUCTURE,f->for_line,"%s=%s starting",name,argv[pid]);
		result = buffer_save(name,argv[pid]);
		if(!result) _exit(1);

		result = ast_group_execute(f->body,stoptime);
		if(result) {
			_exit(0);
		} else {
			_exit(1);
		}
	} else {
		for(i=0;i<argc;i++) {
			char str[LINE_MAX];
			if(s[i].state==MULTI_FORK_STATE_GRAVE) {
				snprintf(str,sizeof(str),"%s=%s",name,argv[i]);
				process_status(str,s[i].pid,s[i].status,f->for_line);
			}
		}

		free(s);

		if(pid==MULTI_FORK_SUCCESS) {
			return 1;
		} else {
			return 0;
		}
	}
}
Ejemplo n.º 2
0
timed_exec_t timed_exec( int line, const char *path, char **argv, int fds[3], pid_t *pid, int *status, time_t stoptime )
{
	int fresult;
	int pfds[2];
	int child_errno;
	int actual;
	struct multi_fork_status s;

	actual = pipe(pfds);
	if(actual!=0) return TIMED_EXEC_NOEXEC;

	fresult = multi_fork(1,&s,stoptime,line);
	if(fresult>=0) {
		/* Move our standard I/O streams into the expected places. */
		/* It seems that cygwin doesn't like dup2 on the same fd. */

		int i, maxfd;

		for( i=0; i<=2; i++ ) {
			if( fds[i]!=i ) {
				if( dup2(fds[i],i) != i ) {
					ftsh_error(FTSH_ERROR_PROCESS,line,"failure to dup2(%d,%d): %s\n",fds[i],i,strerror(errno));
					goto done;
				}
			}
		}

		/* Close all of the file descriptors that we don't need. */

		maxfd = sysconf( _SC_OPEN_MAX );
		if(maxfd<=0) maxfd = 255;
		for(i=3;i<maxfd;i++) {
			if(i==pfds[1]) continue;
			close(i);
		}

		/* Set the pipe to automatically close after exec. */

		if( fcntl(pfds[1],F_SETFD,FD_CLOEXEC)==0 ) {
			setsid();
			execvp(path,argv);
		}

		/*
		If anything goes wrong, write the errno to the pipe,
		where the parent process can collect and print it.
		*/

		done:
		child_errno = errno;
		full_write(pfds[1],&child_errno,sizeof(child_errno));
		_exit(1);

	} else {

		/*
	        Now clear the pipe.  If it contains an int, then the process
	        forked, but was unable to exec.  Set the reason appropriately.
	        Otherwise, live with what we have.
		*/

		close(pfds[1]);
		actual = full_read(pfds[0],&child_errno,sizeof(int));
		close(pfds[0]);
	
		*status = s.status;
		*pid = s.pid;

		if(actual==sizeof(int)) {
			return TIMED_EXEC_NOEXEC;
		} else if(fresult==MULTI_FORK_SUCCESS) {
			return TIMED_EXEC_SUCCESS;
		} else if(fresult==MULTI_FORK_TIMEOUT) {
			return TIMED_EXEC_TIMEOUT;
		} else {
			return TIMED_EXEC_FAILURE;
		}
	}
}