Module Name: src Committed By: uebayasi Date: Sun Apr 13 09:19:43 UTC 2014
Modified Files: src/sys/kern: kern_exec.c Log Message: copyinargs: Refactor. Share code. To generate a diff of this commit: cvs rdiff -u -r1.391 -r1.392 src/sys/kern/kern_exec.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_exec.c diff -u src/sys/kern/kern_exec.c:1.391 src/sys/kern/kern_exec.c:1.392 --- src/sys/kern/kern_exec.c:1.391 Sun Apr 13 06:03:49 2014 +++ src/sys/kern/kern_exec.c Sun Apr 13 09:19:42 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.391 2014/04/13 06:03:49 uebayasi Exp $ */ +/* $NetBSD: kern_exec.c,v 1.392 2014/04/13 09:19:42 uebayasi Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.391 2014/04/13 06:03:49 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.392 2014/04/13 09:19:42 uebayasi Exp $"); #include "opt_exec.h" #include "opt_execfmt.h" @@ -124,6 +124,8 @@ struct execve_data; static int copyinargs(struct execve_data * restrict, char * const *, char * const *, execve_fetch_element_t, char **); +static int copyinargstrs(struct execve_data * restrict, char * const *, + execve_fetch_element_t, char **, size_t *, void (*)(const void *, size_t)); static int exec_sigcode_map(struct proc *, const struct emul *); #ifdef DEBUG_EXEC @@ -1412,7 +1414,7 @@ copyinargs(struct execve_data * restrict char * const *envs, execve_fetch_element_t fetch_element, char **dpp) { struct exec_package * const epp = &data->ed_pack; - char *dp, *sp; + char *dp; size_t i; int error; @@ -1444,70 +1446,80 @@ copyinargs(struct execve_data * restrict epp->ep_flags &= ~EXEC_HASARGL; } - /* Now get argv & environment */ + /* + * Read and count argument strings from user. + */ + if (args == NULL) { DPRINTF(("%s: null args\n", __func__)); return EINVAL; } - /* 'i' will index the argp/envp element to be retrieved */ - i = 0; if (epp->ep_flags & EXEC_SKIPARG) - i++; + args++; + i = 0; + error = copyinargstrs(data, args, fetch_element, &dp, &i, ktr_execarg); + if (error != 0) { + DPRINTF(("%s: copyin arg %d\n", __func__, error)); + return error; + } + data->ed_argc += i; + /* + * Read and count environment strings from user. + */ + + data->ed_envc = 0; + /* environment need not be there */ + if (envs == NULL) + goto done; + i = 0; + error = copyinargstrs(data, envs, fetch_element, &dp, &i, ktr_execenv); + if (error != 0) { + DPRINTF(("%s: copyin env %d\n", __func__, error)); + return error; + } + data->ed_envc += i; + +done: + *dpp = dp; + + return 0; +} + +static int +copyinargstrs(struct execve_data * restrict data, char * const *strs, + execve_fetch_element_t fetch_element, char **dpp, size_t *ip, + void (*ktr)(const void *, size_t)) +{ + char *dp, *sp; + size_t i; + int error; + + dp = *dpp; + + i = 0; while (1) { const size_t maxlen = data->ed_argp + ARG_MAX - dp; size_t len; - if ((error = (*fetch_element)(args, i, &sp)) != 0) { - DPRINTF(("%s: fetch_element args %d\n", - __func__, error)); + if ((error = (*fetch_element)(strs, i, &sp)) != 0) { return error; } if (!sp) break; if ((error = copyinstr(sp, dp, maxlen, &len)) != 0) { - DPRINTF(("%s: copyinstr args %d\n", __func__, error)); if (error == ENAMETOOLONG) error = E2BIG; return error; } - ktrexecarg(dp, len - 1); + if (__predict_false(ktrace_on)) + (*ktr)(dp, len - 1); dp += len; i++; - data->ed_argc++; - } - - data->ed_envc = 0; - /* environment need not be there */ - if (envs != NULL) { - i = 0; - while (1) { - const size_t maxlen = data->ed_argp + ARG_MAX - dp; - size_t len; - - if ((error = (*fetch_element)(envs, i, &sp)) != 0) { - DPRINTF(("%s: fetch_element env %d\n", - __func__, error)); - return error; - } - if (!sp) - break; - if ((error = copyinstr(sp, dp, maxlen, &len)) != 0) { - DPRINTF(("%s: copyinstr env %d\n", - __func__, error)); - if (error == ENAMETOOLONG) - error = E2BIG; - return error; - } - - ktrexecenv(dp, len - 1); - dp += len; - i++; - data->ed_envc++; - } } *dpp = dp; + *ip = i; return 0; }