]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - ps_status.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / ps_status.c
1 /* -*-pgsql-c-*- */
2 /*
3  *
4  * $Header: /cvsroot/pgpool/pgpool-II/ps_status.c,v 1.3.2.1 2009/08/22 04:19:49 t-ishii Exp $
5  *
6  * This file was imported from PostgreSQL source code.
7  * See below for the copyright and description.
8  *
9  * pgpool: a language independent connection pool server for PostgreSQL
10  * written by Tatsuo Ishii
11  *
12  * Portions Copyright (c) 2003-2009     PgPool Global Development Group
13  *
14  */
15 /*--------------------------------------------------------------------
16  * ps_status.c
17  *
18  * Routines to support changing the ps display of PostgreSQL backends
19  * to contain some useful information. Mechanism differs wildly across
20  * platforms.
21  *
22  * $PostgreSQL: pgsql/src/backend/utils/misc/ps_status.c,v 1.33 2006/10/04 00:30:04 momjian Exp $
23  *
24  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
25  * various details abducted from various places
26  *--------------------------------------------------------------------
27  */
28
29 #include <unistd.h>
30 #ifdef HAVE_SYS_PSTAT_H
31 #include <sys/pstat.h>                  /* for HP-UX */
32 #endif
33 #ifdef HAVE_PS_STRINGS
34 #include <machine/vmparam.h>    /* for old BSD */
35 #include <sys/exec.h>
36 #endif
37 #if defined(__darwin__)
38 #include <crt_externs.h>
39 #endif
40
41 #include "pool.h"
42 #include <stdlib.h>
43 #include <string.h>
44
45 extern char **environ;
46 bool            update_process_title = true;
47
48
49 /*
50  * Alternative ways of updating ps display:
51  *
52  * PS_USE_SETPROCTITLE
53  *         use the function setproctitle(const char *, ...)
54  *         (newer BSD systems)
55  * PS_USE_PSTAT
56  *         use the pstat(PSTAT_SETCMD, )
57  *         (HPUX)
58  * PS_USE_PS_STRINGS
59  *         assign PS_STRINGS->ps_argvstr = "string"
60  *         (some BSD systems)
61  * PS_USE_CHANGE_ARGV
62  *         assign argv[0] = "string"
63  *         (some other BSD systems)
64  * PS_USE_CLOBBER_ARGV
65  *         write over the argv and environment area
66  *         (most SysV-like systems)
67  * PS_USE_WIN32
68  *         push the string out as the name of a Windows event
69  * PS_USE_NONE
70  *         don't update ps display
71  *         (This is the default, as it is safest.)
72  */
73 #if defined(HAVE_SETPROCTITLE)
74 #define PS_USE_SETPROCTITLE
75 #elif 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__)) && !defined(__darwin__)
80 #define PS_USE_CHANGE_ARGV
81 #elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__ksr__) || defined(__osf__) || defined(__svr4__) || defined(__svr5__) || defined(__darwin__)
82 #define PS_USE_CLOBBER_ARGV
83 #elif defined(WIN32)
84 #define PS_USE_WIN32
85 #else
86 #define PS_USE_NONE
87 #endif
88
89
90 /* Different systems want the buffer padded differently */
91 #if defined(_AIX) || defined(__linux__) || defined(__svr4__)
92 #define PS_PADDING '\0'
93 #else
94 #define PS_PADDING ' '
95 #endif
96
97
98 #ifndef PS_USE_CLOBBER_ARGV
99 /* all but one options need a buffer to write their ps line in */
100 #define PS_BUFFER_SIZE 256
101 static char ps_buffer[PS_BUFFER_SIZE];
102 static const size_t ps_buffer_size = PS_BUFFER_SIZE;
103 #else                                                   /* PS_USE_CLOBBER_ARGV */
104 static char *ps_buffer;                 /* will point to argv area */
105 static size_t ps_buffer_size;   /* space determined at run time */
106 #endif   /* PS_USE_CLOBBER_ARGV */
107
108 static size_t ps_buffer_fixed_size;             /* size of the constant prefix */
109
110 /* save the original argv[] location here */
111 static int      save_argc;
112 static char **save_argv;
113
114
115 /*
116  * Call this early in startup to save the original argc/argv values.
117  * If needed, we make a copy of the original argv[] array to preserve it
118  * from being clobbered by subsequent ps_display actions.
119  *
120  * (The original argv[] will not be overwritten by this routine, but may be
121  * overwritten during init_ps_display.  Also, the physical location of the
122  * environment strings may be moved, so this should be called before any code
123  * that might try to hang onto a getenv() result.)
124  */
125 char      **
126 save_ps_display_args(int argc, char **argv)
127 {
128         save_argc = argc;
129         save_argv = argv;
130
131 #if defined(PS_USE_CLOBBER_ARGV)
132
133         /*
134          * If we're going to overwrite the argv area, count the available space.
135          * Also move the environment to make additional room.
136          */
137         {
138                 char       *end_of_area = NULL;
139                 char      **new_environ;
140                 int                     i;
141
142                 /*
143                  * check for contiguous argv strings
144                  */
145                 for (i = 0; i < argc; i++)
146                 {
147                         if (i == 0 || end_of_area + 1 == argv[i])
148                                 end_of_area = argv[i] + strlen(argv[i]);
149                 }
150
151                 if (end_of_area == NULL)        /* probably can't happen? */
152                 {
153                         ps_buffer = NULL;
154                         ps_buffer_size = 0;
155                         return argv;
156                 }
157
158                 /*
159                  * check for contiguous environ strings following argv
160                  */
161                 for (i = 0; environ[i] != NULL; i++)
162                 {
163                         if (end_of_area + 1 == environ[i])
164                                 end_of_area = environ[i] + strlen(environ[i]);
165                 }
166
167                 ps_buffer = argv[0];
168                 ps_buffer_size = end_of_area - argv[0];
169
170                 /*
171                  * move the environment out of the way
172                  */
173                 new_environ = (char **) malloc((i + 1) * sizeof(char *));
174                 for (i = 0; environ[i] != NULL; i++)
175                         new_environ[i] = strdup(environ[i]);
176                 new_environ[i] = NULL;
177                 environ = new_environ;
178         }
179 #endif   /* PS_USE_CLOBBER_ARGV */
180
181 #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
182
183         /*
184          * If we're going to change the original argv[] then make a copy for
185          * argument parsing purposes.
186          *
187          * (NB: do NOT think to remove the copying of argv[], even though
188          * postmaster.c finishes looking at argv[] long before we ever consider
189          * changing the ps display.  On some platforms, getopt() keeps pointers
190          * into the argv array, and will get horribly confused when it is
191          * re-called to analyze a subprocess' argument string if the argv storage
192          * has been clobbered meanwhile.  Other platforms have other dependencies
193          * on argv[].
194          */
195         {
196                 char      **new_argv;
197                 int                     i;
198
199                 new_argv = (char **) malloc((argc + 1) * sizeof(char *));
200                 for (i = 0; i < argc; i++)
201                         new_argv[i] = strdup(argv[i]);
202                 new_argv[argc] = NULL;
203
204 #if defined(__darwin__)
205
206                 /*
207                  * Darwin (and perhaps other NeXT-derived platforms?) has a static
208                  * copy of the argv pointer, which we may fix like so:
209                  */
210                 *_NSGetArgv() = new_argv;
211 #endif
212
213                 argv = new_argv;
214         }
215 #endif   /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
216
217         return argv;
218 }
219
220 /*
221  * Call this once during subprocess startup to set the identification
222  * values.      At this point, the original argv[] array may be overwritten.
223  */
224 void
225 init_ps_display(const char *username, const char *dbname,
226                                 const char *host_info, const char *initial_str)
227 {
228 #ifndef PS_USE_NONE
229         /* no ps display if you didn't call save_ps_display_args() */
230         if (!save_argv)
231                 return;
232 #ifdef PS_USE_CLOBBER_ARGV
233         /* If ps_buffer is a pointer, it might still be null */
234         if (!ps_buffer)
235                 return;
236 #endif
237
238         /*
239          * Overwrite argv[] to point at appropriate space, if needed
240          */
241
242 #ifdef PS_USE_CHANGE_ARGV
243         save_argv[0] = ps_buffer;
244         save_argv[1] = NULL;
245 #endif   /* PS_USE_CHANGE_ARGV */
246
247 #ifdef PS_USE_CLOBBER_ARGV
248         {
249                 int                     i;
250
251                 /* make extra argv slots point at end_of_area (a NUL) */
252                 for (i = 1; i < save_argc; i++)
253                         save_argv[i] = ps_buffer + ps_buffer_size;
254         }
255 #endif   /* PS_USE_CLOBBER_ARGV */
256
257         /*
258          * Make fixed prefix of ps display.
259          */
260
261 #ifdef PS_USE_SETPROCTITLE
262
263         /*
264          * apparently setproctitle() already adds a `progname: ' prefix to the
265          * ps line
266          */
267         snprintf(ps_buffer, ps_buffer_size, "");
268 #else
269         snprintf(ps_buffer, ps_buffer_size,
270                          "pgpool: ");
271 #endif
272
273         ps_buffer_fixed_size = strlen(ps_buffer);
274
275         set_ps_display(initial_str, true);
276 #endif   /* not PS_USE_NONE */
277 }
278
279
280
281 /*
282  * Call this to update the ps status display to a fixed prefix plus an
283  * indication of what you're currently doing passed in the argument.
284  */
285 void
286 set_ps_display(const char *activity, bool force)
287 {
288
289         if (!force && !update_process_title)
290                 return;
291
292 #ifndef PS_USE_NONE
293
294 #ifdef PS_USE_CLOBBER_ARGV
295         /* If ps_buffer is a pointer, it might still be null */
296         if (!ps_buffer)
297                 return;
298 #endif
299
300         /* Update ps_buffer to contain both fixed part and activity */
301         strlcpy(ps_buffer + ps_buffer_fixed_size, activity,
302                         ps_buffer_size - ps_buffer_fixed_size);
303
304         /* Transmit new setting to kernel, if necessary */
305
306 #ifdef PS_USE_SETPROCTITLE
307         setproctitle("%s", ps_buffer);
308 #endif
309
310 #ifdef PS_USE_PSTAT
311         {
312                 union pstun pst;
313
314                 pst.pst_command = ps_buffer;
315                 pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0);
316         }
317 #endif   /* PS_USE_PSTAT */
318
319 #ifdef PS_USE_PS_STRINGS
320         PS_STRINGS->ps_nargvstr = 1;
321         PS_STRINGS->ps_argvstr = ps_buffer;
322 #endif   /* PS_USE_PS_STRINGS */
323
324 #ifdef PS_USE_CLOBBER_ARGV
325         {
326                 int                     buflen;
327
328                 /* pad unused memory */
329                 buflen = strlen(ps_buffer);
330                 memset(ps_buffer + buflen, PS_PADDING, ps_buffer_size - buflen);
331         }
332 #endif   /* PS_USE_CLOBBER_ARGV */
333
334 #ifdef PS_USE_WIN32
335         {
336                 /*
337                  * Win32 does not support showing any changed arguments. To make it at
338                  * all possible to track which backend is doing what, we create a
339                  * named object that can be viewed with for example Process Explorer.
340                  */
341                 static HANDLE ident_handle = INVALID_HANDLE_VALUE;
342                 char            name[PS_BUFFER_SIZE + 32];
343
344                 if (ident_handle != INVALID_HANDLE_VALUE)
345                         CloseHandle(ident_handle);
346
347                 sprintf(name, "pgident: %s", ps_buffer);
348
349                 ident_handle = CreateEvent(NULL, TRUE, FALSE, name);
350         }
351 #endif   /* PS_USE_WIN32 */
352 #endif   /* not PS_USE_NONE */
353 }
354
355
356 /*
357  * Returns what's currently in the ps display, in case someone needs
358  * it.  Note that only the activity part is returned.  On some platforms
359  * the string will not be null-terminated, so return the effective
360  * length into *displen.
361  */
362 const char *
363 get_ps_display(int *displen)
364 {
365 #ifdef PS_USE_CLOBBER_ARGV
366         size_t          offset;
367
368         /* If ps_buffer is a pointer, it might still be null */
369         if (!ps_buffer)
370         {
371                 *displen = 0;
372                 return "";
373         }
374
375         /* Remove any trailing spaces to offset the effect of PS_PADDING */
376         offset = ps_buffer_size;
377         while (offset > ps_buffer_fixed_size && ps_buffer[offset - 1] == PS_PADDING)
378                 offset--;
379
380         *displen = offset - ps_buffer_fixed_size;
381 #else
382         *displen = strlen(ps_buffer + ps_buffer_fixed_size);
383 #endif
384
385         return ps_buffer + ps_buffer_fixed_size;
386 }