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