Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <unistd.h>
00018 #ifdef HAVE_SYS_PSTAT_H
00019 #include <sys/pstat.h>
00020 #endif
00021 #ifdef HAVE_PS_STRINGS
00022 #include <machine/vmparam.h>
00023 #include <sys/exec.h>
00024 #endif
00025 #if defined(__darwin__)
00026 #include <crt_externs.h>
00027 #endif
00028
00029 #include "libpq/libpq.h"
00030 #include "miscadmin.h"
00031 #include "utils/ps_status.h"
00032
00033 extern char **environ;
00034 bool update_process_title = true;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #if defined(HAVE_SETPROCTITLE)
00062 #define PS_USE_SETPROCTITLE
00063 #elif defined(HAVE_PSTAT) && defined(PSTAT_SETCMD)
00064 #define PS_USE_PSTAT
00065 #elif defined(HAVE_PS_STRINGS)
00066 #define PS_USE_PS_STRINGS
00067 #elif (defined(BSD) || defined(__hurd__)) && !defined(__darwin__)
00068 #define PS_USE_CHANGE_ARGV
00069 #elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__ksr__) || defined(__osf__) || defined(__svr5__) || defined(__darwin__)
00070 #define PS_USE_CLOBBER_ARGV
00071 #elif defined(WIN32)
00072 #define PS_USE_WIN32
00073 #else
00074 #define PS_USE_NONE
00075 #endif
00076
00077
00078
00079 #if defined(_AIX) || defined(__linux__) || defined(__darwin__)
00080 #define PS_PADDING '\0'
00081 #else
00082 #define PS_PADDING ' '
00083 #endif
00084
00085
00086 #ifndef PS_USE_CLOBBER_ARGV
00087
00088 #define PS_BUFFER_SIZE 256
00089 static char ps_buffer[PS_BUFFER_SIZE];
00090 static const size_t ps_buffer_size = PS_BUFFER_SIZE;
00091 #else
00092 static char *ps_buffer;
00093 static size_t ps_buffer_size;
00094 static size_t last_status_len;
00095 #endif
00096
00097 static size_t ps_buffer_cur_len;
00098
00099 static size_t ps_buffer_fixed_size;
00100
00101
00102 static int save_argc;
00103 static char **save_argv;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 char **
00117 save_ps_display_args(int argc, char **argv)
00118 {
00119 save_argc = argc;
00120 save_argv = argv;
00121
00122 #if defined(PS_USE_CLOBBER_ARGV)
00123
00124
00125
00126
00127
00128 {
00129 char *end_of_area = NULL;
00130 char **new_environ;
00131 int i;
00132
00133
00134
00135
00136 for (i = 0; i < argc; i++)
00137 {
00138 if (i == 0 || end_of_area + 1 == argv[i])
00139 end_of_area = argv[i] + strlen(argv[i]);
00140 }
00141
00142 if (end_of_area == NULL)
00143 {
00144 ps_buffer = NULL;
00145 ps_buffer_size = 0;
00146 return argv;
00147 }
00148
00149
00150
00151
00152 for (i = 0; environ[i] != NULL; i++)
00153 {
00154 if (end_of_area + 1 == environ[i])
00155 end_of_area = environ[i] + strlen(environ[i]);
00156 }
00157
00158 ps_buffer = argv[0];
00159 last_status_len = ps_buffer_size = end_of_area - argv[0];
00160
00161
00162
00163
00164 new_environ = (char **) malloc((i + 1) * sizeof(char *));
00165 for (i = 0; environ[i] != NULL; i++)
00166 new_environ[i] = strdup(environ[i]);
00167 new_environ[i] = NULL;
00168 environ = new_environ;
00169 }
00170 #endif
00171
00172 #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 {
00187 char **new_argv;
00188 int i;
00189
00190 new_argv = (char **) malloc((argc + 1) * sizeof(char *));
00191 for (i = 0; i < argc; i++)
00192 new_argv[i] = strdup(argv[i]);
00193 new_argv[argc] = NULL;
00194
00195 #if defined(__darwin__)
00196
00197
00198
00199
00200
00201 *_NSGetArgv() = new_argv;
00202 #endif
00203
00204 argv = new_argv;
00205 }
00206 #endif
00207
00208 return argv;
00209 }
00210
00211
00212
00213
00214
00215 void
00216 init_ps_display(const char *username, const char *dbname,
00217 const char *host_info, const char *initial_str)
00218 {
00219 Assert(username);
00220 Assert(dbname);
00221 Assert(host_info);
00222
00223 #ifndef PS_USE_NONE
00224
00225 if (!IsUnderPostmaster)
00226 return;
00227
00228
00229 if (!save_argv)
00230 return;
00231
00232 #ifdef PS_USE_CLOBBER_ARGV
00233
00234 if (!ps_buffer)
00235 return;
00236 #endif
00237
00238
00239
00240
00241
00242 #ifdef PS_USE_CHANGE_ARGV
00243 save_argv[0] = ps_buffer;
00244 save_argv[1] = NULL;
00245 #endif
00246
00247 #ifdef PS_USE_CLOBBER_ARGV
00248 {
00249 int i;
00250
00251
00252 for (i = 1; i < save_argc; i++)
00253 save_argv[i] = ps_buffer + ps_buffer_size;
00254 }
00255 #endif
00256
00257
00258
00259
00260
00261 #ifdef PS_USE_SETPROCTITLE
00262
00263
00264
00265
00266
00267 snprintf(ps_buffer, ps_buffer_size,
00268 "%s %s %s ",
00269 username, dbname, host_info);
00270 #else
00271 snprintf(ps_buffer, ps_buffer_size,
00272 "postgres: %s %s %s ",
00273 username, dbname, host_info);
00274 #endif
00275
00276 ps_buffer_cur_len = ps_buffer_fixed_size = strlen(ps_buffer);
00277
00278 set_ps_display(initial_str, true);
00279 #endif
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 void
00289 set_ps_display(const char *activity, bool force)
00290 {
00291 #ifndef PS_USE_NONE
00292
00293 if (!force && !update_process_title)
00294 return;
00295
00296
00297 if (!IsUnderPostmaster)
00298 return;
00299
00300 #ifdef PS_USE_CLOBBER_ARGV
00301
00302 if (!ps_buffer)
00303 return;
00304 #endif
00305
00306
00307 strlcpy(ps_buffer + ps_buffer_fixed_size, activity,
00308 ps_buffer_size - ps_buffer_fixed_size);
00309 ps_buffer_cur_len = strlen(ps_buffer);
00310
00311
00312
00313 #ifdef PS_USE_SETPROCTITLE
00314 setproctitle("%s", ps_buffer);
00315 #endif
00316
00317 #ifdef PS_USE_PSTAT
00318 {
00319 union pstun pst;
00320
00321 pst.pst_command = ps_buffer;
00322 pstat(PSTAT_SETCMD, pst, ps_buffer_cur_len, 0, 0);
00323 }
00324 #endif
00325
00326 #ifdef PS_USE_PS_STRINGS
00327 PS_STRINGS->ps_nargvstr = 1;
00328 PS_STRINGS->ps_argvstr = ps_buffer;
00329 #endif
00330
00331 #ifdef PS_USE_CLOBBER_ARGV
00332
00333 if (last_status_len > ps_buffer_cur_len)
00334 MemSet(ps_buffer + ps_buffer_cur_len, PS_PADDING,
00335 last_status_len - ps_buffer_cur_len);
00336 last_status_len = ps_buffer_cur_len;
00337 #endif
00338
00339 #ifdef PS_USE_WIN32
00340 {
00341
00342
00343
00344
00345
00346 static HANDLE ident_handle = INVALID_HANDLE_VALUE;
00347 char name[PS_BUFFER_SIZE + 32];
00348
00349 if (ident_handle != INVALID_HANDLE_VALUE)
00350 CloseHandle(ident_handle);
00351
00352 sprintf(name, "pgident(%d): %s", MyProcPid, ps_buffer);
00353
00354 ident_handle = CreateEvent(NULL, TRUE, FALSE, name);
00355 }
00356 #endif
00357 #endif
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367 const char *
00368 get_ps_display(int *displen)
00369 {
00370 #ifdef PS_USE_CLOBBER_ARGV
00371
00372 if (!ps_buffer)
00373 {
00374 *displen = 0;
00375 return "";
00376 }
00377 #endif
00378
00379 *displen = (int) (ps_buffer_cur_len - ps_buffer_fixed_size);
00380
00381 return ps_buffer + ps_buffer_fixed_size;
00382 }