1 /* 2 * Based on src/backend/utils/misc/pg_status.c from 3 * PostgreSQL Database Management System 4 * 5 * Portions Copyright (c) 1996-2001, The PostgreSQL Global Development Group 6 * 7 * Portions Copyright (c) 1994, The Regents of the University of California 8 * 9 * Permission to use, copy, modify, and distribute this software and its 10 * documentation for any purpose, without fee, and without a written agreement 11 * is hereby granted, provided that the above copyright notice and this 12 * paragraph and the following two paragraphs appear in all copies. 13 * 14 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR 15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 16 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 17 * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE 18 * POSSIBILITY OF SUCH DAMAGE. 19 * 20 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 23 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO 24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 */ 26 27 /*-------------------------------------------------------------------- 28 * ps_status.c 29 * 30 * Routines to support changing the ps display of PostgreSQL backends 31 * to contain some useful information. Mechanism differs wildly across 32 * platforms. 33 * 34 * $Header: /var/cvs/openssh/openbsd-compat/setproctitle.c,v 1.5 2003/01/20 02:15:11 djm Exp $ 35 * 36 * Copyright 2000 by PostgreSQL Global Development Group 37 * various details abducted from various places 38 *-------------------------------------------------------------------- 39 */ 40 41 #include "includes.h" 42 43 #ifndef HAVE_SETPROCTITLE 44 45 #include <unistd.h> 46 #ifdef HAVE_SYS_PSTAT_H 47 #include <sys/pstat.h> /* for HP-UX */ 48 #endif 49 #ifdef HAVE_PS_STRINGS 50 #include <machine/vmparam.h> /* for old BSD */ 51 #include <sys/exec.h> 52 #endif 53 54 /*------ 55 * Alternative ways of updating ps display: 56 * 57 * SETPROCTITLE_STRATEGY == PS_USE_PSTAT 58 * use the pstat(PSTAT_SETCMD, ) 59 * (HPUX) 60 * SETPROCTITLE_STRATEGY == PS_USE_PS_STRINGS 61 * assign PS_STRINGS->ps_argvstr = "string" 62 * (some BSD systems) 63 * SETPROCTITLE_STRATEGY == PS_USE_CHANGE_ARGV 64 * assign argv[0] = "string" 65 * (some other BSD systems) 66 * SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV 67 * write over the argv and environment area 68 * (most SysV-like systems) 69 * SETPROCTITLE_STRATEGY == PS_USE_NONE 70 * don't update ps display 71 * (This is the default, as it is safest.) 72 */ 73 74 #define PS_USE_NONE 0 75 #define PS_USE_PSTAT 1 76 #define PS_USE_PS_STRINGS 2 77 #define PS_USE_CHANGE_ARGV 3 78 #define PS_USE_CLOBBER_ARGV 4 79 80 #ifndef SETPROCTITLE_STRATEGY 81 # define SETPROCTITLE_STRATEGY PS_USE_NONE 82 #endif 83 84 #ifndef SETPROCTITLE_PS_PADDING 85 # define SETPROCTITLE_PS_PADDING ' ' 86 #endif 87 #endif /* HAVE_SETPROCTITLE */ 88 89 extern char **environ; 90 91 /* 92 * argv clobbering uses existing argv space, all other methods need a buffer 93 */ 94 #if SETPROCTITLE_STRATEGY != PS_USE_CLOBBER_ARGV 95 static char ps_buffer[256]; 96 static const size_t ps_buffer_size = sizeof(ps_buffer); 97 #else 98 static char *ps_buffer; /* will point to argv area */ 99 static size_t ps_buffer_size; /* space determined at run time */ 100 #endif 101 102 /* save the original argv[] location here */ 103 static int save_argc; 104 static char **save_argv; 105 106 extern char *__progname; 107 108 #ifndef HAVE_SETPROCTITLE 109 /* 110 * Call this to update the ps status display to a fixed prefix plus an 111 * indication of what you're currently doing passed in the argument. 112 */ 113 void 114 setproctitle(const char *fmt, ...) 115 { 116 #if SETPROCTITLE_STRATEGY == PS_USE_PSTAT 117 union pstun pst; 118 #endif 119 #if SETPROCTITLE_STRATEGY != PS_USE_NONE 120 ssize_t used; 121 va_list ap; 122 123 /* no ps display if you didn't call save_ps_display_args() */ 124 if (save_argv == NULL) 125 return; 126 #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV 127 /* If ps_buffer is a pointer, it might still be null */ 128 if (ps_buffer == NULL) 129 return; 130 #endif /* PS_USE_CLOBBER_ARGV */ 131 132 /* 133 * Overwrite argv[] to point at appropriate space, if needed 134 */ 135 #if SETPROCTITLE_STRATEGY == PS_USE_CHANGE_ARGV 136 save_argv[0] = ps_buffer; 137 save_argv[1] = NULL; 138 #endif /* PS_USE_CHANGE_ARGV */ 139 140 #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV 141 save_argv[1] = NULL; 142 #endif /* PS_USE_CLOBBER_ARGV */ 143 144 /* 145 * Make fixed prefix of ps display. 146 */ 147 148 va_start(ap, fmt); 149 if (fmt == NULL) 150 snprintf(ps_buffer, ps_buffer_size, "%s", __progname); 151 else { 152 used = snprintf(ps_buffer, ps_buffer_size, "%s: ", __progname); 153 if (used == -1 || used >= ps_buffer_size) 154 used = ps_buffer_size; 155 vsnprintf(ps_buffer + used, ps_buffer_size - used, fmt, ap); 156 } 157 va_end(ap); 158 159 #if SETPROCTITLE_STRATEGY == PS_USE_PSTAT 160 pst.pst_command = ps_buffer; 161 pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0); 162 #endif /* PS_USE_PSTAT */ 163 164 #if SETPROCTITLE_STRATEGY == PS_USE_PS_STRINGS 165 PS_STRINGS->ps_nargvstr = 1; 166 PS_STRINGS->ps_argvstr = ps_buffer; 167 #endif /* PS_USE_PS_STRINGS */ 168 169 #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV 170 /* pad unused memory */ 171 used = strlen(ps_buffer); 172 memset(ps_buffer + used, SETPROCTITLE_PS_PADDING, 173 ps_buffer_size - used); 174 #endif /* PS_USE_CLOBBER_ARGV */ 175 176 #endif /* PS_USE_NONE */ 177 } 178 179 #endif /* HAVE_SETPROCTITLE */ 180 181 /* 182 * Call this early in startup to save the original argc/argv values. 183 * 184 * argv[] will not be overwritten by this routine, but may be overwritten 185 * during setproctitle. Also, the physical location of the environment 186 * strings may be moved, so this should be called before any code that 187 * might try to hang onto a getenv() result. 188 */ 189 void 190 compat_init_setproctitle(int argc, char *argv[]) 191 { 192 #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV 193 char *end_of_area = NULL; 194 char **new_environ; 195 int i; 196 #endif 197 198 save_argc = argc; 199 save_argv = argv; 200 201 #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV 202 /* 203 * If we're going to overwrite the argv area, count the available 204 * space. Also move the environment to make additional room. 205 */ 206 207 /* 208 * check for contiguous argv strings 209 */ 210 for (i = 0; i < argc; i++) { 211 if (i == 0 || end_of_area + 1 == argv[i]) 212 end_of_area = argv[i] + strlen(argv[i]); 213 } 214 215 /* probably can't happen? */ 216 if (end_of_area == NULL) { 217 ps_buffer = NULL; 218 ps_buffer_size = 0; 219 return; 220 } 221 222 /* 223 * check for contiguous environ strings following argv 224 */ 225 for (i = 0; environ[i] != NULL; i++) { 226 if (end_of_area + 1 == environ[i]) 227 end_of_area = environ[i] + strlen(environ[i]); 228 } 229 230 ps_buffer = argv[0]; 231 ps_buffer_size = end_of_area - argv[0] - 1; 232 233 /* 234 * Duplicate and move the environment out of the way 235 */ 236 new_environ = malloc(sizeof(char *) * (i + 1)); 237 for (i = 0; environ[i] != NULL; i++) 238 new_environ[i] = strdup(environ[i]); 239 new_environ[i] = NULL; 240 environ = new_environ; 241 #endif /* PS_USE_CLOBBER_ARGV */ 242 } 243 244