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 46*20Sigor@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 */ 129*20Sigor@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 190*20Sigor@sysoev.ru nxt_process_title(nxt_task_t *task, const char *fmt, ...) 1910Sigor@sysoev.ru { 192*20Sigor@sysoev.ru u_char *p, *start, *end; 193*20Sigor@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 203*20Sigor@sysoev.ru va_start(args, fmt); 204*20Sigor@sysoev.ru p = nxt_vsprintf(start, end, fmt, args); 205*20Sigor@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 244*20Sigor@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 2500Sigor@sysoev.ru nxt_process_arguments(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