]>
Commit | Line | Data |
---|---|---|
f5af5cd5 | 1 | /* |
d0104542 | 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. | |
f5af5cd5 | 25 | */ |
26 | ||
d0104542 | 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. | |
f5af5cd5 | 33 | * |
d0104542 | 34 | * $Header$ |
f5af5cd5 | 35 | * |
d0104542 | 36 | * Copyright 2000 by PostgreSQL Global Development Group |
37 | * various details abducted from various places | |
38 | *-------------------------------------------------------------------- | |
f5af5cd5 | 39 | */ |
40 | ||
f5af5cd5 | 41 | #include "includes.h" |
42 | ||
260d427b | 43 | #ifndef HAVE_SETPROCTITLE |
44 | ||
d0104542 | 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 | ||
d0104542 | 54 | /*------ |
55 | * Alternative ways of updating ps display: | |
56 | * | |
e80fb2a0 | 57 | * SETPROCTITLE_STRATEGY == PS_USE_PSTAT |
d0104542 | 58 | * use the pstat(PSTAT_SETCMD, ) |
59 | * (HPUX) | |
e80fb2a0 | 60 | * SETPROCTITLE_STRATEGY == PS_USE_PS_STRINGS |
d0104542 | 61 | * assign PS_STRINGS->ps_argvstr = "string" |
62 | * (some BSD systems) | |
e80fb2a0 | 63 | * SETPROCTITLE_STRATEGY == PS_USE_CHANGE_ARGV |
d0104542 | 64 | * assign argv[0] = "string" |
65 | * (some other BSD systems) | |
e80fb2a0 | 66 | * SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV |
d0104542 | 67 | * write over the argv and environment area |
68 | * (most SysV-like systems) | |
e80fb2a0 | 69 | * SETPROCTITLE_STRATEGY == PS_USE_NONE |
d0104542 | 70 | * don't update ps display |
71 | * (This is the default, as it is safest.) | |
72 | */ | |
e80fb2a0 | 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 | |
f5af5cd5 | 82 | #endif |
83 | ||
e80fb2a0 | 84 | #ifndef SETPROCTITLE_PS_PADDING |
85 | # define SETPROCTITLE_PS_PADDING ' ' | |
d0104542 | 86 | #endif |
877c5ea2 | 87 | #endif /* HAVE_SETPROCTITLE */ |
88 | ||
89 | extern char **environ; | |
f5af5cd5 | 90 | |
d0104542 | 91 | /* |
92 | * argv clobbering uses existing argv space, all other methods need a buffer | |
93 | */ | |
e80fb2a0 | 94 | #if SETPROCTITLE_STRATEGY != PS_USE_CLOBBER_ARGV |
d0104542 | 95 | static char ps_buffer[256]; |
96 | static const size_t ps_buffer_size = sizeof(ps_buffer); | |
e80fb2a0 | 97 | #else |
d0104542 | 98 | static char *ps_buffer; /* will point to argv area */ |
99 | static size_t ps_buffer_size; /* space determined at run time */ | |
e80fb2a0 | 100 | #endif |
d0104542 | 101 | |
102 | /* save the original argv[] location here */ | |
103 | static int save_argc; | |
104 | static char **save_argv; | |
f5af5cd5 | 105 | |
f5af5cd5 | 106 | extern char *__progname; |
f5af5cd5 | 107 | |
877c5ea2 | 108 | #ifndef HAVE_SETPROCTITLE |
f5af5cd5 | 109 | /* |
d0104542 | 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. | |
f5af5cd5 | 112 | */ |
f5af5cd5 | 113 | void |
114 | setproctitle(const char *fmt, ...) | |
115 | { | |
e80fb2a0 | 116 | #if SETPROCTITLE_STRATEGY == PS_USE_PSTAT |
d0104542 | 117 | union pstun pst; |
118 | #endif | |
e80fb2a0 | 119 | #if SETPROCTITLE_STRATEGY != PS_USE_NONE |
d0104542 | 120 | ssize_t used; |
f5af5cd5 | 121 | va_list ap; |
f5af5cd5 | 122 | |
d0104542 | 123 | /* no ps display if you didn't call save_ps_display_args() */ |
124 | if (save_argv == NULL) | |
125 | return; | |
e80fb2a0 | 126 | #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV |
d0104542 | 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 | */ | |
e80fb2a0 | 135 | #if SETPROCTITLE_STRATEGY == PS_USE_CHANGE_ARGV |
d0104542 | 136 | save_argv[0] = ps_buffer; |
137 | save_argv[1] = NULL; | |
138 | #endif /* PS_USE_CHANGE_ARGV */ | |
139 | ||
e80fb2a0 | 140 | #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV |
d0104542 | 141 | save_argv[1] = NULL; |
142 | #endif /* PS_USE_CLOBBER_ARGV */ | |
143 | ||
144 | /* | |
145 | * Make fixed prefix of ps display. | |
146 | */ | |
f5af5cd5 | 147 | |
148 | va_start(ap, fmt); | |
d0104542 | 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 | } | |
f5af5cd5 | 157 | va_end(ap); |
f5af5cd5 | 158 | |
e80fb2a0 | 159 | #if SETPROCTITLE_STRATEGY == PS_USE_PSTAT |
d0104542 | 160 | pst.pst_command = ps_buffer; |
161 | pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0); | |
162 | #endif /* PS_USE_PSTAT */ | |
163 | ||
e80fb2a0 | 164 | #if SETPROCTITLE_STRATEGY == PS_USE_PS_STRINGS |
d0104542 | 165 | PS_STRINGS->ps_nargvstr = 1; |
166 | PS_STRINGS->ps_argvstr = ps_buffer; | |
167 | #endif /* PS_USE_PS_STRINGS */ | |
f5af5cd5 | 168 | |
e80fb2a0 | 169 | #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV |
d0104542 | 170 | /* pad unused memory */ |
171 | used = strlen(ps_buffer); | |
e80fb2a0 | 172 | memset(ps_buffer + used, SETPROCTITLE_PS_PADDING, |
173 | ps_buffer_size - used); | |
d0104542 | 174 | #endif /* PS_USE_CLOBBER_ARGV */ |
175 | ||
176 | #endif /* PS_USE_NONE */ | |
f5af5cd5 | 177 | } |
d0104542 | 178 | |
f5af5cd5 | 179 | #endif /* HAVE_SETPROCTITLE */ |
d0104542 | 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 | { | |
e80fb2a0 | 192 | #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV |
d0104542 | 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 | ||
e80fb2a0 | 201 | #if SETPROCTITLE_STRATEGY == PS_USE_CLOBBER_ARGV |
d0104542 | 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 |