1 /*
2 * Environment management routines for the CUPS scheduler.
3 *
4 * Copyright © 2020-2024 by OpenPrinting.
5 * Copyright © 2007-2016 by Apple Inc.
6 * Copyright © 1997-2006 by Easy Software Products, all rights reserved.
7 *
8 * Licensed under Apache License v2.0. See the file "LICENSE" for more
9 * information.
10 */
11
12 /*
13 * Include necessary headers...
14 */
15
16 #include "cupsd.h"
17
18
19 /*
20 * Local globals...
21 */
22
23 static int num_common_env = 0; /* Number of common env vars */
24 static char *common_env[MAX_ENV]; /* Common env vars */
25
26
27 /*
28 * Local functions...
29 */
30
31 static void clear_env(void);
32 static int find_env(const char *name);
33
34
35 /*
36 * 'cupsdInitEnv()' - Initialize the current environment with standard variables.
37 */
38
39 void
cupsdInitEnv(void)40 cupsdInitEnv(void)
41 {
42 /*
43 * Clear existing environment variables...
44 */
45
46 clear_env();
47
48 #if defined(__APPLE__)
49 /*
50 * Add special voodoo magic for macOS - this allows macOS
51 * programs to access their bundle resources properly...
52 *
53 * This string is replaced in cupsdStartProcess()...
54 */
55
56 cupsdSetString(common_env, "<CFProcessPath>");
57 num_common_env = 1;
58 #endif /* __APPLE__ */
59 }
60
61
62 /*
63 * 'cupsdLoadEnv()' - Copy common environment variables into an array.
64 */
65
66 int /* O - Number of environment variables */
cupsdLoadEnv(char * envp[],int envmax)67 cupsdLoadEnv(char *envp[], /* I - Environment array */
68 int envmax) /* I - Maximum number of elements */
69 {
70 int i; /* Looping var */
71
72
73 /*
74 * Leave room for a NULL pointer at the end...
75 */
76
77 envmax --;
78
79 /*
80 * Copy pointers to the environment...
81 */
82
83 for (i = 0; i < num_common_env && i < envmax; i ++)
84 envp[i] = common_env[i];
85
86 /*
87 * NULL terminate the environment array and return the number of
88 * elements we added...
89 */
90
91 envp[i] = NULL;
92
93 return (i);
94 }
95
96
97 /*
98 * 'cupsdSetEnv()' - Set a common environment variable.
99 */
100
101 void
cupsdSetEnv(const char * name,const char * value)102 cupsdSetEnv(const char *name, /* I - Name of variable */
103 const char *value) /* I - Value of variable */
104 {
105 int i; /* Index into environment array */
106
107
108 /*
109 * If "value" is NULL, try getting value from current environment...
110 */
111
112 if (!value)
113 value = getenv(name);
114
115 if (!value)
116 return;
117
118 /*
119 * Do not allow dynamic linker variables when running as root outside a Snap...
120 */
121
122 #if !CUPS_SNAP
123 if (!RunUser && (!strncmp(name, "DYLD_", 5) || !strncmp(name, "LD_", 3)))
124 return;
125 #endif /* !CUPS_SNAP */
126
127 /*
128 * See if this variable has already been defined...
129 */
130
131 if ((i = find_env(name)) < 0)
132 {
133 /*
134 * Check for room...
135 */
136
137 if (num_common_env >= (int)(sizeof(common_env) / sizeof(common_env[0])))
138 {
139 cupsdLogMessage(CUPSD_LOG_ERROR,
140 "cupsdSetEnv: Too many environment variables set!");
141 return;
142 }
143
144 i = num_common_env;
145 num_common_env ++;
146 }
147
148 /*
149 * Set the new environment variable...
150 */
151
152 cupsdSetStringf(common_env + i, "%s=%s", name, value);
153
154 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSetEnv: %s", common_env[i]);
155 }
156
157
158 /*
159 * 'cupsdSetEnvf()' - Set a formatted common environment variable.
160 */
161
162 void
cupsdSetEnvf(const char * name,const char * value,...)163 cupsdSetEnvf(const char *name, /* I - Name of variable */
164 const char *value, /* I - Printf-style value of variable */
165 ...) /* I - Additional args as needed */
166 {
167 char v[4096]; /* Formatting string value */
168 va_list ap; /* Argument pointer */
169
170
171 /*
172 * Format the value string...
173 */
174
175 va_start(ap, value);
176 vsnprintf(v, sizeof(v), value, ap);
177 va_end(ap);
178
179 /*
180 * Set the env variable...
181 */
182
183 cupsdSetEnv(name, v);
184 }
185
186
187 /*
188 * 'cupsdUpdateEnv()' - Update the environment for the configured directories.
189 */
190
191 void
cupsdUpdateEnv(void)192 cupsdUpdateEnv(void)
193 {
194 /*
195 * Set common variables...
196 */
197
198 #define set_if_undefined(name,value) if (find_env(name) < 0) cupsdSetEnv(name,value)
199
200 set_if_undefined("CUPS_CACHEDIR", CacheDir);
201 set_if_undefined("CUPS_DATADIR", DataDir);
202 set_if_undefined("CUPS_DOCROOT", DocumentRoot);
203 set_if_undefined("CUPS_REQUESTROOT", RequestRoot);
204 set_if_undefined("CUPS_SERVERBIN", ServerBin);
205 set_if_undefined("CUPS_SERVERROOT", ServerRoot);
206 set_if_undefined("CUPS_STATEDIR", StateDir);
207 set_if_undefined("DYLD_INSERT_LIBRARIES", NULL);
208 set_if_undefined("DYLD_LIBRARY_PATH", NULL);
209 set_if_undefined("HOME", TempDir);
210 set_if_undefined("LD_ASSUME_KERNEL", NULL);
211 set_if_undefined("LD_LIBRARY_PATH", NULL);
212 set_if_undefined("LD_PRELOAD", NULL);
213 set_if_undefined("NLSPATH", NULL);
214 if (find_env("PATH") < 0)
215 {
216 #if CUPS_SNAP
217 const char *path; // PATH environment variable
218
219 if ((path = getenv("PATH")) != NULL)
220 cupsdSetEnvf("PATH", "%s/filter:%s", ServerBin, path);
221 else
222 #endif /* CUPS_SNAP */
223 cupsdSetEnvf("PATH", "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin);
224 }
225 set_if_undefined("SERVER_ADMIN", ServerAdmin);
226 set_if_undefined("SHLIB_PATH", NULL);
227 set_if_undefined("SOFTWARE", CUPS_MINIMAL);
228 set_if_undefined("TMPDIR", TempDir);
229 set_if_undefined("TZ", NULL);
230 set_if_undefined("USER", "root");
231 set_if_undefined("VG_ARGS", NULL);
232
233 cupsdSetEnvf("CUPS_MAX_MESSAGE", "%d", CUPSD_SB_BUFFER_SIZE - 1);
234 }
235
236
237 /*
238 * 'clear_env()' - Clear common environment variables.
239 */
240
241 static void
clear_env(void)242 clear_env(void)
243 {
244 int i; /* Looping var */
245
246
247 for (i = 0; i < num_common_env; i ++)
248 cupsdClearString(common_env + i);
249
250 num_common_env = 0;
251 }
252
253
254 /*
255 * 'find_env()' - Find a common environment variable.
256 */
257
258 static int /* O - Index or -1 if not found */
find_env(const char * name)259 find_env(const char *name) /* I - Variable name */
260 {
261 int i; /* Looping var */
262 size_t namelen; /* Length of name */
263
264
265 for (i = 0, namelen = strlen(name); i < num_common_env; i ++)
266 if (!strncmp(common_env[i], name, namelen) && common_env[i][namelen] == '=')
267 return (i);
268
269 return (-1);
270 }
271