2b27401156c9b697a1bffa1c23942e67515ed7fb
[platform/core/system/tizen-platform-wrapper.git] / src / tzplatform_config.c
1 /*
2  * Copyright (C) 2013 Intel Corporation.
3  * 
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors:
19  *   José Bollo <jose.bollo@open.eurogiciel.org>
20  *   Stéphane Desneux <stephane.desneux@open.eurogiciel.org>
21  *   Jean-Benoit Martin <jean-benoit.martin@open.eurogiciel.org>
22  *
23  */
24 #define _GNU_SOURCE
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <pthread.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #include <stdarg.h>
40 #include <alloca.h>
41 #include <pwd.h>
42
43 #ifndef NOT_MULTI_THREAD_SAFE
44 #include <pthread.h>
45 #endif
46
47 #ifndef CONFIGPATH
48 #define CONFIGPATH "/etc/tizen-platform.conf"
49 #endif
50
51 #include "tzplatform_variables.h"
52 #include "tzplatform_config.h"
53 #include "parser.h"
54 #include "heap.h"
55 #include "buffer.h"
56 #include "foreign.h"
57 #include "scratch.h"
58 #include "passwd.h"
59
60 #define _HAS_IDS_   (  _FOREIGN_HAS_(UID)  \
61                     || _FOREIGN_HAS_(EUID) \
62                     || _FOREIGN_HAS_(GID)  )
63
64 #define _HAS_PWS_   (  _FOREIGN_HAS_(HOME)  \
65                     || _FOREIGN_HAS_(USER)  \
66                     || _FOREIGN_HAS_(EHOME) \
67                     || _FOREIGN_HAS_(EUSER) )
68
69 #define _USER_NOT_SET_  ((uid_t)-1)
70
71 /* local and static variables */
72 static const char metafilepath[] = CONFIGPATH;
73 static const char emptystring[] = "";
74 static const char *var_names[_TZPLATFORM_VARIABLES_COUNT_];
75
76 enum STATE { RESET=0, ERROR, VALID };
77
78 struct tzplatform_context {
79 #ifndef NOT_MULTI_THREAD_SAFE
80     pthread_mutex_t mutex;
81 #endif
82     enum STATE state;
83     uid_t user;
84     struct heap heap;
85     const char *values[_TZPLATFORM_VARIABLES_COUNT_];
86 };
87
88 /* structure for reading config files */
89 struct reading {
90     int errcount;
91     struct tzplatform_context *context;
92     size_t dynvars[_FOREIGN_COUNT_];
93     size_t offsets[_TZPLATFORM_VARIABLES_COUNT_];
94 };
95
96 static struct tzplatform_context global_context = {
97 #ifndef NOT_MULTI_THREAD_SAFE
98     .mutex = PTHREAD_MUTEX_INITIALIZER,
99 #endif
100     .state = RESET,
101     .user = _USER_NOT_SET_
102 };
103
104 #include "hash.inc"
105
106 /* write the error message */
107 static void writerror( const char *format, ...)
108 {
109     va_list ap;
110     fprintf( stderr, "tzplatform_config ERROR: ");
111     va_start(ap, format);
112     vfprintf(stderr, format, ap);
113     va_end(ap);
114     fprintf( stderr, "\n");
115 }
116
117 static uid_t get_uid(struct tzplatform_context *context)
118 {
119     uid_t result;
120
121     result = context->user;
122     if (result == _USER_NOT_SET_)
123         result = getuid();
124
125     return result;
126 }
127
128 #if _FOREIGN_HAS_(EUID)
129 static uid_t get_euid(struct tzplatform_context *context)
130 {
131     uid_t result;
132
133     result = context->user;
134     if (result == _USER_NOT_SET_)
135         result = geteuid();
136
137     return result;
138 }
139 #endif
140
141 #if _FOREIGN_HAS_(GID)
142 static gid_t get_gid(struct tzplatform_context *context)
143 {
144     return getgid();
145 }
146 #endif
147
148 #if _HAS_IDS_
149 /* fill the foreign variables for ids */
150 static void foreignid( struct reading *reading)
151 {
152     int n;
153     char buffer[50];
154
155 #if _FOREIGN_HAS_(UID)
156     /* set the uid */
157     if (reading->dynvars[UID] == HNULL) {
158         n = snprintf( buffer, sizeof buffer, "%d", (int)get_uid(reading->context));
159         if (0 < n && n < (int)(sizeof buffer))
160             reading->dynvars[UID] = heap_strndup( &reading->context->heap, buffer, (size_t)n);
161     }
162 #endif
163
164 #if _FOREIGN_HAS_(EUID)
165     /* set the euid */
166     if (reading->dynvars[EUID] == HNULL) {
167         n = snprintf( buffer, sizeof buffer, "%d", (int)get_euid(reading->context));
168         if (0 < n && n < (int)(sizeof buffer))
169             reading->dynvars[EUID] = heap_strndup( &reading->context->heap, buffer, (size_t)n);
170     }
171 #endif
172
173 #if _FOREIGN_HAS_(GID)
174     /* set the gid */
175     if (reading->dynvars[GID] == HNULL) {
176         n = snprintf( buffer, sizeof buffer, "%d", (int)get_gid(reading->context));
177         if (0 < n && n < (int)(sizeof buffer))
178             reading->dynvars[GID] = heap_strndup( &reading->context->heap, buffer, (size_t)n);
179     }
180 #endif
181 }
182 #endif
183
184 #if _HAS_PWS_
185 /* fill the foreign variables for home and user */
186 static void foreignpw( struct reading *reading)
187 {
188     int n = 0;
189     struct pwget *array[3];
190 #if _FOREIGN_HAS_(HOME) || _FOREIGN_HAS_(USER)
191     struct pwget uid;
192     char suid[50];
193 #endif
194 #if _FOREIGN_HAS_(EHOME) || _FOREIGN_HAS_(EUSER)
195     struct pwget euid;
196     char seuid[50];
197 #endif
198
199 #if _FOREIGN_HAS_(HOME) || _FOREIGN_HAS_(USER)
200     if (
201 #if _FOREIGN_HAS_(HOME)
202         reading->dynvars[HOME] == HNULL
203 #endif
204 #if _FOREIGN_HAS_(HOME) && _FOREIGN_HAS_(USER)
205         ||
206 #endif
207 #if _FOREIGN_HAS_(USER)
208         reading->dynvars[USER] == HNULL
209 #endif
210     ) {
211         snprintf( suid, sizeof suid, "%u", (unsigned)get_uid(reading->context));
212         uid.id = suid;
213         array[n++] = &uid;
214     }
215     else {
216         uid.set = 0;
217     }
218 #endif
219
220 #if _FOREIGN_HAS_(EHOME) || _FOREIGN_HAS_(EUSER)
221     if (
222 #if _FOREIGN_HAS_(EHOME)
223         reading->dynvars[EHOME] == HNULL
224 #endif
225 #if _FOREIGN_HAS_(EHOME) && _FOREIGN_HAS_(USER)
226         ||
227 #endif
228 #if _FOREIGN_HAS_(EUSER)
229         reading->dynvars[EUSER] == HNULL
230 #endif
231     ) {
232         snprintf( seuid, sizeof seuid, "%u", (unsigned)get_euid(reading->context));
233         euid.id = seuid;
234         array[n++] = &euid;
235     }
236     else {
237         euid.set = 0;
238     }
239 #endif
240
241     if (n) {
242         array[n] = NULL;
243         if (pw_get( &reading->context->heap, array) == 0) {
244 #if _FOREIGN_HAS_(HOME)
245             if (uid.set)
246                 reading->dynvars[HOME] = uid.home;
247 #endif
248 #if _FOREIGN_HAS_(USER)
249             if (uid.set)
250                 reading->dynvars[USER] = uid.user;
251 #endif
252 #if _FOREIGN_HAS_(EHOME)
253             if (euid.set)
254                 reading->dynvars[EHOME] = euid.home;
255 #endif
256 #if _FOREIGN_HAS_(EUSER)
257             if (euid.set)
258                 reading->dynvars[EUSER] = euid.user;
259 #endif
260         }
261     }
262 }
263 #endif
264
265 /* get the foreign variable */
266 static const char *foreignvar( struct reading *reading, 
267                                             const char *name, size_t length)
268 {
269     enum fkey key = foreign( name, length);
270     size_t offset;
271
272     switch (key) {
273 #if _HAS_PWS_
274 #if _FOREIGN_HAS_(HOME)
275     case HOME:
276 #endif
277 #if _FOREIGN_HAS_(USER)
278     case USER:
279 #endif
280 #if _FOREIGN_HAS_(EHOME)
281     case EHOME:
282 #endif
283 #if _FOREIGN_HAS_(EUSER)
284     case EUSER:
285 #endif
286         foreignpw( reading);
287         break;
288 #endif
289  
290 #if _HAS_IDS_
291 #if _FOREIGN_HAS_(UID)
292     case UID:
293 #endif
294 #if _FOREIGN_HAS_(GID)
295     case GID:
296 #endif
297 #if _FOREIGN_HAS_(EUID)
298     case EUID:
299 #endif
300         foreignid( reading);
301         break;
302 #endif
303
304     default:
305         return NULL;
306     }
307     offset = reading->dynvars[key];
308     return offset==HNULL ? NULL : heap_address( &reading->context->heap, offset);
309 }
310
311 /* callback for parsing errors */
312 static int errcb( struct parsing *parsing, 
313             size_t position, const char *message)
314 {
315     struct parsinfo info;
316     struct reading *reading = parsing->data;
317
318     /* count the error */
319     reading->errcount++;
320
321     /* print the error */
322     parse_utf8_info( parsing, &info, position);
323     writerror( "%s (file %s line %d)", message, metafilepath, info.lino);
324
325     /* continue to parse */
326     return 0;
327 }
328
329 /* callback for solving variables */
330 static const char *getcb( struct parsing *parsing, 
331             const char *key, size_t length,
332             size_t begin_pos, size_t end_pos)
333 {
334     struct parsinfo info;
335     const char *result;
336     const struct varassoc *vara;
337     size_t offset;
338     struct reading *reading = parsing->data;
339
340     /* try to find a tzplatform variable */
341     vara = hashvar( key, length);
342     if (vara) {
343         /* found: try to use it */
344         offset = reading->offsets[(int)vara->id];
345         if (offset != HNULL)
346             result = heap_address( &reading->context->heap, offset);
347         else 
348             result = NULL;
349     }
350     else {
351         /* that is a foreign variable */
352         result = foreignvar( reading, key, length);
353     }
354
355     /* emit the error and then return */
356     if (result == NULL) {
357         reading->errcount++;
358         parse_utf8_info( parsing, &info, begin_pos);
359         writerror( "undefined value for %.*s (file %s line %d)",
360             length, key, metafilepath, info.lino);
361         result = emptystring; /* avoid error of the parser */
362     }
363     return result;
364 }
365
366 /* callback to define variables */
367 static int putcb( struct parsing *parsing, 
368             const char *key, size_t key_length, 
369             const char *value, size_t value_length,
370             size_t begin_pos, size_t end_pos)
371 {
372     struct parsinfo info;
373     const struct varassoc *vara;
374     size_t offset;
375     char *string;
376     struct reading *reading = parsing->data;
377
378     /* try to find a tzplatform variable */
379     vara = hashvar( key, key_length);
380     if (vara) {
381         /* check that the variable isn't already defined */
382         offset = reading->offsets[(int)vara->id];
383         if (offset != HNULL) {
384             reading->errcount++;
385             parse_utf8_info( parsing, &info, begin_pos);
386             writerror( "redefinition of variable %.*s (file %s line %d)",
387                     key_length, key, metafilepath, info.lino);
388         }
389
390         /* allocate the variable value */
391         offset = heap_alloc( &reading->context->heap, value_length+1);
392         if (offset == HNULL) {
393             /* error of allocation */
394             reading->errcount++;
395             writerror( "out of memory");
396         }
397         else {
398             /* record the variable value */
399             reading->offsets[(int)vara->id] = offset;
400             string = heap_address( &reading->context->heap, offset);
401             memcpy( string, value, value_length);
402             string[value_length] = 0;
403         }
404     }
405     else {
406         /* forbidden variable */
407         parse_utf8_info( parsing, &info, begin_pos);
408         writerror( "forbidden variable name %.*s (file %s line %d)",
409             key_length, key, metafilepath, info.lino);
410         
411     }
412
413     /* continue to parse */
414     return 0;
415 }
416
417 /* initialize the environment */
418 static void initialize(struct tzplatform_context *context)
419 {
420     struct buffer buffer;
421     struct parsing parsing;
422     struct reading reading;
423     size_t offset;
424     int i, result;
425
426     /* clear the variables */
427     reading.errcount = 0;
428     reading.context = context;
429     for (i = 0 ; i < (int)_FOREIGN_COUNT_ ; i++) {
430         reading.dynvars[i] = HNULL;
431     }
432     for (i = 0 ; i < (int)_TZPLATFORM_VARIABLES_COUNT_ ; i++) {
433         context->values[i] = NULL;
434         reading.offsets[i] = HNULL;
435     }
436
437     /* read the configuration file */
438     result = buffer_create( &buffer, metafilepath);
439     if (result != 0) {
440         writerror( "can't read file %s",metafilepath);
441         context->state = ERROR;
442         return;
443     }
444
445     /* create the heap */
446     result = heap_create( &context->heap, 1);
447     if (result != 0) {
448         buffer_destroy( &buffer);
449         writerror( "out of memory");
450         context->state = ERROR;
451         return;
452     }
453
454     /* read the file */
455     parsing.buffer = buffer.buffer;
456     parsing.length = buffer.length;
457     parsing.maximum_data_size = 0;
458     parsing.should_escape = 0;
459     parsing.data = &reading;
460     parsing.get = getcb;
461     parsing.put = putcb;
462     parsing.error = errcb;
463     result = parse_utf8_config( &parsing);
464     buffer_destroy( &buffer);
465     if (result != 0 || reading.errcount != 0) {
466         writerror( "%d errors while parsing file %s",
467                                             reading.errcount, metafilepath);
468     }
469
470     /* set the variables */
471     heap_read_only( &context->heap);
472     for (i = 0 ; i < (int)_TZPLATFORM_VARIABLES_COUNT_ ; i++) {
473         offset = reading.offsets[i];
474         if (offset != HNULL)
475             context->values[i] = heap_address( &context->heap, offset);
476         else
477             writerror( "the variable %s isn't defined in file %s",
478                 tzplatform_getname((enum tzplatform_variable)i), metafilepath);
479             /* TODO undefined variable */;
480     }
481     context->state = VALID;
482 }
483
484 inline static void lock(struct tzplatform_context *context)
485 {
486 #ifndef NOT_MULTI_THREAD_SAFE
487     pthread_mutex_lock( &context->mutex);
488 #endif
489 }
490
491 inline static void unlock(struct tzplatform_context *context)
492 {
493 #ifndef NOT_MULTI_THREAD_SAFE
494     pthread_mutex_unlock( &context->mutex);
495 #endif
496 }
497
498 static const char *get_lock(struct tzplatform_context *context, enum tzplatform_variable id)
499 {
500     const char *result;
501     int offset;
502
503     lock( context);
504     offset = (int)id;
505     if (offset < 0 || (int)_TZPLATFORM_VARIABLES_COUNT_ <= offset) {
506         /*error("invalid id"); TODO*/
507         result = NULL;
508     }
509     else {
510         if (context->state == RESET)
511             initialize( context);
512         result = context->state == ERROR ? NULL : context->values[offset];
513     }
514     return result;
515 }
516
517 int tzplatform_context_create(struct tzplatform_context **result)
518 {
519     struct tzplatform_context *context;
520
521     context = malloc( sizeof * context);
522     *result = context;
523     if (context == NULL)
524         return -1;
525
526     context->state = RESET;
527     context->user = _USER_NOT_SET_;
528 #ifndef NOT_MULTI_THREAD_SAFE
529     pthread_mutex_init( &context->mutex, NULL);
530 #endif
531     return 0;
532 }
533
534 void tzplatform_context_destroy(struct tzplatform_context *context)
535 {
536     if (context->state == VALID)
537             heap_destroy( &context->heap);
538     context->state = ERROR;
539     free( context);
540 }
541
542 void tzplatform_reset()
543 {
544     tzplatform_context_reset( &global_context);
545 }
546
547 void tzplatform_context_reset(struct tzplatform_context *context)
548 {
549     lock( context);
550     if (context->state != RESET) {
551         if (context->state == VALID)
552             heap_destroy( &context->heap);
553         context->state = RESET;
554     }
555     unlock( context);
556 }
557
558 int tzplatform_getcount()
559 {
560     return (int)_TZPLATFORM_VARIABLES_COUNT_;
561 }
562
563 const char* tzplatform_getname(enum tzplatform_variable id)
564 {
565     const struct varassoc *iter, *end;
566     const char *result;
567     int offset;
568
569     offset = (int)id;
570     if (offset < 0 || (int)_TZPLATFORM_VARIABLES_COUNT_ <= offset) {
571         /*error("invalid id"); TODO*/
572         result = NULL;
573     }
574     else {
575         if (!var_names[0]) {
576             iter = namassoc;
577             end = iter + (sizeof namassoc / sizeof namassoc[0]);
578             while (iter != end) {
579                 if (iter->offset >= 0) 
580                     var_names[(int)iter->id] = varpool + iter->offset;
581                 iter++;
582             }
583         }
584         result = var_names[offset];
585     }
586     return result;
587 }
588
589 enum tzplatform_variable tzplatform_getid(const char *name)
590 {
591     const struct varassoc *vara = hashvar( name, strlen(name));
592     return vara ? vara->id : _TZPLATFORM_VARIABLES_INVALID_;
593 }
594
595 const char* tzplatform_getenv(enum tzplatform_variable id) 
596 {
597     return tzplatform_context_getenv( &global_context, id);
598 }
599
600 const char* tzplatform_context_getenv(struct tzplatform_context *context, enum tzplatform_variable id)
601 {
602     const char *array[2];
603     const char *result = get_lock( context, id);
604     if (result != NULL) {
605         array[0] = result;
606         array[1] = NULL;
607         result = scratchcat( 0, array);
608     }
609     unlock( context);
610     return result;
611 }
612
613 int tzplatform_getenv_int(enum tzplatform_variable id)
614 {
615     return tzplatform_context_getenv_int( &global_context, id);
616 }
617
618 int tzplatform_context_getenv_int(struct tzplatform_context *context, enum tzplatform_variable id)
619 {
620     const char *value = get_lock( context, id);
621     int result = value==NULL ? -1 : atoi(value);
622     unlock( context);
623     return result;
624 }
625
626 const char* tzplatform_mkstr(enum tzplatform_variable id, const char * str)
627 {
628     return tzplatform_context_mkstr( &global_context, id, str);
629 }
630
631 const char* tzplatform_context_mkstr(struct tzplatform_context *context, enum tzplatform_variable id, const char *str)
632 {
633     const char *array[3];
634     const char *result = get_lock( context, id);
635     if (result != NULL) {
636         array[0] = result;
637         array[1] = str;
638         array[2] = NULL;
639         result = scratchcat( 0, array);
640     }
641     unlock( context);
642     return result;
643 }
644
645 const char* tzplatform_mkpath(enum tzplatform_variable id, const char * path)
646 {
647     return tzplatform_context_mkpath( &global_context, id, path);
648 }
649
650 const char* tzplatform_context_mkpath(struct tzplatform_context *context, enum tzplatform_variable id, const char *path)
651 {
652     const char *array[3];
653     const char *result = get_lock( context, id);
654     if (result != NULL) {
655         array[0] = result;
656         array[1] = path;
657         array[2] = NULL;
658         result = scratchcat( 1, array);
659     }
660     unlock( context);
661     return result;
662 }
663
664 const char* tzplatform_mkpath3(enum tzplatform_variable id, const char * path,
665                                                         const char* path2)
666 {
667     return tzplatform_context_mkpath3( &global_context, id, path, path2);
668 }
669
670 const char* tzplatform_context_mkpath3(struct tzplatform_context *context, enum tzplatform_variable id, const char *path,
671                                                             const char *path2)
672 {
673     const char *array[4];
674     const char *result = get_lock( context, id);
675     if (result != NULL) {
676         array[0] = result;
677         array[1] = path;
678         array[2] = path2;
679         array[3] = NULL;
680         result = scratchcat( 1, array);
681     }
682     unlock( context);
683     return result;
684 }
685
686 const char* tzplatform_mkpath4(enum tzplatform_variable id, const char * path,
687                                           const char* path2, const char *path3)
688 {
689     return tzplatform_context_mkpath4( &global_context, id, path, path2, path3);
690 }
691
692 const char* tzplatform_context_mkpath4(struct tzplatform_context *context, enum tzplatform_variable id, const char *path,
693                                         const char *path2, const char *path3)
694 {
695     const char *array[5];
696     const char *result = get_lock( context, id);
697     if (result != NULL) {
698         array[0] = result;
699         array[1] = path;
700         array[2] = path2;
701         array[3] = path3;
702         array[4] = NULL;
703         result = scratchcat( 1, array);
704     }
705     unlock( context);
706     return result;
707 }
708
709 uid_t tzplatform_getuid(enum tzplatform_variable id)
710 {
711     return tzplatform_context_getuid( &global_context, id);
712 }
713
714 uid_t tzplatform_context_getuid(struct tzplatform_context *context, enum tzplatform_variable id)
715 {
716     uid_t result = (uid_t)-1;
717     const char *value = get_lock( context, id);
718     if (value != NULL) {
719         pw_get_uid( value, &result);
720     }
721     unlock( context);
722     return result;
723 }
724
725 gid_t tzplatform_getgid(enum tzplatform_variable id)
726 {
727     return tzplatform_context_getgid( &global_context, id);
728 }
729
730 gid_t tzplatform_context_getgid(struct tzplatform_context *context, enum tzplatform_variable id)
731 {
732     gid_t result = (uid_t)-1;
733     const char *value = get_lock( context, id);
734     if (value != NULL) {
735         pw_get_gid( value, &result);
736     }
737     unlock( context);
738     return result;
739 }
740
741 int tzplatform_set_user(uid_t uid)
742 {
743     return tzplatform_context_set_user( &global_context, uid);
744 }
745
746 int tzplatform_context_set_user(struct tzplatform_context *context, uid_t uid)
747 {
748     int result;
749
750     result = 0;
751     lock( context);
752     if (context->user != uid) {
753             if (uid != _USER_NOT_SET_ && !pw_has_uid( uid))
754             result = -1;
755         else {
756             if (context->state == VALID)
757                 heap_destroy( &context->heap);
758             context->state = RESET;
759             context->user = uid;
760         }
761     }
762     unlock( context);
763
764     return result;
765 }
766
767 uid_t tzplatform_get_user()
768 {
769     return tzplatform_context_get_user( &global_context);
770 }
771
772 uid_t tzplatform_context_get_user(struct tzplatform_context *context)
773 {
774     uid_t result;
775
776     lock( context);
777     result = get_uid( context);
778     unlock( context);
779
780     return result;
781 }
782
783 void tzplatform_reset_user()
784 {
785     tzplatform_context_reset_user( &global_context);
786 }
787
788 void tzplatform_context_reset_user(struct tzplatform_context *context)
789 {
790     tzplatform_context_set_user( context, _USER_NOT_SET_);
791 }
792
793 #ifdef TEST
794 int main() {
795     int i;
796     struct tzplatform_context *context;
797     enum tzplatform_variable id;
798     const char *name;
799     const char *value;
800     int xid;
801     uid_t uid;
802
803     i = 0;
804     while(i != tzplatform_getcount()) {
805         id = (enum tzplatform_variable)i;
806         name = tzplatform_getname(id);
807         value = tzplatform_getenv(id);
808         xid = (int)tzplatform_getid(name);
809         printf("%d=%d\t%s=%s\n",i,xid,name,value?value:"<null>");
810         i++;
811     }
812
813     printf("------------------------\n");
814     i = tzplatform_context_create(&context);
815     if (i) {
816         printf("error while creating context %d\n",i);
817         return 1;
818     }
819
820     uid = (uid_t)0;
821     i = tzplatform_context_set_user(context, uid);
822     if (i) {
823         printf("error %d while switching to user %d\n",i,(int)uid);
824         return 1;
825     }
826     i = 0;
827     while(i != tzplatform_getcount()) {
828         id = (enum tzplatform_variable)i;
829         name = tzplatform_getname(id);
830         value = tzplatform_context_getenv(context, id);
831         xid = (int)tzplatform_getid(name);
832         printf("%d=%d\t%s=%s\n",i,xid,name,value?value:"<null>");
833         i++;
834     }
835     tzplatform_context_destroy(context);
836
837     return 0;
838 }
839 #endif
840
841