void spc_sanitize_files(void) {
  int standard_fds[] = { STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO };
  int standard_fds_count
    = (int)(sizeof(standard_fds) / sizeof(standard_fds[0]));

  // Make sure all open descriptors other than the standard ones are closed
  int fds = getdtablesize();
  for (int i = standard_fds_count; i < fds; ++i) close(i);

  // Verify that the standard descriptors are open.  If they're not, attempt to
  // open them using /dev/null.  If any are unsuccessful, abort.
  for (int i = 0; i < standard_fds_count; ++i) {
    struct stat st;
    int fd = standard_fds[i];
    if (fstat(fd, &st) == -1 && (errno != EBADF || !open_devnull(fd))) {
      abort();
    }
  }
}
示例#2
0
文件: process.c 项目: WorMzy/vlock
bool create_child(struct child_process *child)
{
  int errsv;
  int child_errno = 0;
  int status_pipe[2];
  int stdin_pipe[2];
  int stdout_pipe[2];
  int stderr_pipe[2];

  if (pipe(status_pipe) < 0)
    return false;

  (void) fcntl(status_pipe[1], F_SETFD, FD_CLOEXEC);

  if (child->stdin_fd == REDIRECT_PIPE) {
    if (pipe(stdin_pipe) < 0) {
      errsv = errno;
      goto stdin_pipe_failed;
    }
  } 

  if (child->stdout_fd == REDIRECT_PIPE) {
    if (pipe(stdout_pipe) < 0) {
      errsv = errno;
      goto stdout_pipe_failed;
    }
  }

  if (child->stderr_fd == REDIRECT_PIPE) {
    if (pipe(stderr_pipe) < 0) {
      errsv = errno;
      goto stderr_pipe_failed;
    }
  }

  child->pid = fork();

  if (child->pid == 0) {
    /* Child. */
    fd_set except_fds;

    if (child->stdin_fd == REDIRECT_PIPE)
      (void) dup2(stdin_pipe[0], STDIN_FILENO);
    else if (child->stdin_fd == REDIRECT_DEV_NULL)
      (void) dup2(open_devnull(), STDIN_FILENO);
    else if (child->stdin_fd != NO_REDIRECT)
      (void) dup2(child->stdin_fd, STDIN_FILENO);

    if (child->stdout_fd == REDIRECT_PIPE)
      (void) dup2(stdout_pipe[1], STDOUT_FILENO);
    else if (child->stdout_fd == REDIRECT_DEV_NULL)
      (void) dup2(open_devnull(), STDOUT_FILENO);
    else if (child->stdout_fd != NO_REDIRECT)
      (void) dup2(child->stdout_fd, STDOUT_FILENO);

    if (child->stderr_fd == REDIRECT_PIPE)
      (void) dup2(stderr_pipe[1], STDERR_FILENO);
    else if (child->stderr_fd == REDIRECT_DEV_NULL)
      (void) dup2(open_devnull(), STDERR_FILENO);
    else if (child->stderr_fd != NO_REDIRECT)
      (void) dup2(child->stderr_fd, STDERR_FILENO);

    FD_ZERO(&except_fds);
    FD_SET(STDIN_FILENO, &except_fds);
    FD_SET(STDOUT_FILENO, &except_fds);
    FD_SET(STDERR_FILENO, &except_fds);
    FD_SET(status_pipe[1], &except_fds);

    (void) close_fds(&except_fds);

    (void) setgid(getgid());
    (void) setuid(getuid());

    if (child->function != NULL) {
      (void) close(status_pipe[1]);
      _exit(child->function(child->argument));
    } else {
      execv(child->path, (char *const*)child->argv);
      (void) write(status_pipe[1], &errno, sizeof errno);
    }

    _exit(1);
  }

  if (child->pid < 0) {
    errsv = errno;
    goto fork_failed;
  }

  (void) close(status_pipe[1]);

  /* Get the error status from the child, if any. */
  if (read(status_pipe[0], &child_errno, sizeof child_errno) == sizeof child_errno) {
    errsv = child_errno;
    goto child_failed;
  }

  (void) close(status_pipe[0]);

  if (child->stdin_fd == REDIRECT_PIPE) {
    /* Write end. */
    child->stdin_fd = stdin_pipe[1];
    /* Read end. */
    (void) close(stdin_pipe[0]);
  }

  if (child->stdout_fd == REDIRECT_PIPE) {
    /* Read end. */
    child->stdout_fd = stdout_pipe[0];
    /* Write end. */
    (void) close(stdout_pipe[1]);
  }

  if (child->stderr_fd == REDIRECT_PIPE) {
    /* Read end. */
    child->stderr_fd = stderr_pipe[0];
    /* Write end. */
    (void) close(stderr_pipe[1]);
  }

  return true;

child_failed:
fork_failed:
  if (child->stderr_fd == REDIRECT_PIPE) {
    (void) close(stderr_pipe[0]);
    (void) close(stderr_pipe[1]);
  }

stderr_pipe_failed:
  if (child->stdout_fd == REDIRECT_PIPE) {
    (void) close(stdout_pipe[0]);
    (void) close(stdout_pipe[1]);
  }

stdout_pipe_failed:
  if (child->stdin_fd == REDIRECT_PIPE) {
    (void) close(stdin_pipe[0]);
    (void) close(stdin_pipe[1]);
  }

stdin_pipe_failed:
  (void) close(status_pipe[0]);
  (void) close(status_pipe[1]);

  errno = errsv;

  return false;
}
示例#3
0
/**
 * Option parsing routine.
 *
 * Remember to update other places, such as execute_rsh_multiple routine when changing here.
 * @return 1 on failure.
 * @return 0 on success.
 */
