Пример #1
0
Файл: proc.c Проект: koue/httpd
void
proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
    int argc, char **argv, enum privsep_procid proc_id)
{
	struct privsep_proc	*p = NULL;
	unsigned int		 proc;
	unsigned int		 src, dst;

	if (proc_id == PROC_PARENT) {
		privsep_process = PROC_PARENT;
		proc_setup(ps, procs, nproc);

		/* Open socketpair()s for everyone. */
		for (src = 0; src < PROC_MAX; src++)
			for (dst = 0; dst < PROC_MAX; dst++)
				proc_open(ps, src, dst);

		/* Engage! */
		proc_exec(ps, procs, nproc, argc, argv);
		return;
	}

	/* Initialize a child */
	for (proc = 0; proc < nproc; proc++) {
		if (procs[proc].p_id != proc_id)
			continue;
		p = &procs[proc];
		break;
	}
	if (p == NULL || p->p_init == NULL)
		fatalx("%s: process %d missing process initialization",
		    __func__, proc_id);

	p->p_init(ps, p);

	fatalx("failed to initiate child process");
}
Пример #2
0
Файл: proc.c Проект: reyk/snmpd
void
proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
    int argc, char **argv, enum privsep_procid proc_id)
{
	struct privsep_proc	*p = NULL;
	struct privsep_pipes	*pa, *pb;
	unsigned int		 proc;
	unsigned int		 dst;
	int			 fds[2];

	/* Don't initiate anything if we are not really going to run. */
	if (ps->ps_noaction)
		return;

	if (proc_id == PROC_PARENT) {
		privsep_process = PROC_PARENT;
		proc_setup(ps, procs, nproc);

		/*
		 * Create the children sockets so we can use them
		 * to distribute the rest of the socketpair()s using
		 * proc_connect() later.
		 */
		for (dst = 0; dst < PROC_MAX; dst++) {
			/* Don't create socket for ourselves. */
			if (dst == PROC_PARENT)
				continue;

			for (proc = 0; proc < ps->ps_instances[dst]; proc++) {
				pa = &ps->ps_pipes[PROC_PARENT][0];
				pb = &ps->ps_pipes[dst][proc];
				if (socketpair(AF_UNIX,
				    SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
				    PF_UNSPEC, fds) == -1)
					fatal("%s: socketpair", __func__);

				pa->pp_pipes[dst][proc] = fds[0];
				pb->pp_pipes[PROC_PARENT][0] = fds[1];
			}
		}

		/* Engage! */
		proc_exec(ps, procs, nproc, argc, argv);
		return;
	}

	/* Initialize a child */
	for (proc = 0; proc < nproc; proc++) {
		if (procs[proc].p_id != proc_id)
			continue;
		p = &procs[proc];
		break;
	}
	if (p == NULL || p->p_init == NULL)
		fatalx("%s: process %d missing process initialization",
		    __func__, proc_id);

	p->p_init(ps, p);

	fatalx("failed to initiate child process");
}
Пример #3
0
/* everything is based on this exec, we have an extra flag
   (_EXEC_EXECONLY) to differentiate between the exec and fork_exec
   families.  the difference is that the latter forks and then execs
   the process thereby returning in the parent
   */
