]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/ps_status.c
Another pgindent run. Fixes enum indenting, and improves #endif
[postgresql] / src / backend / utils / misc / ps_status.c
1 /*--------------------------------------------------------------------
2  * ps_status.c
3  *
4  * Routines to support changing the ps display of PostgreSQL backends
5  * to contain some useful information. Mechanism differs wildly across
6  * platforms.
7  *
8  * $Header: /cvsroot/pgsql/src/backend/utils/misc/ps_status.c,v 1.9 2001/10/28 06:25:57 momjian Exp $
9  *
10  * Copyright 2000 by PostgreSQL Global Development Group
11  * various details abducted from various places
12  *--------------------------------------------------------------------
13  */
14
15 #include "postgres.h"
16
17 #include <unistd.h>
18 #ifdef HAVE_SYS_PSTAT_H
19 #include <sys/pstat.h>                  /* for HP-UX */
20 #endif
21 #ifdef HAVE_PS_STRINGS
22 #include <machine/vmparam.h>    /* for old BSD */
23 #include <sys/exec.h>
24 #endif
25
26 #include "miscadmin.h"
27 #include "utils/ps_status.h"
28
29 extern char **environ;
30
31
32 /*------
33  * Alternative ways of updating ps display:
34  *
35  * PS_USE_SETPROCTITLE
36  *         use the function setproctitle(const char *, ...)
37  *         (newer BSD systems)
38  * PS_USE_PSTAT
39  *         use the pstat(PSTAT_SETCMD, )
40  *         (HPUX)
41  * PS_USE_PS_STRINGS
42  *         assign PS_STRINGS->ps_argvstr = "string"
43  *         (some BSD systems)
44  * PS_USE_CHANGE_ARGV
45  *         assign argv[0] = "string"
46  *         (some other BSD systems)
47  * PS_USE_CLOBBER_ARGV
48  *         write over the argv and environment area
49  *         (most SysV-like systems)
50  * PS_USE_NONE
51  *         don't update ps display
52  *         (This is the default, as it is safest.)
53  */
54 #if defined(HAVE_SETPROCTITLE)
55 #define PS_USE_SETPROCTITLE
56 #elif defined(HAVE_PSTAT) && defined(PSTAT_SETCMD)
57 #define PS_USE_PSTAT
58 #elif defined(HAVE_PS_STRINGS)
59 #define PS_USE_PS_STRINGS
60 #elif defined(BSD) || defined(__bsdi__) || defined(__hurd__)
61 #define PS_USE_CHANGE_ARGV
62 #elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__ksr__) || defined(__osf__) || defined(__QNX__) || defined(__svr4__) || defined(__svr5__)
63 #define PS_USE_CLOBBER_ARGV
64 #else
65 #define PS_USE_NONE
66 #endif
67
68
69 /* Different systems want the buffer padded differently */
70 #if defined(_AIX) || defined(__linux__) || defined(__QNX__) || defined(__svr4__)
71 #define PS_PADDING '\0'
72 #else
73 #define PS_PADDING ' '
74 #endif
75
76
77 #ifndef PS_USE_CLOBBER_ARGV
78 /* all but one options need a buffer to write their ps line in */
79 #define PS_BUFFER_SIZE 256
80 static char ps_buffer[PS_BUFFER_SIZE];
81 static const size_t ps_buffer_size = PS_BUFFER_SIZE;
82
83 #else                                                   /* PS_USE_CLOBBER_ARGV */
84 static char *ps_buffer;                 /* will point to argv area */
85 static size_t ps_buffer_size;   /* space determined at run time */
86 #endif   /* PS_USE_CLOBBER_ARGV */
87
88 static size_t ps_buffer_fixed_size;             /* size of the constant prefix */
89
90 /* save the original argv[] location here */
91 static int      save_argc;
92 static char **save_argv;
93
94
95 /*
96  * Call this early in startup to save the original argc/argv values.
97  *
98  * argv[] will not be overwritten by this routine, but may be overwritten
99  * during init_ps_display.      Also, the physical location of the environment
100  * strings may be moved, so this should be called before any code that
101  * might try to hang onto a getenv() result.
102  */
103 void
104 save_ps_display_args(int argc, char *argv[])
105 {
106         save_argc = argc;
107         save_argv = argv;
108
109 #ifdef PS_USE_CLOBBER_ARGV
110
111         /*
112          * If we're going to overwrite the argv area, count the available
113          * space.  Also move the environment to make additional room.
114          */
115         {
116                 char       *end_of_area = NULL;
117                 char      **new_environ;
118                 int                     i;
119
120                 /*
121                  * check for contiguous argv strings
122                  */
123                 for (i = 0; i < argc; i++)
124                 {
125                         if (i == 0 || end_of_area + 1 == argv[i])
126                                 end_of_area = argv[i] + strlen(argv[i]);
127                 }
128
129                 if (end_of_area == NULL)        /* probably can't happen? */
130                 {
131                         ps_buffer = NULL;
132                         ps_buffer_size = 0;
133                         return;
134                 }
135
136                 /*
137                  * check for contiguous environ strings following argv
138                  */
139                 for (i = 0; environ[i] != NULL; i++)
140                 {
141                         if (end_of_area + 1 == environ[i])
142                                 end_of_area = environ[i] + strlen(environ[i]);
143                 }
144
145                 ps_buffer = argv[0];
146                 ps_buffer_size = end_of_area - argv[0] - 1;
147
148                 /*
149                  * move the environment out of the way
150                  */
151                 new_environ = malloc(sizeof(char *) * (i + 1));
152                 for (i = 0; environ[i] != NULL; i++)
153                         new_environ[i] = strdup(environ[i]);
154                 new_environ[i] = NULL;
155                 environ = new_environ;
156         }
157 #endif   /* PS_USE_CLOBBER_ARGV */
158 }
159
160 /*
161  * Call this once during subprocess startup to set the identification
162  * values.      At this point, the original argv[] array may be overwritten.
163  */
164 void
165 init_ps_display(const char *username, const char *dbname,
166                                 const char *host_info)
167 {
168         Assert(username);
169         Assert(dbname);
170         Assert(host_info);
171
172 #ifndef PS_USE_NONE
173         /* no ps display for stand-alone backend */
174         if (!IsUnderPostmaster)
175                 return;
176
177         /* no ps display if you didn't call save_ps_display_args() */
178         if (!save_argv)
179                 return;
180 #ifdef PS_USE_CLOBBER_ARGV
181         /* If ps_buffer is a pointer, it might still be null */
182         if (!ps_buffer)
183                 return;
184 #endif
185
186         /*
187          * Overwrite argv[] to point at appropriate space, if needed
188          */
189
190 #ifdef PS_USE_CHANGE_ARGV
191         save_argv[0] = ps_buffer;
192         save_argv[1] = NULL;
193 #endif   /* PS_USE_CHANGE_ARGV */
194
195 #ifdef PS_USE_CLOBBER_ARGV
196         save_argv[1] = NULL;
197 #endif   /* PS_USE_CLOBBER_ARGV */
198
199         /*
200          * Make fixed prefix of ps display.
201          */
202
203 #ifdef PS_USE_SETPROCTITLE
204
205         /*
206          * apparently setproctitle() already adds a `progname:' prefix to the
207          * ps line
208          */
209         snprintf(ps_buffer, ps_buffer_size,
210                          "%s %s %s ",
211                          username, dbname, host_info);
212 #else
213         snprintf(ps_buffer, ps_buffer_size,
214                          "postgres: %s %s %s ",
215                          username, dbname, host_info);
216 #endif
217
218         ps_buffer_fixed_size = strlen(ps_buffer);
219 #endif   /* not PS_USE_NONE */
220 }
221
222
223
224 /*
225  * Call this to update the ps status display to a fixed prefix plus an
226  * indication of what you're currently doing passed in the argument.
227  */
228 void
229 set_ps_display(const char *activity)
230 {
231 #ifndef PS_USE_NONE
232         /* no ps display for stand-alone backend */
233         if (!IsUnderPostmaster)
234                 return;
235
236 #ifdef PS_USE_CLOBBER_ARGV
237         /* If ps_buffer is a pointer, it might still be null */
238         if (!ps_buffer)
239                 return;
240 #endif
241
242         /* Update ps_buffer to contain both fixed part and activity */
243         StrNCpy(ps_buffer + ps_buffer_fixed_size, activity,
244                         ps_buffer_size - ps_buffer_fixed_size);
245
246         /* Transmit new setting to kernel, if necessary */
247
248 #ifdef PS_USE_SETPROCTITLE
249         setproctitle("%s", ps_buffer);
250 #endif
251
252 #ifdef PS_USE_PSTAT
253         {
254                 union pstun pst;
255
256                 pst.pst_command = ps_buffer;
257                 pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0);
258         }
259 #endif   /* PS_USE_PSTAT */
260
261 #ifdef PS_USE_PS_STRINGS
262         PS_STRINGS->ps_nargvstr = 1;
263         PS_STRINGS->ps_argvstr = ps_buffer;
264 #endif   /* PS_USE_PS_STRINGS */
265
266 #ifdef PS_USE_CLOBBER_ARGV
267         {
268                 char       *cp;
269
270                 /* pad unused memory */
271                 for (cp = ps_buffer + strlen(ps_buffer);
272                          cp < ps_buffer + ps_buffer_size;
273                          cp++)
274                         *cp = PS_PADDING;
275         }
276 #endif   /* PS_USE_CLOBBER_ARGV */
277 #endif   /* not PS_USE_NONE */
278 }
279
280
281 /*
282  * Returns what's currently in the ps display, in case someone needs
283  * it.  Note that only the activity part is returned.
284  */
285 const char *
286 get_ps_display(void)
287 {
288 #ifdef PS_USE_CLOBBER_ARGV
289         /* If ps_buffer is a pointer, it might still be null */
290         if (!ps_buffer)
291                 return "";
292 #endif
293
294         return ps_buffer + ps_buffer_fixed_size;
295 }