xref: /PHP-7.3/sapi/fpm/fpm/fpm_env.c (revision 1c850bfc)
1 	/* (c) 2007,2008 Andrei Nigmatulin */
2 
3 #include "fpm_config.h"
4 
5 #ifdef HAVE_ALLOCA_H
6 #include <alloca.h>
7 #endif
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "fpm_env.h"
13 #include "fpm.h"
14 
15 #ifndef HAVE_SETPROCTITLE
16 #ifdef __linux__
17 static char **fpm_env_argv = NULL;
18 static size_t fpm_env_argv_len = 0;
19 #endif
20 #endif
21 
22 #ifndef HAVE_SETENV
23 # ifdef (__sparc__ || __sparc)
setenv(char * name,char * value,int clobber)24 int setenv(char *name, char *value, int clobber) /* {{{ */
25 {
26 	char   *malloc();
27 	char   *getenv();
28 	char   *cp;
29 
30 	if (clobber == 0 && getenv(name) != 0) {
31 		return 0;
32 	}
33 
34 	if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0) {
35 		return 1;
36 	}
37 	sprintf(cp, "%s=%s", name, value);
38 	return putenv(cp);
39 }
40 /* }}} */
41 # else
setenv(char * name,char * value,int overwrite)42 int setenv(char *name, char *value, int overwrite) /* {{{ */
43 {
44 	int name_len = strlen(name);
45 	int value_len = strlen(value);
46 	char *var = alloca(name_len + 1 + value_len + 1);
47 
48 	memcpy(var, name, name_len);
49 
50 	var[name_len] = '=';
51 
52 	memcpy(var + name_len + 1, value, value_len);
53 
54 	var[name_len + 1 + value_len] = '\0';
55 
56 	return putenv(var);
57 }
58 /* }}} */
59 # endif
60 #endif
61 
62 #ifndef HAVE_CLEARENV
clearenv()63 void clearenv() /* {{{ */
64 {
65 	char **envp;
66 	char *s;
67 
68 	/* this algo is the only one known to me
69 		that works well on all systems */
70 	while (*(envp = environ)) {
71 		char *eq = strchr(*envp, '=');
72 
73 		s = strdup(*envp);
74 
75 		if (eq) s[eq - *envp] = '\0';
76 
77 		unsetenv(s);
78 		free(s);
79 	}
80 
81 }
82 /* }}} */
83 #endif
84 
85 #ifndef HAVE_UNSETENV
unsetenv(const char * name)86 void unsetenv(const char *name) /* {{{ */
87 {
88 	if(getenv(name) != NULL) {
89 		int ct = 0;
90 		int del = 0;
91 
92 		while(environ[ct] != NULL) {
93 			if (nvmatch(name, environ[ct]) != 0) del=ct; /* <--- WTF?! */
94 			{ ct++; } /* <--- WTF?! */
95 		}
96 		/* isn't needed free here?? */
97 		environ[del] = environ[ct-1];
98 		environ[ct-1] = NULL;
99 	}
100 }
101 /* }}} */
102 
nvmatch(char * s1,char * s2)103 static char * nvmatch(char *s1, char *s2) /* {{{ */
104 {
105 	while(*s1 == *s2++)
106 	{
107 		if(*s1++ == '=') {
108 			return s2;
109 		}
110 	}
111 	if(*s1 == '\0' && *(s2-1) == '=') {
112 		return s2;
113 	}
114 	return NULL;
115 }
116 /* }}} */
117 #endif
118 
fpm_env_setproctitle(char * title)119 void fpm_env_setproctitle(char *title) /* {{{ */
120 {
121 #if defined(HAVE_SETPROCTITLE_FAST)
122 	setproctitle_fast("%s", title);
123 #elif defined(HAVE_SETPROCTITLE)
124 	setproctitle("%s", title);
125 #else
126 #ifdef __linux__
127 	if (fpm_env_argv != NULL && fpm_env_argv_len > strlen(SETPROCTITLE_PREFIX) + 3) {
128 		memset(fpm_env_argv[0], 0, fpm_env_argv_len);
129 		strncpy(fpm_env_argv[0], SETPROCTITLE_PREFIX, fpm_env_argv_len - 2);
130 		strncpy(fpm_env_argv[0] + strlen(SETPROCTITLE_PREFIX), title, fpm_env_argv_len - strlen(SETPROCTITLE_PREFIX) - 2);
131 		fpm_env_argv[1] = NULL;
132 	}
133 #endif
134 #endif
135 }
136 /* }}} */
137 
fpm_env_init_child(struct fpm_worker_pool_s * wp)138 int fpm_env_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
139 {
140 	struct key_value_s *kv;
141 	char *title;
142 	spprintf(&title, 0, "pool %s", wp->config->name);
143 	fpm_env_setproctitle(title);
144 	efree(title);
145 
146 	if (wp->config->clear_env) {
147 		clearenv();
148 	}
149 
150 	for (kv = wp->config->env; kv; kv = kv->next) {
151 		setenv(kv->key, kv->value, 1);
152 	}
153 
154 	if (wp->user) {
155 		setenv("USER", wp->user, 1);
156 	}
157 
158 	if (wp->home) {
159 		setenv("HOME", wp->home, 1);
160 	}
161 
162 	return 0;
163 }
164 /* }}} */
165 
fpm_env_conf_wp(struct fpm_worker_pool_s * wp)166 static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
167 {
168 	struct key_value_s *kv;
169 
170 	for (kv = wp->config->env; kv; kv = kv->next) {
171 		if (*kv->value == '$') {
172 			char *value = getenv(kv->value + 1);
173 
174 			if (!value) {
175 				value = "";
176 			}
177 
178 			free(kv->value);
179 			kv->value = strdup(value);
180 		}
181 
182 		/* autodetected values should be removed
183 			if these vars specified in config */
184 		if (!strcmp(kv->key, "USER")) {
185 			free(wp->user);
186 			wp->user = 0;
187 		}
188 
189 		if (!strcmp(kv->key, "HOME")) {
190 			free(wp->home);
191 			wp->home = 0;
192 		}
193 	}
194 
195 	return 0;
196 }
197 /* }}} */
198 
fpm_env_init_main()199 int fpm_env_init_main() /* {{{ */
200 {
201 	struct fpm_worker_pool_s *wp;
202 	int i;
203 	char *first = NULL;
204 	char *last = NULL;
205 	char *title;
206 
207 	for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
208 		if (0 > fpm_env_conf_wp(wp)) {
209 			return -1;
210 		}
211 	}
212 #ifndef HAVE_SETPROCTITLE
213 #ifdef __linux__
214 	/*
215 	 * This piece of code has been inspirated from nginx and pureftpd code, which
216 	 * are under BSD licence.
217 	 *
218 	 * To change the process title in Linux we have to set argv[1] to NULL
219 	 * and to copy the title to the same place where the argv[0] points to.
220 	 * However, argv[0] may be too small to hold a new title.  Fortunately, Linux
221 	 * store argv[] and environ[] one after another.  So we should ensure that is
222 	 * the continuous memory and then we allocate the new memory for environ[]
223 	 * and copy it.  After this we could use the memory starting from argv[0] for
224 	 * our process title.
225 	 */
226 
227 	for (i = 0; i < fpm_globals.argc; i++) {
228 		if (first == NULL) {
229 			first = fpm_globals.argv[i];
230 		}
231 		if (last == NULL || fpm_globals.argv[i] == last + 1) {
232 			last = fpm_globals.argv[i] + strlen(fpm_globals.argv[i]);
233 		}
234 	}
235 	if (environ) {
236 		for (i = 0; environ[i]; i++) {
237 			if (first == NULL) {
238 				first = environ[i];
239 			}
240 			if (last == NULL || environ[i] == last + 1) {
241 				last = environ[i] + strlen(environ[i]);
242 			}
243 		}
244 	}
245 	if (first == NULL || last == NULL) {
246 		return 0;
247 	}
248 
249 	fpm_env_argv_len = last - first;
250 	fpm_env_argv = fpm_globals.argv;
251 	if (environ != NULL) {
252 		char **new_environ;
253 		unsigned int env_nb = 0U;
254 
255 		while (environ[env_nb]) {
256 			env_nb++;
257 		}
258 
259 		if ((new_environ = malloc((1U + env_nb) * sizeof (char *))) == NULL) {
260 			return -1;
261 		}
262 		new_environ[env_nb] = NULL;
263 		while (env_nb > 0U) {
264 			env_nb--;
265 			new_environ[env_nb] = strdup(environ[env_nb]);
266 		}
267 		environ = new_environ;
268 	}
269 #endif
270 #endif
271 
272 	spprintf(&title, 0, "master process (%s)", fpm_globals.config);
273 	fpm_env_setproctitle(title);
274 	efree(title);
275 	return 0;
276 }
277 /* }}} */
278