28c28
< __FBSDID("$FreeBSD: projects/jailconf/usr.sbin/jail/command.c 223188 2011-06-17 16:06:13Z jamie $");
---
> __FBSDID("$FreeBSD: projects/jailconf/usr.sbin/jail/command.c 223189 2011-06-17 16:18:44Z jamie $");
53d52
< #define COMSTRING_DUMMY ((struct cfstring *)1)
69,70c68
< static int get_user_info(struct cfjail *j, const char *username,
< const struct passwd **pwdp, login_cap_t **lcapp);
---
> static int run_command(struct cfjail *j);
74a73,74
> static int get_user_info(struct cfjail *j, const char *username,
> const struct passwd **pwdp, login_cap_t **lcapp);
84c84
< * Run a command associated with a jail, possibly inside the jail.
---
> * Run the next command associated with a jail.
87c87
< run_command(struct cfjail *j, enum intparam comparam)
---
> next_command(struct cfjail *j)
88a89,245
> const struct cfstring *comstring;
> enum intparam comparam;
> int rval, create_failed;
>
> static struct cfstring dummystring = { .len = 1 };
>
> rval = 0;
> create_failed = (j->flags & (JF_STOP | JF_FAILED)) == JF_FAILED;
> for (; (comparam = *j->comparam) && comparam != IP__OP;
> j->comparam += create_failed ? -1 : 1) {
> if (j->comstring == NULL) {
> switch (comparam) {
> case IP_MOUNT_DEVFS:
> if (!bool_param(j->intparams[IP_MOUNT_DEVFS]))
> continue;
> /* FALLTHROUGH */
> case IP_STOP_TIMEOUT:
> j->comstring = &dummystring;
> break;
> default:
> if (j->intparams[comparam] == NULL)
> continue;
> j->comstring = create_failed
> ? TAILQ_LAST(&j->intparams[comparam]->val,
> cfstrings)
> : TAILQ_FIRST(&j->intparams[comparam]->val);
> }
> }
> for (; j->comstring != NULL;
> j->comstring = create_failed
> ? TAILQ_PREV(j->comstring, cfstrings, tq)
> : TAILQ_NEXT(j->comstring, tq)) {
> if (rval != 0)
> return rval;
> if (j->comstring->len == 0 || (create_failed &&
> (comparam == IP_EXEC_PRESTART || comparam ==
> IP_EXEC_START || comparam == IP_COMMAND ||
> comparam == IP_EXEC_POSTSTART)))
> continue;
> if (paralimit == 0) {
> requeue(j, &runnable);
> return 1;
> }
> rval = run_command(j);
> create_failed =
> (j->flags & (JF_STOP | JF_FAILED)) == JF_FAILED;
> }
> }
> return rval;
> }
>
> /*
> * Check command exit status
> */
> int
> finish_command(struct cfjail *j)
> {
> int error;
>
> if (!(j->flags & JF_SLEEPQ))
> return 0;
> j->flags &= ~JF_SLEEPQ;
> if (*j->comparam != IP_STOP_TIMEOUT) {
> paralimit++;
> if (!TAILQ_EMPTY(&runnable))
> requeue(TAILQ_FIRST(&runnable), &ready);
> }
> error = 0;
> if (j->flags & JF_TIMEOUT) {
> j->flags &= ~JF_TIMEOUT;
> if (*j->comparam != IP_STOP_TIMEOUT) {
> jail_warnx(j, "%s: timed out", j->comline);
> failed(j);
> error = -1;
> } else if (verbose > 0)
> jail_note(j, "timed out\n");
> } else if (j->pstatus != 0) {
> if (WIFSIGNALED(j->pstatus))
> jail_warnx(j, "%s: exited on signal %d",
> j->comline, WTERMSIG(j->pstatus));
> else
> jail_warnx(j, "%s: failed", j->comline);
> j->pstatus = 0;
> failed(j);
> error = -1;
> }
> free(j->comline);
> j->comline = NULL;
> return error;
> }
>
> /*
> * Check for finished processed or timeouts.
> */
> struct cfjail *
> next_proc(int nonblock)
> {
> struct kevent ke;
> struct timespec ts;
> struct timespec *tsp;
> struct cfjail *j;
>
> if (!TAILQ_EMPTY(&sleeping)) {
> again:
> tsp = NULL;
> if ((j = TAILQ_FIRST(&sleeping)) && j->timeout.tv_sec) {
> clock_gettime(CLOCK_REALTIME, &ts);
> ts.tv_sec = j->timeout.tv_sec - ts.tv_sec;
> ts.tv_nsec = j->timeout.tv_nsec - ts.tv_nsec;
> if (ts.tv_nsec < 0) {
> ts.tv_sec--;
> ts.tv_nsec += 1000000000;
> }
> if (ts.tv_sec < 0 ||
> (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
> j->flags |= JF_TIMEOUT;
> clear_procs(j);
> return j;
> }
> tsp = &ts;
> }
> if (nonblock) {
> ts.tv_sec = 0;
> ts.tv_nsec = 0;
> tsp = &ts;
> }
> switch (kevent(kq, NULL, 0, &ke, 1, tsp)) {
> case -1:
> if (errno != EINTR)
> err(1, "kevent");
> goto again;
> case 0:
> if (!nonblock) {
> j = TAILQ_FIRST(&sleeping);
> j->flags |= JF_TIMEOUT;
> clear_procs(j);
> return j;
> }
> break;
> case 1:
> (void)waitpid(ke.ident, NULL, WNOHANG);
> if ((j = find_proc(ke.ident))) {
> j->pstatus = ke.data;
> return j;
> }
> goto again;
> }
> }
> return NULL;
> }
>
> /*
> * Run a single command for a jail, possible inside the jail.
> */
> int
> run_command(struct cfjail *j)
> {
90c247
< struct cfstring *comstring, *s;
---
> const struct cfstring *comstring, *s;
94a252
> enum intparam comparam;
101,130d258
< if (comparam) {
< switch (comparam) {
< case IP_MOUNT_DEVFS:
< if (!bool_param(j->intparams[IP_MOUNT_DEVFS]))
< return 0;
< /* FALLTHROUGH */
< case IP_STOP_TIMEOUT:
< j->comstring = COMSTRING_DUMMY;
< break;
< default:
< if (j->intparams[comparam] == NULL)
< return 0;
< j->comstring =
< TAILQ_FIRST(&j->intparams[comparam]->val);
< }
< j->comparam = comparam;
< } else
< comparam = j->comparam;
< next_comstring:
< comstring = j->comstring;
< if (comstring == NULL)
< return 0;
< if (paralimit == 0) {
< requeue(j, &runnable);
< return 1;
< }
< j->comstring =
< comstring == COMSTRING_DUMMY ? NULL : TAILQ_NEXT(comstring, tq);
< if (comstring != COMSTRING_DUMMY && comstring->len == 0)
< goto next_comstring;
135c263,265
< bg = j->flags & JF_FAILED;
---
> comparam = *j->comparam;
> comstring = j->comstring;
> bg = 0;
172d301
< j->flags |= JF_IFUP;
198d326
< j->flags |= JF_IFUP;
211d338
< j->flags |= JF_IFUP;
224c351
< goto next_comstring;
---
> return 0;
255d381
< j->flags |= JF_MOUNTED;
290d415
< j->flags |= JF_MOUNTED;
336d460
<
338c462,463
< goto next_comstring;
---
> return 0;
>
401a527
> /* Set up the environment and run the command */
465,564d590
< * Check command exit status
< */
< int
< finish_command(struct cfjail *j)
< {
< int error;
<
< if (!(j->flags & JF_SLEEPQ))
< return 0;
< j->flags &= ~JF_SLEEPQ;
< if (j->comparam != IP_STOP_TIMEOUT) {
< paralimit++;
< if (!TAILQ_EMPTY(&runnable))
< requeue(TAILQ_FIRST(&runnable), &ready);
< }
< error = 0;
< if (j->flags & JF_TIMEOUT) {
< j->flags &= ~JF_TIMEOUT;
< if (j->comparam != IP_STOP_TIMEOUT) {
< jail_warnx(j, "%s: timed out", j->comline);
< failed(j);
< error = -1;
< } else if (verbose > 0)
< jail_note(j, "timed out\n");
< } else if (j->pstatus != 0) {
< if (WIFSIGNALED(j->pstatus))
< jail_warnx(j, "%s: exited on signal %d",
< j->comline, WTERMSIG(j->pstatus));
< else
< jail_warnx(j, "%s: failed", j->comline);
< j->pstatus = 0;
< failed(j);
< error = -1;
< }
< free(j->comline);
< j->comline = NULL;
< return error;
< }
<
< /*
< * Check for finished processed or timeouts.
< */
< struct cfjail *
< next_proc(int nonblock)
< {
< struct kevent ke;
< struct timespec ts;
< struct timespec *tsp;
< struct cfjail *j;
<
< if (!TAILQ_EMPTY(&sleeping)) {
< again:
< tsp = NULL;
< if ((j = TAILQ_FIRST(&sleeping)) && j->timeout.tv_sec) {
< clock_gettime(CLOCK_REALTIME, &ts);
< ts.tv_sec = j->timeout.tv_sec - ts.tv_sec;
< ts.tv_nsec = j->timeout.tv_nsec - ts.tv_nsec;
< if (ts.tv_nsec < 0) {
< ts.tv_sec--;
< ts.tv_nsec += 1000000000;
< }
< if (ts.tv_sec < 0 ||
< (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
< j->flags |= JF_TIMEOUT;
< clear_procs(j);
< return j;
< }
< tsp = &ts;
< }
< if (nonblock) {
< ts.tv_sec = 0;
< ts.tv_nsec = 0;
< tsp = &ts;
< }
< switch (kevent(kq, NULL, 0, &ke, 1, tsp)) {
< case -1:
< if (errno != EINTR)
< err(1, "kevent");
< goto again;
< case 0:
< if (!nonblock) {
< j = TAILQ_FIRST(&sleeping);
< j->flags |= JF_TIMEOUT;
< clear_procs(j);
< return j;
< }
< break;
< case 1:
< (void)waitpid(ke.ident, NULL, WNOHANG);
< if ((j = find_proc(ke.ident))) {
< j->pstatus = ke.data;
< return j;
< }
< goto again;
< }
< }
< return NULL;
< }
<
< /*
< __FBSDID("$FreeBSD: projects/jailconf/usr.sbin/jail/command.c 223188 2011-06-17 16:06:13Z jamie $");
---
> __FBSDID("$FreeBSD: projects/jailconf/usr.sbin/jail/command.c 223189 2011-06-17 16:18:44Z jamie $");
53d52
< #define COMSTRING_DUMMY ((struct cfstring *)1)
69,70c68
< static int get_user_info(struct cfjail *j, const char *username,
< const struct passwd **pwdp, login_cap_t **lcapp);
---
> static int run_command(struct cfjail *j);
74a73,74
> static int get_user_info(struct cfjail *j, const char *username,
> const struct passwd **pwdp, login_cap_t **lcapp);
84c84
< * Run a command associated with a jail, possibly inside the jail.
---
> * Run the next command associated with a jail.
87c87
< run_command(struct cfjail *j, enum intparam comparam)
---
> next_command(struct cfjail *j)
88a89,245
> const struct cfstring *comstring;
> enum intparam comparam;
> int rval, create_failed;
>
> static struct cfstring dummystring = { .len = 1 };
>
> rval = 0;
> create_failed = (j->flags & (JF_STOP | JF_FAILED)) == JF_FAILED;
> for (; (comparam = *j->comparam) && comparam != IP__OP;
> j->comparam += create_failed ? -1 : 1) {
> if (j->comstring == NULL) {
> switch (comparam) {
> case IP_MOUNT_DEVFS:
> if (!bool_param(j->intparams[IP_MOUNT_DEVFS]))
> continue;
> /* FALLTHROUGH */
> case IP_STOP_TIMEOUT:
> j->comstring = &dummystring;
> break;
> default:
> if (j->intparams[comparam] == NULL)
> continue;
> j->comstring = create_failed
> ? TAILQ_LAST(&j->intparams[comparam]->val,
> cfstrings)
> : TAILQ_FIRST(&j->intparams[comparam]->val);
> }
> }
> for (; j->comstring != NULL;
> j->comstring = create_failed
> ? TAILQ_PREV(j->comstring, cfstrings, tq)
> : TAILQ_NEXT(j->comstring, tq)) {
> if (rval != 0)
> return rval;
> if (j->comstring->len == 0 || (create_failed &&
> (comparam == IP_EXEC_PRESTART || comparam ==
> IP_EXEC_START || comparam == IP_COMMAND ||
> comparam == IP_EXEC_POSTSTART)))
> continue;
> if (paralimit == 0) {
> requeue(j, &runnable);
> return 1;
> }
> rval = run_command(j);
> create_failed =
> (j->flags & (JF_STOP | JF_FAILED)) == JF_FAILED;
> }
> }
> return rval;
> }
>
> /*
> * Check command exit status
> */
> int
> finish_command(struct cfjail *j)
> {
> int error;
>
> if (!(j->flags & JF_SLEEPQ))
> return 0;
> j->flags &= ~JF_SLEEPQ;
> if (*j->comparam != IP_STOP_TIMEOUT) {
> paralimit++;
> if (!TAILQ_EMPTY(&runnable))
> requeue(TAILQ_FIRST(&runnable), &ready);
> }
> error = 0;
> if (j->flags & JF_TIMEOUT) {
> j->flags &= ~JF_TIMEOUT;
> if (*j->comparam != IP_STOP_TIMEOUT) {
> jail_warnx(j, "%s: timed out", j->comline);
> failed(j);
> error = -1;
> } else if (verbose > 0)
> jail_note(j, "timed out\n");
> } else if (j->pstatus != 0) {
> if (WIFSIGNALED(j->pstatus))
> jail_warnx(j, "%s: exited on signal %d",
> j->comline, WTERMSIG(j->pstatus));
> else
> jail_warnx(j, "%s: failed", j->comline);
> j->pstatus = 0;
> failed(j);
> error = -1;
> }
> free(j->comline);
> j->comline = NULL;
> return error;
> }
>
> /*
> * Check for finished processed or timeouts.
> */
> struct cfjail *
> next_proc(int nonblock)
> {
> struct kevent ke;
> struct timespec ts;
> struct timespec *tsp;
> struct cfjail *j;
>
> if (!TAILQ_EMPTY(&sleeping)) {
> again:
> tsp = NULL;
> if ((j = TAILQ_FIRST(&sleeping)) && j->timeout.tv_sec) {
> clock_gettime(CLOCK_REALTIME, &ts);
> ts.tv_sec = j->timeout.tv_sec - ts.tv_sec;
> ts.tv_nsec = j->timeout.tv_nsec - ts.tv_nsec;
> if (ts.tv_nsec < 0) {
> ts.tv_sec--;
> ts.tv_nsec += 1000000000;
> }
> if (ts.tv_sec < 0 ||
> (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
> j->flags |= JF_TIMEOUT;
> clear_procs(j);
> return j;
> }
> tsp = &ts;
> }
> if (nonblock) {
> ts.tv_sec = 0;
> ts.tv_nsec = 0;
> tsp = &ts;
> }
> switch (kevent(kq, NULL, 0, &ke, 1, tsp)) {
> case -1:
> if (errno != EINTR)
> err(1, "kevent");
> goto again;
> case 0:
> if (!nonblock) {
> j = TAILQ_FIRST(&sleeping);
> j->flags |= JF_TIMEOUT;
> clear_procs(j);
> return j;
> }
> break;
> case 1:
> (void)waitpid(ke.ident, NULL, WNOHANG);
> if ((j = find_proc(ke.ident))) {
> j->pstatus = ke.data;
> return j;
> }
> goto again;
> }
> }
> return NULL;
> }
>
> /*
> * Run a single command for a jail, possible inside the jail.
> */
> int
> run_command(struct cfjail *j)
> {
90c247
< struct cfstring *comstring, *s;
---
> const struct cfstring *comstring, *s;
94a252
> enum intparam comparam;
101,130d258
< if (comparam) {
< switch (comparam) {
< case IP_MOUNT_DEVFS:
< if (!bool_param(j->intparams[IP_MOUNT_DEVFS]))
< return 0;
< /* FALLTHROUGH */
< case IP_STOP_TIMEOUT:
< j->comstring = COMSTRING_DUMMY;
< break;
< default:
< if (j->intparams[comparam] == NULL)
< return 0;
< j->comstring =
< TAILQ_FIRST(&j->intparams[comparam]->val);
< }
< j->comparam = comparam;
< } else
< comparam = j->comparam;
< next_comstring:
< comstring = j->comstring;
< if (comstring == NULL)
< return 0;
< if (paralimit == 0) {
< requeue(j, &runnable);
< return 1;
< }
< j->comstring =
< comstring == COMSTRING_DUMMY ? NULL : TAILQ_NEXT(comstring, tq);
< if (comstring != COMSTRING_DUMMY && comstring->len == 0)
< goto next_comstring;
135c263,265
< bg = j->flags & JF_FAILED;
---
> comparam = *j->comparam;
> comstring = j->comstring;
> bg = 0;
172d301
< j->flags |= JF_IFUP;
198d326
< j->flags |= JF_IFUP;
211d338
< j->flags |= JF_IFUP;
224c351
< goto next_comstring;
---
> return 0;
255d381
< j->flags |= JF_MOUNTED;
290d415
< j->flags |= JF_MOUNTED;
336d460
<
338c462,463
< goto next_comstring;
---
> return 0;
>
401a527
> /* Set up the environment and run the command */
465,564d590
< * Check command exit status
< */
< int
< finish_command(struct cfjail *j)
< {
< int error;
<
< if (!(j->flags & JF_SLEEPQ))
< return 0;
< j->flags &= ~JF_SLEEPQ;
< if (j->comparam != IP_STOP_TIMEOUT) {
< paralimit++;
< if (!TAILQ_EMPTY(&runnable))
< requeue(TAILQ_FIRST(&runnable), &ready);
< }
< error = 0;
< if (j->flags & JF_TIMEOUT) {
< j->flags &= ~JF_TIMEOUT;
< if (j->comparam != IP_STOP_TIMEOUT) {
< jail_warnx(j, "%s: timed out", j->comline);
< failed(j);
< error = -1;
< } else if (verbose > 0)
< jail_note(j, "timed out\n");
< } else if (j->pstatus != 0) {
< if (WIFSIGNALED(j->pstatus))
< jail_warnx(j, "%s: exited on signal %d",
< j->comline, WTERMSIG(j->pstatus));
< else
< jail_warnx(j, "%s: failed", j->comline);
< j->pstatus = 0;
< failed(j);
< error = -1;
< }
< free(j->comline);
< j->comline = NULL;
< return error;
< }
<
< /*
< * Check for finished processed or timeouts.
< */
< struct cfjail *
< next_proc(int nonblock)
< {
< struct kevent ke;
< struct timespec ts;
< struct timespec *tsp;
< struct cfjail *j;
<
< if (!TAILQ_EMPTY(&sleeping)) {
< again:
< tsp = NULL;
< if ((j = TAILQ_FIRST(&sleeping)) && j->timeout.tv_sec) {
< clock_gettime(CLOCK_REALTIME, &ts);
< ts.tv_sec = j->timeout.tv_sec - ts.tv_sec;
< ts.tv_nsec = j->timeout.tv_nsec - ts.tv_nsec;
< if (ts.tv_nsec < 0) {
< ts.tv_sec--;
< ts.tv_nsec += 1000000000;
< }
< if (ts.tv_sec < 0 ||
< (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
< j->flags |= JF_TIMEOUT;
< clear_procs(j);
< return j;
< }
< tsp = &ts;
< }
< if (nonblock) {
< ts.tv_sec = 0;
< ts.tv_nsec = 0;
< tsp = &ts;
< }
< switch (kevent(kq, NULL, 0, &ke, 1, tsp)) {
< case -1:
< if (errno != EINTR)
< err(1, "kevent");
< goto again;
< case 0:
< if (!nonblock) {
< j = TAILQ_FIRST(&sleeping);
< j->flags |= JF_TIMEOUT;
< clear_procs(j);
< return j;
< }
< break;
< case 1:
< (void)waitpid(ke.ident, NULL, WNOHANG);
< if ((j = find_proc(ke.ident))) {
< j->pstatus = ke.data;
< return j;
< }
< goto again;
< }
< }
< return NULL;
< }
<
< /*