Changeset 2311

Show
Ignore:
Timestamp:
04/05/07 09:57:00 (2 years ago)
Author:
isak
Message:

Update binreloc in frontend-gtk to new one (glib API).
Add binreloc enable/disable macro to configure
Fix enabling/disabling of 'Remove' button more accurately (previously, it could be left stuck in a disabled state)
Add 'No description available' to packages missing descriptions instead of writing error message to stderr.
Hopefully, this fixes #1 :-)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • frontend/trunk/manager/ChangeLog

    r2299 r2311  
     12007-04-05  Isak Savo  <isak.savo@gmail.com> 
     2 
     3        * configure.in: Add autoconf macro for enabling/disabling binreloc 
     4 
     5        * frontend-gtk/main.c (main): Upgrade binreloc from that ancient version to the new one with glib API. 
     6        (update_selection): Handle NULL selection and disable/enable controls accordingly (fixes instances where the Remove button was disabled forever) 
     7        (add_to_list): Add a "No description available" to packages that has no description (instead of outputting an error on stderr) 
     8 
    192007-03-29  Isak Savo  <isak.savo@gmail.com> 
    210 
  • frontend/trunk/manager/acinclude.m4

    r637 r2311  
    1313    if test -f $i/include/qglobal.h -a x$QTDIR = x; then QTDIR=$i; fi 
    1414done 
     15 
    1516 
    1617if test x"$QTDIR" = x ; then 
     
    218219 
    219220]) 
     221 
     222# Check for binary relocation support. 
     223# Written by Hongli Lai 
     224# http://autopackage.org/ 
     225 
     226AC_DEFUN([AM_BINRELOC], 
     227[ 
     228        AC_ARG_ENABLE(binreloc, 
     229                [  --enable-binreloc       compile with binary relocation support 
     230                          (default=enable when available)], 
     231                enable_binreloc=$enableval,enable_binreloc=auto) 
     232 
     233        BINRELOC_CFLAGS= 
     234        BINRELOC_LIBS= 
     235        if test "x$enable_binreloc" = "xauto"; then 
     236                AC_CHECK_FILE([/proc/self/maps]) 
     237                AC_CACHE_CHECK([whether everything is installed to the same prefix], 
     238                               [br_cv_valid_prefixes], [ 
     239                               # datarootdir variables was introduced with autoconf-2.60 
     240                                if test "$bindir" = '${exec_prefix}/bin' -a "$sbindir" = '${exec_prefix}/sbin' -a \ 
     241                                       \( "$datadir" = '${prefix}/share' -o \( "$datadir" = '${datarootdir}' -a "$datarootdir" = '${prefix}/share' \) \) -a \ 
     242                                       "$libdir" = '${exec_prefix}/lib' -a \ 
     243                                        "$libexecdir" = '${exec_prefix}/libexec' -a "$sysconfdir" = '${prefix}/etc' 
     244                                then 
     245                                        br_cv_valid_prefixes=yes 
     246                                else 
     247                                        br_cv_valid_prefixes=no 
     248                                fi 
     249                                ]) 
     250        fi 
     251        AC_CACHE_CHECK([whether binary relocation support should be enabled], 
     252                       [br_cv_binreloc], 
     253                       [if test "x$enable_binreloc" = "xyes"; then 
     254                               br_cv_binreloc=yes 
     255                       elif test "x$enable_binreloc" = "xauto"; then 
     256                               if test "x$br_cv_valid_prefixes" = "xyes" -a \ 
     257                                       "x$ac_cv_file__proc_self_maps" = "xyes"; then 
     258                                       br_cv_binreloc=yes 
     259                               else 
     260                                       br_cv_binreloc=no 
     261                               fi 
     262                       else 
     263                               br_cv_binreloc=no 
     264                       fi]) 
     265 
     266        if test "x$br_cv_binreloc" = "xyes"; then 
     267                BINRELOC_CFLAGS="-DENABLE_BINRELOC" 
     268                AC_DEFINE(ENABLE_BINRELOC,,[Use binary relocation?]) 
     269        fi 
     270        AC_SUBST(BINRELOC_CFLAGS) 
     271        AC_SUBST(BINRELOC_LIBS) 
     272]) 
  • frontend/trunk/manager/configure.in

    r2310 r2311  
    88AM_PROG_LIBTOOL 
    99AC_PROG_INTLTOOL([0.31]) 
    10  
     10AM_BINRELOC 
    1111GETTEXT_PACKAGE=autopackage-gtk 
    1212AC_SUBST(GETTEXT_PACKAGE) 
  • frontend/trunk/manager/frontend-gtk/main.c

    r2307 r2311  
    5353GladeXML *xml; 
    5454GtkListStore *store; 
    55  
     55gchar *selfpath = NULL; 
     56gchar *prefix = NULL; 
    5657ApplicationInfo *selected; 
    5758 
     
    157158    char *file; 
    158159 
    159     file = g_strdup_printf ("%s/autopackage-manager/%s", DATADIR, name); 
     160    file = g_build_filename (prefix, "share/autopackage-manager", name, NULL); 
    160161    if (!g_file_test (file, G_FILE_TEST_IS_REGULAR)) 
    161162    { 
    162         char *dir = g_path_get_dirname(SELFPATH); 
     163        char *dir = g_path_get_dirname(selfpath); 
    163164        g_free (file); 
    164165        file = g_strdup_printf("%s/%s", dir, name); 
     
    168169} 
    169170 
     171// Called every time the selected app changes 
    170172static void update_selection(ApplicationInfo *info) 
    171173{ 
    172     TRACE("user selected %s, %s\n", info->name, info->root ? "root install" : "user install"); 
    173     if (info->root && geteuid() != 0) 
    174     { 
    175         gtk_widget_show(W("rootwarning")); 
    176     } else 
    177     { 
    178         gtk_widget_hide(W("rootwarning")); 
    179     } 
    180     selected = info;     
     174        if (info == NULL) 
     175        { 
     176                TRACE("user has nothing selected\n "); 
     177                gtk_widget_hide (W("rootwarning")); 
     178                gtk_widget_set_sensitive(W("remove"), FALSE); 
     179        } 
     180        else 
     181        { 
     182                TRACE("user selected %s, %s\n", info->name, info->root ? "root install" : "user install"); 
     183                if (info->root && geteuid() != 0) 
     184                        gtk_widget_show(W("rootwarning")); 
     185                else 
     186                        gtk_widget_hide(W("rootwarning")); 
     187                 
     188                gtk_widget_set_sensitive(W("remove"), TRUE); 
     189        } 
     190        selected = info; 
    181191} 
    182192 
     
    388398        g_free(size); 
    389399        gchar *name = string_to_utf8 (info->name); 
    390         gchar *comment = string_to_utf8 (info->comment); 
     400        gchar *comment = NULL; 
     401        if (info->comment) 
     402                comment = string_to_utf8 (info->comment); 
     403        else 
     404                comment = g_strdup (_("No description available")); 
    391405        if (*name == '\0') { 
    392406                g_free(name); 
     
    394408                name = g_strdup(_("Unknown Application")); 
    395409        } 
    396                         
     410         
    397411        namestr = g_strdup_printf ("<b>%s</b>\n<span size=\"smaller\">%s</span>", name, comment); 
    398412         
     
    493507    if (gtk_tree_selection_get_selected(selection, &model, &iter)) 
    494508    { 
    495         ApplicationInfo *info; 
    496          
    497         gtk_tree_model_get(model, &iter, COL_INFO, &info, -1); 
    498         update_selection(info); 
    499     }     
     509            ApplicationInfo *info; 
     510             
     511            gtk_tree_model_get(model, &iter, COL_INFO, &info, -1); 
     512            update_selection(info); 
     513    } 
     514    else 
     515            update_selection(NULL); 
    500516} 
    501517 
     
    578594    if (selected->root && geteuid() != 0) 
    579595    { 
    580             TRACE("Need elevated privileges to remove selected package.."); 
     596            TRACE("Need elevated privileges to remove selected package!\n"); 
    581597        gpointer gnomesu_spawn_async2; 
    582598        GModule *mod = g_module_open("libgnomesu.so.0", G_MODULE_BIND_LAZY ); 
     
    584600        if (mod && g_module_symbol(mod, "gnomesu_spawn_async2", &gnomesu_spawn_async2)) 
    585601        { 
    586                 TRACE("using libgnomesu\n"); 
     602                TRACE("Using libgnomesu to spawn '%s'\n", selfpath); 
    587603            /* libgnomesu is available */ 
    588604            typedef gboolean (*GnomesuSpawnAsync2) (const gchar *user, const gchar **argv, GPid *pid, 
     
    590606            const gchar *argv[3]; 
    591607 
    592             argv[0] = SELFPATH
     608            argv[0] = selfpath
    593609            argv[1] = "--rootmode"; 
    594610            argv[2] = NULL; 
     
    608624                autosu = g_strdup(home); 
    609625            g_free (home); 
    610             TRACE("using autosu (%s)\n", autosu); 
     626            TRACE("Using autosu (%s) to spawn '%s'\n", autosu, selfpath); 
    611627            if (!autosu) 
    612628            { 
     
    626642            argv[2] = "-m"; 
    627643            argv[3] = "manage"; 
    628             argv[4] = (gchar *) SELFPATH
     644            argv[4] = (gchar *) selfpath
    629645            argv[5] = "--rootmode"; 
    630646            argv[6] = NULL; 
     
    696712} 
    697713 
     714static void init_binreloc() 
     715{ 
     716        GError *err = NULL; 
     717 
     718        if (!gbr_init(&err)) 
     719        { 
     720                g_print ("WARNING: Couldn't initialize the binary relocation support (binreloc): %s\n", err->message); 
     721                g_print ("WARNING: Falling back to hard-coded default prefix (/usr)\n"); 
     722        } 
     723        selfpath = gbr_find_exe("/usr/bin/autopackage-manager-gtk"); 
     724        prefix = gbr_find_prefix("/usr"); 
     725} 
     726 
    698727int main(int argc, char *argv[]) 
    699728{ 
    700     const char *xml_file; 
    701  
    702     TRACE("starting up\n"); 
    703  
     729    char *xml_file; 
     730     
    704731    if (getenv("AUTOPACKAGE_MANAGER_GTK_DEBUG") && *getenv("AUTOPACKAGE_MANAGER_GTK_DEBUG")) 
    705732        logging = 1; 
    706733 
     734    TRACE("starting up\n"); 
     735    init_binreloc(); 
    707736    g_thread_init(NULL); 
     737     
    708738#ifdef ENABLE_NLS 
    709     bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); 
    710     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 
    711     textdomain (GETTEXT_PACKAGE); 
     739    { 
     740            gchar *localedir = g_build_filename(prefix, "share", "locale", NULL); 
     741            TRACE("Loading locale files from '%s'\n", localedir); 
     742            bindtextdomain (GETTEXT_PACKAGE, localedir); 
     743            bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 
     744            textdomain (GETTEXT_PACKAGE); 
     745            g_free (localedir); 
     746    } 
    712747#endif 
    713748     
     
    715750     
    716751    /* set up the GUI */ 
    717     xml_file = BR_DATADIR("/autopackage-manager/manager-gtk.glade"); 
     752    xml_file = g_build_filename(prefix, "share/autopackage-manager/manager-gtk.glade", NULL); 
     753    TRACE("Loading GUI from file %s...", xml_file); 
    718754    if (!g_file_test (xml_file, G_FILE_TEST_IS_REGULAR)) 
    719755    { 
    720         char *dir = g_path_get_dirname(SELFPATH); 
     756        char *dir = g_path_get_dirname(selfpath); 
    721757        xml_file = g_strdup_printf("%s/manager-gtk.glade", dir); 
    722758        g_free (dir); 
    723759    } 
    724  
     760     
    725761    xml = glade_xml_new(xml_file, NULL, NULL); 
    726     assert( xml ); 
     762    g_assert( xml ); 
     763 
     764    g_free (xml_file); 
     765    xml_file = NULL; 
    727766 
    728767    GdkColor *white = &gtk_widget_get_style(W("topbox"))->white; 
     
    753792    TRACE("shutting down\n"); 
    754793    cleanup(); 
    755 
    756  
     794    g_free (prefix); 
     795    g_free (selfpath); 
     796
     797 
  • frontend/trunk/manager/frontend-gtk/prefix.c

    r402 r2311  
    11/* 
    22 * BinReloc - a library for creating relocatable executables 
    3  * Written by: Mike Hearn <mike@theoretic.com> 
    4  *             Hongli Lai <h.lai@chello.nl> 
     3 * Written by: Hongli Lai <h.lai@chello.nl> 
    54 * http://autopackage.org/ 
    6  *  
     5 * 
    76 * This source code is public domain. You can relicense this code 
    87 * under whatever license you want. 
    98 * 
    10  * NOTE: if you're using C++ and are getting "undefined reference 
    11  * to br_*", try renaming prefix.c to prefix.cpp 
    12  */ 
    13  
    14 /* WARNING, BEFORE YOU MODIFY PREFIX.C: 
    15  * 
    16  * If you make changes to any of the functions in prefix.c, you MUST 
    17  * change the BR_NAMESPACE macro (in prefix.h). 
    18  * This way you can avoid symbol table conflicts with other libraries 
    19  * that also happen to use BinReloc. 
    20  * 
    21  * Example: 
    22  * #define BR_NAMESPACE(funcName) foobar_ ## funcName 
    23  * --> expands br_locate to foobar_br_locate 
    24  */ 
    25  
    26 #ifndef _PREFIX_C_ 
    27 #define _PREFIX_C_ 
    28  
    29 #define ENABLE_BINRELOC 
    30  
    31 #ifdef HAVE_CONFIG_H 
    32         #include "config.h" 
    33 #endif 
    34  
    35 #ifndef BR_PTHREADS 
    36         /* Change 1 to 0 if you don't want pthread support */ 
    37         #define BR_PTHREADS 1 
    38 #endif /* BR_PTHREADS */ 
    39  
     9 * See http://autopackage.org/docs/binreloc/ for 
     10 * more information and how to use this. 
     11 */ 
     12 
     13#ifndef __BINRELOC_C__ 
     14#define __BINRELOC_C__ 
     15 
     16#ifdef ENABLE_BINRELOC 
     17        #include <sys/types.h> 
     18        #include <sys/stat.h> 
     19        #include <unistd.h> 
     20#endif /* ENABLE_BINRELOC */ 
     21#include <stdio.h> 
    4022#include <stdlib.h> 
    41 #include <stdio.h> 
    4223#include <limits.h> 
    4324#include <string.h> 
    4425#include "prefix.h" 
    4526 
    46 #ifdef __cplusplus 
    47 extern "C" { 
    48 #endif /* __cplusplus */ 
    49  
    50  
    51 #undef NULL 
    52 #define NULL ((void *) 0) 
    53  
    54 #ifdef __GNUC__ 
    55         #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;} 
     27G_BEGIN_DECLS 
     28 
     29 
     30/** @internal 
     31 * Find the canonical filename of the executable. Returns the filename 
     32 * (which must be freed) or NULL on error. If the parameter 'error' is 
     33 * not NULL, the error code will be stored there, if an error occured. 
     34 */ 
     35static char * 
     36_br_find_exe (GbrInitError *error) 
     37
     38#ifndef ENABLE_BINRELOC 
     39        if (error) 
     40                *error = GBR_INIT_ERROR_DISABLED; 
     41        return NULL; 
    5642#else 
    57         #define br_return_val_if_fail(expr,val) if (!(expr)) return val 
    58 #endif /* __GNUC__ */ 
    59  
    60  
    61 static br_locate_fallback_func fallback_func = NULL; 
    62 static void *fallback_data = NULL; 
    63  
    64  
    65 #ifdef ENABLE_BINRELOC 
    66 #include <sys/types.h> 
    67 #include <sys/stat.h> 
    68 #include <sys/param.h> 
    69 #include <unistd.h> 
    70  
    71  
    72 /** 
    73  * br_locate: 
    74  * symbol: A symbol that belongs to the app/library you want to locate. 
    75  * Returns: A newly allocated string containing the full path of the 
    76  *          app/library that func belongs to, or NULL on error. This 
    77  *          string should be freed when not when no longer needed. 
    78  * 
    79  * Finds out to which application or library symbol belongs, then locate 
    80  * the full path of that application or library. 
    81  * Note that symbol cannot be a pointer to a function. That will not work. 
    82  * 
    83  * Example: 
    84  * --> main.c 
    85  * #include "prefix.h" 
    86  * #include "libfoo.h" 
    87  * 
    88  * int main (int argc, char *argv[]) { 
    89  *      printf ("Full path of this app: %s\n", br_locate (&argc)); 
    90  *      libfoo_start (); 
    91  *      return 0; 
    92  * } 
    93  * 
    94  * --> libfoo.c starts here 
    95  * #include "prefix.h" 
    96  * 
    97  * void libfoo_start () { 
    98  *      --> "" is a symbol that belongs to libfoo (because it's called 
    99  *      --> from libfoo_start()); that's why this works. 
    100  *      printf ("libfoo is located in: %s\n", br_locate ("")); 
    101  * } 
    102  */ 
    103 char * 
    104 br_locate (void *symbol) 
    105 
    106         char line[5000]; 
     43        char *path, *path2, *line, *result; 
     44        size_t buf_size; 
     45        ssize_t size; 
     46        struct stat stat_buf; 
    10747        FILE *f; 
    108         char *path; 
    109  
    110         br_return_val_if_fail (symbol != NULL, NULL); 
     48 
     49        /* Read from /proc/self/exe (symlink) */ 
     50        if (sizeof (path) > SSIZE_MAX) 
     51                buf_size = SSIZE_MAX - 1; 
     52        else 
     53                buf_size = PATH_MAX - 1; 
     54        path = (char *) g_try_malloc (buf_size); 
     55        if (path == NULL) { 
     56                /* Cannot allocate memory. */ 
     57                if (error) 
     58                        *error = GBR_INIT_ERROR_NOMEM; 
     59                return NULL; 
     60        } 
     61        path2 = (char *) g_try_malloc (buf_size); 
     62        if (path2 == NULL) { 
     63                /* Cannot allocate memory. */ 
     64                if (error) 
     65                        *error = GBR_INIT_ERROR_NOMEM; 
     66                g_free (path); 
     67                return NULL; 
     68        } 
     69 
     70        strncpy (path2, "/proc/self/exe", buf_size - 1); 
     71 
     72        while (1) { 
     73                int i; 
     74 
     75                size = readlink (path2, path, buf_size - 1); 
     76                if (size == -1) { 
     77                        /* Error. */ 
     78                        g_free (path2); 
     79                        break; 
     80                } 
     81 
     82                /* readlink() success. */ 
     83                path[size] = '\0'; 
     84 
     85                /* Check whether the symlink's target is also a symlink. 
     86                 * We want to get the final target. */ 
     87                i = stat (path, &stat_buf); 
     88                if (i == -1) { 
     89                        /* Error. */ 
     90                        g_free (path2); 
     91                        break; 
     92                } 
     93 
     94                /* stat() success. */ 
     95                if (!S_ISLNK (stat_buf.st_mode)) { 
     96                        /* path is not a symlink. Done. */ 
     97                        g_free (path2); 
     98                        return path; 
     99                } 
     100 
     101                /* path is a symlink. Continue loop and resolve this. */ 
     102                strncpy (path, path2, buf_size - 1); 
     103        } 
     104 
     105 
     106        /* readlink() or stat() failed; this can happen when the program is 
     107         * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ 
     108 
     109        buf_size = PATH_MAX + 128; 
     110        line = (char *) g_try_realloc (path, buf_size); 
     111        if (line == NULL) { 
     112                /* Cannot allocate memory. */ 
     113                g_free (path); 
     114                if (error) 
     115                        *error = GBR_INIT_ERROR_NOMEM; 
     116                return NULL; 
     117        } 
    111118 
    112119        f = fopen ("/proc/self/maps", "r"); 
    113         if (!f) { 
    114                 if (fallback_func) 
    115                         return fallback_func(symbol, fallback_data); 
    116                 else 
    117                         return NULL; 
    118         } 
    119  
    120         while (!feof (f)) 
    121         { 
    122                 unsigned long start, end; 
    123  
    124                 if (!fgets (line, sizeof (line), f)) 
     120        if (f == NULL) { 
     121                g_free (line); 
     122                if (error) 
     123                        *error = GBR_INIT_ERROR_OPEN_MAPS; 
     124                return NULL; 
     125        } 
     126 
     127        /* The first entry should be the executable name. */ 
     128        result = fgets (line, (int) buf_size, f); 
     129        if (result == NULL) { 
     130                fclose (f); 
     131                g_free (line); 
     132                if (error) 
     133                        *error = GBR_INIT_ERROR_READ_MAPS; 
     134                return NULL; 
     135        } 
     136 
     137        /* Get rid of newline character. */ 
     138        buf_size = strlen (line); 
     139        if (buf_size <= 0) { 
     140                /* Huh? An empty string? */ 
     141                fclose (f); 
     142                g_free (line); 
     143                if (error) 
     144                        *error = GBR_INIT_ERROR_INVALID_MAPS; 
     145                return NULL; 
     146        } 
     147        if (line[buf_size - 1] == 10) 
     148                line[buf_size - 1] = 0; 
     149 
     150        /* Extract the filename; it is always an absolute path. */ 
     151        path = strchr (line, '/'); 
     152 
     153        /* Sanity check. */ 
     154        if (strstr (line, " r-xp ") == NULL || path == NULL) { 
     155                fclose (f); 
     156                g_free (line); 
     157                if (error) 
     158                        *error = GBR_INIT_ERROR_INVALID_MAPS; 
     159                return NULL; 
     160        } 
     161 
     162        path = g_strdup (path); 
     163        g_free (line); 
     164        fclose (f); 
     165        return path; 
     166#endif /* ENABLE_BINRELOC */ 
     167
     168 
     169 
     170/** @internal 
     171 * Find the canonical filename of the executable which owns symbol. 
     172 * Returns a filename which must be freed, or NULL on error. 
     173 */ 
     174static char * 
     175_br_find_exe_for_symbol (const void *symbol, GbrInitError *error) 
     176
     177#ifndef ENABLE_BINRELOC 
     178        if (error) 
     179                *error = GBR_INIT_ERROR_DISABLED; 
     180        return (char *) NULL; 
     181#else 
     182        #define SIZE PATH_MAX + 100 
     183        FILE *f; 
     184        size_t address_string_len; 
     185        char *address_string, line[SIZE], *found; 
     186 
     187        if (symbol == NULL) 
     188                return (char *) NULL; 
     189 
     190        f = fopen ("/proc/self/maps", "r"); 
     191        if (f == NULL) 
     192                return (char *) NULL; 
     193 
     194        address_string_len = 4; 
     195        address_string = (char *) g_try_malloc (address_string_len); 
     196        found = (char *) NULL; 
     197 
     198        while (!feof (f)) { 
     199                char *start_addr, *end_addr, *end_addr_end, *file; 
     200                void *start_addr_p, *end_addr_p; 
     201                size_t len; 
     202 
     203                if (fgets (line, SIZE, f) == NULL) 
     204                        break; 
     205 
     206                /* Sanity check. */ 
     207                if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL) 
    125208                        continue; 
    126                 if (!strstr (line, " r-xp ") || !strchr (line, '/')) 
     209 
     210                /* Parse line. */ 
     211                start_addr = line; 
     212                end_addr = strchr (line, '-'); 
     213                file = strchr (line, '/'); 
     214 
     215                /* More sanity check. */ 
     216                if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) 
    127217                        continue; 
    128218 
    129                 sscanf (line, "%lx-%lx ", &start, &end); 
    130                 if (symbol >= (void *) start && symbol < (void *) end) 
    131                 { 
    132                         char *tmp; 
    133                         size_t len; 
    134  
    135                         /* Extract the filename; it is always an absolute path */ 
    136                         path = strchr (line, '/'); 
    137  
    138                         /* Get rid of the newline */ 
    139                         tmp = strrchr (path, '\n'); 
    140                         if (tmp) *tmp = 0; 
    141  
    142                         /* Get rid of "(deleted)" */ 
    143                         len = strlen (path); 
    144                         if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0) 
    145                         { 
    146                                 tmp = path + len - 10; 
    147                                 *tmp = 0; 
    148                         } 
    149  
    150                         fclose(f); 
    151                         return strdup (path); 
     219                end_addr[0] = '\0'; 
     220                end_addr++; 
     221                end_addr_end = strchr (end_addr, ' '); 
     222                if (end_addr_end == NULL) 
     223                        continue; 
     224 
     225                end_addr_end[0] = '\0'; 
     226                len = strlen (file); 
     227                if (len == 0) 
     228                        continue; 
     229                if (file[len - 1] == '\n') 
     230                        file[len - 1] = '\0'; 
     231 
     232                /* Get rid of "(deleted)" from the filename. */ 
     233                len = strlen (file); 
     234                if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0) 
     235                        file[len - 10] = '\0'; 
     236 
     237                /* I don't know whether this can happen but better safe than sorry. */ 
     238                len = strlen (start_addr); 
     239                if (len != strlen (end_addr)) 
     240                        continue; 
     241 
     242 
     243                /* Transform the addresses into a string in the form of 0xdeadbeef, 
     244                 * then transform that into a pointer. */ 
     245                if (address_string_len < len + 3) { 
     246                        address_string_len = len + 3; 
     247                        address_string = (char *) g_try_realloc (address_string, address_string_len); 
    152248                } 
    153         } 
    154  
     249 
     250                memcpy (address_string, "0x", 2); 
     251                memcpy (address_string + 2, start_addr, len); 
     252                address_string[2 + len] = '\0'; 
     253                sscanf (address_string, "%p", &start_addr_p); 
     254 
     255                memcpy (address_string, "0x", 2); 
     256                memcpy (address_string + 2, end_addr, len); 
     257                address_string[2 + len] = '\0'; 
     258                sscanf (address_string, "%p", &end_addr_p); 
     259 
     260 
     261                if (symbol >= start_addr_p && symbol < end_addr_p) { 
     262                        found = file; 
     263                        break; 
     264                } 
     265        } 
     266 
     267        g_free (address_string); 
    155268        fclose (f); 
    156         return NULL; 
    157 
    158  
    159  
    160 /** 
    161  * br_locate_prefix: 
    162  * symbol: A symbol that belongs to the app/library you want to locate. 
    163  * Returns: A prefix. This string should be freed when no longer needed. 
    164  * 
    165  * Locates the full path of the app/library that symbol belongs to, and return 
    166  * the prefix of that path, or NULL on error. 
    167  * Note that symbol cannot be a pointer to a function. That will not work. 
    168  * 
    169  * Example: 
    170  * --> This application is located in /usr/bin/foo 
    171  * br_locate_prefix (&argc);   --> returns: "/usr" 
    172  */ 
    173 char * 
    174 br_locate_prefix (void *symbol) 
    175 
    176         char *path, *prefix; 
    177  
    178         br_return_val_if_fail (symbol != NULL, NULL); 
    179  
    180         path = br_locate (symbol); 
    181         if (!path) return NULL; 
    182  
    183         prefix = br_extract_prefix (path); 
    184         free (path); 
    185         return prefix; 
    186 
    187  
    188  
    189 /** 
    190  * br_prepend_prefix: 
    191  * symbol: A symbol that belongs to the app/library you want to locate. 
    192  * path: The path that you want to prepend the prefix to. 
    193  * Returns: The new path, or NULL on error. This string should be freed when no 
    194  *          longer needed. 
    195  * 
    196  * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path. 
    197  * Note that symbol cannot be a pointer to a function. That will not work. 
    198  * 
    199  * Example: 
    200  * --> The application is /usr/bin/foo 
    201  * br_prepend_prefix (&argc, "/share/foo/data.png");   --> Returns "/usr/share/foo/data.png" 
    202  */ 
    203 char * 
    204 br_prepend_prefix (void *symbol, char *path) 
    205 
    206         char *tmp, *newpath; 
    207  
    208         br_return_val_if_fail (symbol != NULL, NULL); 
    209         br_return_val_if_fail (path != NULL, NULL); 
    210  
    211         tmp = br_locate_prefix (symbol); 
    212         if (!tmp) return NULL; 
    213  
    214         if (strcmp (tmp, "/") == 0) 
    215                 newpath = strdup (path); 
     269 
     270        if (found == NULL) 
     271                return (char *) NULL; 
    216272        else 
    217                 newpath = br_strcat (tmp, path); 
    218  
    219         /* Get rid of compiler warning ("br_prepend_prefix never used") */ 
    220         if (0) br_prepend_prefix (NULL, NULL); 
    221  
    222         free (tmp); 
    223         return newpath; 
    224 
    225  
     273                return g_strdup (found); 
    226274#endif /* ENABLE_BINRELOC */ 
    227  
    228  
    229 /* Pthread stuff for thread safetiness */ 
    230 #if BR_PTHREADS 
    231  
    232 #include <pthread.h> 
    233  
    234 static pthread_key_t br_thread_key; 
    235 static pthread_once_t br_thread_key_once = PTHREAD_ONCE_INIT; 
     275
     276 
     277 
     278static gchar *exe = NULL; 
     279 
     280static void set_gerror (GError **error, GbrInitError errcode); 
     281 
     282 
     283/** Initialize the BinReloc library (for applications). 
     284 * 
     285 * This function must be called before using any other BinReloc functions. 
     286 * It attempts to locate the application's canonical filename. 
     287 * 
     288 * @note If you want to use BinReloc for a library, then you should call 
     289 *       gbr_init_lib() instead. 
     290 * @note Initialization failure is not fatal. BinReloc functions will just 
     291 *       fallback to the supplied default path. 
     292 * 
     293 * @param error  If BinReloc failed to initialize, then the error report will 
     294 *               be stored in this variable. Set to NULL if you don't want an 
     295 *               error report. See the #GbrInitError for a list of error 
     296 *               codes. 
     297 * 
     298 * @returns TRUE on success, FALSE if BinReloc failed to initialize. 
     299 */ 
     300gboolean 
     301gbr_init (GError **error) 
     302
     303       GbrInitError errcode = 0; 
     304 
     305        /* Shut up compiler warning about uninitialized variable. */ 
     306        errcode = GBR_INIT_ERROR_NOMEM; 
     307 
     308        /* Locate the application's filename. */ 
     309        exe = _br_find_exe (&errcode); 
     310        if (exe != NULL) 
     311                /* Success! */ 
     312                return TRUE; 
     313        else { 
     314                /* Failed :-( */ 
     315                set_gerror (error, errcode); 
     316                return FALSE; 
     317        } 
     318
     319 
     320 
     321/** Initialize the BinReloc library (for libraries). 
     322 * 
     323 * This function must be called before using any other BinReloc functions. 
     324 * It attempts to locate the calling library's canonical filename. 
     325 * 
     326 * @note The BinReloc source code MUST be included in your library, or this 
     327 *       function won't work correctly. 
     328 * @note Initialization failure is not fatal. BinReloc functions will just 
     329 *       fallback to the supplied default path. 
     330 * 
     331 * @returns TRUE on success, FALSE if a filename cannot be found. 
     332 */ 
     333gboolean 
     334gbr_init_lib (GError **error) 
     335
     336       GbrInitError errcode = 0; 
     337 
     338        /* Shut up compiler warning about uninitialized variable. */ 
     339        errcode = GBR_INIT_ERROR_NOMEM; 
     340 
     341        exe = _br_find_exe_for_symbol ((const void *) "", &errcode); 
     342        if (exe != NULL) 
     343                /* Success! */ 
     344                return TRUE; 
     345        else { 
     346                /* Failed :-( */ 
     347                set_gerror (error, errcode); 
     348                return exe != NULL; 
     349        } 
     350
    236351 
    237352 
    238353static void 
    239 br_thread_local_store_fini () 
    240 
    241         char *specific; 
    242  
    243         specific = (char *) pthread_getspecific (br_thread_key); 
    244         if (specific) 
    245         { 
    246                 free (specific); 
    247                 pthread_setspecific (br_thread_key, NULL); 
    248         } 
    249         pthread_key_delete (br_thread_key); 
    250         br_thread_key = 0; 
    251 
    252  
    253  
    254 static void 
    255 br_str_free (void *str) 
    256 
    257         if (str) 
    258                 free (str); 
    259 
    260  
    261  
    262 static void 
    263 br_thread_local_store_init () 
    264 
    265         if (pthread_key_create (&br_thread_key, br_str_free) == 0) 
    266                 atexit (br_thread_local_store_fini); 
    267 
    268  
    269 #else /* BR_PTHREADS */ 
    270  
    271 static char *br_last_value = (char *) NULL; 
    272  
    273 static void 
    274 br_free_last_value () 
    275 
    276         if (br_last_value) 
    277                 free (br_last_value); 
    278 
    279  
    280 #endif /* BR_PTHREADS */ 
    281  
    282  
    283 /** 
    284  * br_thread_local_store: 
    285  * str: A dynamically allocated string. 
    286  * Returns: str. This return value must not be freed. 
    287  * 
    288  * Store str in a thread-local variable and return str. The next 
    289  * you run this function, that variable is freed too. 
    290  * This function is created so you don't have to worry about freeing 
    291  * strings. Just be careful about doing this sort of thing: 
    292  * 
    293  * some_function( BR_DATADIR("/one.png"), BR_DATADIR("/two.png") ) 
    294  * 
    295  * Examples: 
    296  * char *foo; 
    297  * foo = br_thread_local_store (strdup ("hello")); --> foo == "hello" 
    298  * foo = br_thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed. 
    299  */ 
    300 const char * 
    301 br_thread_local_store (char *str) 
    302 
    303         #if BR_PTHREADS 
    304                 char *specific; 
    305  
    306                 pthread_once (&br_thread_key_once, br_thread_local_store_init); 
    307  
    308                 specific = (char *) pthread_getspecific (br_thread_key); 
    309                 br_str_free (specific); 
    310                 pthread_setspecific (br_thread_key, str); 
    311  
    312         #else /* BR_PTHREADS */ 
    313                 static int initialized = 0; 
    314  
    315                 if (!initialized) 
    316                 { 
    317                         atexit (br_free_last_value); 
    318                         initialized = 1; 
    319                 } 
    320  
    321                 if (br_last_value) 
    322                         free (br_last_value); 
    323                 br_last_value = str; 
    324         #endif /* BR_PTHREADS */ 
    325  
    326         return (const char *) str; 
    327 
    328  
    329  
    330 /** 
    331  * br_strcat: 
    332  * str1: A string. 
    333  * str2: Another string. 
    334  * Returns: A newly-allocated string. This string should be freed when no longer needed. 
    335  * 
    336  * Concatenate str1 and str2 to a newly allocated string. 
    337  */ 
    338 char * 
    339 br_strcat (const char *str1, const char *str2) 
    340 
    341         char *result; 
    342         size_t len1, len2; 
    343  
    344         if (!str1) str1 = ""; 
    345         if (!str2) str2 = ""; 
    346  
    347         len1 = strlen (str1); 
    348         len2 = strlen (str2); 
    349  
    350         result = (char *) malloc (len1 + len2 + 1); 
    351         memcpy (result, str1, len1); 
    352         memcpy (result + len1, str2, len2); 
    353         result[len1 + len2] = '\0'; 
    354  
    355         return result; 
    356 
    357  
    358  
    359 /* Emulates glibc's strndup() */ 
    360 static char * 
    361 br_strndup (char *str, size_t size) 
    362 
    363         char *result = (char *) NULL; 
    364         size_t len; 
    365  
    366         br_return_val_if_fail (str != (char *) NULL, (char *) NULL); 
    367  
    368         len = strlen (str); 
    369         if (!len) return strdup (""); 
    370         if (size > len) size = len; 
    371  
    372         result = (char *) calloc (sizeof (char), len + 1); 
    373         memcpy (result, str, size); 
    374         return result; 
    375 
    376  
    377  
    378 /** 
    379  * br_extract_dir: 
    380  * path: A path. 
    381  * Returns: A directory name. This string should be freed when no longer needed. 
    382  * 
    383  * Extracts the directory component of path. Similar to g_dirname() or the dirname 
    384  * commandline application. 
    385  * 
    386  * Example: 
    387  * br_extract_dir ("/usr/local/foobar");  --> Returns: "/usr/local" 
    388  */ 
    389 char * 
    390 br_extract_dir (const char *path) 
    391 
    392         char *end, *result; 
    393  
    394         br_return_val_if_fail (path != (char *) NULL, (char *) NULL); 
    395  
    396         end = strrchr (path, '/'); 
    397         if (!end) return strdup ("."); 
    398  
    399         while (end > path && *end == '/') 
    400                 end--; 
    401         result = br_strndup ((char *) path, end - path + 1); 
    402         if (!*result) 
    403         { 
    404                 free (result); 
    405                 return strdup ("/"); 
    406         } else 
    407                 return result; 
    408 
    409  
    410  
    411 /** 
    412  * br_extract_prefix: 
    413  * path: The full path of an executable or library. 
    414  * Returns: The prefix, or NULL on error. This string should be freed when no longer needed. 
    415  * 
    416  * Extracts the prefix from path. This function assumes that your executable 
    417  * or library is installed in an LSB-compatible directory structure. 
    418  * 
    419  * Example: 
    420  * br_extract_prefix ("/usr/bin/gnome-panel");       --> Returns "/usr" 
    421  * br_extract_prefix ("/usr/local/lib/libfoo.so");   --> Returns "/usr/local" 
    422  * br_extract_prefix ("/usr/local/libfoo.so");       --> Returns "/usr" 
    423  */ 
    424 char * 
    425 br_extract_prefix (const char *path) 
    426 
    427         char *end, *tmp, *result; 
    428  
    429         br_return_val_if_fail (path != (char *) NULL, (char *) NULL); 
    430  
    431         if (!*path) return strdup ("/"); 
    432         end = strrchr (path, '/'); 
    433         if (!end) return strdup (path); 
    434  
    435         tmp = br_strndup ((char *) path, end - path); 
    436         if (!*tmp) 
    437         { 
    438                 free (tmp); 
    439                 return strdup ("/"); 
    440         } 
    441         end = strrchr (tmp, '/'); 
    442         if (!end) return tmp; 
    443  
    444         result = br_strndup (tmp, end - tmp); 
    445         free (tmp); 
    446  
    447         if (!*result) 
    448         {