Adding context and user switching 58/24658/1 accepted/tizen/common/20140724.001804 submit/tizen_common/20140723.151203 submit/tizen_ivi/20140729.000000 submit/tizen_ivi/20140729.000001 submit/tizen_ivi/20140730.000000
authorJosé Bollo <jose.bollo@open.eurogiciel.org>
Thu, 17 Jul 2014 10:41:46 +0000 (12:41 +0200)
committerJosé Bollo <jose.bollo@open.eurogiciel.org>
Thu, 17 Jul 2014 14:16:49 +0000 (16:16 +0200)
The main evolution is to able to switch the
user. It has the side effect to imply a context switch
that would make the code safe in multi-threaded context.

Added option --user to tzplatform_get.
This will allow to display data for a given user.

Change-Id: Ifeabfbce3821fda04707e6fc6bfa5a571e3c2ceb
Signed-off-by: José Bollo <jose.bollo@open.eurogiciel.org>
src/heap.c
src/passwd.c
src/passwd.h
src/scratch.c
src/tzplatform_config.c
src/tzplatform_config.h
src/tzplatform_get.c

index 6bca486..2e4365d 100644 (file)
@@ -45,9 +45,13 @@ inline static size_t align(size_t size)
 /* align to a page size */
 inline static size_t pagealign( size_t size)
 {
+    static size_t pagemask = 0;
     /* we assume that pagesize is a power of 2 */
-    size_t pagemask = (size_t)sysconf(_SC_PAGE_SIZE) - 1;
-    assert( (pagemask & (pagemask+1)) == 0 );
+    if (!pagemask) {
+       pagemask = (size_t)sysconf(_SC_PAGE_SIZE) - 1;
+       assert( pagemask );
+       assert( (pagemask & (pagemask+1)) == 0 );
+    }
     return (size + pagemask) & ~pagemask;
 }
 
index 20ae2c6..5aa32b8 100644 (file)
@@ -132,6 +132,20 @@ int pw_get( struct heap *heap, struct pwget **items)
     return result;
 }
 
+int pw_has_uid( uid_t uid)
+{
+    if (oppw() == 0) {
+        while (rdpw()) {
+            if (lengths[iuid] && (int)uid == atoi(starts[iuid])) {
+                clpw();
+                return 1;
+            }
+        }
+        clpw();
+    }
+    return 0;
+}
+
 int pw_get_uid( const char *name, uid_t *uid)
 {
     int result = oppw();
@@ -200,6 +214,16 @@ int pw_get( struct heap *heap, struct pwget **items)
     return 0;
 }
 
