10Sigor@sysoev.ru
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru */
60Sigor@sysoev.ru
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru
90Sigor@sysoev.ru
100Sigor@sysoev.ru /* The arguments passed to main(). */
110Sigor@sysoev.ru char **nxt_process_argv;
120Sigor@sysoev.ru
130Sigor@sysoev.ru /*
140Sigor@sysoev.ru * MacOSX environ(7):
150Sigor@sysoev.ru *
160Sigor@sysoev.ru * Shared libraries and bundles don't have direct access to environ,
170Sigor@sysoev.ru * which is only available to the loader ld(1) when a complete program
180Sigor@sysoev.ru * is being linked.
190Sigor@sysoev.ru *
200Sigor@sysoev.ru * So nxt_process_environ contains an address of environ to allow
210Sigor@sysoev.ru * change environ[] placement.
220Sigor@sysoev.ru */
230Sigor@sysoev.ru char ***nxt_process_environ;
240Sigor@sysoev.ru
250Sigor@sysoev.ru
260Sigor@sysoev.ru #if (NXT_SETPROCTITLE_ARGV)
270Sigor@sysoev.ru
280Sigor@sysoev.ru /*
290Sigor@sysoev.ru * A process title on Linux, Solaris, and MacOSX can be changed by
300Sigor@sysoev.ru * copying a new title to a place where the program argument argv[0]
310Sigor@sysoev.ru * points originally to. However, the argv[0] may be too small to hold
320Sigor@sysoev.ru * the new title. Fortunately, these OSes place the program argument
330Sigor@sysoev.ru * argv[] strings and the environment environ[] strings contiguously
340Sigor@sysoev.ru * and their space can be used for the long new process title.
350Sigor@sysoev.ru *
360Sigor@sysoev.ru * Solaris "ps" command shows the new title only if it is run in
370Sigor@sysoev.ru * UCB mode: either "/usr/ucb/ps -axwww" or "/usr/bin/ps axwww".
380Sigor@sysoev.ru */
390Sigor@sysoev.ru
400Sigor@sysoev.ru
410Sigor@sysoev.ru static u_char *nxt_process_title_start;
420Sigor@sysoev.ru static u_char *nxt_process_title_end;
430Sigor@sysoev.ru
440Sigor@sysoev.ru
450Sigor@sysoev.ru void
nxt_process_arguments(nxt_task_t * task,char ** orig_argv,char *** orig_envp)4620Sigor@sysoev.ru nxt_process_arguments(nxt_task_t *task, char **orig_argv, char ***orig_envp)
470Sigor@sysoev.ru {
480Sigor@sysoev.ru u_char *p, *end, *argv_end, **argv, **env;
490Sigor@sysoev.ru size_t size, argv_size, environ_size, strings_size;
500Sigor@sysoev.ru nxt_uint_t i;
510Sigor@sysoev.ru
520Sigor@sysoev.ru nxt_process_argv = orig_argv;
530Sigor@sysoev.ru nxt_process_environ = orig_envp;
540Sigor@sysoev.ru
550Sigor@sysoev.ru if (orig_envp == NULL) {
560Sigor@sysoev.ru return;
570Sigor@sysoev.ru }
580Sigor@sysoev.ru
590Sigor@sysoev.ru /*
600Sigor@sysoev.ru * Set a conservative title space for a case if program argument
610Sigor@sysoev.ru * strings and environment strings are not contiguous.
620Sigor@sysoev.ru */
630Sigor@sysoev.ru argv = (u_char **) orig_argv;
640Sigor@sysoev.ru nxt_process_title_start = argv[0];
650Sigor@sysoev.ru nxt_process_title_end = argv[0] + nxt_strlen(argv[0]);
660Sigor@sysoev.ru
670Sigor@sysoev.ru end = argv[0];
680Sigor@sysoev.ru strings_size = 0;
690Sigor@sysoev.ru argv_size = sizeof(void *);
700Sigor@sysoev.ru
710Sigor@sysoev.ru for (i = 0; argv[i] != NULL; i++) {
720Sigor@sysoev.ru argv_size += sizeof(void *);
730Sigor@sysoev.ru
740Sigor@sysoev.ru if (argv[i] == end) {
750Sigor@sysoev.ru /* Argument strings are contiguous. */
760Sigor@sysoev.ru size = nxt_strlen(argv[i]) + 1;
770Sigor@sysoev.ru strings_size += size;
780Sigor@sysoev.ru end = argv[i] + size;
790Sigor@sysoev.ru }
800Sigor@sysoev.ru }
810Sigor@sysoev.ru
820Sigor@sysoev.ru argv = nxt_malloc(argv_size);
830Sigor@sysoev.ru if (argv == NULL) {
840Sigor@sysoev.ru return;
850Sigor@sysoev.ru }
860Sigor@sysoev.ru
870Sigor@sysoev.ru /*
880Sigor@sysoev.ru * Copy the entire original argv[] array. The elements of this array
890Sigor@sysoev.ru * can point to copied strings or if original argument strings are not
900Sigor@sysoev.ru * contiguous, to the original argument strings.
910Sigor@sysoev.ru */
920Sigor@sysoev.ru nxt_memcpy(argv, orig_argv, argv_size);
930Sigor@sysoev.ru
940Sigor@sysoev.ru /*
950Sigor@sysoev.ru * The argv[1] must be set to NULL on Solaris otherwise the "ps"
960Sigor@sysoev.ru * command outputs strings pointed by original argv[] elements.
970Sigor@sysoev.ru * The original argv[] array has always at least two elements so
980Sigor@sysoev.ru * it is safe to set argv[1].
990Sigor@sysoev.ru */
1000Sigor@sysoev.ru orig_argv[1] = NULL;
1010Sigor@sysoev.ru
1020Sigor@sysoev.ru nxt_process_argv = (char **) argv;
1030Sigor@sysoev.ru
1040Sigor@sysoev.ru argv_end = end;
1050Sigor@sysoev.ru env = (u_char **) *orig_envp;
1060Sigor@sysoev.ru environ_size = sizeof(void *);
1070Sigor@sysoev.ru
1080Sigor@sysoev.ru for (i = 0; env[i] != NULL; i++) {
1090Sigor@sysoev.ru environ_size += sizeof(void *);
1100Sigor@sysoev.ru
1110Sigor@sysoev.ru if (env[i] == end) {
1120Sigor@sysoev.ru /* Environment strings are contiguous. */
1130Sigor@sysoev.ru size = nxt_strlen(env[i]) + 1;
1140Sigor@sysoev.ru strings_size += size;
1150Sigor@sysoev.ru end = env[i] + size;
1160Sigor@sysoev.ru }
1170Sigor@sysoev.ru }
1180Sigor@sysoev.ru
1190Sigor@sysoev.ru p = nxt_malloc(strings_size);
1200Sigor@sysoev.ru if (p == NULL) {
1210Sigor@sysoev.ru return;
1220Sigor@sysoev.ru }
1230Sigor@sysoev.ru
1240Sigor@sysoev.ru if (argv_end == end) {
1250Sigor@sysoev.ru /*
1260Sigor@sysoev.ru * There is no reason to modify environ if arguments
1270Sigor@sysoev.ru * and environment are not contiguous.
1280Sigor@sysoev.ru */
12920Sigor@sysoev.ru nxt_debug(task, "arguments and environment are not contiguous");
1300Sigor@sysoev.ru goto done;
1310Sigor@sysoev.ru }
1320Sigor@sysoev.ru
1330Sigor@sysoev.ru end = argv[0];
1340Sigor@sysoev.ru
1350Sigor@sysoev.ru for (i = 0; argv[i] != NULL; i++) {
1360Sigor@sysoev.ru
1370Sigor@sysoev.ru if (argv[i] != end) {
1380Sigor@sysoev.ru /* Argument strings are not contiguous. */
1390Sigor@sysoev.ru goto done;
1400Sigor@sysoev.ru }
1410Sigor@sysoev.ru
1420Sigor@sysoev.ru size = nxt_strlen(argv[i]) + 1;
1430Sigor@sysoev.ru nxt_memcpy(p, argv[i], size);
1440Sigor@sysoev.ru
1450Sigor@sysoev.ru end = argv[i] + size;
1460Sigor@sysoev.ru argv[i] = p;
1470Sigor@sysoev.ru p += size;
1480Sigor@sysoev.ru }
1490Sigor@sysoev.ru
1500Sigor@sysoev.ru env = nxt_malloc(environ_size);
1510Sigor@sysoev.ru if (env == NULL) {
1520Sigor@sysoev.ru return;
1530Sigor@sysoev.ru }
1540Sigor@sysoev.ru
1550Sigor@sysoev.ru /*
1560Sigor@sysoev.ru * Copy the entire original environ[] array. The elements of
1570Sigor@sysoev.ru * this array can point to copied strings or if original environ
1580Sigor@sysoev.ru * strings are not contiguous, to the original environ strings.
1590Sigor@sysoev.ru */
1600Sigor@sysoev.ru nxt_memcpy(env, *orig_envp, environ_size);
1610Sigor@sysoev.ru
1620Sigor@sysoev.ru /* Set the global environ variable to the new array. */
1630Sigor@sysoev.ru *orig_envp = (char **) env;
1640Sigor@sysoev.ru
1650Sigor@sysoev.ru for (i = 0; env[i] != NULL; i++) {
1660Sigor@sysoev.ru
1670Sigor@sysoev.ru if (env[i] != end) {
1680Sigor@sysoev.ru /* Environment strings are not contiguous. */
1690Sigor@sysoev.ru goto done;
1700Sigor@sysoev.ru }
1710Sigor@sysoev.ru
1720Sigor@sysoev.ru size = nxt_strlen(env[i]) + 1;
1730Sigor@sysoev.ru nxt_memcpy(p, env[i], size);
1740Sigor@sysoev.ru
1750Sigor@sysoev.ru end = env[i] + size;
1760Sigor@sysoev.ru env[i] = p;
1770Sigor@sysoev.ru p += size;
1780Sigor@sysoev.ru }
1790Sigor@sysoev.ru
1800Sigor@sysoev.ru done:
1810Sigor@sysoev.ru
1820Sigor@sysoev.ru /* Preserve space for the trailing zero. */
1830Sigor@sysoev.ru end--;
1840Sigor@sysoev.ru
1850Sigor@sysoev.ru nxt_process_title_end = end;
1860Sigor@sysoev.ru }
1870Sigor@sysoev.ru
1880Sigor@sysoev.ru
1890Sigor@sysoev.ru void
nxt_process_title(nxt_task_t * task,const char * fmt,...)19020Sigor@sysoev.ru nxt_process_title(nxt_task_t *task, const char *fmt, ...)
1910Sigor@sysoev.ru {
19220Sigor@sysoev.ru u_char *p, *start, *end;
19320Sigor@sysoev.ru va_list args;
1940Sigor@sysoev.ru
1950Sigor@sysoev.ru start = nxt_process_title_start;
1960Sigor@sysoev.ru
1970Sigor@sysoev.ru if (start == NULL) {
1980Sigor@sysoev.ru return;
1990Sigor@sysoev.ru }
2000Sigor@sysoev.ru
2010Sigor@sysoev.ru end = nxt_process_title_end;
2020Sigor@sysoev.ru
20320Sigor@sysoev.ru va_start(args, fmt);
20420Sigor@sysoev.ru p = nxt_vsprintf(start, end, fmt, args);
20520Sigor@sysoev.ru va_end(args);
2060Sigor@sysoev.ru
2070Sigor@sysoev.ru #if (NXT_SOLARIS)
2080Sigor@sysoev.ru /*
2090Sigor@sysoev.ru * Solaris "ps" command shows a new process title only if it is
2100Sigor@sysoev.ru * longer than original command line. A simple workaround is just
2110Sigor@sysoev.ru * to append the original command line in parenthesis to the title.
2120Sigor@sysoev.ru */
2130Sigor@sysoev.ru {
2140Sigor@sysoev.ru size_t size;
2150Sigor@sysoev.ru nxt_uint_t i;
2160Sigor@sysoev.ru
2170Sigor@sysoev.ru size = 0;
2180Sigor@sysoev.ru
2190Sigor@sysoev.ru for (i = 0; nxt_process_argv[i] != NULL; i++) {
2200Sigor@sysoev.ru size += nxt_strlen(nxt_process_argv[i]);
2210Sigor@sysoev.ru }
2220Sigor@sysoev.ru
2230Sigor@sysoev.ru if (size > (size_t) (p - start)) {
2240Sigor@sysoev.ru
2250Sigor@sysoev.ru p = nxt_sprintf(p, end, " (");
2260Sigor@sysoev.ru
2270Sigor@sysoev.ru for (i = 0; nxt_process_argv[i] != NULL; i++) {
2280Sigor@sysoev.ru p = nxt_sprintf(p, end, "%s ", nxt_process_argv[i]);
2290Sigor@sysoev.ru }
2300Sigor@sysoev.ru
2310Sigor@sysoev.ru if (*(p - 1) == ' ') {
2320Sigor@sysoev.ru *(p - 1) = ')';
2330Sigor@sysoev.ru }
2340Sigor@sysoev.ru }
2350Sigor@sysoev.ru }
2360Sigor@sysoev.ru #endif
2370Sigor@sysoev.ru
2380Sigor@sysoev.ru /*
2390Sigor@sysoev.ru * A process title must be padded with zeros on MacOSX. Otherwise
2400Sigor@sysoev.ru * the "ps" command may output parts of environment strings.
2410Sigor@sysoev.ru */
2420Sigor@sysoev.ru nxt_memset(p, '\0', end - p);
2430Sigor@sysoev.ru
24420Sigor@sysoev.ru nxt_debug(task, "setproctitle: \"%s\"", start);
2450Sigor@sysoev.ru }
2460Sigor@sysoev.ru
2470Sigor@sysoev.ru #else /* !(NXT_SETPROCTITLE_ARGV) */
2480Sigor@sysoev.ru
2490Sigor@sysoev.ru void
nxt_process_arguments(nxt_task_t * task,char ** orig_argv,char *** orig_envp)250*24Sigor@sysoev.ru nxt_process_arguments(nxt_task_t *task, char **orig_argv, char ***orig_envp)
2510Sigor@sysoev.ru {
2520Sigor@sysoev.ru nxt_process_argv = orig_argv;
2530Sigor@sysoev.ru nxt_process_environ = orig_envp;
2540Sigor@sysoev.ru }
2550Sigor@sysoev.ru
2560Sigor@sysoev.ru #endif
257