xref: /netbsd-src/external/bsd/nsd/dist/compat/setproctitle.c (revision f3d63a561b22e5536a0779632985057ed3d766aa)
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