/*
- * 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 <daniel.lezcano at free.fr>
- *
- * 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 <sys/prctl.h>
-#include <sys/syscall.h>
-
-#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
-#include <unistd.h>
#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);
}
/*
- * 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 <daniel.lezcano at free.fr>
- *
- * 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
#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
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)
{
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;
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;
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
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) {
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);
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]" : "",
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);
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 */