+int pw_has_uid( uid_t uid)
+{
+    char buffer[BUFSIZE];
+    struct passwd entry, *pe;
+    int result;
+
+    result = getpwuid_r( uid, &entry, buffer, sizeof buffer, &pe);
+    return !result && pe;
+}
+
 int pw_get_uid( const char *name, uid_t *uid)
 {
     char buffer[BUFSIZE];
index 23352fe..d3c1d1c 100644 (file)
@@ -34,6 +34,7 @@ struct pwget {
 int pw_get( struct heap *heap, struct pwget **items);
 int pw_get_uid( const char *name, uid_t *uid);
 int pw_get_gid( const char *name, gid_t *gid);
+int pw_has_uid( uid_t uid);
 
 #endif
 
index c5816f8..7c71da4 100644 (file)
 
 #define INSTANCIATE 1
 #if INSTANCIATE
-#define SET_CAPACITY           97
+#define SET_CAPACITY        97
 #define HASHCODE_INIT       5381
 #define HASHCODE_NEXT(H,C)  (((H) << 5) + (H) + (C))
-#ifndef NOT_MULTI_THREAD_SAFE
-#define NOT_MULTI_THREAD_SAFE
-#endif
 #endif
 
 #ifndef NOT_MULTI_THREAD_SAFE
 #include <pthread.h>
-static pthread_key_t tlskey;
-static int key_initialized = 0;
+#endif
+
+#if !(defined(NOT_MULTI_THREAD_SAFE) || INSTANCIATE)
+static __thread void *global_scratch = NULL;
 #else
 static void *global_scratch = NULL;
 #endif
+#if INSTANCIATE && !defined(NOT_MULTI_THREAD_SAFE)
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
 
 #if INSTANCIATE
 /* structure for recording items in the hash map */
 struct set_item {
-       struct set_item *next;  /* chain to next item */
-       size_t hashcode;                /* hash of the string */
-       size_t length;                  /* length of the string including null */
+    struct set_item *next;        /* chain to next item */
+    size_t hashcode;                /* hash of the string */
+    size_t length;                /* length of the string including null */
 };
 
 /* the array of recorded strings */
@@ -72,40 +74,40 @@ is granted to have the 'length' including terminating null and a
 hash code 'hashcode' */
 static const char *instantiate(const char *string, size_t length, size_t hashcode)
 {
-       struct set_item **pp, *item;
-       char *result;
-
-       /* get first item in the table */
-       pp = &global_path_set[hashcode % SET_CAPACITY];
-       result = 0;
-       do {
-               /* inspect the item */
-               item = *pp;
-               if (!item) {
-                       /* no item: create it */
-                       item = malloc(length + sizeof * item);
-                       if (!item)
-                               return NULL;
-                       /* init it */
-                       item->next = 0;
-                       item->hashcode = hashcode;
-                       item->length = length;
-                       result = (char *)(item + 1);
-                       memcpy(result, string, length);
-                       /* record it */
-                       *pp = item;
-               } else if (item->hashcode == hashcode
-                       && item->length == length
-                       && 0 == strcmp(string, (const char *)(item + 1))) {
-                       /* item found */
-                       result = (char *)(item + 1);
-               } else {
-                       /* try the next */
-                       pp = &item->next;
-               }
-       } while (!result);
-
-       return result;
+    struct set_item **pp, *item;
+    char *result;
+
+    /* get first item in the table */
+    pp = &global_path_set[hashcode % SET_CAPACITY];
+    result = 0;
+    do {
+        /* inspect the item */
+        item = *pp;
+        if (!item) {
+            /* no item: create it */
+            item = malloc(length + sizeof * item);
+            if (!item)
+                return NULL;
+            /* init it */
+            item->next = 0;
+            item->hashcode = hashcode;
+            item->length = length;
+            result = (char *)(item + 1);
+            memcpy(result, string, length);
+            /* record it */
+            *pp = item;
+        } else if (item->hashcode == hashcode
+                && item->length == length
+                && 0 == strcmp(string, (const char *)(item + 1))) {
+            /* item found */
+            result = (char *)(item + 1);
+        } else {
+            /* try the next */
+            pp = &item->next;
+        }
+    } while (!result);
+
+    return result;
 }
 #endif
 
@@ -114,27 +116,34 @@ static const char *instantiate(const char *string, size_t length, size_t hashcod
 If it is not the case please check for initializing 'tlskey' 
 only one time before use of it. */
 
+#if INSTANCIATE && !defined(NOT_MULTI_THREAD_SAFE)
+static const char *_scratchcat( int ispath, const char **strings);
+
 const char *scratchcat( int ispath, const char **strings)
 {
+    const char *result;
+    pthread_mutex_lock(&mutex);
+    result = _scratchcat( ispath, strings);
+    pthread_mutex_unlock(&mutex);
+    return result;
+}
+
+static const char *_scratchcat( int ispath, const char **strings)
+#else
+const char *scratchcat( int ispath, const char **strings)
+#endif
+{
     void *scratch, *p;
     char *result;
     size_t length, capacity;
     const char *instr;
     char c, pc;
 #if INSTANCIATE
-       size_t hashcode = HASHCODE_INIT;
+    size_t hashcode = HASHCODE_INIT;
 #endif
 
     /* get the recorded pointer on scrtch area */
-#ifndef NOT_MULTI_THREAD_SAFE
-    if (!key_initialized) {
-        key_initialized = 1;
-        pthread_key_create( &tlskey, (void(*)(void*))free);
-    }
-    scratch = pthread_getspecific( tlskey);
-#else
     scratch = global_scratch;
-#endif
 
     /* create the scratch area if needed */
     if (scratch == NULL) {
@@ -144,11 +153,7 @@ const char *scratchcat( int ispath, const char **strings)
             return NULL;
         *((size_t*)p) = capacity;
         scratch = p;
-#ifndef NOT_MULTI_THREAD_SAFE
-        pthread_setspecific( tlskey, p);
-#else
         global_scratch = p;
-#endif
     }
 
     /* set local data for scratch area */
@@ -195,11 +200,7 @@ const char *scratchcat( int ispath, const char **strings)
             *((size_t*)p) = capacity;
             if (p != scratch) {
                 scratch = p;
-#ifndef NOT_MULTI_THREAD_SAFE
-                pthread_setspecific( tlskey, p);
-#else
                 global_scratch = p;
-#endif
                 result = (char*)(1+((size_t*)p));
             }
         }
@@ -207,12 +208,12 @@ const char *scratchcat( int ispath, const char **strings)
         /* append the char */
         pc = result[length++] = c;
 #if INSTANCIATE
-               hashcode = HASHCODE_NEXT(hashcode, (size_t)c);
+        hashcode = HASHCODE_NEXT(hashcode, (size_t)c);
 #endif
     }
 
 #if INSTANCIATE
-       return instantiate(result, length, hashcode);
+    return instantiate(result, length, hashcode);
 #else
     return result;
 #endif
@@ -225,13 +226,13 @@ int main(int argc, const char**argv) {
     int ispath, iter, i;
     argv++;
     ispath = argv[0] && argv[0][0] == '-' && argv[0][1] == 'p';
-       for (i = 0 ; i < 2 ; i++) {
-               iter = ispath;
-               while (iter < argc) {
-               const char *p = scratchcat(ispath,argv+iter++);
-               printf("%p: %s\n",p,p);
-               }
-       }
+    for (i = 0 ; i < 2 ; i++) {
+        iter = ispath;
+        while (iter < argc) {
+            const char *p = scratchcat(ispath,argv+iter++);
+            printf("%p: %s\n",p,p);
+        }
+    }
     return 0;
 }
 #endif
index 735fef6..2b27401 100644 (file)
 
 #ifndef NOT_MULTI_THREAD_SAFE
 #include <pthread.h>
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static inline void lock() { pthread_mutex_lock(&mutex); }
-static inline void unlock() { pthread_mutex_unlock(&mutex); }
-#else
-static inline void lock() { }
-static inline void unlock() { }
 #endif
 
 #ifndef CONFIGPATH
@@ -72,20 +66,40 @@ static inline void unlock() { }
                     || _FOREIGN_HAS_(EHOME) \
                     || _FOREIGN_HAS_(EUSER) )
 
+#define _USER_NOT_SET_  ((uid_t)-1)
+
+/* local and static variables */
+static const char metafilepath[] = CONFIGPATH;
+static const char emptystring[] = "";
+static const char *var_names[_TZPLATFORM_VARIABLES_COUNT_];
+
+enum STATE { RESET=0, ERROR, VALID };
+
+struct tzplatform_context {
+#ifndef NOT_MULTI_THREAD_SAFE
+    pthread_mutex_t mutex;
+#endif
+    enum STATE state;
+    uid_t user;
+    struct heap heap;
+    const char *values[_TZPLATFORM_VARIABLES_COUNT_];
+};
+
 /* structure for reading config files */
 struct reading {
     int errcount;
+    struct tzplatform_context *context;
     size_t dynvars[_FOREIGN_COUNT_];
     size_t offsets[_TZPLATFORM_VARIABLES_COUNT_];
 };
 
-/* local and static variables */
-static const char metafilepath[] = CONFIGPATH;
-static const char emptystring[] = "";
-static struct heap heap;
-static enum { RESET=0, ERROR, VALID } state = RESET;
-static const char *var_values[_TZPLATFORM_VARIABLES_COUNT_];
-static const char *var_names[_TZPLATFORM_VARIABLES_COUNT_];
+static struct tzplatform_context global_context = {
+#ifndef NOT_MULTI_THREAD_SAFE
+    .mutex = PTHREAD_MUTEX_INITIALIZER,
+#endif
+    .state = RESET,
+    .user = _USER_NOT_SET_
+};
 
 #include "hash.inc"
 
@@ -100,6 +114,37 @@ static void writerror( const char *format, ...)
     fprintf( stderr, "\n");
 }
 
