1/****************************************************************************
2
3 Copyright (C) 2005 Lubos Lunak <l.lunak@kde.org>
4
5Permission is hereby granted, free of charge, to any person obtaining a
6copy of this software and associated documentation files (the "Software"),
7to deal in the Software without restriction, including without limitation
8the rights to use, copy, modify, merge, publish, distribute, sublicense,
9and/or sell copies of the Software, and to permit persons to whom the
10Software is furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23****************************************************************************/
24
25/*
26
27This utility helps to have some configuration options available in startkde
28without the need to launch anything linked to KDE libraries (which may need
29some time to load).
30
31The configuration options are written to $KDEHOME/share/config/startupconfigkeys,
32one option per line, as <file> <group> <key> <default>. It is possible to
33use ' for quoting multiword entries. Values of these options will be written
34to $KDEHOME/share/config/startupconfig as a shell script that will set
35the values to shell variables, named <file>_<group>_<key> (all spaces replaced
36by underscores, everything lowercase). So e.g. line
37"ksplashrc KSplash Theme Default" may result in "ksplashrc_ksplash_theme=Default".
38
39In order to real a whole group it is possible to use <file> <[group]>, e.g.
40"ksplashrc [KSplash]", which will set shell variables for all keys in the group.
41It is not possible to specify default values, but since the configuration options
42are processed in the order they are specified this can be solved by first
43specifying a group and then all the entries that need default values.
44
45When a kconf_update script is used to update such option, kstartupconfig is run
46before kconf_update and therefore cannot see the change in time. To avoid this
47problem, together with the kconf_update script also the matching global config
48file should be updated (any change, kstartupconfig will see the timestamp change).
49
50Note that the kdeglobals config file is not used as a depedendency for other config
51files.
52
53Since the checking is timestamp-based, config files that are frequently updated
54should not be used.
55
56Kstartupconfig works by storing every line from startupconfigkeys in file startupconfigfiles
57followed by paths of all files that are relevant to the option. Non-existent files
58have '!' prepended (for the case they'll be later created), the list of files is
59terminated by line containing '*'. If the timestamps of all relevant files are older
60than the timestamp of the startupconfigfile file, there's no need to update anything.
61Otherwise kdostartupconfig is launched to create or update all the necessary files
62(which already requires loading KDE libraries, but this case should be rare).
63
64*/
65
66#include <kdefakes.h>
67
68#include <config-workspace.h>
69
70#include <sys/types.h>
71#include <sys/stat.h>
72#include <sys/wait.h>
73#include <unistd.h>
74#include <stdio.h>
75#include <string.h>
76#include <stdlib.h>
77
78int main()
79 {
80 time_t config_time;
81 FILE* config;
82 FILE* keys;
83 struct stat st;
84 char kdehome[ 1024 ];
85 char filename[ 1024 ];
86
87 if( getenv( "KDEHOME" ))
88 strlcpy( kdehome, getenv( "KDEHOME" ), 1024 );
89 else if( getenv( "HOME" ))
90 {
91 strlcpy( kdehome, getenv( "HOME" ), 1024 );
92 strlcat( kdehome, "/" KDE_DEFAULT_HOME, 1024 );
93 }
94 else
95 return 1;
96 strlcpy( filename, kdehome, 1024 );
97 strlcat( filename, "/share/config/startupconfig", 1024 );
98 if( access( filename, R_OK ) != 0 )
99 goto doit;
100 strlcpy( filename, kdehome, 1024 );
101 strlcat( filename, "/share/config/startupconfigfiles", 1024 );
102 if( stat( filename, &st ) != 0 )
103 goto doit;
104 config_time = st.st_mtime;
105 config = fopen( filename, "r" );
106 if( config == NULL )
107 goto doit;
108 strlcpy( filename, kdehome, 1024 );
109 strlcat( filename, "/share/config/startupconfigkeys", 1024 );
110 keys = fopen( filename, "r" );
111 if( keys == NULL )
112 return 2;
113 for(;;)
114 {
115 char* nl;
116 char keyline[ 1024 ];
117 char line[ 1024 ];
118
119 if( fgets( keyline, 1023, keys ) == NULL )
120 return 0;
121 if( (nl = strchr( keyline, '\n' )) )
122 *nl = '\0';
123 if( fgets( line, 1023, config ) == NULL )
124 break;
125 if( (nl = strchr( line, '\n' )) )
126 *nl = '\0';
127 if( strcmp( keyline, line ) != 0 )
128 break;
129 for(;;)
130 {
131 if( fgets( line, 1023, config ) == NULL )
132 goto doit2;
133 if( (nl = strchr( line, '\n' )) )
134 *nl = '\0';
135 if( *line == '\0' )
136 goto doit2;
137 if( *line == '*' )
138 break;
139 if( *line == '!' )
140 {
141 if( access( line + 1, R_OK ) == 0 )
142 goto doit2; /* file now exists -> update */
143 }
144 else
145 {
146 if( stat( line, &st ) != 0 )
147 goto doit2;
148 if( st.st_mtime > config_time )
149 goto doit2;
150 }
151 }
152 }
153 doit2:
154 fclose( keys );
155 fclose( config );
156 doit:
157 return system( "kdostartupconfig4" );
158 }
159