int
parse_options ( int ac, char ** av)
{
  int c;			/* option */
  linkedlist * machinelist = NULL;
  linkedlist * rshcommandline_r = NULL; /* command line for rsh in reverse order*/

#ifdef HAVE_GETOPT_LONG
  int index_point;  
  static struct option long_options[]=
  {
    {"verbose", no_argument, 0, 'v'},
    {"quiet", no_argument, 0, 'q'},
    {"show-machine-names", no_argument, 0, 'M'},
    {"hide-machine-names", no_argument, 0, 'H'},
    {"duplicate-input", no_argument, 0, 'i'},
    {"bufsize", required_argument, 0, 'b'},

				/* machine-specification */
    {"machine", required_argument, 0, 'm'},
    {"num-topology", required_argument, 0, 'n'},
    {"all", no_argument, 0, 'a' },
    {"group", required_argument, 0, 'g'},
    {"file", required_argument, 0, 'f'},

				/* rsh/ssh specification */
    {"remoteshell", required_argument, 0, 'r'},
    {"remoteshellopt", required_argument, 0, 'o'},

    {"help", no_argument, 0, 'h'},
    {"version", no_argument, 0, 'V'},
    {"wait-shell", no_argument, 0, 'w'},
    {"concurrent-shell", no_argument, 0, 'c'},
    {"forklimit", required_argument, 0, 'F'},
    {0,0,0,0}
  };
#else
#define getopt_long(a,b,c,d,e) getopt(a,b,c)
#endif  
  
#ifdef GETOPT_WITH_GNU_REORDERING_EXTENTION
#define EXTRAVALUE			  "+"	/* add this to get GNU getopt to work in POSIX manner */
#else
#define EXTRAVALUE
#endif

  while((c = getopt_long (ac, av, 
			  EXTRAVALUE "vqm:ar:f:g:hVcwo:MHn:ib:F:", 
			  long_options, &index_point)) != -1)
    {
      switch (c)
	{
	case 'a':
	  if (verbose_flag) printf (_("Adding all machines to the list\n"));
	  {
	    char * buf;
	    if (asprintf(&buf, "%s/.dsh/machines.list", getenv("HOME"))<0)
	      {
		fprintf (stderr, _("%s: asprintf failed\n"), PACKAGE);
		return 1;
	      }
	    
	    machinelist = read_machinelist(machinelist, buf, DSHCONFDIR"/machines.list");
	    free (buf);	    
	  }	  
	  break;	  
	case 'g':
	  {
            if ('@' == *optarg)
              {			/* using libc call for using netgroup. */
                /* +1 to skip @ */
		if (verbose_flag) printf (_("Adding netgroup %s to the list\n"), optarg + 1);
                machinelist = read_machinenetgroup(machinelist, optarg+1);
              }
            else
              {			/* using dsh's own method. */
		char * buf1, *buf2;
		if (verbose_flag) printf (_("Adding group %s to the list\n"), optarg);
		if (asprintf(&buf1, DSHCONFDIR"/group/%s", optarg) < 0)
		  {
		    fprintf (stderr, _("%s: asprintf failed\n"), PACKAGE);
		    return 1;
		  }
		
		if (asprintf(&buf2, "%s/.dsh/group/%s", getenv("HOME"), optarg)<0)
		  {
		    fprintf (stderr, _("%s: asprintf failed\n"), PACKAGE);
		    return 1;
		  }
		
		machinelist = read_machinelist (machinelist, buf2, buf1); 
		free(buf1);free(buf2);
	      }
	  }
	  break;	  
	case 'f':
	  if (verbose_flag) printf (_("Adding file %s to the list\n"), optarg);
	  machinelist = read_machinelist (machinelist, optarg, NULL); 
	  break;	  
	case 'F':
	  forklimit = atoi (optarg);
	  wait_shell = 0;
	  if (verbose_flag) printf (_("Setting forklimit to %i and wait_shell to %i\n"), forklimit, wait_shell);
	  break;
	case 'v':
	  if (verbose_flag) printf (_("Verbose flag on\n"));
	  verbose_flag=1;	  
	  break;
	case 'q':
	  if (verbose_flag) printf (_("Verbose flag off\n"));
	  verbose_flag=0; 
	  break;
	case 'M':
	  if (verbose_flag) printf (_("Show machine names on output\n"));
	  pipe_option |= PIPE_OPTION_OUTPUT;
	  break;	  
	case 'H':
	  if (verbose_flag) printf (_("Dont show machine names on output\n"));
	  pipe_option &=  ~(PIPE_OPTION_OUTPUT);
	  break;	  
	case 'i':
	  if (verbose_flag) printf (_("Duplicate input to all processes\n"));
	  pipe_option |= PIPE_OPTION_INPUT;
	  break;	  
	case 'b':
	  if (verbose_flag) printf (_("Buffer size used for dupliation\n"));
	  buffer_size = atoi(optarg);	  
	  if (buffer_size < 1)
	    {
	      fprintf (stderr, _("Buffer size needs to be greater than 1\n"));
	      return 1;
	    }
	  break;	  
	case 'm':
	  if (verbose_flag) printf (_("Adding machine %s to list\n"), optarg);
	  machinelist = split_machines_list_and_add_machines (machinelist, optarg);
	  break;
	case 'n':
	  if (verbose_flag) printf (_("Topology number set to %s\n"), optarg);
	  num_topology = atoi (optarg);	  
	  break;	  
	case 'h':
	  print_help();
	  exit(1);
	  break;	  
	case 'V':
	  print_version();
	  exit(1);
	  break;	  
	case 'r':		/* specify the shell command */
	  if (verbose_flag) printf(_("Using %s as the remote shell\n"), optarg);
	  remoteshell_command = strdup (optarg);
	  break;	  
	case 'o':		/* specify the shell command options */
	  if (verbose_flag) printf(_("Adding [%s] to shell options\n"), optarg);
	  remoteshell_command_opt_r = lladd (remoteshell_command_opt_r, optarg);
	  break;	  
	case 'w':		/* wait shell */
	  if (verbose_flag) printf (_("Wait for shell to finish executing\n"));
	  wait_shell=1;
	  break;
	case 'c':		/* concurrent shell */
	  if (verbose_flag) printf (_("Do not wait for shell to finish\n"));
	  wait_shell=0;
	  break;
	case '?':
#ifndef HAVE_GETOPT_LONG
	  /* getopt-long handles this option properly. */
	  if (isprint (optopt))
	    fprintf (stderr, _("Unkown option -%c.\n"), optopt);
	  else
	    fprintf (stderr, _("Unkown option character 0x%x.\n"), optopt);
#endif	  
	  return 1;
	default:
	  if (verbose_flag) printf (_("Unhandled option\n"));
	  break;	  
	}
    }

  if (!machinelist)
    {
      fprintf (stderr, _("%s: no machine specified\n"), PACKAGE);
      return 1;
    }

  {				/* generate the command line for remote. */
    int i;
    for (i=optind; i < ac; ++i)
      {
	rshcommandline_r = lladd(rshcommandline_r, av[i]);
      }
  }
  

  /* do sanity checking, and exit if it fails. */
  if (sanity_checking())
    return 1;

  if (!(pipe_option & PIPE_OPTION_INPUT))
    open_devnull();		/* open /dev/null if no input pipe is required */


  /* reverse the list, which is in reverse order, to make the right order */
  machinelist = llreverse (machinelist);
  
				/* actually execute the code. */
  return do_shell(machinelist, rshcommandline_r);
}