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