Search
lxdream.org :: lxdream/src/lxpaths.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/lxpaths.c
changeset 1298:d0eb2307b847
prev1296:30ecee61f811
author nkeynes
date Wed Feb 04 08:38:23 2015 +1000 (5 years ago)
permissions -rw-r--r--
last change Fix assorted compile warnings reported by Clang
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * GUI helper functions that aren't specific to any particular implementation.
     5  *
     6  * Copyright (c) 2009 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <ctype.h>
    20 #include <unistd.h>
    21 #include <stdlib.h>
    22 #include <glib.h>
    24 #include "gui.h"
    25 #include "config.h"
    27 static gchar *gui_paths[CONFIG_KEY_MAX];
    29 /**
    30  * Test if we need to escape a path to prevent substitution mangling. 
    31  * @return TRUE if the input value contains any character that doesn't
    32  * match [a-zA-Z0-9._@%/] (this will escape slightly more than it needs to,
    33  * but is safe)
    34  */
    35 static gboolean path_needs_escaping( const gchar *value )
    36 {
    37    const gchar *p = value;
    38    while( *p ) {
    39        if( !isalnum(*p) && *p != '.' && *p != '_' &&
    40                *p != '@' && *p != '%' && *p != '/' ) {
    41            return TRUE;
    42        }
    43        p++;
    44    }
    45    return FALSE;
    46 }
    48 gchar *get_escaped_path( const gchar *value )
    49 {
    50     if( value != NULL && path_needs_escaping(value) ) {
    51         /* Escape with "", and backslash the remaining characters:
    52          *   \ " $ `
    53          */
    54         char buf[strlen(value)*2+3];  
    55         const char *s = value;
    56         char *p = buf;
    57         *p++ = '\"';
    58         while( *s ) {
    59             if( *s == '\\' || *s == '"' || *s == '$' || *s == '`' ) {
    60                 *p++ = '\\';
    61             }
    62             *p++ = *s++;
    63         }
    64         *p++ = '\"';
    65         *p = '\0';
    66         return g_strdup(buf);
    67     } else {
    68         return g_strdup(value);
    69     }
    70 }
    72 gchar *get_expanded_path( const gchar *input )
    73 {
    74     char result[PATH_MAX];
    76     char *d, *e;
    77     const char *s;
    78     d = result;
    79     e = result+sizeof(result)-1;
    80     s = input;
    81     gboolean inDQstring = FALSE;
    83     if( input == NULL )
    84         return NULL;
    86     while( *s ) {
    87         if( d == e ) {
    88             return g_strdup(input); /* expansion too long */
    89         }
    90         char c = *s++;
    91         if( c == '$' ) {
    92             if( *s == '{' ) {
    93                 s++;
    94                 const char *q = s;
    95                 while( *q != '}' ) {
    96                     if( ! *q ) {
    97                         return g_strdup(input); /* unterminated variable */
    98                     }
    99                     q++;
   100                 }
   101                 char *tmp = g_strndup(s, (q-s));
   102                 s = q+1;
   103                 char *value = getenv(tmp);
   104                 g_free(tmp);
   105                 if( value != NULL ) {
   106                     int len = strlen(value);
   107                     if( d + len > e )
   108                         return g_strdup(input);
   109                     strcpy(d, value);
   110                     d+=len;
   111                 } /* Else, empty string */
   112             } else {
   113                 const char *q = s;
   114                 while( isalnum(*q) || *q == '_' ) {
   115                     q++;
   116                 }
   117                 if( q == s ) {
   118                     *d++ = '$';
   119                 } else {
   120                     char *tmp = g_strndup(s,q-s);
   121                     s = q;
   122                     char *value = getenv(tmp);
   123                     g_free(tmp);
   124                     if( value != NULL ) {
   125                         int len = strlen(value);
   126                         if( d + len > e )
   127                             return g_strdup(input);
   128                         strcpy(d, value);
   129                         d += len;
   130                     }
   131                 }
   132             }
   133         } else if( c == '\\' ) {
   134             c = *s++;
   135             if( c ) {
   136                 *d++ = c;
   137             } else {
   138                 *d++ = '\\';
   139             }
   140         } else if( c == '\"' ) {
   141             /* Unescaped double-quotes start a DQ string. Although we treat the
   142              * string as if it were double-quoted for most purposes anyway, so
   143              * this has little effect.
   144              */
   145             inDQstring = !inDQstring;
   146         } else {
   147             *d++ = c;
   148         }
   149     }
   150     *d = '\0';
   151     if( inDQstring ) {
   152         WARN( "Unterminated double-quoted string '%s'", input );
   153     }
   154     return g_strdup(result);
   155 }
   156 gchar *get_absolute_path( const gchar *in_path )
   157 {
   158     char tmp[PATH_MAX];
   159     if( in_path == NULL ) {
   160         return NULL;
   161     }
   162     if( in_path[0] == '/' || in_path[0] == 0 ) {
   163         return g_strdup(in_path);
   164     } else {
   165         getcwd(tmp, sizeof(tmp));
   166         return g_strdup_printf("%s%c%s", tmp, G_DIR_SEPARATOR, in_path);
   167     }
   168 }
   170 gchar *get_filename_at( const gchar *at, const gchar *filename )
   171 {
   172     char *p = strrchr( at, '/' );
   173     if( p == NULL ) {
   174         /* No path at all, so just return filename */
   175         return g_strdup(filename);
   176     } else {
   177         int off = p-at;
   178         return g_strdup_printf("%.*s%c%s", off, at, G_DIR_SEPARATOR, filename );
   179     }
   180 }
   182 const gchar *get_gui_path( int key )
   183 {
   184     if( gui_paths[key] == NULL ) {
   185         gui_paths[key] = lxdream_get_global_config_path_value(key);
   186         /* If no path defined, go with the current working directory */
   187         if( gui_paths[key] == NULL ) {
   188             gui_paths[key] = get_absolute_path(".");
   189         }
   190     }
   191     return gui_paths[key];
   192 }
   194 void set_gui_path( int key, const gchar *path )
   195 {
   196     g_free(gui_paths[key]);
   197     gui_paths[key] = g_strdup(path);
   198 }
   200 void reset_gui_paths()
   201 {
   202     int i;
   203     for( i=0; i < CONFIG_KEY_MAX; i++ ) {
   204         g_free(gui_paths[i]);
   205         gui_paths[i] = NULL;
   206     }
   207 }
.