static int
fork_execve0(const char *path, char *const argv[], char * const envptr[],
	     int fd, u_int flags)
{
  u_int k = 0;
  int target_cpu = 0;
  struct Uenv cu;
  int NewPid = 0;
  int envid = 0; /* XXX -- init to supress warning */
  char **old_argv = (char **)argv;
  int r, exec_format;
  struct Env e;

  OSCALLENTER(OSCALL_execve);
  /* verify executable permission */
  if (!(flags & _EXEC_USE_FD) && access(path, X_OK) == -1) {
    /* access will set errno */
    r = -errno;
    goto err;
  }

  if (!(envid = sys_env_alloc (0, &r))) {
    fprintf(stderr,"could not sys_env_alloc\n");
    r = -ENOEXEC;
    goto err;
  }

  e = __envs[envidx(envid)];
  if ((exec_format = fork_execve0_part2(path, argv, envptr, &e, fd, flags)) < 0)
    goto err_env_free;

  /* write environment */
  if ((r = sys_wrenv (k, envid, &e)) < 0) {
    kprintf ("sys_wrenv failed\n");
    r = -ENOEXEC;
    goto err;
  }

  if (ExecuteOnExecHandlers(k, envid, flags & _EXEC_EXECONLY) == -1) {
    fprintf(stderr,"cleanup code not done yet\n");
    assert(-1);
  }

#ifdef PROCESS_TABLE
  if (flags & _EXEC_EXECONLY) {
    /* because true exec */
    NewPid = getpid();
  
    dlockputs(__PROCD_LD,"fork_execve0 get lock ");
    EXOS_LOCK(PROCINFO_LOCK);
    dlockputs(__PROCD_LD,"... got lock\n");
    EnterCritical (); 

    ProcChangeEnv(NewPid,envid);
    
    EXOS_UNLOCK(PROCINFO_LOCK);
    dlockputs(__PROCD_LD,"fork_execve0 release lock\n");
    ExitCritical (); 

  } else {
    /* because we are forking */
    NewPid = AllocateFreePid (envid);
  }

  cu = UAREA;
  if (!execonly) {
    AddProcEntry (&cu, (char *)path, (char **)argv, NewPid, UAREA.pid);
    if ((cu.parent_slot = GetChildSlot (NewPid)) < 0) {
      r = -ENOEXEC;
      goto err_env_free;
    }
  } else {
    /* TO TOM: what do we do this for?
    strncpy (UAREA.name, (char*)(((u_int)argv[0]) + ARGV_START_LOCAL - ARGV_START),
	     U_NAMEMAX-1);
    UAREA.name[U_NAMEMAX-1] = '\0'; */
  }
  /* XXX -- on an exec we'll forget to unref our children's pids */
  /* TO TOM: shouldnt this clearchildinfo be at the top */
  ClearChildInfo (&cu);
#else
#ifdef PROCD
  if (flags & _EXEC_EXECONLY) 
  {
    NewPid = getpid();
    /* only register us if we are of the right format */ 
    if (exec_format == EXEC_EXOS_AOUT)
      proc_exec(envid);
  } else {
    NewPid = proc_fork(envid);
  }
  cu = UAREA;
  //kprintf("NewPid %d envid: %d %s proc_%s: (%d) -> %d\n",
	    //NewPid,__envid,execonly ? "exec" : "fork",path,envid,NewPid);
#else
  NewPid = envid;
#endif /* PROCD */
#endif /* PROCESS_TABLE */

  strncpy (cu.name, path, U_NAMEMAX-1);
  cu.name[U_NAMEMAX-1] = '\0';
  cu.u_fpu = 0;
  cu.u_in_critical = 0;
  cu.u_status = U_RUN;
  cu.u_entprologue = e.env_tf.tf_eip;
  cu.u_entepilogue = e.env_tf.tf_eip;
  cu.u_entfault = 0;
  cu.u_entipc1 = 0;
  cu.u_entipc2 = 0;
  cu.u_ppc = 0;
#ifdef PROCESS_TABLE
  cu.u_chld_state_chng = 0;
#endif /* PROCESS_TABLE */
  cu.u_next_timeout = 0;
  cu.u_in_pfault = 0;
  cu.u_donate = -1;
  cu.u_yield_count = 0;
  cu.u_epilogue_count = 0;
  cu.u_epilogue_abort_count = 0;

  STOPP(misc,step7);
  ISTART(misc,step8);

  cu.u_start_kern_call_counting = 0;

  if ((r = sys_wru (0, envid, &cu)) < 0) {
    fprintf (stderr,"sys_wru failed\n");
    r = -ENOEXEC;
    goto err_env_free;
  }

  target_cpu = 0;

#ifdef __SMP__
  if (strncmp(path,"_cpu",4)==0 && strlen(path)>4) 
  {
    target_cpu = path[4]-'0';
    if (target_cpu<0 || target_cpu>sys_get_num_cpus()-1) 
      target_cpu = 0;
  }
#endif

  /* we can't do this until all the child state is setup */
  if ((r = sys_quantum_alloc (k, -1, target_cpu, envid)) < 0) {
    fprintf (stderr,"could not alloc quantum\n");
    r = -ENOEXEC;
    goto err_env_free;
  }

  /* if we're doing a true unix exec and not a combined fork/spawn
     we need to destroy ourselves since our child should have
     replaced us. */

  if (flags & _EXEC_EXECONLY) 
  {
    /* if not an exos format, should not expect normal child behaviors, so we
     * just quit from procd to avoid any hanging...
     */
    if (exec_format == EXEC_SIMPLE)
      proc_exit(0);

    /* we die anyways, so free quantum and env */
    ProcessFreeQuanta(__envid);
    sys_env_free (0, __envid);
  }

  if (old_argv != argv) __free((char**)argv);
  OSCALLEXIT(OSCALL_execve);
  return (NewPid);

err_env_free:
  ProcessFreeQuanta(__envid);
  sys_env_free (k, envid);

err:
  if (old_argv != argv) __free((char**)argv);
  errno = -r;
  OSCALLEXIT(OSCALL_execve);
  return -1;
}
Пример #4
0
int job_start(struct job *j)
{
	struct proc *p;
	struct redir *redir_iter;
	int pipey[2] = { -1, -1 };

#define REDIR(a, b) \
					do{ \
						if(a != b){ \
							/* close b and copy a into b */ \
							if(dup2(a, b) == -1) \
								perror("dup2()"); \
							if(close(a) == -1) \
								perror("close()"); \
						} \
					}while(0)

	for(redir_iter = j->redir; redir_iter; redir_iter = redir_iter->next){
		int fd;

		if(redir_iter->fname){
			fd = open(redir_iter->fname, O_WRONLY | O_CREAT | O_TRUNC); /* FIXME: only out for now - need "<" and ">>" */
			if(fd == -1){
				fprintf(stderr, "ush: open %s: %s\n", redir_iter->fname, strerror(errno));
				/* FIXME: close all other fds */
				return 1;
			}
		}else{
			fd = redir_iter->fd_out;
		}

		fprintf(stderr, "job_start(): REDIR(%d [%s], %d)\n", fd, redir_iter->fname, redir_iter->fd_in);
		REDIR(fd, redir_iter->fd_in);
	}

	j->proc->in = STDIN_FILENO;
	for(p = j->proc; p; p = p->next){
		p->err = STDERR_FILENO;
		if(p->next){
			if(pipe(pipey) < 0){
				perror("pipe()");
				goto bail;
			}
			p->out = pipey[1];
			p->next->in = pipey[0];
		}else{
			p->out = STDOUT_FILENO;
		}

		/* TODO: cd, fg, rehash */

		switch(p->pid = fork()){
			case 0:
				p->pid = getpid();
				REDIR(p->in,   STDIN_FILENO);
				REDIR(p->out, STDOUT_FILENO);
				REDIR(p->err, STDERR_FILENO);
#undef REDIR
				job_close_fds(j, p->next);
				proc_exec(p, j->gid);
				break; /* unreachable */

			case -1:
				perror("fork()");
				goto bail;

			default:
				if(interactive){
					if(!j->gid)
						j->gid = p->pid;
					setpgid(p->pid, j->gid);
				}
				p->state = PROC_RUN;
		}
	}

	/* close our access to all these pipes */
	job_close_fds(j, NULL);

	j->state = JOB_RUNNING;

	return 0;
bail:
	fprintf(stderr, "warning: error starting job: %s\n", strerror(errno));
	for(; p; p = p->next)
		p->state = PROC_FIN;
	job_close_fds(j, NULL);
	job_sig(j, SIGCONT);
	return 1;
}