113039Speter/* 213039Speter * Copyright (c) 1995 Peter Wemm <peter@freebsd.org> 313039Speter * All rights reserved. 413039Speter * 513039Speter * Redistribution and use in source and binary forms, with or without 613039Speter * modification, is permitted provided that the following conditions 713039Speter * are met: 813039Speter * 1. Redistributions of source code must retain the above copyright 913039Speter * notice immediately at the beginning of the file, without modification, 1013039Speter * this list of conditions, and the following disclaimer. 1113039Speter * 2. Redistributions in binary form must reproduce the above copyright 1213039Speter * notice, this list of conditions and the following disclaimer in the 1313039Speter * documentation and/or other materials provided with the distribution. 1414236Speter * 3. Absolutely no warranty of function or purpose is made by the author 1513039Speter * Peter Wemm. 1613039Speter */ 1713039Speter 1890039Sobrien#include <sys/cdefs.h> 1990039Sobrien__FBSDID("$FreeBSD: stable/11/lib/libc/gen/setproctitle.c 336449 2018-07-18 09:54:32Z kib $"); 2090039Sobrien 2193399Smarkm#include "namespace.h" 2213039Speter#include <sys/param.h> 2313039Speter#include <sys/exec.h> 2414236Speter#include <sys/sysctl.h> 2513039Speter 2613039Speter#include <stdio.h> 2713039Speter#include <string.h> 2813039Speter#include <stdlib.h> 2953239Sphk#include <unistd.h> 3093399Smarkm#include "un-namespace.h" 3113039Speter 3293399Smarkm#include "libc_private.h" 3393399Smarkm 3413039Speter/* 3513039Speter * Older FreeBSD 2.0, 2.1 and 2.2 had different ps_strings structures and 3613039Speter * in different locations. 3713039Speter * 1: old_ps_strings at the very top of the stack. 3813039Speter * 2: old_ps_strings at SPARE_USRSPACE below the top of the stack. 3913039Speter * 3: ps_strings at the very top of the stack. 40281763Skib * We only support a kernel providing #3 style ps_strings. 41281763Skib * 42281763Skib * For historical purposes, a definition of the old ps_strings structure 43281763Skib * and location is preserved below: 4413039Speterstruct old_ps_strings { 4513039Speter char *old_ps_argvstr; 4613039Speter int old_ps_nargvstr; 4713039Speter char *old_ps_envstr; 4813039Speter int old_ps_nenvstr; 4913039Speter}; 5013039Speter#define OLD_PS_STRINGS ((struct old_ps_strings *) \ 5113039Speter (USRSTACK - SPARE_USRSPACE - sizeof(struct old_ps_strings))) 52281763Skib */ 5313039Speter 5413039Speter#include <stdarg.h> 5513039Speter 5635491Sdg#define SPT_BUFSIZE 2048 /* from other parts of sendmail */ 5713039Speter 58336449Skibstatic char * 59336449Skibsetproctitle_internal(const char *fmt, va_list ap) 6013039Speter{ 6153297Sbrian static struct ps_strings *ps_strings; 62108163Sbbraun static char *buf = NULL; 63108163Sbbraun static char *obuf = NULL; 6453297Sbrian static char **oargv, *kbuf; 6553297Sbrian static int oargc = -1; 66108163Sbbraun static char *nargv[2] = { NULL, NULL }; 6753297Sbrian char **nargvp; 6853297Sbrian int nargc; 6969558Sjdp int i; 7014236Speter size_t len; 7141875Sbde unsigned long ul_ps_strings; 7213039Speter 73108163Sbbraun if (buf == NULL) { 74108163Sbbraun buf = malloc(SPT_BUFSIZE); 75108163Sbbraun if (buf == NULL) 76336449Skib return (NULL); 77108163Sbbraun nargv[0] = buf; 78108163Sbbraun } 79108163Sbbraun 80108163Sbbraun if (obuf == NULL ) { 81108163Sbbraun obuf = malloc(SPT_BUFSIZE); 82108163Sbbraun if (obuf == NULL) 83336449Skib return (NULL); 84117102Salfred *obuf = '\0'; 85108163Sbbraun } 86108163Sbbraun 8713039Speter if (fmt) { 88108163Sbbraun buf[SPT_BUFSIZE - 1] = '\0'; 8913039Speter 9064094Sps if (fmt[0] == '-') { 9164094Sps /* skip program name prefix */ 9264094Sps fmt++; 9364094Sps len = 0; 9464094Sps } else { 9564094Sps /* print program name heading for grep */ 96108163Sbbraun (void)snprintf(buf, SPT_BUFSIZE, "%s: ", _getprogname()); 9764094Sps len = strlen(buf); 9864094Sps } 9913039Speter 10013039Speter /* print the argument string */ 101108163Sbbraun (void) vsnprintf(buf + len, SPT_BUFSIZE - len, fmt, ap); 10213039Speter 10353297Sbrian nargvp = nargv; 10453297Sbrian nargc = 1; 10553297Sbrian kbuf = buf; 10653297Sbrian } else if (*obuf != '\0') { 10753297Sbrian /* Idea from NetBSD - reset the title on fmt == NULL */ 10853297Sbrian nargvp = oargv; 10953297Sbrian nargc = oargc; 11053297Sbrian kbuf = obuf; 11153297Sbrian } else 11253297Sbrian /* Nothing to restore */ 113336449Skib return (NULL); 11453297Sbrian 11535490Sdg if (ps_strings == NULL) { 11641875Sbde len = sizeof(ul_ps_strings); 11741875Sbde if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &len, NULL, 11841875Sbde 0) == -1) 119336449Skib return (NULL); 12041875Sbde ps_strings = (struct ps_strings *)ul_ps_strings; 12135490Sdg } 12214236Speter 123281763Skib /* 124281763Skib * PS_STRINGS points to zeroed memory on a style #2 kernel. 125281763Skib * Should not happen. 126281763Skib */ 127281763Skib if (ps_strings->ps_argvstr == NULL) 128336449Skib return (NULL); 129281763Skib 130281763Skib /* style #3 */ 131281763Skib if (oargc == -1) { 132281763Skib /* Record our original args */ 133281763Skib oargc = ps_strings->ps_nargvstr; 134281763Skib oargv = ps_strings->ps_argvstr; 135281763Skib for (i = len = 0; i < oargc; i++) { 136281763Skib /* 137281763Skib * The program may have scribbled into its 138281763Skib * argv array, e.g., to remove some arguments. 139281763Skib * If that has happened, break out before 140281763Skib * trying to call strlen on a NULL pointer. 141281763Skib */ 142281763Skib if (oargv[i] == NULL) { 143281763Skib oargc = i; 144281763Skib break; 14553297Sbrian } 146281763Skib snprintf(obuf + len, SPT_BUFSIZE - len, "%s%s", 147281763Skib len != 0 ? " " : "", oargv[i]); 148281763Skib if (len != 0) 149281763Skib len++; 150281763Skib len += strlen(oargv[i]); 151281763Skib if (len >= SPT_BUFSIZE) 152281763Skib break; 15353297Sbrian } 15413039Speter } 155281763Skib ps_strings->ps_nargvstr = nargc; 156281763Skib ps_strings->ps_argvstr = nargvp; 157336449Skib 158336449Skib return (nargvp[0]); 15913039Speter} 160336449Skib 161336449Skibstatic int fast_update = 0; 162336449Skib 163336449Skibvoid 164336449Skibsetproctitle_fast(const char *fmt, ...) 165336449Skib{ 166336449Skib va_list ap; 167336449Skib char *buf; 168336449Skib int oid[4]; 169336449Skib 170336449Skib va_start(ap, fmt); 171336449Skib buf = setproctitle_internal(fmt, ap); 172336449Skib va_end(ap); 173336449Skib 174336449Skib if (buf && !fast_update) { 175336449Skib /* Tell the kernel to start looking in user-space */ 176336449Skib oid[0] = CTL_KERN; 177336449Skib oid[1] = KERN_PROC; 178336449Skib oid[2] = KERN_PROC_ARGS; 179336449Skib oid[3] = getpid(); 180336449Skib sysctl(oid, 4, 0, 0, "", 0); 181336449Skib fast_update = 1; 182336449Skib } 183336449Skib} 184336449Skib 185336449Skibvoid 186336449Skibsetproctitle(const char *fmt, ...) 187336449Skib{ 188336449Skib va_list ap; 189336449Skib char *buf; 190336449Skib int oid[4]; 191336449Skib 192336449Skib va_start(ap, fmt); 193336449Skib buf = setproctitle_internal(fmt, ap); 194336449Skib va_end(ap); 195336449Skib 196336449Skib if (buf != NULL) { 197336449Skib /* Set the title into the kernel cached command line */ 198336449Skib oid[0] = CTL_KERN; 199336449Skib oid[1] = KERN_PROC; 200336449Skib oid[2] = KERN_PROC_ARGS; 201336449Skib oid[3] = getpid(); 202336449Skib sysctl(oid, 4, 0, 0, buf, strlen(buf) + 1); 203336449Skib fast_update = 0; 204336449Skib } 205336449Skib} 206