]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/ps_status.c
pgindent run. Make it all clean.
[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. Differs wildly across
6  * platforms.
7  *
8  * $Header: /cvsroot/pgsql/src/backend/utils/misc/ps_status.c,v 1.4 2001/03/22 04:00:06 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
19
20 #ifdef HAVE_SYS_PSTAT_H
21 #include <sys/pstat.h>                  /* for HP-UX */
22 #endif
23 #ifdef HAVE_PS_STRINGS
24 #include <machine/vmparam.h>    /* for old BSD */
25 #include <sys/exec.h>
26 #endif
27
28 #include "miscadmin.h"
29
30 #include "utils/ps_status.h"
31
32 extern char **environ;
33
34
35 /*------
36  * Alternative ways of updating ps display:
37  *
38  * PS_USE_SETPROCTITLE
39  *         use the function setproctitle(const char *, ...)
40  *         (newer BSD systems)
41  * PS_USE_PSTAT
42  *         use the pstat(PSTAT_SETCMD, )
43  *         (HPUX)
44  * PS_USE_PS_STRINGS
45  *         assign PS_STRINGS->ps_argvstr = "string"
46  *         (some BSD systems)
47  * PS_USE_CHANGE_ARGV
48  *         assign argv[0] = "string"
49  *         (some other BSD systems)
50  * PS_USE_CLOBBER_ARGV
51  *         write over the argv and environment area
52  *         (most SysV-like systems)
53  * PS_USE_NONE
54  *         don't update ps display
55  *         (This is the default, as it is safest.)
56  */
57 #if defined(HAVE_SETPROCTITLE)
58 #define PS_USE_SETPROCTITLE
59 #elif defined(HAVE_PSTAT) && defined(PSTAT_SETCMD)
60 #define PS_USE_PSTAT
61 #elif defined(HAVE_PS_STRINGS)
62 #define PS_USE_PS_STRINGS
63 #elif defined(BSD) || defined(__bsdi__) || defined(__hurd__)
64 #define PS_USE_CHANGE_ARGV
65 #elif defined(__linux__) || defined(_AIX4) || defined(_AIX3) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__ksr__) || defined(__osf__) || defined(__QNX__) || defined(__svr4__) || defined(__svr5__)
66 #define PS_USE_CLOBBER_ARGV
67 #else
68 #define PS_USE_NONE
69 #endif
70
71
72 /* Different systems want the buffer padded differently */
73 #if defined(_AIX3) || defined(__linux__) || defined(__QNX__) || defined(__svr4__)
74 #define PS_PADDING '\0'
75 #else
76 #define PS_PADDING ' '
77 #endif
78
79
80 #ifndef PS_USE_CLOBBER_ARGV
81 /* all but one options need a buffer to write their ps line in */
82 #define PS_BUFFER_SIZE 256
83 static char ps_buffer[PS_BUFFER_SIZE];
84 static const size_t ps_buffer_size = PS_BUFFER_SIZE;
85
86 #else                                                   /* PS_USE_CLOBBER_ARGV */
87 static char *ps_buffer;                 /* will point to argv area */
88 static size_t ps_buffer_size;   /* space determined at run time */
89
90 #endif   /* PS_USE_CLOBBER_ARGV */
91
92 static size_t ps_buffer_fixed_size;             /* size of the constant prefix */
93
94
95
96 /*
97  * Call this once at backend start.
98  */
99 void
100 init_ps_display(int argc, char *argv[],
101                                 const char *username, const char *dbname,
102                                 const char *host_info)
103 {
104 #ifndef PS_USE_NONE
105         Assert(username);
106         Assert(dbname);
107
108         /* no ps display for stand-alone backend */
109         if (!IsUnderPostmaster)
110                 return;
111
112 #ifdef PS_USE_CHANGE_ARGV
113         argv[0] = ps_buffer;
114         argv[1] = NULL;
115 #endif   /* PS_USE_CHANGE_ARGV */
116
117 #ifdef PS_USE_CLOBBER_ARGV
118
119         /*
120          * If we're going to overwrite the argv area, count the space.
121          */
122         {
123                 char       *end_of_area = NULL;
124                 char      **new_environ;
125                 int                     i;
126
127                 /*
128                  * check for contiguous argv strings
129                  */
130                 for (i = 0; i < argc; i++)
131                         if (i == 0 || end_of_area + 1 == argv[i])
132                                 end_of_area = argv[i] + strlen(argv[i]);
133
134                 /*
135                  * check for contiguous environ strings following argv
136                  */
137                 for (i = 0; end_of_area != NULL && environ[i] != NULL; i++)
138                         if (end_of_area + 1 == environ[i])
139                                 end_of_area = environ[i] + strlen(environ[i]);
140
141                 if (end_of_area == NULL)
142                 {
143                         ps_buffer = NULL;
144                         ps_buffer_size = 0;
145                 }
146                 else
147                 {
148                         ps_buffer = argv[0];
149                         ps_buffer_size = end_of_area - argv[0] - 1;
150                 }
151                 argv[1] = NULL;
152
153                 /*
154                  * move the environment out of the way
155                  */
156                 for (i = 0; environ[i] != NULL; i++)
157                         ;
158                 new_environ = malloc(sizeof(char *) * (i + 1));
159                 for (i = 0; environ[i] != NULL; i++)
160                         new_environ[i] = strdup(environ[i]);
161                 new_environ[i] = NULL;
162                 environ = new_environ;
163         }
164 #endif   /* PS_USE_CLOBBER_ARGV */
165
166         /*
167          * Make fixed prefix
168          */
169 #ifdef PS_USE_SETPROCTITLE
170
171         /*
172          * apparently setproctitle() already adds a `progname:' prefix to the
173          * ps line
174          */
175         snprintf(ps_buffer, ps_buffer_size,
176                          "%s %s %s ",
177                          username, dbname, host_info);
178 #else
179         snprintf(ps_buffer, ps_buffer_size,
180                          "postgres: %s %s %s ",
181                          username, dbname, host_info);
182 #endif
183
184         ps_buffer_fixed_size = strlen(ps_buffer);
185 #endif   /* not PS_USE_NONE */
186 }
187
188
189
190 /*
191  * Call this to update the ps status display to a fixed prefix plus an
192  * indication of what you're currently doing passed in the argument.
193  */
194 void
195 set_ps_display(const char *value)
196 {
197 #ifndef PS_USE_NONE
198         /* no ps display for stand-alone backend */
199         if (!IsUnderPostmaster)
200                 return;
201
202 #ifdef PS_USE_CLOBBER_ARGV
203         /* If ps_buffer is a pointer, it might still be null */
204         if (!ps_buffer)
205                 return;
206 #endif
207
208         /* Update ps_buffer to contain both fixed part and value */
209         StrNCpy(ps_buffer + ps_buffer_fixed_size, value,
210                         ps_buffer_size - ps_buffer_fixed_size);
211
212         /* Transmit new setting to kernel, if necessary */
213
214 #ifdef PS_USE_SETPROCTITLE
215         setproctitle("%s", ps_buffer);
216 #endif
217
218 #ifdef PS_USE_PSTAT
219         {
220                 union pstun pst;
221
222                 pst.pst_command = ps_buffer;
223                 pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0);
224         }
225 #endif   /* PS_USE_PSTAT */
226
227 #ifdef PS_USE_PS_STRINGS
228         PS_STRINGS->ps_nargvstr = 1;
229         PS_STRINGS->ps_argvstr = ps_buffer;
230 #endif   /* PS_USE_PS_STRINGS */
231
232 #ifdef PS_USE_CLOBBER_ARGV
233         {
234                 char       *cp;
235
236                 /* pad unused memory */
237                 for (cp = ps_buffer + strlen(ps_buffer);
238                          cp < ps_buffer + ps_buffer_size;
239                          cp++)
240                         *cp = PS_PADDING;
241         }
242 #endif   /* PS_USE_CLOBBER_ARGV */
243
244 #endif   /* not PS_USE_NONE */
245 }
246
247
248 /*
249  * Returns what's currently in the ps display, in case someone needs
250  * it.  Note that only the variable part is returned.
251  */
252 const char *
253 get_ps_display(void)
254 {
255 #ifdef PS_USE_CLOBBER_ARGV
256         /* If ps_buffer is a pointer, it might still be null */
257         if (!ps_buffer)
258                 return "";
259 #endif
260
261         return ps_buffer + ps_buffer_fixed_size;
262 }