1*f3d63a56Schristos /*
2*f3d63a56Schristos * setproctitle.c -- mimic setproctitle
3*f3d63a56Schristos *
4*f3d63a56Schristos * Copyright (c) 2020, NLnet Labs. All rights reserved.
5*f3d63a56Schristos *
6*f3d63a56Schristos * See LICENSE for the license.
7*f3d63a56Schristos *
8*f3d63a56Schristos */
9*f3d63a56Schristos #include "config.h"
10*f3d63a56Schristos
11*f3d63a56Schristos #if defined(__linux)
12*f3d63a56Schristos #include <assert.h>
13*f3d63a56Schristos #include <errno.h>
14*f3d63a56Schristos #ifndef HAVE_CONFIG_H
15*f3d63a56Schristos #include <libgen.h>
16*f3d63a56Schristos #endif
17*f3d63a56Schristos #include <stdarg.h>
18*f3d63a56Schristos #include <stdio.h>
19*f3d63a56Schristos #include <stdlib.h>
20*f3d63a56Schristos #include <sys/prctl.h>
21*f3d63a56Schristos #include <unistd.h>
22*f3d63a56Schristos
executable(void)23*f3d63a56Schristos static char *executable(void)
24*f3d63a56Schristos {
25*f3d63a56Schristos char *ptr, *buf = NULL;
26*f3d63a56Schristos size_t len = 0;
27*f3d63a56Schristos ssize_t cnt = 0;
28*f3d63a56Schristos
29*f3d63a56Schristos buf = NULL;
30*f3d63a56Schristos do {
31*f3d63a56Schristos len += 32;
32*f3d63a56Schristos ptr = realloc(buf, len);
33*f3d63a56Schristos if (ptr == NULL) {
34*f3d63a56Schristos if (buf != NULL) {
35*f3d63a56Schristos free(buf);
36*f3d63a56Schristos }
37*f3d63a56Schristos return NULL;
38*f3d63a56Schristos }
39*f3d63a56Schristos buf = ptr;
40*f3d63a56Schristos cnt = readlink("/proc/self/exe", buf, len);
41*f3d63a56Schristos } while (cnt >= 0 && (size_t)cnt == len);
42*f3d63a56Schristos
43*f3d63a56Schristos if (cnt >= 0) {
44*f3d63a56Schristos buf[cnt] = '\0';
45*f3d63a56Schristos return buf;
46*f3d63a56Schristos }
47*f3d63a56Schristos
48*f3d63a56Schristos free(buf);
49*f3d63a56Schristos
50*f3d63a56Schristos return NULL;
51*f3d63a56Schristos }
52*f3d63a56Schristos
setproctitle(const char * fmt,...)53*f3d63a56Schristos void setproctitle(const char *fmt, ...)
54*f3d63a56Schristos {
55*f3d63a56Schristos va_list ap;
56*f3d63a56Schristos char buf[32];
57*f3d63a56Schristos int cnt = 0, off = 0;
58*f3d63a56Schristos
59*f3d63a56Schristos /* prepend executable name if fmt does not start with '-' */
60*f3d63a56Schristos if (fmt == NULL || fmt[0] != '-' || fmt[(off = 1)] == '\0') {
61*f3d63a56Schristos char *exe;
62*f3d63a56Schristos const char *sep = (fmt && fmt[off] != '\0') ? ": " : "";
63*f3d63a56Schristos if ((exe = executable()) != NULL) {
64*f3d63a56Schristos cnt = snprintf(buf, sizeof(buf), "%s%s", basename(exe), sep);
65*f3d63a56Schristos if ((size_t)cnt >= sizeof(buf)) {
66*f3d63a56Schristos cnt = 31; /* leave room for '\0' */
67*f3d63a56Schristos }
68*f3d63a56Schristos free(exe);
69*f3d63a56Schristos }
70*f3d63a56Schristos }
71*f3d63a56Schristos
72*f3d63a56Schristos if (fmt != NULL && fmt[off] != '\0') {
73*f3d63a56Schristos va_start(ap, fmt);
74*f3d63a56Schristos cnt = vsnprintf(
75*f3d63a56Schristos buf+(size_t)cnt, sizeof(buf)-(size_t)cnt, fmt+(size_t)off, ap);
76*f3d63a56Schristos va_end(ap);
77*f3d63a56Schristos }
78*f3d63a56Schristos
79*f3d63a56Schristos if (cnt > 0) {
80*f3d63a56Schristos assert(cnt > 0 && (size_t)cnt < sizeof(buf));
81*f3d63a56Schristos (void)prctl(PR_SET_NAME, buf, 0, 0, 0);
82*f3d63a56Schristos }
83*f3d63a56Schristos }
84*f3d63a56Schristos #endif /* __linux */
85