257 lines
6.1 KiB
C
257 lines
6.1 KiB
C
|
|
/*
|
|
* Copyright (C) Igor Sysoev
|
|
* Copyright (C) NGINX, Inc.
|
|
*/
|
|
|
|
#include <nxt_main.h>
|
|
|
|
|
|
/* The arguments passed to main(). */
|
|
char **nxt_process_argv;
|
|
|
|
/*
|
|
* MacOSX environ(7):
|
|
*
|
|
* Shared libraries and bundles don't have direct access to environ,
|
|
* which is only available to the loader ld(1) when a complete program
|
|
* is being linked.
|
|
*
|
|
* So nxt_process_environ contains an address of environ to allow
|
|
* change environ[] placement.
|
|
*/
|
|
char ***nxt_process_environ;
|
|
|
|
|
|
#if (NXT_SETPROCTITLE_ARGV)
|
|
|
|
/*
|
|
* A process title on Linux, Solaris, and MacOSX can be changed by
|
|
* copying a new title to a place where the program argument argv[0]
|
|
* points originally to. However, the argv[0] may be too small to hold
|
|
* the new title. Fortunately, these OSes place the program argument
|
|
* argv[] strings and the environment environ[] strings contiguously
|
|
* and their space can be used for the long new process title.
|
|
*
|
|
* Solaris "ps" command shows the new title only if it is run in
|
|
* UCB mode: either "/usr/ucb/ps -axwww" or "/usr/bin/ps axwww".
|
|
*/
|
|
|
|
|
|
static u_char *nxt_process_title_start;
|
|
static u_char *nxt_process_title_end;
|
|
|
|
|
|
void
|
|
nxt_process_arguments(nxt_task_t *task, char **orig_argv, char ***orig_envp)
|
|
{
|
|
u_char *p, *end, *argv_end, **argv, **env;
|
|
size_t size, argv_size, environ_size, strings_size;
|
|
nxt_uint_t i;
|
|
|
|
nxt_process_argv = orig_argv;
|
|
nxt_process_environ = orig_envp;
|
|
|
|
if (orig_envp == NULL) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Set a conservative title space for a case if program argument
|
|
* strings and environment strings are not contiguous.
|
|
*/
|
|
argv = (u_char **) orig_argv;
|
|
nxt_process_title_start = argv[0];
|
|
nxt_process_title_end = argv[0] + nxt_strlen(argv[0]);
|
|
|
|
end = argv[0];
|
|
strings_size = 0;
|
|
argv_size = sizeof(void *);
|
|
|
|
for (i = 0; argv[i] != NULL; i++) {
|
|
argv_size += sizeof(void *);
|
|
|
|
if (argv[i] == end) {
|
|
/* Argument strings are contiguous. */
|
|
size = nxt_strlen(argv[i]) + 1;
|
|
strings_size += size;
|
|
end = argv[i] + size;
|
|
}
|
|
}
|
|
|
|
argv = nxt_malloc(argv_size);
|
|
if (argv == NULL) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Copy the entire original argv[] array. The elements of this array
|
|
* can point to copied strings or if original argument strings are not
|
|
* contiguous, to the original argument strings.
|
|
*/
|
|
nxt_memcpy(argv, orig_argv, argv_size);
|
|
|
|
/*
|
|
* The argv[1] must be set to NULL on Solaris otherwise the "ps"
|
|
* command outputs strings pointed by original argv[] elements.
|
|
* The original argv[] array has always at least two elements so
|
|
* it is safe to set argv[1].
|
|
*/
|
|
orig_argv[1] = NULL;
|
|
|
|
nxt_process_argv = (char **) argv;
|
|
|
|
argv_end = end;
|
|
env = (u_char **) *orig_envp;
|
|
environ_size = sizeof(void *);
|
|
|
|
for (i = 0; env[i] != NULL; i++) {
|
|
environ_size += sizeof(void *);
|
|
|
|
if (env[i] == end) {
|
|
/* Environment strings are contiguous. */
|
|
size = nxt_strlen(env[i]) + 1;
|
|
strings_size += size;
|
|
end = env[i] + size;
|
|
}
|
|
}
|
|
|
|
p = nxt_malloc(strings_size);
|
|
if (p == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (argv_end == end) {
|
|
/*
|
|
* There is no reason to modify environ if arguments
|
|
* and environment are not contiguous.
|
|
*/
|
|
nxt_debug(task, "arguments and environment are not contiguous");
|
|
goto done;
|
|
}
|
|
|
|
end = argv[0];
|
|
|
|
for (i = 0; argv[i] != NULL; i++) {
|
|
|
|
if (argv[i] != end) {
|
|
/* Argument strings are not contiguous. */
|
|
goto done;
|
|
}
|
|
|
|
size = nxt_strlen(argv[i]) + 1;
|
|
nxt_memcpy(p, argv[i], size);
|
|
|
|
end = argv[i] + size;
|
|
argv[i] = p;
|
|
p += size;
|
|
}
|
|
|
|
env = nxt_malloc(environ_size);
|
|
if (env == NULL) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Copy the entire original environ[] array. The elements of
|
|
* this array can point to copied strings or if original environ
|
|
* strings are not contiguous, to the original environ strings.
|
|
*/
|
|
nxt_memcpy(env, *orig_envp, environ_size);
|
|
|
|
/* Set the global environ variable to the new array. */
|
|
*orig_envp = (char **) env;
|
|
|
|
for (i = 0; env[i] != NULL; i++) {
|
|
|
|
if (env[i] != end) {
|
|
/* Environment strings are not contiguous. */
|
|
goto done;
|
|
}
|
|
|
|
size = nxt_strlen(env[i]) + 1;
|
|
nxt_memcpy(p, env[i], size);
|
|
|
|
end = env[i] + size;
|
|
env[i] = p;
|
|
p += size;
|
|
}
|
|
|
|
done:
|
|
|
|
/* Preserve space for the trailing zero. */
|
|
end--;
|
|
|
|
nxt_process_title_end = end;
|
|
}
|
|
|
|
|
|
void
|
|
nxt_process_title(nxt_task_t *task, const char *fmt, ...)
|
|
{
|
|
u_char *p, *start, *end;
|
|
va_list args;
|
|
|
|
start = nxt_process_title_start;
|
|
|
|
if (start == NULL) {
|
|
return;
|
|
}
|
|
|
|
end = nxt_process_title_end;
|
|
|
|
va_start(args, fmt);
|
|
p = nxt_vsprintf(start, end, fmt, args);
|
|
va_end(args);
|
|
|
|
#if (NXT_SOLARIS)
|
|
/*
|
|
* Solaris "ps" command shows a new process title only if it is
|
|
* longer than original command line. A simple workaround is just
|
|
* to append the original command line in parenthesis to the title.
|
|
*/
|
|
{
|
|
size_t size;
|
|
nxt_uint_t i;
|
|
|
|
size = 0;
|
|
|
|
for (i = 0; nxt_process_argv[i] != NULL; i++) {
|
|
size += nxt_strlen(nxt_process_argv[i]);
|
|
}
|
|
|
|
if (size > (size_t) (p - start)) {
|
|
|
|
p = nxt_sprintf(p, end, " (");
|
|
|
|
for (i = 0; nxt_process_argv[i] != NULL; i++) {
|
|
p = nxt_sprintf(p, end, "%s ", nxt_process_argv[i]);
|
|
}
|
|
|
|
if (*(p - 1) == ' ') {
|
|
*(p - 1) = ')';
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* A process title must be padded with zeros on MacOSX. Otherwise
|
|
* the "ps" command may output parts of environment strings.
|
|
*/
|
|
nxt_memset(p, '\0', end - p);
|
|
|
|
nxt_debug(task, "setproctitle: \"%s\"", start);
|
|
}
|
|
|
|
#else /* !(NXT_SETPROCTITLE_ARGV) */
|
|
|
|
void
|
|
nxt_process_arguments(char **orig_argv, char ***orig_envp)
|
|
{
|
|
nxt_process_argv = orig_argv;
|
|
nxt_process_environ = orig_envp;
|
|
}
|
|
|
|
#endif
|