Release 960717
[wine.git] / files / profile.c
blob63a302807e32d3a0e6b8dd50aff10faed7037b94
1 /*
2 * Profile functions
4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include "dos_fs.h"
14 #include "windows.h"
15 #include "xmalloc.h"
16 #include "stddebug.h"
17 #include "debug.h"
19 typedef struct tagPROFILEKEY
21 char *name;
22 char *value;
23 struct tagPROFILEKEY *next;
24 } PROFILEKEY;
26 typedef struct tagPROFILESECTION
28 char *name;
29 struct tagPROFILEKEY *key;
30 struct tagPROFILESECTION *next;
31 } PROFILESECTION;
34 typedef struct
36 int changed;
37 PROFILESECTION *section;
38 char *dos_name;
39 } PROFILE;
42 /* Cached profile file */
43 static PROFILE CurProfile = { FALSE, NULL, NULL };
45 /* wine.ini profile content */
46 static PROFILESECTION *WineProfile;
48 #define PROFILE_MAX_LINE_LEN 1024
50 /* Wine profile name in $HOME directory; must begin with slash */
51 static const char PROFILE_WineIniName[] = "/.winerc";
53 /* Check for comments in profile */
54 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
56 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
58 /***********************************************************************
59 * PROFILE_CopyEntry
61 * Copy the content of an entry into a buffer, removing quotes, and possibly
62 * translating environment variables.
64 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
65 int handle_env )
67 char quote = '\0';
68 const char *p;
70 if ((*value == '\'') || (*value == '\"'))
72 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
75 if (!handle_env)
77 lstrcpyn32A( buffer, value, len );
78 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
79 return;
82 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
84 if ((*p == '$') && (p[1] == '{'))
86 char env_val[1024];
87 const char *env_p;
88 const char *p2 = strchr( p, '}' );
89 if (!p2) continue; /* ignore it */
90 lstrcpyn32A(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
91 if ((env_p = getenv( env_val )) != NULL)
93 lstrcpyn32A( buffer, env_p, len );
94 buffer += strlen( buffer );
95 len -= strlen( buffer );
97 p = p2 + 1;
100 *buffer = '\0';
104 /***********************************************************************
105 * PROFILE_Save
107 * Save a profile tree to a file.
109 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
111 PROFILEKEY *key;
113 for ( ; section; section = section->next)
115 if (section->name) fprintf( file, "[%s]\r\n", section->name );
116 for (key = section->key; key; key = key->next)
118 fprintf( file, "%s", key->name );
119 if (key->value) fprintf( file, "=%s", key->value );
120 fprintf( file, "\r\n" );
126 /***********************************************************************
127 * PROFILE_Free
129 * Free a profile tree.
131 static void PROFILE_Free( PROFILESECTION *section )
133 PROFILESECTION *next_section;
134 PROFILEKEY *key, *next_key;
136 for ( ; section; section = next_section)
138 if (section->name) free( section->name );
139 for (key = section->key; key; key = next_key)
141 next_key = key->next;
142 if (key->name) free( key->name );
143 if (key->value) free( key->value );
144 free( key );
146 next_section = section->next;
147 free( section );
152 /***********************************************************************
153 * PROFILE_Load
155 * Load a profile tree from a file.
157 static PROFILESECTION *PROFILE_Load( FILE *file )
159 char buffer[PROFILE_MAX_LINE_LEN];
160 char *p, *p2;
161 int line = 0;
162 PROFILESECTION *section, *first_section;
163 PROFILESECTION **prev_section;
164 PROFILEKEY *key, **prev_key;
166 first_section = (PROFILESECTION *)xmalloc( sizeof(*section) );
167 first_section->name = NULL;
168 first_section->key = NULL;
169 first_section->next = NULL;
170 prev_section = &first_section->next;
171 prev_key = &first_section->key;
173 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
175 line++;
176 p = buffer + strlen(buffer) - 1;
177 while ((p > buffer) && ((*p == '\n') || isspace(*p))) *p-- = '\0';
178 p = buffer;
179 while (*p && isspace(*p)) p++;
180 if (*p == '[') /* section start */
182 if (!(p2 = strrchr( p, ']' )))
184 fprintf( stderr, "PROFILE_Load: Invalid section header at line %d: '%s'\n",
185 line, p );
187 else
189 *p2 = '\0';
190 p++;
191 section = (PROFILESECTION *)xmalloc( sizeof(*section));
192 section->name = xstrdup( p );
193 section->key = NULL;
194 section->next = NULL;
195 *prev_section = section;
196 prev_section = &section->next;
197 prev_key = &section->key;
198 continue;
201 if ((p2 = strchr( p, '=' )) != NULL)
203 char *p3 = p2 - 1;
204 while ((p3 > p) && isspace(*p3)) *p3-- = '\0';
205 *p2++ = '\0';
206 while (*p2 && isspace(*p2)) p2++;
208 key = (PROFILEKEY *)xmalloc( sizeof(*key) );
209 key->name = xstrdup( p );
210 key->value = p2 ? xstrdup( p2 ) : NULL;
211 key->next = NULL;
212 *prev_key = key;
213 prev_key = &key->next;
215 if (debugging_profile)
217 fprintf( stddeb, "PROFILE_Load:\n" );
218 PROFILE_Save( stddeb, first_section );
219 fprintf( stddeb, "PROFILE_Load finished.\n" );
221 return first_section;
225 /***********************************************************************
226 * PROFILE_DeleteSection
228 * Delete a section from a profile tree.
230 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, const char *name )
232 while (*section)
234 if ((*section)->name && !lstrcmpi32A( (*section)->name, name ))
236 PROFILESECTION *to_del = *section;
237 *section = to_del->next;
238 to_del->next = NULL;
239 PROFILE_Free( to_del );
240 return TRUE;
242 section = &(*section)->next;
244 return FALSE;
248 /***********************************************************************
249 * PROFILE_DeleteKey
251 * Delete a key from a profile tree.
253 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
254 const char *section_name, const char *key_name )
256 while (*section)
258 if ((*section)->name && !lstrcmpi32A( (*section)->name, section_name ))
260 PROFILEKEY **key = &(*section)->key;
261 while (*key)
263 if (!lstrcmpi32A( (*key)->name, key_name ))
265 PROFILEKEY *to_del = *key;
266 *key = to_del->next;
267 if (to_del->name) free( to_del->name );
268 if (to_del->value) free( to_del->value );
269 free( to_del );
270 return TRUE;
272 key = &(*key)->next;
275 section = &(*section)->next;
277 return FALSE;
281 /***********************************************************************
282 * PROFILE_Find
284 * Find a key in a profile tree, optionally creating it.
286 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
287 const char *section_name,
288 const char *key_name, int create )
290 while (*section)
292 if ((*section)->name && !lstrcmpi32A( (*section)->name, section_name ))
294 PROFILEKEY **key = &(*section)->key;
295 while (*key)
297 if (!lstrcmpi32A( (*key)->name, key_name )) return *key;
298 key = &(*key)->next;
300 if (!create) return NULL;
301 *key = (PROFILEKEY *)xmalloc( sizeof(PROFILEKEY) );
302 (*key)->name = xstrdup( key_name );
303 (*key)->value = NULL;
304 (*key)->next = NULL;
305 return *key;
307 section = &(*section)->next;
309 if (!create) return NULL;
310 *section = (PROFILESECTION *)xmalloc( sizeof(PROFILESECTION) );
311 (*section)->name = xstrdup(section_name);
312 (*section)->next = NULL;
313 (*section)->key = (PROFILEKEY *)xmalloc( sizeof(PROFILEKEY) );
314 (*section)->key->name = xstrdup( key_name );
315 (*section)->key->value = NULL;
316 (*section)->key->next = NULL;
317 return (*section)->key;
321 /***********************************************************************
322 * PROFILE_FlushFile
324 * Flush the current profile to disk if changed.
326 static BOOL PROFILE_FlushFile(void)
328 char *p, buffer[MAX_PATHNAME_LEN];
329 const char *unix_name;
330 FILE *file = NULL;
332 if (!CurProfile.changed || !CurProfile.dos_name) return TRUE;
333 if (!(unix_name = DOSFS_GetUnixFileName( CurProfile.dos_name, FALSE )) ||
334 !(file = fopen( unix_name, "w" )))
336 /* Try to create it in $HOME/.wine */
337 /* FIXME: this will need a more general solution */
338 if ((p = getenv( "HOME" )) != NULL)
340 strcpy( buffer, p );
341 strcat( buffer, "/.wine/" );
342 p = buffer + strlen(buffer);
343 strcpy( p, strrchr( CurProfile.dos_name, '\\' ) + 1 );
344 AnsiLower( p );
345 file = fopen( buffer, "w" );
346 unix_name = buffer;
350 if (!file)
352 fprintf( stderr, "Warning: could not save profile file %s\n",
353 CurProfile.dos_name );
354 return FALSE;
357 dprintf_profile( stddeb, "Saving '%s' into '%s'\n",
358 CurProfile.dos_name, unix_name );
359 PROFILE_Save( file, CurProfile.section );
360 fclose( file );
361 CurProfile.changed = FALSE;
362 return TRUE;
366 /***********************************************************************
367 * PROFILE_Open
369 * Open a profile file, checking the cached file first.
371 static BOOL PROFILE_Open( const char *filename )
373 char buffer[MAX_PATHNAME_LEN];
374 const char *dos_name, *unix_name;
375 char *newdos_name, *p;
376 FILE *file = NULL;
378 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
379 strchr( filename, ':' ))
381 if (!(dos_name = DOSFS_GetDosTrueName( filename, FALSE))) return FALSE;
383 else
385 GetWindowsDirectory( buffer, sizeof(buffer) );
386 strcat( buffer, "\\" );
387 strcat( buffer, filename );
388 if (!(dos_name = DOSFS_GetDosTrueName( buffer, FALSE ))) return FALSE;
390 if (CurProfile.dos_name && !strcmp( dos_name, CurProfile.dos_name ))
392 dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
393 filename );
394 return TRUE;
397 /* Flush the previous profile */
399 newdos_name = xstrdup( dos_name );
400 PROFILE_FlushFile();
401 PROFILE_Free( CurProfile.section );
402 if (CurProfile.dos_name) free( CurProfile.dos_name );
403 CurProfile.section = NULL;
404 CurProfile.dos_name = newdos_name;
406 /* Try to open the profile file, first in $HOME/.wine */
408 /* FIXME: this will need a more general solution */
409 if ((p = getenv( "HOME" )) != NULL)
411 strcpy( buffer, p );
412 strcat( buffer, "/.wine/" );
413 p = buffer + strlen(buffer);
414 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
415 AnsiLower( p );
416 if ((file = fopen( buffer, "r" )))
417 dprintf_profile( stddeb, "Found it in %s\n", buffer );
420 if (!file && ((unix_name = DOSFS_GetUnixFileName( dos_name, TRUE ))))
422 if ((file = fopen( unix_name, "r" )))
423 dprintf_profile( stddeb, "Found it in %s\n", unix_name );
426 if (file)
428 CurProfile.section = PROFILE_Load( file );
429 fclose( file );
431 else
432 fprintf( stderr, "Warning: profile file %s not found\n", newdos_name );
433 dprintf_profile( stddeb, "PROFILE_Open(%s): successful\n", filename );
434 return TRUE;
438 /***********************************************************************
439 * PROFILE_GetSection
441 * Enumerate all the keys of a section.
443 static INT PROFILE_GetSection( PROFILESECTION *section,
444 const char *section_name,
445 char *buffer, INT len, int handle_env )
447 PROFILEKEY *key;
448 while (section)
450 if (section->name && !lstrcmpi32A( section->name, section_name ))
452 INT oldlen = len;
453 for (key = section->key; key; key = key->next)
455 if (len <= 2) break;
456 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
457 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
458 len -= strlen(buffer) + 1;
459 buffer += strlen(buffer) + 1;
461 *buffer = '\0';
462 return oldlen - len + 1;
464 section = section->next;
466 buffer[0] = buffer[1] = '\0';
467 return 2;
471 /***********************************************************************
472 * PROFILE_GetString
474 * Get a profile string.
476 static INT PROFILE_GetString( const char *section, const char *key_name,
477 const char *def_val, char *buffer, INT len )
479 PROFILEKEY *key = NULL;
481 if (!def_val) def_val = "";
482 if (key_name)
484 key = PROFILE_Find( &CurProfile.section, section, key_name, FALSE );
485 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
486 len, FALSE );
487 dprintf_profile( stddeb, "PROFILE_GetString('%s','%s','%s'): returning '%s'\n",
488 section, key_name, def_val, buffer );
489 return strlen( buffer );
491 return PROFILE_GetSection(CurProfile.section, section, buffer, len, FALSE);
495 /***********************************************************************
496 * PROFILE_SetString
498 * Set a profile string.
500 static BOOL PROFILE_SetString( const char *section_name, const char *key_name,
501 const char *value )
503 BOOL ret;
505 if (!key_name) /* Delete a whole section */
507 dprintf_profile(stddeb, "PROFILE_DeleteSection('%s')\n", section_name);
508 ret = PROFILE_DeleteSection( &CurProfile.section, section_name );
509 CurProfile.changed |= ret;
510 return ret;
512 else if (!value) /* Delete a key */
514 dprintf_profile( stddeb, "PROFILE_DeleteKey('%s','%s')\n",
515 section_name, key_name );
516 ret = PROFILE_DeleteKey( &CurProfile.section, section_name, key_name );
517 CurProfile.changed |= ret;
518 return ret;
520 else /* Set the key value */
522 PROFILEKEY *key = PROFILE_Find( &CurProfile.section, section_name,
523 key_name, TRUE );
524 dprintf_profile( stddeb, "PROFILE_SetString('%s','%s','%s'): ",
525 section_name, key_name, value );
526 if (key->value)
528 if (!strcmp( key->value, value ))
530 dprintf_profile( stddeb, "no change needed\n" );
531 return TRUE; /* No change needed */
533 dprintf_profile( stddeb, "replacing '%s'\n", key->value );
534 free( key->value );
536 else dprintf_profile( stddeb, "creating key\n" );
537 key->value = xstrdup( value );
538 CurProfile.changed = TRUE;
539 return TRUE;
544 /***********************************************************************
545 * PROFILE_GetWineIniString
547 * Get a config string from the wine.ini file.
549 int PROFILE_GetWineIniString( const char *section, const char *key_name,
550 const char *def, char *buffer, int len )
552 if (key_name)
554 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
555 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
556 len, TRUE );
557 dprintf_profile( stddeb, "PROFILE_GetWineIniString('%s','%s','%s'): returning '%s'\n",
558 section, key_name, def, buffer );
559 return strlen( buffer );
561 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE );
565 /***********************************************************************
566 * PROFILE_GetWineIniInt
568 * Get a config integer from the wine.ini file.
570 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
572 char buffer[20];
573 char *p;
574 long result;
576 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
577 if (!key || !key->value) return def;
578 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
579 result = strtol( buffer, &p, 0 );
580 if (p == buffer) return 0; /* No digits at all */
581 return (int)result;
585 /***********************************************************************
586 * PROFILE_LoadWineIni
588 * Load the wine.ini file.
590 int PROFILE_LoadWineIni(void)
592 char buffer[MAX_PATHNAME_LEN];
593 const char *p;
594 FILE *f;
596 if ((p = getenv( "HOME" )) != NULL)
598 lstrcpyn32A(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
599 strcat( buffer, PROFILE_WineIniName );
600 if ((f = fopen( buffer, "r" )) != NULL)
602 WineProfile = PROFILE_Load( f );
603 fclose( f );
604 return 1;
607 else fprintf( stderr, "Warning: could not get $HOME value for config file.\n" );
609 /* Try global file */
611 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
613 WineProfile = PROFILE_Load( f );
614 fclose( f );
615 return 1;
617 fprintf( stderr, "Can't open configuration file %s or $HOME%s\n",
618 WINE_INI_GLOBAL, PROFILE_WineIniName );
619 return 0;
623 /***********************************************************************
624 * GetProfileInt (KERNEL.57)
626 UINT GetProfileInt( LPCSTR section, LPCSTR entry, INT def_val )
628 return GetPrivateProfileInt( section, entry, def_val, "win.ini" );
632 /***********************************************************************
633 * GetProfileString (KERNEL.58)
635 INT GetProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
636 LPSTR buffer, INT len )
638 return GetPrivateProfileString( section, entry, def_val,
639 buffer, len, "win.ini" );
643 /***********************************************************************
644 * WriteProfileString (KERNEL.59)
646 BOOL WriteProfileString( LPCSTR section, LPCSTR entry, LPCSTR string )
648 return WritePrivateProfileString( section, entry, string, "win.ini" );
652 /***********************************************************************
653 * GetPrivateProfileInt (KERNEL.127)
655 UINT GetPrivateProfileInt( LPCSTR section, LPCSTR entry, INT def_val,
656 LPCSTR filename )
658 char buffer[20];
659 char *p;
660 long result;
662 GetPrivateProfileString( section, entry, "",
663 buffer, sizeof(buffer), filename );
664 if (!buffer[0]) return (UINT)def_val;
665 result = strtol( buffer, &p, 0 );
666 if (p == buffer) return 0; /* No digits at all */
667 #ifdef WINELIB32
668 return (UINT)result;
669 #else
670 if (result > 65535) return 65535;
671 if (result >= 0) return (UINT)result;
672 if (result < -32768) return -32768;
673 return (UINT)(INT)result;
674 #endif
678 /***********************************************************************
679 * GetPrivateProfileString (KERNEL.128)
681 INT GetPrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
682 LPSTR buffer, INT len, LPCSTR filename )
684 if (PROFILE_Open( filename ))
685 return PROFILE_GetString( section, entry, def_val, buffer, len );
686 lstrcpyn32A( buffer, def_val, len );
687 return strlen( buffer );
691 /***********************************************************************
692 * WritePrivateProfileString (KERNEL.129)
694 BOOL WritePrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR string,
695 LPCSTR filename )
697 if (!PROFILE_Open( filename )) return FALSE;
698 if (!section) return PROFILE_FlushFile();
699 return PROFILE_SetString( section, entry, string );
703 /***********************************************************************
704 * WriteOutProfiles (KERNEL.315)
706 void WriteOutProfiles(void)
708 PROFILE_FlushFile();