示例#1
0
文件: picocom.c 项目: hajuuk/R7000
int
run_cmd(int fd, ...)
{
	pid_t pid;
	sigset_t sigm, sigm_old;

	/* block signals, let child establish its own handlers */
	sigemptyset(&sigm);
	sigaddset(&sigm, SIGTERM);
	sigprocmask(SIG_BLOCK, &sigm, &sigm_old);

	pid = fork();
	if ( pid < 0 ) {
		sigprocmask(SIG_SETMASK, &sigm_old, NULL);
		fd_printf(STO, "*** cannot fork: %s\n", strerror(errno));
		return -1;
	} else if ( pid ) {
		/* father: picocom */
		int r;

		/* reset the mask */
		sigprocmask(SIG_SETMASK, &sigm_old, NULL);
		/* wait for child to finish */
		waitpid(pid, &r, 0);
		/* reset terminal (back to raw mode) */
		term_apply(STI);
		/* check and report child return status */
		if ( WIFEXITED(r) ) { 
			fd_printf(STO, "\r\n*** exit status: %d\r\n", 
					  WEXITSTATUS(r));
			return WEXITSTATUS(r);
		} else {
			fd_printf(STO, "\r\n*** abnormal termination: 0x%x\r\n", r);
			return -1;
		}
	} else {
		/* child: external program */
		int r;
		long fl;
		char cmd[512];

		establish_child_signal_handlers();
		sigprocmask(SIG_SETMASK, &sigm_old, NULL);
		/* unmanage terminal, and reset it to canonical mode */
		term_remove(STI);
		/* unmanage serial port fd, without reset */
		term_erase(fd);
		/* set serial port fd to blocking mode */
		fl = fcntl(fd, F_GETFL); 
		fl &= ~O_NONBLOCK;
		fcntl(fd, F_SETFL, fl);
		/* connect stdin and stdout to serial port */
		close(STI);
		close(STO);
		dup2(fd, STI);
		dup2(fd, STO);
		{
			/* build command-line */
			char *c, *ce;
			const char *s;
			int n;
			va_list vls;
			
			c = cmd;
			ce = cmd + sizeof(cmd) - 1;
			va_start(vls, fd);
			while ( (s = va_arg(vls, const char *)) ) {
				n = strlen(s);
				if ( c + n + 1 >= ce ) break;
				memcpy(c, s, n); c += n;
				*c++ = ' ';
			}
			va_end(vls);
			*c = '\0';
		}
		/* run extenral command */
		fd_printf(STDERR_FILENO, "%s\n", cmd);
		r = system(cmd);
		if ( WIFEXITED(r) ) exit(WEXITSTATUS(r));
		else exit(128);
	}
}
示例#2
0
int
run_cmd(int fd, const char *cmd, const char *args_extra)
{
	pid_t pid;
	sigset_t sigm, sigm_old;

	/* block signals, let child establish its own handlers */
	sigemptyset(&sigm);
	sigaddset(&sigm, SIGTERM);
	sigprocmask(SIG_BLOCK, &sigm, &sigm_old);

	pid = fork();
	if ( pid < 0 ) {
		sigprocmask(SIG_SETMASK, &sigm_old, NULL);
		fd_printf(STO, "*** cannot fork: %s ***\r\n", strerror(errno));
		return -1;
	} else if ( pid ) {
		/* father: picocom */
		int status, r;

		/* reset the mask */
		sigprocmask(SIG_SETMASK, &sigm_old, NULL);
		/* wait for child to finish */
		do {
			r = waitpid(pid, &status, 0);
		} while ( r < 0 && errno == EINTR );
		/* reset terminal (back to raw mode) */
		term_apply(STI, 0);
		/* check and report child return status */
		if ( WIFEXITED(status) ) { 
			fd_printf(STO, "\r\n*** exit status: %d ***\r\n", 
					  WEXITSTATUS(status));
			return WEXITSTATUS(status);
		} else if ( WIFSIGNALED(status) ) {
			fd_printf(STO, "\r\n*** killed by signal: %d ***\r\n", 
					  WTERMSIG(status));
			return -1;
		} else {
			fd_printf(STO, "\r\n*** abnormal termination: 0x%x ***\r\n", r);
			return -1;
		}
	} else {
		/* child: external program */
		long fl;
		int argc;
		char *argv[RUNCMD_ARGS_MAX + 1];
		int r;
			
		/* unmanage terminal, and reset it to canonical mode */
		term_remove(STI);
		/* unmanage serial port fd, without reset */
		term_erase(fd);
		/* set serial port fd to blocking mode */
		fl = fcntl(fd, F_GETFL); 
		fl &= ~O_NONBLOCK;
		fcntl(fd, F_SETFL, fl);
		/* connect stdin and stdout to serial port */
		close(STI);
		close(STO);
		dup2(fd, STI);
		dup2(fd, STO);
		
		/* build command arguments vector */
		argc = 0;
		r = split_quoted(cmd, &argc, argv, RUNCMD_ARGS_MAX);
		if ( r < 0 ) {
			fd_printf(STDERR_FILENO, "Cannot parse command\n");
			exit(RUNCMD_EXEC_FAIL);
		}
		r = split_quoted(args_extra, &argc, argv, RUNCMD_ARGS_MAX);
		if ( r < 0 ) {
			fd_printf(STDERR_FILENO, "Cannot parse extra args\n");
			exit(RUNCMD_EXEC_FAIL);
		}
		if ( argc < 1 ) {
			fd_printf(STDERR_FILENO, "No command given\n");
			exit(RUNCMD_EXEC_FAIL);
		}	
		argv[argc] = NULL;
			
		/* run extenral command */
		fd_printf(STDERR_FILENO, "$ %s %s\n", cmd, args_extra);
		establish_child_signal_handlers();
		sigprocmask(SIG_SETMASK, &sigm_old, NULL);
		execvp(argv[0], argv);

		fd_printf(STDERR_FILENO, "exec: %s\n", strerror(errno));
		exit(RUNCMD_EXEC_FAIL);
	}
}