]>
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 | ||
54 | extern char **environ; | |
f5af5cd5 | 55 | |
d0104542 | 56 | /*------ |
57 | * Alternative ways of updating ps display: | |
58 | * | |
59 | * PS_USE_PSTAT | |
60 | * use the pstat(PSTAT_SETCMD, ) | |
61 | * (HPUX) | |
62 | * PS_USE_PS_STRINGS | |
63 | * assign PS_STRINGS->ps_argvstr = "string" | |
64 | * (some BSD systems) | |
65 | * PS_USE_CHANGE_ARGV | |
66 | * assign argv[0] = "string" | |
67 | * (some other BSD systems) | |
68 | * PS_USE_CLOBBER_ARGV | |
69 | * write over the argv and environment area | |
70 | * (most SysV-like systems) | |
71 | * PS_USE_NONE | |
72 | * don't update ps display | |
73 | * (This is the default, as it is safest.) | |
74 | */ | |
75 | #if defined(HAVE_PSTAT) && defined(PSTAT_SETCMD) | |
76 | #define PS_USE_PSTAT | |
77 | #elif defined(HAVE_PS_STRINGS) | |
78 | #define PS_USE_PS_STRINGS | |
79 | #elif defined(BSD) || defined(__bsdi__) || defined(__hurd__) | |
80 | #define PS_USE_CHANGE_ARGV | |
81 | #elif defined(__linux__) || defined(_AIX) | |
82 | #define PS_USE_CLOBBER_ARGV | |
83 | #else | |
84 | #define PS_USE_NONE | |
f5af5cd5 | 85 | #endif |
86 | ||
d0104542 | 87 | /* Different systems want the buffer padded differently */ |
88 | #if defined(_AIX) || defined(__linux__) || defined(__QNX__) || defined(__svr4__) | |
89 | #define PS_PADDING '\0' | |
90 | #else | |
91 | #define PS_PADDING ' ' | |
92 | #endif | |
f5af5cd5 | 93 | |
d0104542 | 94 | /* |
95 | * argv clobbering uses existing argv space, all other methods need a buffer | |
96 | */ | |
97 | #ifndef PS_USE_CLOBBER_ARGV | |
98 | static char ps_buffer[256]; | |
99 | static const size_t ps_buffer_size = sizeof(ps_buffer); | |
100 | #else /* PS_USE_CLOBBER_ARGV */ | |
101 | static char *ps_buffer; /* will point to argv area */ | |
102 | static size_t ps_buffer_size; /* space determined at run time */ | |
103 | #endif /* PS_USE_CLOBBER_ARGV */ | |
104 | ||
105 | /* save the original argv[] location here */ | |
106 | static int save_argc; | |
107 | static char **save_argv; | |
f5af5cd5 | 108 | |
f5af5cd5 | 109 | extern char *__progname; |
f5af5cd5 | 110 | |
111 | /* | |
d0104542 | 112 | * Call this to update the ps status display to a fixed prefix plus an |
113 | * indication of what you're currently doing passed in the argument. | |
f5af5cd5 | 114 | */ |
f5af5cd5 | 115 | void |
116 | setproctitle(const char *fmt, ...) | |
117 | { | |
d0104542 | 118 | #ifdef PS_USE_PSTAT |
119 | union pstun pst; | |
120 | #endif | |
121 | #ifndef PS_USE_NONE | |
122 | ssize_t used; | |
f5af5cd5 | 123 | va_list ap; |
f5af5cd5 | 124 | |
d0104542 | 125 | /* no ps display if you didn't call save_ps_display_args() */ |
126 | if (save_argv == NULL) | |
127 | return; | |
128 | #ifdef PS_USE_CLOBBER_ARGV | |
129 | /* If ps_buffer is a pointer, it might still be null */ | |
130 | if (ps_buffer == NULL) | |
131 | return; | |
132 | #endif /* PS_USE_CLOBBER_ARGV */ | |
133 | ||
134 | /* | |
135 | * Overwrite argv[] to point at appropriate space, if needed | |
136 | */ | |
137 | #ifdef PS_USE_CHANGE_ARGV | |
138 | save_argv[0] = ps_buffer; | |
139 | save_argv[1] = NULL; | |
140 | #endif /* PS_USE_CHANGE_ARGV */ | |
141 | ||
142 | #ifdef PS_USE_CLOBBER_ARGV | |
143 | save_argv[1] = NULL; | |
144 | #endif /* PS_USE_CLOBBER_ARGV */ | |
145 | ||
146 | /* | |
147 | * Make fixed prefix of ps display. | |
148 | */ | |
f5af5cd5 | 149 | |
150 | va_start(ap, fmt); | |
d0104542 | 151 | if (fmt == NULL) |
152 | snprintf(ps_buffer, ps_buffer_size, "%s", __progname); | |
153 | else { | |
154 | used = snprintf(ps_buffer, ps_buffer_size, "%s: ", __progname); | |
155 | if (used == -1 || used >= ps_buffer_size) | |
156 | used = ps_buffer_size; | |
157 | vsnprintf(ps_buffer + used, ps_buffer_size - used, fmt, ap); | |
158 | } | |
f5af5cd5 | 159 | va_end(ap); |
f5af5cd5 | 160 | |
d0104542 | 161 | #if 0 |
162 | error("XXXXXXXXX %s", __progname); | |
163 | error("XXXXXXXXX %d", ps_buffer_size); | |
164 | error("XXXXXXXXX %s", ps_buffer); | |
165 | #endif | |
166 | ||
167 | #ifdef PS_USE_PSTAT | |
168 | pst.pst_command = ps_buffer; | |
169 | pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0); | |
170 | #endif /* PS_USE_PSTAT */ | |
171 | ||
172 | #ifdef PS_USE_PS_STRINGS | |
173 | PS_STRINGS->ps_nargvstr = 1; | |
174 | PS_STRINGS->ps_argvstr = ps_buffer; | |
175 | #endif /* PS_USE_PS_STRINGS */ | |
f5af5cd5 | 176 | |
d0104542 | 177 | #ifdef PS_USE_CLOBBER_ARGV |
178 | /* pad unused memory */ | |
179 | used = strlen(ps_buffer); | |
180 | memset(ps_buffer + used, PS_PADDING, ps_buffer_size - used); | |
181 | #endif /* PS_USE_CLOBBER_ARGV */ | |
182 | ||
183 | #endif /* PS_USE_NONE */ | |
f5af5cd5 | 184 | } |
d0104542 | 185 | |
f5af5cd5 | 186 | #endif /* HAVE_SETPROCTITLE */ |
d0104542 | 187 | |
188 | /* | |
189 | * Call this early in startup to save the original argc/argv values. | |
190 | * | |
191 | * argv[] will not be overwritten by this routine, but may be overwritten | |
192 | * during setproctitle. Also, the physical location of the environment | |
193 | * strings may be moved, so this should be called before any code that | |
194 | * might try to hang onto a getenv() result. | |
195 | */ | |
196 | void | |
197 | compat_init_setproctitle(int argc, char *argv[]) | |
198 | { | |
199 | #ifdef PS_USE_CLOBBER_ARGV | |
200 | char *end_of_area = NULL; | |
201 | char **new_environ; | |
202 | int i; | |
203 | #endif | |
204 | ||
205 | save_argc = argc; | |
206 | save_argv = argv; | |
207 | ||
208 | #ifdef PS_USE_CLOBBER_ARGV | |
209 | /* | |
210 | * If we're going to overwrite the argv area, count the available | |
211 | * space. Also move the environment to make additional room. | |
212 | */ | |
213 | ||
214 | /* | |
215 | * check for contiguous argv strings | |
216 | */ | |
217 | for (i = 0; i < argc; i++) { | |
218 | if (i == 0 || end_of_area + 1 == argv[i]) | |
219 | end_of_area = argv[i] + strlen(argv[i]); | |
220 | } | |
221 | ||
222 | /* probably can't happen? */ | |
223 | if (end_of_area == NULL) { | |
224 | ps_buffer = NULL; | |
225 | ps_buffer_size = 0; | |
226 | return; | |
227 | } | |
228 | ||
229 | /* | |
230 | * check for contiguous environ strings following argv | |
231 | */ | |
232 | for (i = 0; environ[i] != NULL; i++) { | |
233 | if (end_of_area + 1 == environ[i]) | |
234 | end_of_area = environ[i] + strlen(environ[i]); | |
235 | } | |
236 | ||
237 | ps_buffer = argv[0]; | |
238 | ps_buffer_size = end_of_area - argv[0] - 1; | |
239 | ||
240 | /* | |
241 | * Duplicate and move the environment out of the way | |
242 | */ | |
243 | new_environ = malloc(sizeof(char *) * (i + 1)); | |
244 | for (i = 0; environ[i] != NULL; i++) | |
245 | new_environ[i] = strdup(environ[i]); | |
246 | new_environ[i] = NULL; | |
247 | environ = new_environ; | |
248 | #endif /* PS_USE_CLOBBER_ARGV */ | |
249 | } | |
250 |