• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Global variable access routines for CUPS.
3  *
4  * Copyright 2007-2015 by Apple Inc.
5  * Copyright 1997-2007 by Easy Software Products, all rights reserved.
6  *
7  * These coded instructions, statements, and computer programs are the
8  * property of Apple Inc. and are protected by Federal copyright
9  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
10  * which should have been included with this file.  If this file is
11  * missing or damaged, see the license at "http://www.cups.org/".
12  *
13  * This file is subject to the Apple OS-Developed Software exception.
14  */
15 
16 /*
17  * Include necessary headers...
18  */
19 
20 #include "cups-private.h"
21 
22 
23 /*
24  * Local globals...
25  */
26 
27 #ifdef DEBUG
28 static int		cups_global_index = 0;
29 					/* Next thread number */
30 #endif /* DEBUG */
31 static _cups_threadkey_t cups_globals_key = _CUPS_THREADKEY_INITIALIZER;
32 					/* Thread local storage key */
33 #ifdef HAVE_PTHREAD_H
34 static pthread_once_t	cups_globals_key_once = PTHREAD_ONCE_INIT;
35 					/* One-time initialization object */
36 #endif /* HAVE_PTHREAD_H */
37 #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
38 static _cups_mutex_t	cups_global_mutex = _CUPS_MUTEX_INITIALIZER;
39 					/* Global critical section */
40 #endif /* HAVE_PTHREAD_H || _WIN32 */
41 
42 
43 /*
44  * Local functions...
45  */
46 
47 #ifdef _WIN32
48 static void		cups_fix_path(char *path);
49 #endif /* _WIN32 */
50 static _cups_globals_t	*cups_globals_alloc(void);
51 #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
52 static void		cups_globals_free(_cups_globals_t *g);
53 #endif /* HAVE_PTHREAD_H || _WIN32 */
54 #ifdef HAVE_PTHREAD_H
55 static void		cups_globals_init(void);
56 #endif /* HAVE_PTHREAD_H */
57 
58 
59 /*
60  * '_cupsGlobalLock()' - Lock the global mutex.
61  */
62 
63 void
_cupsGlobalLock(void)64 _cupsGlobalLock(void)
65 {
66 #ifdef HAVE_PTHREAD_H
67   pthread_mutex_lock(&cups_global_mutex);
68 #elif defined(_WIN32)
69   EnterCriticalSection(&cups_global_mutex.m_criticalSection);
70 #endif /* HAVE_PTHREAD_H */
71 }
72 
73 
74 /*
75  * '_cupsGlobals()' - Return a pointer to thread local storage
76  */
77 
78 _cups_globals_t *			/* O - Pointer to global data */
_cupsGlobals(void)79 _cupsGlobals(void)
80 {
81   _cups_globals_t *cg;			/* Pointer to global data */
82 
83 
84 #ifdef HAVE_PTHREAD_H
85  /*
86   * Initialize the global data exactly once...
87   */
88 
89   pthread_once(&cups_globals_key_once, cups_globals_init);
90 #endif /* HAVE_PTHREAD_H */
91 
92  /*
93   * See if we have allocated the data yet...
94   */
95 
96   if ((cg = (_cups_globals_t *)_cupsThreadGetData(cups_globals_key)) == NULL)
97   {
98    /*
99     * No, allocate memory as set the pointer for the key...
100     */
101 
102     if ((cg = cups_globals_alloc()) != NULL)
103       _cupsThreadSetData(cups_globals_key, cg);
104   }
105 
106  /*
107   * Return the pointer to the data...
108   */
109 
110   return (cg);
111 }
112 
113 
114 /*
115  * '_cupsGlobalUnlock()' - Unlock the global mutex.
116  */
117 
118 void
_cupsGlobalUnlock(void)119 _cupsGlobalUnlock(void)
120 {
121 #ifdef HAVE_PTHREAD_H
122   pthread_mutex_unlock(&cups_global_mutex);
123 #elif defined(_WIN32)
124   LeaveCriticalSection(&cups_global_mutex.m_criticalSection);
125 #endif /* HAVE_PTHREAD_H */
126 }
127 
128 
129 #ifdef _WIN32
130 /*
131  * 'DllMain()' - Main entry for library.
132  */
133 
134 BOOL WINAPI				/* O - Success/failure */
DllMain(HINSTANCE hinst,DWORD reason,LPVOID reserved)135 DllMain(HINSTANCE hinst,		/* I - DLL module handle */
136         DWORD     reason,		/* I - Reason */
137         LPVOID    reserved)		/* I - Unused */
138 {
139   _cups_globals_t *cg;			/* Global data */
140 
141 
142   (void)hinst;
143   (void)reserved;
144 
145   switch (reason)
146   {
147     case DLL_PROCESS_ATTACH :		/* Called on library initialization */
148         InitializeCriticalSection(&cups_global_mutex.m_criticalSection);
149 
150         if ((cups_globals_key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
151           return (FALSE);
152         break;
153 
154     case DLL_THREAD_DETACH :		/* Called when a thread terminates */
155         if ((cg = (_cups_globals_t *)TlsGetValue(cups_globals_key)) != NULL)
156           cups_globals_free(cg);
157         break;
158 
159     case DLL_PROCESS_DETACH :		/* Called when library is unloaded */
160         if ((cg = (_cups_globals_t *)TlsGetValue(cups_globals_key)) != NULL)
161           cups_globals_free(cg);
162 
163         TlsFree(cups_globals_key);
164         DeleteCriticalSection(&cups_global_mutex.m_criticalSection);
165         break;
166 
167     default:
168         break;
169   }
170 
171   return (TRUE);
172 }
173 #endif /* _WIN32 */
174 
175 
176 /*
177  * 'cups_globals_alloc()' - Allocate and initialize global data.
178  */
179 
180 static _cups_globals_t *		/* O - Pointer to global data */
cups_globals_alloc(void)181 cups_globals_alloc(void)
182 {
183   _cups_globals_t *cg = malloc(sizeof(_cups_globals_t));
184 					/* Pointer to global data */
185 #ifdef _WIN32
186   HKEY		key;			/* Registry key */
187   DWORD		size;			/* Size of string */
188   static char	installdir[1024] = "",	/* Install directory */
189 		confdir[1024] = "",	/* Server root directory */
190 		localedir[1024] = "";	/* Locale directory */
191 #endif /* _WIN32 */
192 
193 
194   if (!cg)
195     return (NULL);
196 
197  /*
198   * Clear the global storage and set the default encryption and password
199   * callback values...
200   */
201 
202   memset(cg, 0, sizeof(_cups_globals_t));
203   cg->encryption     = (http_encryption_t)-1;
204   cg->password_cb    = (cups_password_cb2_t)_cupsGetPassword;
205   cg->trust_first    = -1;
206   cg->any_root       = -1;
207   cg->expired_certs  = -1;
208   cg->validate_certs = -1;
209 
210 #ifdef DEBUG
211  /*
212   * Friendly thread ID for debugging...
213   */
214 
215   cg->thread_id = ++ cups_global_index;
216 #endif /* DEBUG */
217 
218  /*
219   * Then set directories as appropriate...
220   */
221 
222 #ifdef _WIN32
223   if (!installdir[0])
224   {
225    /*
226     * Open the registry...
227     */
228 
229     strlcpy(installdir, "C:/Program Files/cups.org", sizeof(installdir));
230 
231     if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\cups.org", 0, KEY_READ,
232                       &key))
233     {
234      /*
235       * Grab the installation directory...
236       */
237 
238       char  *ptr;			/* Pointer into installdir */
239 
240       size = sizeof(installdir);
241       RegQueryValueEx(key, "installdir", NULL, NULL, installdir, &size);
242       RegCloseKey(key);
243 
244       for (ptr = installdir; *ptr;)
245       {
246         if (*ptr == '\\')
247         {
248           if (ptr[1])
249             *ptr++ = '/';
250           else
251             *ptr = '\0';		/* Strip trailing \ */
252         }
253         else if (*ptr == '/' && !ptr[1])
254           *ptr = '\0';			/* Strip trailing / */
255         else
256           ptr ++;
257       }
258     }
259 
260     snprintf(confdir, sizeof(confdir), "%s/conf", installdir);
261     snprintf(localedir, sizeof(localedir), "%s/locale", installdir);
262   }
263 
264   if ((cg->cups_datadir = getenv("CUPS_DATADIR")) == NULL)
265     cg->cups_datadir = installdir;
266 
267   if ((cg->cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
268     cg->cups_serverbin = installdir;
269 
270   if ((cg->cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
271     cg->cups_serverroot = confdir;
272 
273   if ((cg->cups_statedir = getenv("CUPS_STATEDIR")) == NULL)
274     cg->cups_statedir = confdir;
275 
276   if ((cg->localedir = getenv("LOCALEDIR")) == NULL)
277     cg->localedir = localedir;
278 
279 #else
280 #  ifdef HAVE_GETEUID
281   if ((geteuid() != getuid() && getuid()) || getegid() != getgid())
282 #  else
283   if (!getuid())
284 #  endif /* HAVE_GETEUID */
285   {
286    /*
287     * When running setuid/setgid, don't allow environment variables to override
288     * the directories...
289     */
290 
291     cg->cups_datadir    = CUPS_DATADIR;
292     cg->cups_serverbin  = CUPS_SERVERBIN;
293     cg->cups_serverroot = CUPS_SERVERROOT;
294     cg->cups_statedir   = CUPS_STATEDIR;
295     cg->localedir       = CUPS_LOCALEDIR;
296   }
297   else
298   {
299    /*
300     * Allow directories to be overridden by environment variables.
301     */
302 
303     if ((cg->cups_datadir = getenv("CUPS_DATADIR")) == NULL)
304       cg->cups_datadir = CUPS_DATADIR;
305 
306     if ((cg->cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
307       cg->cups_serverbin = CUPS_SERVERBIN;
308 
309     if ((cg->cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
310       cg->cups_serverroot = CUPS_SERVERROOT;
311 
312     if ((cg->cups_statedir = getenv("CUPS_STATEDIR")) == NULL)
313       cg->cups_statedir = CUPS_STATEDIR;
314 
315     if ((cg->localedir = getenv("LOCALEDIR")) == NULL)
316       cg->localedir = CUPS_LOCALEDIR;
317   }
318 #endif /* _WIN32 */
319 
320   return (cg);
321 }
322 
323 
324 /*
325  * 'cups_globals_free()' - Free global data.
326  */
327 
328 #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
329 static void
cups_globals_free(_cups_globals_t * cg)330 cups_globals_free(_cups_globals_t *cg)	/* I - Pointer to global data */
331 {
332   _cups_buffer_t	*buffer,	/* Current read/write buffer */
333 			*next;		/* Next buffer */
334 
335 
336   if (cg->last_status_message)
337     _cupsStrFree(cg->last_status_message);
338 
339   for (buffer = cg->cups_buffers; buffer; buffer = next)
340   {
341     next = buffer->next;
342     free(buffer);
343   }
344 
345   cupsArrayDelete(cg->leg_size_lut);
346   cupsArrayDelete(cg->ppd_size_lut);
347   cupsArrayDelete(cg->pwg_size_lut);
348 
349   httpClose(cg->http);
350 
351 #ifdef HAVE_SSL
352   _httpFreeCredentials(cg->tls_credentials);
353 #endif /* HAVE_SSL */
354 
355   cupsFileClose(cg->stdio_files[0]);
356   cupsFileClose(cg->stdio_files[1]);
357   cupsFileClose(cg->stdio_files[2]);
358 
359   cupsFreeOptions(cg->cupsd_num_settings, cg->cupsd_settings);
360 
361   free(cg);
362 }
363 #endif /* HAVE_PTHREAD_H || _WIN32 */
364 
365 
366 #ifdef HAVE_PTHREAD_H
367 /*
368  * 'cups_globals_init()' - Initialize environment variables.
369  */
370 
371 static void
cups_globals_init(void)372 cups_globals_init(void)
373 {
374  /*
375   * Register the global data for this thread...
376   */
377 
378   pthread_key_create(&cups_globals_key, (void (*)(void *))cups_globals_free);
379 }
380 #endif /* HAVE_PTHREAD_H */
381