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 23static 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 53void 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