kstartupconfig.cpp
00001 /**************************************************************************** 00002 00003 Copyright (C) 2005 Lubos Lunak <l.lunak@kde.org> 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a 00006 copy of this software and associated documentation files (the "Software"), 00007 to deal in the Software without restriction, including without limitation 00008 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00009 and/or sell copies of the Software, and to permit persons to whom the 00010 Software is furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00018 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00020 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00021 DEALINGS IN THE SOFTWARE. 00022 00023 ****************************************************************************/ 00024 00025 /* 00026 00027 This utility helps to have some configuration options available in startkde 00028 without the need to launch anything linked to KDE libraries (which may need 00029 some time to load). 00030 00031 The configuration options are written to $KDEHOME/share/config/startupconfigkeys, 00032 one option per line, as <file> <group> <key> <default>. It is possible to 00033 use ' for quoting multiword entries. Values of these options will be written 00034 to $KDEHOME/share/config/startupconfig as a shell script that will set 00035 the values to shell variables, named <file>_<group>_<key> (all spaces replaced 00036 by underscores, everything lowercase). So e.g. line 00037 "ksplashrc KSplash Theme Default" may result in "ksplashrc_ksplash_theme=Default". 00038 00039 In order to real a whole group it is possible to use <file> <[group]>, e.g. 00040 "ksplashrc [KSplash]", which will set shell variables for all keys in the group. 00041 It is not possible to specify default values, but since the configuration options 00042 are processed in the order they are specified this can be solved by first 00043 specifying a group and then all the entries that need default values. 00044 00045 When a kconf_update script is used to update such option, kstartupconfig is run 00046 before kconf_update and therefore cannot see the change in time. To avoid this 00047 problem, together with the kconf_update script also the matching global config 00048 file should be updated (any change, kstartupconfig will see the timestamp change). 00049 00050 Note that the kdeglobals config file is not used as a depedendency for other config 00051 files. 00052 00053 Since the checking is timestamp-based, config files that are frequently updated 00054 should not be used. 00055 00056 It is required to pass $KDEHOME from startkde as the argument for kstartupconfig. 00057 00058 Kstartupconfig works by storing every line from startupconfigkeys in file startupconfigfiles 00059 followed by paths of all files that are relevant to the option. Non-existent files 00060 have '!' prepended (for the case they'll be later created), the list of files is 00061 terminated by line containing '*'. If the timestamps of all relevant files are older 00062 than the timestamp of the startupconfigfile file, there's no need to update anything. 00063 Otherwise kdostartupconfig is launched to create or update all the necessary files 00064 (which already requires loading KDE libraries, but this case should be rare). 00065 00066 */ 00067 00068 #include <config.h> 00069 00070 #include <sys/types.h> 00071 #include <sys/stat.h> 00072 #include <sys/wait.h> 00073 #include <unistd.h> 00074 #include <stdio.h> 00075 #include <string.h> 00076 #include <stdlib.h> 00077 00078 int main() 00079 { 00080 char kdehome[ 1024 ]; 00081 if( getenv( "KDEHOME" )) 00082 strlcpy( kdehome, getenv( "KDEHOME" ), 1024 ); 00083 else if( getenv( "HOME" )) 00084 { 00085 strlcpy( kdehome, getenv( "HOME" ), 1024 ); 00086 strlcat( kdehome, "/.kde", 1024 ); 00087 } 00088 else 00089 return 1; 00090 char filename[ 1024 ]; 00091 strlcpy( filename, kdehome, 1024 ); 00092 strlcat( filename, "/share/config/startupconfig", 1024 ); 00093 if( access( filename, R_OK ) != 0 ) 00094 { 00095 int ret = system( "kdostartupconfig" ); 00096 return WEXITSTATUS( ret ); 00097 } 00098 strlcpy( filename, kdehome, 1024 ); 00099 strlcat( filename, "/share/config/startupconfigfiles", 1024 ); 00100 struct stat st; 00101 if( stat( filename, &st ) != 0 ) 00102 { 00103 int ret = system( "kdostartupconfig" ); 00104 return WEXITSTATUS( ret ); 00105 } 00106 time_t config_time = st.st_mtime; 00107 FILE* config = fopen( filename, "r" ); 00108 if( config == NULL ) 00109 { 00110 int ret = system( "kdostartupconfig" ); 00111 return WEXITSTATUS( ret ); 00112 } 00113 strlcpy( filename, kdehome, 1024 ); 00114 strlcat( filename, "/share/config/startupconfigkeys", 1024 ); 00115 FILE* keys = fopen( filename, "r" ); 00116 if( keys == NULL ) 00117 { 00118 fclose( config ); 00119 return 2; 00120 } 00121 bool need_update = true; 00122 for(;;) 00123 { 00124 char keyline[ 1024 ]; 00125 if( fgets( keyline, 1023, keys ) == NULL ) 00126 { 00127 need_update = false; 00128 break; 00129 } 00130 if( char* nl = strchr( keyline, '\n' )) 00131 *nl = '\0'; 00132 char line[ 1024 ]; 00133 if( fgets( line, 1023, config ) == NULL ) 00134 break; 00135 if( char* nl = strchr( line, '\n' )) 00136 *nl = '\0'; 00137 if( strcmp( keyline, line ) != 0 ) 00138 break; 00139 bool ok = false; 00140 for(;;) 00141 { 00142 if( fgets( line, 1023, config ) == NULL ) 00143 break; 00144 if( char* nl = strchr( line, '\n' )) 00145 *nl = '\0'; 00146 if( *line == '\0' ) 00147 break; 00148 if( *line == '*' ) 00149 { 00150 ok = true; 00151 break; 00152 } 00153 if( *line == '!' ) 00154 { 00155 if( access( line + 1, R_OK ) == 0 ) 00156 break; // file now exists -> update 00157 } 00158 else 00159 { 00160 struct stat st; 00161 if( stat( line, &st ) != 0 ) 00162 break; 00163 if( st.st_mtime > config_time ) 00164 break; 00165 } 00166 } 00167 if( !ok ) 00168 break; 00169 } 00170 fclose( keys ); 00171 fclose( config ); 00172 if( need_update ) 00173 { 00174 int ret = system( "kdostartupconfig" ); 00175 return WEXITSTATUS( ret ); 00176 } 00177 return 0; 00178 }