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