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