From: Roy Marples Date: Tue, 15 Oct 2019 10:59:58 +0000 (+0100) Subject: compat: Use more portable setproctitle from nginx X-Git-Tag: v8.1.1~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6612fecc125c29b1501d01b1e6e4fdbaac3a6631;p=thirdparty%2Fdhcpcd.git compat: Use more portable setproctitle from nginx Hopefully works on older Linux and Solaris. --- diff --git a/compat/setproctitle.c b/compat/setproctitle.c index f5ff0ac0..9350e5ee 100644 --- a/compat/setproctitle.c +++ b/compat/setproctitle.c @@ -1,156 +1,136 @@ /* - * lxc: linux Container library + * Copyright (C) 2002-2019 Igor Sysoev + * Copyright (C) 2011-2019 Nginx, Inc. + * All rights reserved. * - * (C) Copyright IBM Corp. 2007, 2008 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * Authors: - * Daniel Lezcano - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif -#include -#include - -#include #include #include -#include #include -#include #include "config.h" -#define prctl_arg(x) ((unsigned long)x) - -/* - * Sets the process title to the specified title. Note that this may fail if - * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18). - */ -int setproctitle(const char *fmt, ...) -{ - char title[1024], *tp, *progname; - va_list args; - int fd, i; - char *buf_ptr, *tmp_proctitle; - char buf[BUFSIZ]; - int ret = 0; - ssize_t bytes_read = 0; - size_t len; - static char *proctitle = NULL; - -#if 0 - progname = getprogname(); +#ifdef __sun +#define SETPROCTITLE_PAD ' ' #else - progname = "dhcpcd"; +#define SETPROCTITLE_PAD '\0' #endif - tp = title; - tp += snprintf(title, sizeof(title), "%s: ", progname); - va_start(args, fmt); - vsnprintf(tp, sizeof(title) - strlen(progname), fmt, args); - va_end(args); +static int setproctitle_argc; +static char *setproctitle_argv_last; +static char **setproctitle_argv; +static char *setproctitle_buf; - /* - * We don't really need to know all of this stuff, but unfortunately - * PR_SET_MM_MAP requires us to set it all at once, so we have to - * figure it out anyway. - */ - unsigned long start_data, end_data, start_brk, start_code, end_code, - start_stack, arg_start, arg_end, env_start, env_end; - long brk_val; - struct prctl_mm_map prctl_map; - - fd = open("/proc/self/stat", O_RDONLY); - if (fd == -1) - return -1; - bytes_read = read(fd, buf, sizeof(buf) - 1); - close(fd); - if (bytes_read == -1) +int +setproctitle_init(int argc, char **argv) +{ + size_t i, len; + char *p; + + len = 0; + for (i = 0; environ[i] != NULL; i++) + len += strlen(environ[i]) + 1; + if ((setproctitle_buf = malloc(len)) == NULL) return -1; - buf[bytes_read] = '\0'; + setproctitle_argc = argc; + setproctitle_argv = argv; + setproctitle_argv_last = setproctitle_argv[0]; + for (i = 0; setproctitle_argv[i] != NULL; i++) { + if (setproctitle_argv_last == setproctitle_argv[i]) + setproctitle_argv_last = setproctitle_argv[i] + + strlen(setproctitle_argv[i]) + 1; + } - /* Skip the first 25 fields, column 26-28 are start_code, end_code, - * and start_stack */ - buf_ptr = strchr(buf, ' '); - for (i = 0; i < 24; i++) { - if (!buf_ptr) - return -1; - buf_ptr = strchr(buf_ptr + 1, ' '); + p = setproctitle_buf; + for (i = 0; environ[i] != NULL; i++) { + if (setproctitle_argv_last != environ[i]) + continue; + len = strlen(environ[i]) + 1; + setproctitle_argv_last = environ[i] + len; + strlcpy(p, environ[i], len); + environ[i] = p; + p += len; } - if (!buf_ptr) - return -1; - i = sscanf(buf_ptr, "%lu %lu %lu", &start_code, &end_code, &start_stack); - if (i != 3) - return -1; + setproctitle_argv_last--; + return 0; +} - /* Skip the next 19 fields, column 45-51 are start_data to arg_end */ - for (i = 0; i < 19; i++) { - if (!buf_ptr) - return -1; - buf_ptr = strchr(buf_ptr + 1, ' '); - } +void +setproctitle_free(void) +{ - if (!buf_ptr) - return -1; + free(setproctitle_buf); +} - i = sscanf(buf_ptr, "%lu %lu %lu %*u %*u %lu %lu", &start_data, - &end_data, &start_brk, &env_start, &env_end); - if (i != 5) - return -1; +void +setproctitle(const char *fmt, ...) +{ + const char *progname; + char *p; + int n; + va_list args; +#if 0 + progname = getprogname(); +#else + progname = "dhcpcd"; +#endif - /* Include the null byte here, because in the calculations below we - * want to have room for it. */ - len = strlen(title) + 1; + setproctitle_argv[1] = NULL; +#define LAST_SIZE (size_t)(setproctitle_argv_last - p) - tmp_proctitle = realloc(proctitle, len); - if (!tmp_proctitle) - return -1; + p = setproctitle_argv[0]; + n = snprintf(p, LAST_SIZE, "%s: ", progname); + if (n == -1) + return; + p += n; + + va_start(args, fmt); + n = vsnprintf(p, LAST_SIZE, fmt, args); + va_end(args); + if (n == -1) + return; + p += n; + +#ifdef __sun + size_t len; + int i; + + len = 0; + for (i = 0; i < setproctitle_argc; i++) + len += strlen(setproctitle_argv[i]) + 1; + + if (len > (size_t)(p - setproctitle_argv[0])) { + p += strlcpy(p, " (", LAST_SIZE); + for (i = 0; i < setproctitle_argc; i++) { + p += strlcpy(p, setproctitle_argv[i], LAST_SIZE); + p += strlcpy(p, " ", LAST_SIZE); + } + } +#endif - proctitle = tmp_proctitle; - - arg_start = (unsigned long)proctitle; - arg_end = arg_start + len; - - brk_val = syscall(__NR_brk, 0); - - prctl_map = (struct prctl_mm_map){ - .start_code = start_code, - .end_code = end_code, - .start_stack = start_stack, - .start_data = start_data, - .end_data = end_data, - .start_brk = start_brk, - .brk = (unsigned long long)brk_val, - .arg_start = arg_start, - .arg_end = arg_end, - .env_start = env_start, - .env_end = env_end, - .auxv = NULL, - .auxv_size = 0, - .exe_fd = (unsigned int)-1, - }; - - ret = prctl(PR_SET_MM, prctl_arg(PR_SET_MM_MAP), prctl_arg(&prctl_map), - prctl_arg(sizeof(prctl_map)), prctl_arg(0)); - if (ret == 0) - (void)strlcpy((char *)arg_start, title, len); - return ret; + if (setproctitle_argv_last - p > 0) + memset(p, SETPROCTITLE_PAD, LAST_SIZE); } diff --git a/compat/setproctitle.h b/compat/setproctitle.h index 2fe685f1..18249947 100644 --- a/compat/setproctitle.h +++ b/compat/setproctitle.h @@ -1,24 +1,28 @@ /* - * lxc: linux Container library + * Copyright (C) 2002-2019 Igor Sysoev + * Copyright (C) 2011-2019 Nginx, Inc. + * All rights reserved. * - * (C) Copyright IBM Corp. 2007, 2008 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * Authors: - * Daniel Lezcano - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef SETPROCTITLE_H @@ -32,5 +36,7 @@ #endif #endif /* !__printflike */ -__printflike(1, 2) int setproctitle(const char *, ...); +int setproctitle_init(int, char **); +void setproctitle_free(void); +__printflike(1, 2) void setproctitle(const char *, ...); #endif diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 193414ed..85d9081f 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -1549,6 +1549,47 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, return 0; } +static int +dhcpcd_saveargv(struct dhcpcd_ctx *ctx, int argc, char **argv) +{ +#ifdef SETPROCTITLE_H + int i; + + ctx->argv = reallocarray(ctx->argv, (size_t)argc + 1, sizeof(char *)); + if (ctx->argv == NULL) { + logerr(__func__); + return -1; + } + + ctx->argc = argc; + for (i = 0; i < argc; i++) { + if ((ctx->argv[i] = strdup(argv[i])) == NULL) { + logerr(__func__); + return -1; + } + } + + ctx->argv[i] = NULL; +#else + ctx->argv = argv; + ctx->argc = argc; +#endif + return 0; + +} + +static void +dhcpcd_freeargv(struct dhcpcd_ctx *ctx) +{ +#ifdef SETPROCTITLE_H + int i; + + for (i = 0; i < ctx->argc; i++) + free(ctx->argv[i]); + free(ctx->argv); +#endif +} + int main(int argc, char **argv) { @@ -1691,8 +1732,8 @@ main(int argc, char **argv) logsetopts(logopts); logopen(ctx.logfile); - ctx.argv = argv; - ctx.argc = argc; + if (dhcpcd_saveargv(&ctx, argc, argv) == -1) + goto exit_failure; ctx.ifc = argc - optind; ctx.ifv = argv + optind; @@ -1702,7 +1743,7 @@ main(int argc, char **argv) goto printpidfile; goto exit_failure; } - opt = add_options(&ctx, NULL, ifo, argc, argv); + opt = add_options(&ctx, NULL, ifo, ctx.argc, ctx.argv); if (opt != 1) { if (ctx.options & DHCPCD_PRINT_PIDFILE) goto printpidfile; @@ -1717,7 +1758,7 @@ main(int argc, char **argv) ifo = read_config(&ctx, argv[optind], NULL, NULL); if (ifo == NULL) goto exit_failure; - add_options(&ctx, NULL, ifo, argc, argv); + add_options(&ctx, NULL, ifo, ctx.argc, ctx.argv); } if_printoptions(); #ifdef INET @@ -1840,7 +1881,7 @@ printpidfile: logerr("%s: if_discover", __func__); goto exit_failure; } - ifp = if_find(ctx.ifaces, argv[optind]); + ifp = if_find(ctx.ifaces, ctx.argv[optind]); if (ifp == NULL) { ifp = calloc(1, sizeof(*ifp)); if (ifp == NULL) { @@ -1848,7 +1889,7 @@ printpidfile: goto exit_failure; } if (optind != argc) - strlcpy(ctx.pidfile, argv[optind], + strlcpy(ctx.pidfile, ctx.argv[optind], sizeof(ctx.pidfile)); ifp->ctx = &ctx; TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next); @@ -1984,6 +2025,9 @@ printpidfile: logdebugx(PACKAGE "-" VERSION " starting"); ctx.options |= DHCPCD_STARTED; +#ifdef SETPROCTITLE_H + setproctitle_init(argc, argv); +#endif setproctitle("%s%s%s", ctx.options & DHCPCD_MASTER ? "[master]" : argv[optind], ctx.options & DHCPCD_IPV4 ? " [ip4]" : "", @@ -2044,7 +2088,7 @@ printpidfile: TAILQ_FOREACH(ifp, ctx.ifaces, next) { if (ifp->active) - dhcpcd_initstate1(ifp, argc, argv, 0); + dhcpcd_initstate1(ifp, ctx.argc, ctx.argv, 0); } if_learnaddrs(&ctx, ctx.ifaces, &ifaddrs); @@ -2153,6 +2197,10 @@ exit1: loginfox(PACKAGE " exited"); logclose(); free(ctx.logfile); + dhcpcd_freeargv(&ctx); +#ifdef SETPROCTITLE_H + setproctitle_free(); +#endif #ifdef USE_SIGNALS if (ctx.options & DHCPCD_FORKED) _exit(i); /* so atexit won't remove our pidfile */