+static uid_t get_uid(struct tzplatform_context *context)
+{
+    uid_t result;
+
+    result = context->user;
+    if (result == _USER_NOT_SET_)
+        result = getuid();
+
+    return result;
+}
+
+#if _FOREIGN_HAS_(EUID)
+static uid_t get_euid(struct tzplatform_context *context)
+{
+    uid_t result;
+
+    result = context->user;
+    if (result == _USER_NOT_SET_)
+        result = geteuid();
+
+    return result;
+}
+#endif
+
+#if _FOREIGN_HAS_(GID)
+static gid_t get_gid(struct tzplatform_context *context)
+{
+    return getgid();
+}
+#endif
+
 #if _HAS_IDS_
 /* fill the foreign variables for ids */
 static void foreignid( struct reading *reading)
@@ -110,27 +155,27 @@ static void foreignid( struct reading *reading)
 #if _FOREIGN_HAS_(UID)
     /* set the uid */
     if (reading->dynvars[UID] == HNULL) {
-        n = snprintf( buffer, sizeof buffer, "%d", (int)getuid());
+        n = snprintf( buffer, sizeof buffer, "%d", (int)get_uid(reading->context));
         if (0 < n && n < (int)(sizeof buffer))
-            reading->dynvars[UID] = heap_strndup( &heap, buffer, (size_t)n);
+            reading->dynvars[UID] = heap_strndup( &reading->context->heap, buffer, (size_t)n);
     }
 #endif
 
 #if _FOREIGN_HAS_(EUID)
     /* set the euid */
     if (reading->dynvars[EUID] == HNULL) {
-        n = snprintf( buffer, sizeof buffer, "%d", (int)geteuid());
+        n = snprintf( buffer, sizeof buffer, "%d", (int)get_euid(reading->context));
         if (0 < n && n < (int)(sizeof buffer))
-            reading->dynvars[EUID] = heap_strndup( &heap, buffer, (size_t)n);
+            reading->dynvars[EUID] = heap_strndup( &reading->context->heap, buffer, (size_t)n);
     }
 #endif
 
 #if _FOREIGN_HAS_(GID)
     /* set the gid */
     if (reading->dynvars[GID] == HNULL) {
-        n = snprintf( buffer, sizeof buffer, "%d", (int)getgid());
+        n = snprintf( buffer, sizeof buffer, "%d", (int)get_gid(reading->context));
         if (0 < n && n < (int)(sizeof buffer))
-            reading->dynvars[GID] = heap_strndup( &heap, buffer, (size_t)n);
+            reading->dynvars[GID] = heap_strndup( &reading->context->heap, buffer, (size_t)n);
     }
 #endif
 }
@@ -163,7 +208,7 @@ static void foreignpw( struct reading *reading)
         reading->dynvars[USER] == HNULL
 #endif
     ) {
-        snprintf( suid, sizeof suid, "%u", (unsigned)getuid());
+        snprintf( suid, sizeof suid, "%u", (unsigned)get_uid(reading->context));
         uid.id = suid;
         array[n++] = &uid;
     }
@@ -184,7 +229,7 @@ static void foreignpw( struct reading *reading)
         reading->dynvars[EUSER] == HNULL
 #endif
     ) {
-        snprintf( seuid, sizeof seuid, "%u", (unsigned)geteuid());
+        snprintf( seuid, sizeof seuid, "%u", (unsigned)get_euid(reading->context));
         euid.id = seuid;
         array[n++] = &euid;
     }
