setproctitle.c revision 93399
1150850Sscottl/* 2150850Sscottl * Copyright (c) 1995 Peter Wemm <peter@freebsd.org> 3150850Sscottl * All rights reserved. 4150850Sscottl * 5150850Sscottl * Redistribution and use in source and binary forms, with or without 6150850Sscottl * modification, is permitted provided that the following conditions 7150850Sscottl * are met: 8150850Sscottl * 1. Redistributions of source code must retain the above copyright 9150850Sscottl * notice immediately at the beginning of the file, without modification, 10150850Sscottl * this list of conditions, and the following disclaimer. 11150850Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12150850Sscottl * notice, this list of conditions and the following disclaimer in the 13150850Sscottl * documentation and/or other materials provided with the distribution. 14150850Sscottl * 3. Absolutely no warranty of function or purpose is made by the author 15150850Sscottl * Peter Wemm. 16150850Sscottl */ 17150850Sscottl 18150850Sscottl#include <sys/cdefs.h> 19150850Sscottl__FBSDID("$FreeBSD: head/lib/libc/gen/setproctitle.c 93399 2002-03-29 22:43:43Z markm $"); 20150850Sscottl 21150850Sscottl#include "namespace.h" 22150850Sscottl#include <sys/types.h> 23150850Sscottl#include <sys/param.h> 24150850Sscottl#include <sys/exec.h> 25150850Sscottl#include <sys/sysctl.h> 26150850Sscottl 27150850Sscottl#include <vm/vm.h> 28150850Sscottl#include <vm/vm_param.h> 29150850Sscottl#include <vm/pmap.h> 30150850Sscottl 31150850Sscottl#include <stdio.h> 32150850Sscottl#include <string.h> 33150850Sscottl#include <stdlib.h> 34150850Sscottl#include <unistd.h> 35150850Sscottl#include "un-namespace.h" 36150850Sscottl 37150850Sscottl#include "libc_private.h" 38150850Sscottl 39150850Sscottl/* 40150850Sscottl * Older FreeBSD 2.0, 2.1 and 2.2 had different ps_strings structures and 41150850Sscottl * in different locations. 42150850Sscottl * 1: old_ps_strings at the very top of the stack. 43150850Sscottl * 2: old_ps_strings at SPARE_USRSPACE below the top of the stack. 44150850Sscottl * 3: ps_strings at the very top of the stack. 45150850Sscottl * This attempts to support a kernel built in the #2 and #3 era. 46150850Sscottl */ 47150850Sscottl 48150850Sscottlstruct old_ps_strings { 49150850Sscottl char *old_ps_argvstr; 50150850Sscottl int old_ps_nargvstr; 51150850Sscottl char *old_ps_envstr; 52150850Sscottl int old_ps_nenvstr; 53150850Sscottl}; 54150850Sscottl#define OLD_PS_STRINGS ((struct old_ps_strings *) \ 55150850Sscottl (USRSTACK - SPARE_USRSPACE - sizeof(struct old_ps_strings))) 56150850Sscottl 57150850Sscottl#include <stdarg.h> 58150850Sscottl 59150850Sscottl#define SPT_BUFSIZE 2048 /* from other parts of sendmail */ 60150850Sscottl 61150850Sscottlvoid 62150850Sscottlsetproctitle(const char *fmt, ...) 63150850Sscottl{ 64150850Sscottl static struct ps_strings *ps_strings; 65150850Sscottl static char buf[SPT_BUFSIZE]; 66150850Sscottl static char obuf[SPT_BUFSIZE]; 67150850Sscottl static char **oargv, *kbuf; 68216600Suqs static int oargc = -1; 69216600Suqs static char *nargv[2] = { buf, NULL }; 70216600Suqs char **nargvp; 71216600Suqs int nargc; 72216600Suqs int i; 73216600Suqs va_list ap; 74150850Sscottl size_t len; 75150850Sscottl unsigned long ul_ps_strings; 76188826Simp int oid[4]; 77188826Simp 78216600Suqs va_start(ap, fmt); 79150850Sscottl 80150850Sscottl if (fmt) { 81150850Sscottl buf[sizeof(buf) - 1] = '\0'; 82150850Sscottl 83150850Sscottl if (fmt[0] == '-') { 84150850Sscottl /* skip program name prefix */ 85150850Sscottl fmt++; 86150850Sscottl len = 0; 87150850Sscottl } else { 88150850Sscottl /* print program name heading for grep */ 89150850Sscottl (void)snprintf(buf, sizeof(buf), "%s: ", _getprogname()); 90150850Sscottl len = strlen(buf); 91150850Sscottl } 92150850Sscottl 93150850Sscottl /* print the argument string */ 94150850Sscottl (void) vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); 95150850Sscottl 96150850Sscottl nargvp = nargv; 97150850Sscottl nargc = 1; 98150850Sscottl kbuf = buf; 99216600Suqs } else if (*obuf != '\0') { 100216600Suqs /* Idea from NetBSD - reset the title on fmt == NULL */ 101216600Suqs nargvp = oargv; 102216600Suqs nargc = oargc; 103216600Suqs kbuf = obuf; 104216600Suqs } else 105216600Suqs /* Nothing to restore */ 106150850Sscottl return; 107150850Sscottl 108150850Sscottl va_end(ap); 109150850Sscottl 110150850Sscottl /* Set the title into the kernel cached command line */ 111150850Sscottl oid[0] = CTL_KERN; 112150850Sscottl oid[1] = KERN_PROC; 113150850Sscottl oid[2] = KERN_PROC_ARGS; 114150850Sscottl oid[3] = getpid(); 115150850Sscottl sysctl(oid, 4, 0, 0, kbuf, strlen(kbuf) + 1); 116150850Sscottl 117150850Sscottl if (ps_strings == NULL) { 118150850Sscottl len = sizeof(ul_ps_strings); 119150850Sscottl if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &len, NULL, 120150850Sscottl 0) == -1) 121150850Sscottl ul_ps_strings = PS_STRINGS; 122150850Sscottl ps_strings = (struct ps_strings *)ul_ps_strings; 123150850Sscottl } 124150850Sscottl 125150850Sscottl /* PS_STRINGS points to zeroed memory on a style #2 kernel */ 126150850Sscottl if (ps_strings->ps_argvstr) { 127150850Sscottl /* style #3 */ 128150850Sscottl if (oargc == -1) { 129150850Sscottl /* Record our original args */ 130150850Sscottl oargc = ps_strings->ps_nargvstr; 131150850Sscottl oargv = ps_strings->ps_argvstr; 132150850Sscottl for (i = len = 0; i < oargc; i++) { 133150850Sscottl /* 134150850Sscottl * The program may have scribbled into its 135150850Sscottl * argv array, e.g., to remove some arguments. 136150850Sscottl * If that has happened, break out before 137150850Sscottl * trying to call strlen on a NULL pointer. 138150850Sscottl */ 139150850Sscottl if (oargv[i] == NULL) { 140150850Sscottl oargc = i; 141150850Sscottl break; 142150850Sscottl } 143150850Sscottl snprintf(obuf + len, sizeof(obuf) - len, "%s%s", 144150850Sscottl len ? " " : "", oargv[i]); 145150850Sscottl if (len) 146150850Sscottl len++; 147150850Sscottl len += strlen(oargv[i]); 148150850Sscottl if (len >= sizeof(obuf)) 149150850Sscottl break; 150150850Sscottl } 151150850Sscottl } 152150850Sscottl ps_strings->ps_nargvstr = nargc; 153150850Sscottl ps_strings->ps_argvstr = nargvp; 154150850Sscottl } else { 155150850Sscottl /* style #2 - we can only restore our first arg :-( */ 156216600Suqs if (*obuf == '\0') 157150850Sscottl strncpy(obuf, OLD_PS_STRINGS->old_ps_argvstr, 158150850Sscottl sizeof(obuf) - 1); 159150850Sscottl OLD_PS_STRINGS->old_ps_nargvstr = 1; 160150850Sscottl OLD_PS_STRINGS->old_ps_argvstr = nargvp[0]; 161150850Sscottl } 162150850Sscottl} 163150850Sscottl