1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #include <nxt_main.h> 8*0Sigor@sysoev.ru 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru /* The arguments passed to main(). */ 11*0Sigor@sysoev.ru char **nxt_process_argv; 12*0Sigor@sysoev.ru 13*0Sigor@sysoev.ru /* 14*0Sigor@sysoev.ru * MacOSX environ(7): 15*0Sigor@sysoev.ru * 16*0Sigor@sysoev.ru * Shared libraries and bundles don't have direct access to environ, 17*0Sigor@sysoev.ru * which is only available to the loader ld(1) when a complete program 18*0Sigor@sysoev.ru * is being linked. 19*0Sigor@sysoev.ru * 20*0Sigor@sysoev.ru * So nxt_process_environ contains an address of environ to allow 21*0Sigor@sysoev.ru * change environ[] placement. 22*0Sigor@sysoev.ru */ 23*0Sigor@sysoev.ru char ***nxt_process_environ; 24*0Sigor@sysoev.ru 25*0Sigor@sysoev.ru 26*0Sigor@sysoev.ru #if (NXT_SETPROCTITLE_ARGV) 27*0Sigor@sysoev.ru 28*0Sigor@sysoev.ru /* 29*0Sigor@sysoev.ru * A process title on Linux, Solaris, and MacOSX can be changed by 30*0Sigor@sysoev.ru * copying a new title to a place where the program argument argv[0] 31*0Sigor@sysoev.ru * points originally to. However, the argv[0] may be too small to hold 32*0Sigor@sysoev.ru * the new title. Fortunately, these OSes place the program argument 33*0Sigor@sysoev.ru * argv[] strings and the environment environ[] strings contiguously 34*0Sigor@sysoev.ru * and their space can be used for the long new process title. 35*0Sigor@sysoev.ru * 36*0Sigor@sysoev.ru * Solaris "ps" command shows the new title only if it is run in 37*0Sigor@sysoev.ru * UCB mode: either "/usr/ucb/ps -axwww" or "/usr/bin/ps axwww". 38*0Sigor@sysoev.ru */ 39*0Sigor@sysoev.ru 40*0Sigor@sysoev.ru 41*0Sigor@sysoev.ru static u_char *nxt_process_title_start; 42*0Sigor@sysoev.ru static u_char *nxt_process_title_end; 43*0Sigor@sysoev.ru 44*0Sigor@sysoev.ru 45*0Sigor@sysoev.ru void 46*0Sigor@sysoev.ru nxt_process_arguments(char **orig_argv, char ***orig_envp) 47*0Sigor@sysoev.ru { 48*0Sigor@sysoev.ru u_char *p, *end, *argv_end, **argv, **env; 49*0Sigor@sysoev.ru size_t size, argv_size, environ_size, strings_size; 50*0Sigor@sysoev.ru nxt_uint_t i; 51*0Sigor@sysoev.ru 52*0Sigor@sysoev.ru nxt_process_argv = orig_argv; 53*0Sigor@sysoev.ru nxt_process_environ = orig_envp; 54*0Sigor@sysoev.ru 55*0Sigor@sysoev.ru if (orig_envp == NULL) { 56*0Sigor@sysoev.ru return; 57*0Sigor@sysoev.ru } 58*0Sigor@sysoev.ru 59*0Sigor@sysoev.ru /* 60*0Sigor@sysoev.ru * Set a conservative title space for a case if program argument 61*0Sigor@sysoev.ru * strings and environment strings are not contiguous. 62*0Sigor@sysoev.ru */ 63*0Sigor@sysoev.ru argv = (u_char **) orig_argv; 64*0Sigor@sysoev.ru nxt_process_title_start = argv[0]; 65*0Sigor@sysoev.ru nxt_process_title_end = argv[0] + nxt_strlen(argv[0]); 66*0Sigor@sysoev.ru 67*0Sigor@sysoev.ru end = argv[0]; 68*0Sigor@sysoev.ru strings_size = 0; 69*0Sigor@sysoev.ru argv_size = sizeof(void *); 70*0Sigor@sysoev.ru 71*0Sigor@sysoev.ru for (i = 0; argv[i] != NULL; i++) { 72*0Sigor@sysoev.ru argv_size += sizeof(void *); 73*0Sigor@sysoev.ru 74*0Sigor@sysoev.ru if (argv[i] == end) { 75*0Sigor@sysoev.ru /* Argument strings are contiguous. */ 76*0Sigor@sysoev.ru size = nxt_strlen(argv[i]) + 1; 77*0Sigor@sysoev.ru strings_size += size; 78*0Sigor@sysoev.ru end = argv[i] + size; 79*0Sigor@sysoev.ru } 80*0Sigor@sysoev.ru } 81*0Sigor@sysoev.ru 82*0Sigor@sysoev.ru argv = nxt_malloc(argv_size); 83*0Sigor@sysoev.ru if (argv == NULL) { 84*0Sigor@sysoev.ru return; 85*0Sigor@sysoev.ru } 86*0Sigor@sysoev.ru 87*0Sigor@sysoev.ru /* 88*0Sigor@sysoev.ru * Copy the entire original argv[] array. The elements of this array 89*0Sigor@sysoev.ru * can point to copied strings or if original argument strings are not 90*0Sigor@sysoev.ru * contiguous, to the original argument strings. 91*0Sigor@sysoev.ru */ 92*0Sigor@sysoev.ru nxt_memcpy(argv, orig_argv, argv_size); 93*0Sigor@sysoev.ru 94*0Sigor@sysoev.ru /* 95*0Sigor@sysoev.ru * The argv[1] must be set to NULL on Solaris otherwise the "ps" 96*0Sigor@sysoev.ru * command outputs strings pointed by original argv[] elements. 97*0Sigor@sysoev.ru * The original argv[] array has always at least two elements so 98*0Sigor@sysoev.ru * it is safe to set argv[1]. 99*0Sigor@sysoev.ru */ 100*0Sigor@sysoev.ru orig_argv[1] = NULL; 101*0Sigor@sysoev.ru 102*0Sigor@sysoev.ru nxt_process_argv = (char **) argv; 103*0Sigor@sysoev.ru 104*0Sigor@sysoev.ru argv_end = end; 105*0Sigor@sysoev.ru env = (u_char **) *orig_envp; 106*0Sigor@sysoev.ru environ_size = sizeof(void *); 107*0Sigor@sysoev.ru 108*0Sigor@sysoev.ru for (i = 0; env[i] != NULL; i++) { 109*0Sigor@sysoev.ru environ_size += sizeof(void *); 110*0Sigor@sysoev.ru 111*0Sigor@sysoev.ru if (env[i] == end) { 112*0Sigor@sysoev.ru /* Environment strings are contiguous. */ 113*0Sigor@sysoev.ru size = nxt_strlen(env[i]) + 1; 114*0Sigor@sysoev.ru strings_size += size; 115*0Sigor@sysoev.ru end = env[i] + size; 116*0Sigor@sysoev.ru } 117*0Sigor@sysoev.ru } 118*0Sigor@sysoev.ru 119*0Sigor@sysoev.ru p = nxt_malloc(strings_size); 120*0Sigor@sysoev.ru if (p == NULL) { 121*0Sigor@sysoev.ru return; 122*0Sigor@sysoev.ru } 123*0Sigor@sysoev.ru 124*0Sigor@sysoev.ru if (argv_end == end) { 125*0Sigor@sysoev.ru /* 126*0Sigor@sysoev.ru * There is no reason to modify environ if arguments 127*0Sigor@sysoev.ru * and environment are not contiguous. 128*0Sigor@sysoev.ru */ 129*0Sigor@sysoev.ru nxt_thread_log_debug("arguments and environment are not contiguous"); 130*0Sigor@sysoev.ru goto done; 131*0Sigor@sysoev.ru } 132*0Sigor@sysoev.ru 133*0Sigor@sysoev.ru end = argv[0]; 134*0Sigor@sysoev.ru 135*0Sigor@sysoev.ru for (i = 0; argv[i] != NULL; i++) { 136*0Sigor@sysoev.ru 137*0Sigor@sysoev.ru if (argv[i] != end) { 138*0Sigor@sysoev.ru /* Argument strings are not contiguous. */ 139*0Sigor@sysoev.ru goto done; 140*0Sigor@sysoev.ru } 141*0Sigor@sysoev.ru 142*0Sigor@sysoev.ru size = nxt_strlen(argv[i]) + 1; 143*0Sigor@sysoev.ru nxt_memcpy(p, argv[i], size); 144*0Sigor@sysoev.ru 145*0Sigor@sysoev.ru end = argv[i] + size; 146*0Sigor@sysoev.ru argv[i] = p; 147*0Sigor@sysoev.ru p += size; 148*0Sigor@sysoev.ru } 149*0Sigor@sysoev.ru 150*0Sigor@sysoev.ru env = nxt_malloc(environ_size); 151*0Sigor@sysoev.ru if (env == NULL) { 152*0Sigor@sysoev.ru return; 153*0Sigor@sysoev.ru } 154*0Sigor@sysoev.ru 155*0Sigor@sysoev.ru /* 156*0Sigor@sysoev.ru * Copy the entire original environ[] array. The elements of 157*0Sigor@sysoev.ru * this array can point to copied strings or if original environ 158*0Sigor@sysoev.ru * strings are not contiguous, to the original environ strings. 159*0Sigor@sysoev.ru */ 160*0Sigor@sysoev.ru nxt_memcpy(env, *orig_envp, environ_size); 161*0Sigor@sysoev.ru 162*0Sigor@sysoev.ru /* Set the global environ variable to the new array. */ 163*0Sigor@sysoev.ru *orig_envp = (char **) env; 164*0Sigor@sysoev.ru 165*0Sigor@sysoev.ru for (i = 0; env[i] != NULL; i++) { 166*0Sigor@sysoev.ru 167*0Sigor@sysoev.ru if (env[i] != end) { 168*0Sigor@sysoev.ru /* Environment strings are not contiguous. */ 169*0Sigor@sysoev.ru goto done; 170*0Sigor@sysoev.ru } 171*0Sigor@sysoev.ru 172*0Sigor@sysoev.ru size = nxt_strlen(env[i]) + 1; 173*0Sigor@sysoev.ru nxt_memcpy(p, env[i], size); 174*0Sigor@sysoev.ru 175*0Sigor@sysoev.ru end = env[i] + size; 176*0Sigor@sysoev.ru env[i] = p; 177*0Sigor@sysoev.ru p += size; 178*0Sigor@sysoev.ru } 179*0Sigor@sysoev.ru 180*0Sigor@sysoev.ru done: 181*0Sigor@sysoev.ru 182*0Sigor@sysoev.ru /* Preserve space for the trailing zero. */ 183*0Sigor@sysoev.ru end--; 184*0Sigor@sysoev.ru 185*0Sigor@sysoev.ru nxt_process_title_end = end; 186*0Sigor@sysoev.ru } 187*0Sigor@sysoev.ru 188*0Sigor@sysoev.ru 189*0Sigor@sysoev.ru void 190*0Sigor@sysoev.ru nxt_process_title(const char *title) 191*0Sigor@sysoev.ru { 192*0Sigor@sysoev.ru u_char *p, *start, *end; 193*0Sigor@sysoev.ru 194*0Sigor@sysoev.ru start = nxt_process_title_start; 195*0Sigor@sysoev.ru 196*0Sigor@sysoev.ru if (start == NULL) { 197*0Sigor@sysoev.ru return; 198*0Sigor@sysoev.ru } 199*0Sigor@sysoev.ru 200*0Sigor@sysoev.ru end = nxt_process_title_end; 201*0Sigor@sysoev.ru 202*0Sigor@sysoev.ru p = nxt_sprintf(start, end, "%s", title); 203*0Sigor@sysoev.ru 204*0Sigor@sysoev.ru #if (NXT_SOLARIS) 205*0Sigor@sysoev.ru /* 206*0Sigor@sysoev.ru * Solaris "ps" command shows a new process title only if it is 207*0Sigor@sysoev.ru * longer than original command line. A simple workaround is just 208*0Sigor@sysoev.ru * to append the original command line in parenthesis to the title. 209*0Sigor@sysoev.ru */ 210*0Sigor@sysoev.ru { 211*0Sigor@sysoev.ru size_t size; 212*0Sigor@sysoev.ru nxt_uint_t i; 213*0Sigor@sysoev.ru 214*0Sigor@sysoev.ru size = 0; 215*0Sigor@sysoev.ru 216*0Sigor@sysoev.ru for (i = 0; nxt_process_argv[i] != NULL; i++) { 217*0Sigor@sysoev.ru size += nxt_strlen(nxt_process_argv[i]); 218*0Sigor@sysoev.ru } 219*0Sigor@sysoev.ru 220*0Sigor@sysoev.ru if (size > (size_t) (p - start)) { 221*0Sigor@sysoev.ru 222*0Sigor@sysoev.ru p = nxt_sprintf(p, end, " ("); 223*0Sigor@sysoev.ru 224*0Sigor@sysoev.ru for (i = 0; nxt_process_argv[i] != NULL; i++) { 225*0Sigor@sysoev.ru p = nxt_sprintf(p, end, "%s ", nxt_process_argv[i]); 226*0Sigor@sysoev.ru } 227*0Sigor@sysoev.ru 228*0Sigor@sysoev.ru if (*(p - 1) == ' ') { 229*0Sigor@sysoev.ru *(p - 1) = ')'; 230*0Sigor@sysoev.ru } 231*0Sigor@sysoev.ru } 232*0Sigor@sysoev.ru } 233*0Sigor@sysoev.ru #endif 234*0Sigor@sysoev.ru 235*0Sigor@sysoev.ru /* 236*0Sigor@sysoev.ru * A process title must be padded with zeros on MacOSX. Otherwise 237*0Sigor@sysoev.ru * the "ps" command may output parts of environment strings. 238*0Sigor@sysoev.ru */ 239*0Sigor@sysoev.ru nxt_memset(p, '\0', end - p); 240*0Sigor@sysoev.ru 241*0Sigor@sysoev.ru nxt_thread_log_debug("setproctitle: \"%s\"", start); 242*0Sigor@sysoev.ru } 243*0Sigor@sysoev.ru 244*0Sigor@sysoev.ru #else /* !(NXT_SETPROCTITLE_ARGV) */ 245*0Sigor@sysoev.ru 246*0Sigor@sysoev.ru void 247*0Sigor@sysoev.ru nxt_process_arguments(char **orig_argv, char ***orig_envp) 248*0Sigor@sysoev.ru { 249*0Sigor@sysoev.ru nxt_process_argv = orig_argv; 250*0Sigor@sysoev.ru nxt_process_environ = orig_envp; 251*0Sigor@sysoev.ru } 252*0Sigor@sysoev.ru 253*0Sigor@sysoev.ru #endif 254