@@ -195,7 +240,7 @@ static void foreignpw( struct reading *reading)
 
     if (n) {
         array[n] = NULL;
-        if (pw_get( &heap, array) == 0) {
+        if (pw_get( &reading->context->heap, array) == 0) {
 #if _FOREIGN_HAS_(HOME)
             if (uid.set)
                 reading->dynvars[HOME] = uid.home;
@@ -260,7 +305,7 @@ static const char *foreignvar( struct reading *reading,
         return NULL;
     }
     offset = reading->dynvars[key];
-    return offset==HNULL ? NULL : heap_address( &heap, offset);
+    return offset==HNULL ? NULL : heap_address( &reading->context->heap, offset);
 }
 
 /* callback for parsing errors */
@@ -298,7 +343,7 @@ static const char *getcb( struct parsing *parsing,
         /* found: try to use it */
         offset = reading->offsets[(int)vara->id];
         if (offset != HNULL)
-            result = heap_address( &heap, offset);
+            result = heap_address( &reading->context->heap, offset);
         else 
             result = NULL;
     }
@@ -343,7 +388,7 @@ static int putcb( struct parsing *parsing,
         }
 
         /* allocate the variable value */
-        offset = heap_alloc( &heap, value_length+1);
+        offset = heap_alloc( &reading->context->heap, value_length+1);
         if (offset == HNULL) {
             /* error of allocation */
             reading->errcount++;
@@ -352,7 +397,7 @@ static int putcb( struct parsing *parsing,
         else {
             /* record the variable value */
             reading->offsets[(int)vara->id] = offset;
-            string = heap_address( &heap, offset);
+            string = heap_address( &reading->context->heap, offset);
             memcpy( string, value, value_length);
             string[value_length] = 0;
         }
@@ -370,7 +415,7 @@ static int putcb( struct parsing *parsing,
 }
 
 /* initialize the environment */
-static void initialize()
+static void initialize(struct tzplatform_context *context)
 {
     struct buffer buffer;
     struct parsing parsing;
@@ -380,11 +425,12 @@ static void initialize()
 
     /* clear the variables */
     reading.errcount = 0;
+    reading.context = context;
     for (i = 0 ; i < (int)_FOREIGN_COUNT_ ; i++) {
         reading.dynvars[i] = HNULL;
     }
     for (i = 0 ; i < (int)_TZPLATFORM_VARIABLES_COUNT_ ; i++) {
-        var_values[i] = NULL;
+        context->values[i] = NULL;
         reading.offsets[i] = HNULL;
     }
 
@@ -392,16 +438,16 @@ static void initialize()
     result = buffer_create( &buffer, metafilepath);
     if (result != 0) {
         writerror( "can't read file %s",metafilepath);
-        state = ERROR;
+        context->state = ERROR;
         return;
     }
 
     /* create the heap */
-    result = heap_create( &heap, 1);
+    result = heap_create( &context->heap, 1);
     if (result != 0) {
         buffer_destroy( &buffer);
         writerror( "out of memory");
-        state = ERROR;
+        context->state = ERROR;
         return;
     }
 
@@ -422,48 +468,91 @@ static void initialize()
     }
 
     /* set the variables */
-    heap_read_only( &heap);
+    heap_read_only( &context->heap);
     for (i = 0 ; i < (int)_TZPLATFORM_VARIABLES_COUNT_ ; i++) {
         offset = reading.offsets[i];
         if (offset != HNULL)
-            var_values[i] = heap_address( &heap, offset);
+            context->values[i] = heap_address( &context->heap, offset);
         else
             writerror( "the variable %s isn't defined in file %s",
                 tzplatform_getname((enum tzplatform_variable)i), metafilepath);
             /* TODO undefined variable */;
     }
-    state = VALID;
+    context->state = VALID;
+}
+
+inline static void lock(struct tzplatform_context *context)
+{
+#ifndef NOT_MULTI_THREAD_SAFE
+    pthread_mutex_lock( &context->mutex);
+#endif
+}
+
+inline static void unlock(struct tzplatform_context *context)
+{
+#ifndef NOT_MULTI_THREAD_SAFE
+    pthread_mutex_unlock( &context->mutex);
+#endif
 }
 
-static const char *get_lock(enum tzplatform_variable id)
+static const char *get_lock(struct tzplatform_context *context, enum tzplatform_variable id)
 {
     const char *result;
     int offset;
 
-    lock();
+    lock( context);
     offset = (int)id;
     if (offset < 0 || (int)_TZPLATFORM_VARIABLES_COUNT_ <= offset) {
         /*error("invalid id"); TODO*/
         result = NULL;
     }
     else {
-        if (state == RESET)
-            initialize();
-        result = var_values[offset];
+        if (context->state == RESET)
+            initialize( context);
+        result = context->state == ERROR ? NULL : context->values[offset];
     }
     return result;
 }
 
-/* reset the state of the environement */
+int tzplatform_context_create(struct tzplatform_context **result)
+{
+    struct tzplatform_context *context;
+
+    context = malloc( sizeof * context);
+    *result = context;
+    if (context == NULL)
+        return -1;
+
+    context->state = RESET;
+    context->user = _USER_NOT_SET_;
+#ifndef NOT_MULTI_THREAD_SAFE
+    pthread_mutex_init( &context->mutex, NULL);
+#endif
+    return 0;
+}
+
+void tzplatform_context_destroy(struct tzplatform_context *context)
+{
+    if (context->state == VALID)
+            heap_destroy( &context->heap);
+    context->state = ERROR;
+    free( context);
+}
+
 void tzplatform_reset()
 {
-    lock();
-    if (state != RESET) {
-        if (state == VALID)
-            heap_destroy( &heap);
-        state = RESET;
+    tzplatform_context_reset( &global_context);
+}
+
+void tzplatform_context_reset(struct tzplatform_context *context)
+{
+    lock( context);
+    if (context->state != RESET) {
+        if (context->state == VALID)
+            heap_destroy( &context->heap);
+        context->state = RESET;
     }
-    unlock();
+    unlock( context);
 }
 
 int tzplatform_getcount()
@@ -505,52 +594,84 @@ enum tzplatform_variable tzplatform_getid(const char *name)
 
 const char* tzplatform_getenv(enum tzplatform_variable id) 
 {
-    const char *result = get_lock( id);
-    unlock();
+    return tzplatform_context_getenv( &global_context, id);
+}
+
+const char* tzplatform_context_getenv(struct tzplatform_context *context, enum tzplatform_variable id)
+{
+    const char *array[2];
+    const char *result = get_lock( context, id);
+    if (result != NULL) {
+        array[0] = result;
+        array[1] = NULL;
+        result = scratchcat( 0, array);
+    }
+    unlock( context);
     return result;
 }
 
 int tzplatform_getenv_int(enum tzplatform_variable id)
 {
-    const char *value = get_lock( id);
+    return tzplatform_context_getenv_int( &global_context, id);
+}
+
+int tzplatform_context_getenv_int(struct tzplatform_context *context, enum tzplatform_variable id)
+{
+    const char *value = get_lock( context, id);
     int result = value==NULL ? -1 : atoi(value);
-    unlock();
+    unlock( context);
     return result;
 }
 
 const char* tzplatform_mkstr(enum tzplatform_variable id, const char * str)
 {
+    return tzplatform_context_mkstr( &global_context, id, str);
+}
+
+const char* tzplatform_context_mkstr(struct tzplatform_context *context, enum tzplatform_variable id, const char *str)
+{
     const char *array[3];
-    const char *result = get_lock( id);
+    const char *result = get_lock( context, id);
     if (result != NULL) {
         array[0] = result;
         array[1] = str;
         array[2] = NULL;
         result = scratchcat( 0, array);
     }
-    unlock();
+    unlock( context);
     return result;
 }
 
 const char* tzplatform_mkpath(enum tzplatform_variable id, const char * path)
 {
+    return tzplatform_context_mkpath( &global_context, id, path);
+}
+
+const char* tzplatform_context_mkpath(struct tzplatform_context *context, enum tzplatform_variable id, const char *path)
+{
     const char *array[3];
-    const char *result = get_lock( id);
+    const char *result = get_lock( context, id);
     if (result != NULL) {
         array[0] = result;
         array[1] = path;
         array[2] = NULL;
         result = scratchcat( 1, array);
     }
-    unlock();
+    unlock( context);
     return result;
 }
 
 const char* tzplatform_mkpath3(enum tzplatform_variable id, const char * path,
                                                         const char* path2)
 {
+    return tzplatform_context_mkpath3( &global_context, id, path, path2);
+}
+
+const char* tzplatform_context_mkpath3(struct tzplatform_context *context, enum tzplatform_variable id, const char *path,
+                                                            const char *path2)
+{
     const char *array[4];
-    const char *result = get_lock( id);
+    const char *result = get_lock( context, id);
     if (result != NULL) {
         array[0] = result;
         array[1] = path;
@@ -558,15 +679,21 @@ const char* tzplatform_mkpath3(enum tzplatform_variable id, const char * path,
         array[3] = NULL;
         result = scratchcat( 1, array);
     }
-    unlock();
+    unlock( context);
     return result;
 }
 
 const char* tzplatform_mkpath4(enum tzplatform_variable id, const char * path,
                                           const char* path2, const char *path3)
 {
+    return tzplatform_context_mkpath4( &global_context, id, path, path2, path3);
+}
+
+const char* tzplatform_context_mkpath4(struct tzplatform_context *context, enum tzplatform_variable id, const char *path,
+                                        const char *path2, const char *path3)
+{
     const char *array[5];
-    const char *result = get_lock( id);
+    const char *result = get_lock( context, id);
     if (result != NULL) {
         array[0] = result;
         array[1] = path;
@@ -575,43 +702,140 @@ const char* tzplatform_mkpath4(enum tzplatform_variable id, const char * path,
         array[4] = NULL;
         result = scratchcat( 1, array);
     }
-    unlock();
+    unlock( context);
     return result;
 }
 
 uid_t tzplatform_getuid(enum tzplatform_variable id)
 {
+    return tzplatform_context_getuid( &global_context, id);
+}
+
+uid_t tzplatform_context_getuid(struct tzplatform_context *context, enum tzplatform_variable id)
+{
     uid_t result = (uid_t)-1;
-    const char *value = get_lock( id);
+    const char *value = get_lock( context, id);
     if (value != NULL) {
         pw_get_uid( value, &result);
     }
-    unlock();
+    unlock( context);
     return result;
 }
 
 gid_t tzplatform_getgid(enum tzplatform_variable id)
 {
+    return tzplatform_context_getgid( &global_context, id);
+}
+
+gid_t tzplatform_context_getgid(struct tzplatform_context *context, enum tzplatform_variable id)
+{
     gid_t result = (uid_t)-1;
-    const char *value = get_lock( id);
+    const char *value = get_lock( context, id);
     if (value != NULL) {
         pw_get_gid( value, &result);
     }
-    unlock();
+    unlock( context);
+    return result;
+}
+
+int tzplatform_set_user(uid_t uid)
+{
+    return tzplatform_context_set_user( &global_context, uid);
+}
+
+int tzplatform_context_set_user(struct tzplatform_context *context, uid_t uid)
+{
+    int result;
+
+    result = 0;
+    lock( context);
+    if (context->user != uid) {
+           if (uid != _USER_NOT_SET_ && !pw_has_uid( uid))
+            result = -1;
+        else {
+            if (context->state == VALID)
+                heap_destroy( &context->heap);
+            context->state = RESET;
+            context->user = uid;
+        }
+    }
+    unlock( context);
+
+    return result;
+}
+
+uid_t tzplatform_get_user()
+{
+    return tzplatform_context_get_user( &global_context);
+}
+
+uid_t tzplatform_context_get_user(struct tzplatform_context *context)
+{
+    uid_t result;
+
+    lock( context);
+    result = get_uid( context);
+    unlock( context);
+
     return result;
 }
 
+void tzplatform_reset_user()
+{
+    tzplatform_context_reset_user( &global_context);
+}
+
+void tzplatform_context_reset_user(struct tzplatform_context *context)
+{
+    tzplatform_context_set_user( context, _USER_NOT_SET_);
+}
+
 #ifdef TEST
 int main() {
-    int i = 0;
-    while(i != (int)_TZPLATFORM_VARIABLES_COUNT_) {
-        enum tzplatform_variable id = (enum tzplatform_variable)i;
-        const char*name = tzplatform_getname(id);
-        const char*value = tzplatform_getenv(id);
-        int xid = (int)tzplatform_getid(name);
-        printf("%d=%d\t%s=%s\n",i,xid,name,value);
+    int i;
+    struct tzplatform_context *context;
+    enum tzplatform_variable id;
+    const char *name;
+    const char *value;
+    int xid;
+    uid_t uid;
+
+    i = 0;
+    while(i != tzplatform_getcount()) {
+        id = (enum tzplatform_variable)i;
+        name = tzplatform_getname(id);
+        value = tzplatform_getenv(id);
+        xid = (int)tzplatform_getid(name);
+        printf("%d=%d\t%s=%s\n",i,xid,name,value?value:"<null>");
         i++;
     }
+
+    printf("------------------------\n");
+    i = tzplatform_context_create(&context);
+    if (i) {
+        printf("error while creating context %d\n",i);
+        return 1;
+    }
+
+    uid = (uid_t)0;
+    i = tzplatform_context_set_user(context, uid);
+    if (i) {
+        printf("error %d while switching to user %d\n",i,(int)uid);
+        return 1;
+    }
+    i = 0;
+    while(i != tzplatform_getcount()) {
+        id = (enum tzplatform_variable)i;
+        name = tzplatform_getname(id);
+        value = tzplatform_context_getenv(context, id);
+        xid = (int)tzplatform_getid(name);
+        printf("%d=%d\t%s=%s\n",i,xid,name,value?value:"<null>");
+        i++;
+    }
+    tzplatform_context_destroy(context);
+
     return 0;
 }
 #endif
+
+
index 490970a..ca78b35 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Intel Corporation.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
@@ -31,13 +31,7 @@ extern "C" {
 #include <sys/types.h>
 #include <tzplatform_variables.h>
 
-/*
- Enforces the removal of the previously evaluated tizen platform variables.
-
- Call this function in case of changing of user inside the application.
-*/
-extern
-void tzplatform_reset();
+/*------------------------------ COMMON API (no context) ---------------*/
 
 /*
  Return the count of variables.
@@ -54,15 +48,49 @@ const char* tzplatform_getname(enum tzplatform_variable id);
 
 /*
  Return the id of the variable of 'name'.
- Return _TZPLATFORM_VARIABLES_INVALID_ if 'name' doesn't match a 
+ Return _TZPLATFORM_VARIABLES_INVALID_ if 'name' doesn't match a
  valid variable name.
 */
 extern
 enum tzplatform_variable tzplatform_getid(const char *name);
 
+/*------------------------------ GLOBAL API (default global context) ----*/
+
+/*
+ Enforces the removal of the previously evaluated tizen platform variables.
+
+ Call this function in case of changing of user inside the application.
+*/
+extern
+void tzplatform_reset();
+
+/*
+ Set the user used for UID/EUID/USER/EUSER computations.
+ Using uid==(uid_t)-1 reset the context as if tzplatform_reset_user
+ was called.
+
+ Returns 0 if uid is valid or -1 if not valid.
+*/
+extern
+int tzplatform_set_user(uid_t uid);
+
+/*
+*/
+extern
+uid_t tzplatform_get_user();
+
+/*
+ Reset the user context to use the values returned by
+ getuid and geteuid.
+*/
+extern
+void tzplatform_reset_user();
+
 /*
  Return the read-only string value of the tizen plaform variable 'id'.
- The tizen global values are globals to the application.
+
+ The returned value is an allocated unique string that MUST not be freed.
+
  Can return NULL in case of internal error or when 'id' isn't defined.
 */
 extern
@@ -75,7 +103,7 @@ extern
 int tzplatform_getenv_int(enum tzplatform_variable id);
 
 /*
- Return the string resulting of the concatenation of string value of the 
+ Return the string resulting of the concatenation of string value of the
  tizen plaform variable 'id' and the given string 'str'.
 
  The returned value is an allocated unique string that MUST not be freed.
@@ -85,7 +113,7 @@ int tzplatform_getenv_int(enum tzplatform_variable id);
  Example:
     if TZ_SYS_HOME == "/opt/home" then calling
 
-       tzplatform_mkstr(TZ_SYS_HOME,"-yes") 
+       tzplatform_mkstr(TZ_SYS_HOME,"-yes")
 
     will return "/opt/home-yes"
 */
@@ -93,7 +121,7 @@ extern
 const char* tzplatform_mkstr(enum tzplatform_variable id, const char *str);
 
 /*
- Return the string resulting of the path-concatenation of string value of the 
+ Return the string resulting of the path-concatenation of string value of the
  tizen plaform variable 'id' and the given string 'path'.
 
  path-concatenation is the concatenation taking care of / characters.
@@ -105,7 +133,7 @@ const char* tzplatform_mkstr(enum tzplatform_variable id, const char *str);
  Example:
     if TZ_SYS_HOME == "/opt/home" then calling
 
-       tzplatform_mkpath(TZ_SYS_HOME,"yes") 
+       tzplatform_mkpath(TZ_SYS_HOME,"yes")
 
     will return "/opt/home/yes"
 */
@@ -113,7 +141,7 @@ extern
 const char* tzplatform_mkpath(enum tzplatform_variable id, const char *path);
 
 /*
- Return the string resulting of the path-concatenation of string value of the 
+ Return the string resulting of the path-concatenation of string value of the
  tizen plaform variable 'id' and the given strings 'path' and 'path2'.
 
  path-concatenation is the concatenation taking care of / characters.
@@ -130,11 +158,11 @@ const char* tzplatform_mkpath(enum tzplatform_variable id, const char *path);
     will return "/opt/home/yes/no"
 */
 extern
-const char* tzplatform_mkpath3(enum tzplatform_variable id, const char *path, 
+const char* tzplatform_mkpath3(enum tzplatform_variable id, const char *path,
                                                             const char *path2);
 
 /*
- Return the string resulting of the path-concatenation of string value of the 
+ Return the string resulting of the path-concatenation of string value of the
  tizen plaform variable 'id' and the given strings 'path', 'path2' and 'path3'.
 
  path-concatenation is the concatenation taking care of / characters.
@@ -151,7 +179,7 @@ const char* tzplatform_mkpath3(enum tzplatform_variable id, const char *path,
     will return "/opt/home/yes/no/maybe"
 */
 extern
-const char* tzplatform_mkpath4(enum tzplatform_variable id, const char *path, 
+const char* tzplatform_mkpath4(enum tzplatform_variable id, const char *path,
                                         const char *path2, const char *path3);
 
 /*
@@ -159,11 +187,11 @@ const char* tzplatform_mkpath4(enum tzplatform_variable id, const char *path,
  Retun -1 in case of error.
 
  Example:
-       if TZ_USER_NAME=="app" then calling:
-          
-          tzplatform_getuid(TZ_USER_NAME)
-       
-       will return the uid of the user 'app'
+    if TZ_USER_NAME=="app" then calling:
+
+       tzplatform_getuid(TZ_USER_NAME)
+
+    will return the uid of the user 'app'
 */
 extern
 uid_t tzplatform_getuid(enum tzplatform_variable id);
@@ -173,17 +201,190 @@ uid_t tzplatform_getuid(enum tzplatform_variable id);
  Retun -1 in case of error.
 
  Example:
-       if TZ_USER_GROUP=="app" then calling:
-          
-          tzplatform_getuid(TZ_USER_GROUP)
-       
-       will return the gid of the group 'app'
+    if TZ_USER_GROUP=="app" then calling:
+
+       tzplatform_getuid(TZ_USER_GROUP)
+
+    will return the gid of the group 'app'
 */
 extern
 gid_t tzplatform_getgid(enum tzplatform_variable id);
 
+/*------------------------------ CONTEXTUAL API --------------------------*/
+
+struct tzplatform_context;
+
+/*
+ Creates a new platform 'context'.
+ Return 0 in case of success or a negative value in case of error.
+*/
+extern
+int tzplatform_context_create(struct tzplatform_context **context);
+
+/*
+ Destroys the platform 'context' previously created with 'tzplatform_context_create'.
+ The destroyed context must not be used after calling this function.
+*/
+extern
+void tzplatform_context_destroy(struct tzplatform_context *context);
+
+/*
+ Enforces the removal of the previously evaluated tizen platform variables.
+
+ Call this function in case of changing of user inside the application.
+*/
+extern
+void tzplatform_context_reset(struct tzplatform_context *context);
+
+/*
+ Set the user used for UID/EUID/USER/EUSER computations.
+ Using uid==(uid_t)-1 reset the context as if tzplatform_context_reset_user
+ was called.
+
+ Returns 0 if uid is valid or -1 if not valid.
+*/
+extern
+int tzplatform_context_set_user(struct tzplatform_context *context, uid_t uid);
+
+/*
+*/
+extern
+uid_t tzplatform_context_get_user(struct tzplatform_context *context);
+
+/*
+ Reset the user context to use the values returned by
+ getuid and geteuid.
+*/
+extern
+void tzplatform_context_reset_user(struct tzplatform_context *context);
+
+/*
+ Return the read-only string value of the tizen plaform variable 'id'.
+
+ The returned value is an allocated unique string that MUST not be freed.
+
+ Can return NULL in case of internal error or when 'id' isn't defined.
+*/
+extern
+const char* tzplatform_context_getenv(struct tzplatform_context *context, enum tzplatform_variable id);
+
+/*
+ Return the integer value of the tizen plaform variable 'id'.
+*/
+extern
+int tzplatform_context_getenv_int(struct tzplatform_context *context, enum tzplatform_variable id);
+
+/*
+ Return the string resulting of the concatenation of string value of the
+ tizen plaform variable 'id' and the given string 'str'.
+
+ The returned value is an allocated unique string that MUST not be freed.
+
+ Can return NULL in case of internal error.
+
+ Example:
+    if TZ_SYS_HOME == "/opt/home" then calling
+
+       tzplatform_context_mkstr(context, TZ_SYS_HOME,"-yes")
+
+    will return "/opt/home-yes"
+*/
+extern
+const char* tzplatform_context_mkstr(struct tzplatform_context *context, enum tzplatform_variable id, const char *str);
+
+/*
+ Return the string resulting of the path-concatenation of string value of the
+ tizen plaform variable 'id' and the given string 'path'.
+
+ path-concatenation is the concatenation taking care of / characters.
+
+ The returned value is an allocated unique string that MUST not be freed.
+
+ Can return NULL in case of internal error.
+
+ Example:
+    if TZ_SYS_HOME == "/opt/home" then calling
+
+       tzplatform_context_mkpath(context, TZ_SYS_HOME,"yes")
+
+    will return "/opt/home/yes"
+*/
+extern
+const char* tzplatform_context_mkpath(struct tzplatform_context *context, enum tzplatform_variable id, const char *path);
+
+/*
+ Return the string resulting of the path-concatenation of string value of the
+ tizen plaform variable 'id' and the given strings 'path' and 'path2'.
+
+ path-concatenation is the concatenation taking care of / characters.
+
+ The returned value is an allocated unique string that MUST not be freed.
+
+ Can return NULL in case of internal error.
+
+ Example:
+    if TZ_SYS_HOME == "/opt/home" then calling
+
+       tzplatform_context_mkpath3(context, TZ_SYS_HOME,"yes","no")
+
+    will return "/opt/home/yes/no"
+*/
+extern
+const char* tzplatform_context_mkpath3(struct tzplatform_context *context, enum tzplatform_variable id, const char *path,
+                                                            const char *path2);
+
+/*
+ Return the string resulting of the path-concatenation of string value of the
+ tizen plaform variable 'id' and the given strings 'path', 'path2' and 'path3'.
+
+ path-concatenation is the concatenation taking care of / characters.
+
+ The returned value is an allocated unique string that MUST not be freed.
+
+ Can return NULL in case of internal error.
+
+ Example:
+    if TZ_SYS_HOME == "/opt/home" then calling
+
+       tzplatform_context_mkpath4(context, TZ_SYS_HOME,"yes","no","/maybe")
+
+    will return "/opt/home/yes/no/maybe"
+*/
+extern
+const char* tzplatform_context_mkpath4(struct tzplatform_context *context, enum tzplatform_variable id, const char *path,
+                                        const char *path2, const char *path3);
+
+/*
+ Return the uid for a given user name, stored in variable <id>
+ Retun -1 in case of error.
+
+ Example:
+    if TZ_USER_NAME=="app" then calling:
+
+       tzplatform_context_getuid(context, TZ_USER_NAME)
+
+    will return the uid of the user 'app'
+*/
+extern
+uid_t tzplatform_context_getuid(struct tzplatform_context *context, enum tzplatform_variable id);
+
+/*
+ Return the gid for a given group name, stored in variable <id>
+ Retun -1 in case of error.
+
+ Example:
+    if TZ_USER_GROUP=="app" then calling:
+
+       tzplatform_context_getuid(context, TZ_USER_GROUP)
+
+    will return the gid of the group 'app'
+*/
+extern
+gid_t tzplatform_context_getgid(struct tzplatform_context *context, enum tzplatform_variable id);
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif // _LIBTIZEN-PLATFORM-WRAPPER
+#endif /* LIBTIZEN_PLATFORM_WRAPPER */
+
index a698b11..f254f54 100644 (file)
@@ -25,6 +25,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
 
 #include <tzplatform_config.h>
 
@@ -45,15 +47,17 @@ options:\n\
 -s --space      separate with spaces instead of new-lines\n\
 -q --query      silently check that given variables are existing\n\
 -c --continue   continue to process if error\n\
+-u --user  id   set the user using its 'id' (name or numeric)\n\
 \n\
 ";
 
 int main(int argc, char **argv)
 {
-       char *progname = *argv++;
+       char *progname = *argv++, *user = 0;
        int all = 0, not = 0, query = 0, export = 0, space = 0, list = 0, cont = 0;
        int i, n, *sel, p;
        enum tzplatform_variable id;
+       struct passwd *spw;
 
        /* parse args */
        while(*argv && **argv=='-') {
@@ -71,6 +75,7 @@ int main(int argc, char **argv)
                                        case 'l': x = "list"; break;
                                        case 'c': x = "continue"; break;
                                        case 'h': x = "help"; break;
+                                       case 'u': x = "user"; break;
                                }
                                if (!x || strcmp(x,opt))
                                        c = 0;
@@ -89,6 +94,7 @@ int main(int argc, char **argv)
                        case 's': space = 1; break;
                        case 'l': list = 1; break;
                        case 'c': cont = 1; break;
+                       case 'u': user = *argv; if (user) argv++; break;
                        case 'h':
                                fprintf( stdout, help, basename(progname));
                                return 0;
@@ -168,6 +174,27 @@ int main(int argc, char **argv)
        if (query) 
                return 0;
 
+       /* set the user */
+       if (user) {
+               for (i=0 ; '0' <= user[i] && user[i] <= '9' ; i++);
+               if (user[i])
+                       spw = getpwnam(user);
+               else
+                       spw = getpwuid((uid_t)atoi(user));
+               if (!spw) {
+                       fprintf( stderr, "error! %s isn't standing for a valid user.\n", user);
+                       if (!cont)
+                               return 1;
+               } else {
+                       i = tzplatform_set_user(spw->pw_uid);
+                       if (i) {
+                               fprintf( stderr, "error! can't set the valid user %s.\n", user);
+                               if (!cont)
+                                       return 1;
+                       }
+               }
+       }
+
        /* emits the result */
        for (p = i = 0 ; i < n ; i++) {
                if (sel[i] != not) {