Coverage Report

Created: 2025-12-27 07:05

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