2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $TOG: UserPreference.C /main/7 1998/04/17 11:38:58 mgreess $
26 * Copyright (c) 1993 HAL Computer Systems International, Ltd.
27 * All rights reserved. Unpublished -- rights reserved under
28 * the Copyright Laws of the United States. USE OF A COPYRIGHT
29 * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
32 * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
33 * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
34 * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
35 * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
38 * RESTRICTED RIGHTS LEGEND
39 * Use, duplication, or disclosure by the Government is subject
40 * to the restrictions as set forth in subparagraph (c)(l)(ii)
41 * of the Rights in Technical Data and Computer Software clause
42 * at DFARS 252.227-7013.
44 * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
51 #define C_UserPreference
66 #if !defined(hpux) && !defined(__osf__) && !defined(USL)
69 #include <sys/types.h>
74 PreferenceRecord *PreferenceRecord::g_head;
75 PreferenceRecord *PreferenceRecord::g_tail;
76 int PreferenceRecord::g_update_count = -1;
79 PreferenceRecord::PreferenceRecord (const char *key, const char *value)
80 : f_key (strdup (key)),
81 f_value (strdup (value)),
87 g_tail->f_next = this;
92 PreferenceRecord::~PreferenceRecord()
94 free ((char *) f_key);
95 free ((char *) f_value);
100 PreferenceRecord::set_value (const char *value)
102 free ((char *) f_value);
103 f_value = strdup (value);
108 PreferenceRecord::form_filename()
110 // Form the file name of the preferences.
111 static char filename[256];
112 if (filename[0] == '\0')
114 sprintf (filename, "%s/preferences", env().user_path());
116 const char *home = env().home();
118 throw (CASTEXCEPT Exception());
119 const char *lang = env().lang();
121 throw (CASTEXCEPT Exception());
123 sprintf (filename, "%s/.dt/dtinfo/%s/preferences",
133 revert_from_backup (const char *filename)
135 // Failed, so look for the backup file.
136 char backup[256], original[256];
137 sprintf (backup, "%s.bak", filename);
138 struct stat file_info;
140 if (stat (backup, &file_info) != -1 &&
141 S_ISREG(file_info.st_mode))
144 link (backup, filename);
150 read_version (FILE *stream)
152 // Make sure the file is valid.
154 fread (&V, 1, 1, stream);
157 // Nab the version from the file.
159 fscanf (stream, "%d", &version);
165 read_update_count (FILE *stream)
167 char buffer[256], *p;
170 fgets (buffer, 256, stream);
172 while (*p != ',' && *p != '\0')
177 sscanf (p, "%d", &update_count);
178 ON_DEBUG (printf ("Update count = %d\n", update_count));
179 return (update_count);
183 PreferenceRecord::read_prefs()
185 // Open it and read in the preferences.
186 const char *filename;
193 filename = form_filename();
195 struct stat file_info;
196 int status = stat (filename, &file_info);
199 // Check for access failure or IO error.
200 if (errno == EACCES || errno == EIO)
201 throw (CASTEXCEPT Exception());
202 // It doesn't exists otherwise.
206 else if (!S_ISREG (file_info.st_mode))
207 throw (CASTEXCEPT Exception());
208 stream = fopen (filename, "r");
209 if (stream == NULL) // Open failed, something is bogus.
210 throw (CASTEXCEPT Exception());
212 int version = read_version (stream); // Snag the version.
213 if (version == 0) // See if file is ok.
216 if (attempt == 2) // give up on 2nd attempt
217 throw (CASTEXCEPT Exception());
219 revert_from_backup (filename);
223 g_update_count = read_update_count (stream);
225 // Read in the preference lines.
226 char key[256], *value;
227 while (fgets (key, 256, stream) != NULL)
230 while (*value != ':' && *value != '\0')
232 if (*value == '\0') // Ignore bogus lines.
235 while (isspace (*value))
237 int len = strlen(value);
239 ON_DEBUG (printf ("Got Pref: %s = %s\n", key, value));
240 new PreferenceRecord (key, value);
247 PreferenceRecord::write_prefs()
249 assert (g_update_count != -1);
251 const char *filename = form_filename();
252 struct stat file_info;
253 int status = stat (filename, &file_info);
254 // Make sure it's a regular file if it exists.
255 if (status == 0 && !S_ISREG (file_info.st_mode))
256 throw (CASTEXCEPT Exception());
258 // Check the update count to guard against overwrites.
259 // This isn't foolproof, but we can't trust NFS locking
260 // so this will have to do for now. 13:39 15-Sep-93 DJB
262 int update_count = 0;
266 // If the file isn't readable, we won't write the prefs.
267 stream = fopen (filename, "r");
269 throw (CASTEXCEPT Exception());
271 if (read_version (stream) != 0)
272 update_count = read_update_count (stream);
276 if (update_count != g_update_count)
278 bool doit = message_mgr().
279 question_dialog ("Preferences have changed on disk.\nOverwrite?");
284 // Create a backup file from the current preferences, if any.
289 sprintf (backup, "%s.bak", filename);
291 if (rename (filename, backup) == -1)
292 throw (CASTEXCEPT Exception());
294 else // Make sure the parent directory exists.
297 sprintf (dirname, "%s", env().user_path());
298 status = stat (dirname, &file_info);
301 if (mkdir (dirname, 0777) == -1)
302 throw (CASTEXCEPT Exception());
304 else if (!S_ISDIR (file_info.st_mode))
305 throw (CASTEXCEPT Exception());
308 // Open the file and write the preferences.
309 stream = fopen (filename, "w");
312 // Put the backup file back where it came from.
313 if (backup[0] != '\0')
314 rename (backup, filename);
315 throw (CASTEXCEPT Exception());
318 // Write out the preference records.
319 PreferenceRecord *current = g_head;
320 // First line is version and update count.
321 fprintf (stream, "-1.0, %d # AUTOMATICALLY GENERATED - DO NOT EDIT!\n",
323 while (current != NULL)
325 if (*(current->f_value) != '\0' &&
326 fprintf(stream, "%s: %s\n", current->f_key, current->f_value) == EOF)
329 // Remove the file and restore the backup file.
330 if (unlink (filename) == 0 && backup[0] != '\0')
331 rename (backup, filename);
332 throw (CASTEXCEPT Exception());
334 current = current->f_next;
337 // Rewrite first character to indicate file is complete.
338 fseek (stream, 0L, 0);
339 fwrite ("V", 1, 1, stream);
346 PreferenceRecord::lookup (const char *key)
348 if (g_update_count == -1)
356 // This will only happen the first time through.
357 message_mgr().error_dialog ("Unable to read preferences.");
363 // Scan through the list of preferences looking for the record.
364 PreferenceRecord *current = g_head;
365 while (current != NULL)
367 if (strcmp (key, current->f_key) == 0)
369 current = current->f_next;
372 // Not found, so create a new record.
373 return (new PreferenceRecord (key, ""));
377 UserPreference::UserPreference (const char *key)
378 : f_preference (PreferenceRecord::lookup (key))
383 UserPreference::~UserPreference()