~ubuntu-branches/ubuntu/saucy/cpufreqd/saucy-updates

« back to all changes in this revision

Viewing changes to config_parser.c

  • Committer: Bazaar Package Importer
  • Author(s): Mattia Dongili
  • Date: 2006-12-17 17:13:57 UTC
  • mfrom: (3.1.5 feisty)
  • Revision ID: james.westby@ubuntu.com-20061217171357-atrpxy6jqdq846jm
Tags: 2.2.1-2
Provide a more conservative config files, users owning non ondemand
capable CPU have complained. (Closes: #400580)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2002,2003,2004  Mattia Dongili<dongili@supereva.it>
3
 
 *                                George Staikos <staikos@0wned.org>
4
 
 *
5
 
 *  2004.08.22
6
 
 *  - added percentage/absolute frequency translation based on a patch submitted
7
 
 *    by Herv� Eychenne
8
 
 *
9
 
 *  2003.16.08
10
 
 *  - added support for cpu monitoring, base code by Dietz Proepper and minor
11
 
 *    fixes by Mattia Dongili
12
 
 *
13
 
 *  This program is free software; you can redistribute it and/or modify
14
 
 *  it under the terms of the GNU General Public License as published by
15
 
 *  the Free Software Foundation; either version 2 of the License, or
16
 
 *  (at your option) any later version.
17
 
 *
18
 
 *  This program is distributed in the hope that it will be useful,
19
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 
 *  GNU General Public License for more details.
22
 
 *
23
 
 *  You should have received a copy of the GNU General Public License
24
 
 *  along with this program; if not, write to the Free Software
25
 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 
 */
27
 
 
28
 
#include "cpufreqd.h"
29
 
#include "main.h"
30
 
#include "config_parser.h"
31
 
 
32
 
/*
33
 
 * Parse configuration file.
34
 
 *
35
 
 * As long as the config file is quite simple let's keep also a veryvery simple parser.
36
 
 */
37
 
int parse_config (general *g) {
38
 
  FILE *config;
39
 
  profile *last_profile = 0L, *p_iter = 0L;
40
 
  rule *last_rule = 0L, *r_iter = 0L;
41
 
  char buf[256];
42
 
 
43
 
  /* configuration file */
44
 
  cp_log(LOG_INFO, "parse_config(): reading configuration file %s\n", g->config_file);
45
 
  config = fopen(g->config_file, "r");
46
 
  if (!config) {
47
 
    cp_log(LOG_ERR, "parse_config(): %s: %s\n", g->config_file, strerror(errno));
48
 
    return -1;
49
 
  }
50
 
 
51
 
  while (!feof(config)) {
52
 
    char *clean = 0L;
53
 
 
54
 
    if (!fgets(buf, 255, config))
55
 
      break;
56
 
 
57
 
    clean = clean_config_line(buf);
58
 
 
59
 
    if (!clean[0]) /* returned an empty line */
60
 
      continue;
61
 
 
62
 
    clean = strip_comments_line(clean);
63
 
 
64
 
    if (!clean[0]) /* returned an empty line */
65
 
      continue;
66
 
 
67
 
    /* if General scan general options */
68
 
    if (strstr(clean,"[General]")) {
69
 
      if (parse_config_general (config, g) < 0) {
70
 
        return -1;
71
 
      }
72
 
      continue;
73
 
    }
74
 
 
75
 
    /* if Profile scan profile options */
76
 
    if (strstr(clean,"[Profile]")) {
77
 
 
78
 
      profile *prof = (profile *)malloc(sizeof(profile));
79
 
      memset(prof, 0, sizeof(profile));
80
 
      if (parse_config_profile (config, prof, g) < 0) {
81
 
        cp_log(LOG_CRIT, "parse_config(): [Profile] error parsing %s, see logs for details.\n", g->config_file);
82
 
        fclose(config);
83
 
        return -1;
84
 
      }
85
 
      if (!g->profiles) {
86
 
        g->profiles = last_profile = prof;
87
 
      } else {
88
 
        p_iter = g->profiles;
89
 
        /* checks duplicate names */
90
 
        while (p_iter) {
91
 
          if (strcmp(p_iter->name, prof->name) == 0) {
92
 
            cp_log(LOG_CRIT, "parse_config(): [Profile] name \"%s\" already exists.\n", prof->name);
93
 
            fclose(config);
94
 
            return -1;
95
 
          }
96
 
          p_iter = p_iter->next;
97
 
        }
98
 
        last_profile->next = prof;
99
 
        last_profile = last_profile->next;
100
 
      }
101
 
      continue;
102
 
    }
103
 
 
104
 
    /* if Rule scan rules options */
105
 
    if (strstr(clean,"[Rule]")) {
106
 
      rule *rul = (rule *)malloc(sizeof(rule));
107
 
      memset(rul, 0, sizeof(rule));
108
 
      if (parse_config_rule (config, rul) < 0) {
109
 
        cp_log(LOG_CRIT, "parse_config(): [Rule] error parsing %s, see logs for details.\n", g->config_file);
110
 
        return -1;
111
 
      }
112
 
      if (!g->rules) {
113
 
        g->rules = last_rule = rul;
114
 
      } else {
115
 
        r_iter = g->rules;
116
 
        /* check duplicate names */
117
 
        while (r_iter != NULL) {
118
 
          if (strcmp(r_iter->name, rul->name) == 0) {
119
 
            cp_log(LOG_CRIT, "parse_config(): [Rule] name \"%s\" already exists.\n", rul->name);
120
 
            return -1;
121
 
          }
122
 
          r_iter = r_iter->next;
123
 
        }
124
 
        last_rule->next = rul;
125
 
        last_rule = last_rule->next;
126
 
      }
127
 
 
128
 
      continue;
129
 
    }
130
 
  }
131
 
  fclose(config);
132
 
 
133
 
  /* did I read something? 
134
 
   * chek if I read at least one rule, otherwise exit
135
 
   */
136
 
  if (g->rules == NULL) {
137
 
    cp_log(LOG_ERR, "parse_config(): No rules found!\n");
138
 
    return -1;
139
 
  }
140
 
  
141
 
  /*
142
 
   * associate rules->profiles
143
 
   * go through rules and associate to the proper profile
144
 
   */
145
 
  r_iter = g->rules;
146
 
  while (r_iter != NULL) {
147
 
    int profile_found = 0;
148
 
 
149
 
    p_iter = g->profiles;
150
 
    /* go through profiles */
151
 
    while (p_iter != NULL) {
152
 
      if (strcmp(r_iter->profile_name, p_iter->name)==0) {
153
 
        /* a profile is allowed to be addressed by more than 1 rule */
154
 
        r_iter->prof = p_iter;
155
 
        profile_found = 1;
156
 
        break;
157
 
      }
158
 
      p_iter = p_iter->next;
159
 
    }
160
 
 
161
 
    if (!profile_found) {
162
 
      cp_log(LOG_CRIT, "parse_config(): Syntax error: no Profile section found for Rule \"%s\" \
163
 
                        (requested Profile \"%s\")\n",
164
 
                       r_iter->name,
165
 
                       r_iter->profile_name);
166
 
      return -1;
167
 
    }
168
 
    r_iter = r_iter->next;
169
 
  }
170
 
 
171
 
  r_iter = g->rules;
172
 
  while (r_iter != NULL) {
173
 
     cp_log(LOG_NOTICE, "parse_config(): Rule \"%s\" has Profile \"%s\"\n", r_iter->name, r_iter->prof->name);
174
 
     r_iter = r_iter->next;
175
 
  }
176
 
 
177
 
  return 0;
178
 
}
179
 
 
180
 
/*
181
 
 * parse the [General] section
182
 
 *
183
 
 * Returns -1 if required properties are missing, 0 otherwise
184
 
 */
185
 
int parse_config_general (FILE *config, general *g) {
186
 
char buf[256];
187
 
 
188
 
  while (!feof(config)) {
189
 
    char *clean;
190
 
    char *name;
191
 
    char *value;
192
 
 
193
 
    if (!fgets(buf, 255, config))
194
 
      break;
195
 
 
196
 
    clean = strip_comments_line(buf);
197
 
 
198
 
    if (!clean[0]) /* returned an empty line */
199
 
      continue;
200
 
 
201
 
    clean = clean_config_line(clean);
202
 
 
203
 
    if (!clean[0]) /* returned an empty line */
204
 
      break;
205
 
 
206
 
    name = strtok(clean, "=");
207
 
    value = strtok(NULL, "");
208
 
 
209
 
    if (strcmp(name,"poll_interval") == 0) {
210
 
      if (value != NULL) {
211
 
        g->poll_interval = atoi (value);
212
 
      }
213
 
      /* validate */
214
 
      if (g->poll_interval < 1) {
215
 
        cp_log(LOG_WARNING, "WARNING: [General] poll_interval has invalid value, using default.\n");
216
 
        g->poll_interval = DEFAULT_POLL;
217
 
      }
218
 
    } else if (strcmp(name,"verbosity") == 0) {
219
 
      if (!g->log_level_overridden) {
220
 
        if (value != NULL) {
221
 
          g->log_level = atoi (value);
222
 
          /* validate */
223
 
          if (g->log_level < 0 || g->log_level > 7) {
224
 
            cp_log(LOG_WARNING, "WARNING: [General] verbosity has invalid value, using default (%d).\n", DEFAULT_VERBOSITY);
225
 
            g->log_level = DEFAULT_VERBOSITY;
226
 
          }
227
 
        } else {
228
 
          g->log_level = DEFAULT_VERBOSITY;
229
 
          cp_log(LOG_WARNING, "WARNING: [General] verbosity has empty value, using default (%d).\n", DEFAULT_VERBOSITY);
230
 
        }
231
 
      } else {
232
 
          cp_log(LOG_DEBUG, "parse_config_general(): skipping \"verbosity\", overridden in the command line.\n");
233
 
      }
234
 
    } else if (strcmp(name,"pm_type") == 0) {
235
 
      if (value != NULL) {
236
 
        strncpy(g->pm_plugin, value, 101);
237
 
      } else {
238
 
        cp_log(LOG_WARNING, "parse_config_general(): empty \"pm_type\", using default "DEFAULT_PMPLUGIN".\n");
239
 
        strncpy(g->pm_plugin, DEFAULT_PMPLUGIN, 101);
240
 
      }
241
 
      g->pm_plugin[100] = 0;
242
 
    } else if (strcmp(name,"pidfile") == 0) {
243
 
      if (value != NULL) {
244
 
        strncpy(g->pidfile, value, 512);
245
 
      } else {
246
 
        cp_log(LOG_WARNING, "parse_config_general(): empty \"pidfile\", using default "CPUFREQD_PIDFILE".\n");
247
 
        strncpy(g->pidfile, CPUFREQD_PIDFILE, 512);
248
 
      }
249
 
      g->pidfile[511] = 0;
250
 
    } else if (strcmp(name,"acpi_workaround") == 0) {
251
 
      if (value != NULL) {
252
 
        g->acpi_workaround = atoi (value);
253
 
        cp_log(LOG_WARNING, "parse_config_general(): ACPI workaround enabled.\n");
254
 
      }
255
 
    } else {
256
 
      cp_log(LOG_WARNING, "WARNING: [General] skipping unknown config option \"%s\"\n", name);
257
 
    }
258
 
  }
259
 
 
260
 
  return 0;
261
 
}
262
 
 
263
 
/*
264
 
 * parse a [Profile] section
265
 
 *
266
 
 * Returns -1 if required properties are missing, 0 otherwise
267
 
 */
268
 
int parse_config_profile (FILE *config, profile *p, general *g) {
269
 
#define HAS_NAME    1
270
 
#define HAS_MIN     2
271
 
#define HAS_MAX     4
272
 
#define HAS_POLICY  8
273
 
int state = 0;
274
 
char buf[256];
275
 
 
276
 
  while (!feof(config)) {
277
 
    char *clean;
278
 
    char *name;
279
 
    char *value;
280
 
 
281
 
    if (!fgets(buf, 255, config))
282
 
      break;
283
 
 
284
 
    clean = strip_comments_line(buf);
285
 
 
286
 
    if (!clean[0]) /* returned an empty line */
287
 
      continue;
288
 
 
289
 
    clean = clean_config_line(clean);
290
 
 
291
 
    if (!clean[0]) /* returned an empty line */
292
 
      break;
293
 
 
294
 
    name = strtok(clean, "=");
295
 
    value = strtok(NULL, "");
296
 
    
297
 
    /* empty value: skip */
298
 
    if (value == NULL)
299
 
      continue;
300
 
    
301
 
    if (strcmp(name,"name")==0) {
302
 
      strncpy(p->name, value, 255);
303
 
      p->name[254] = 0;
304
 
      state |= HAS_NAME;
305
 
    } else if (strcmp(name,"minfreq")==0) {
306
 
      if (strstr(value, "%") != NULL) {
307
 
        /* set separator (useful for 2.4 kernels only) */
308
 
        if (p->sep != ':') {
309
 
          p->sep = '%';
310
 
        } else {
311
 
          cp_log(LOG_CRIT, "parse_config_profile(): cannot mix percentage and absolute kHz values in a single profile.\n");
312
 
          return -1;
313
 
        }
314
 
      } else {
315
 
        /* set separator (useful for 2.4 kernels only) */
316
 
        if (p->sep != '%') {
317
 
          p->sep = ':';
318
 
        } else {
319
 
          cp_log(LOG_CRIT, "parse_config_profile(): cannot mix percentage and absolute kHz values in a single profile.\n");
320
 
          return -1;
321
 
        }
322
 
      }
323
 
      p->min_freq = atol(value);
324
 
      state |= HAS_MIN;
325
 
      
326
 
    } else if (strcmp(name,"maxfreq") == 0) {
327
 
      
328
 
      if (strstr(value, "%") != NULL) {
329
 
        /* set separator (useful for 2.4 kernels only) */
330
 
        if (p->sep != ':') {
331
 
          p->sep = '%';
332
 
        } else {
333
 
          cp_log(LOG_CRIT, "parse_config_profile(): cannot mix percentage and absolute kHz values in a single profile.\n");
334
 
          return -1;
335
 
        }
336
 
      } else {
337
 
        /* set separator (useful for 2.4 kernels only) */
338
 
        if (p->sep != '%') {
339
 
          p->sep = ':';
340
 
        } else {
341
 
          cp_log(LOG_CRIT, "parse_config_profile(): cannot mix percentage and absolute kHz values in a single profile.\n");
342
 
          return -1;
343
 
        }
344
 
      }
345
 
      p->max_freq = atol(value);
346
 
      state |= HAS_MAX;
347
 
    
348
 
    } else if (strcmp(name,"policy") == 0) {
349
 
      
350
 
      strncpy(p->policy_name, value, 255);
351
 
      p->policy_name[254] = 0;
352
 
      state |= HAS_POLICY;
353
 
    
354
 
    } else {
355
 
      cp_log(LOG_WARNING, "WARNING: [Profile] skipping unknown config option \"%s\"\n", name);
356
 
    }
357
 
  }
358
 
 
359
 
  if (!(state & HAS_NAME)) {
360
 
    cp_log(LOG_ERR, "parse_config_profile(): [Profile] missing required property \"name\".\n");
361
 
    return -1;
362
 
  }
363
 
  if (!(state & HAS_MIN)) {
364
 
    cp_log(LOG_ERR, "parse_config_profile(): [Profile] \"%s\" missing required property \"minfreq\".\n", p->name);
365
 
    return -1;
366
 
  }
367
 
  if (!(state & HAS_MAX)) {
368
 
    cp_log(LOG_ERR, "parse_config_profile(): [Profile] \"%s\" missing required property \"maxfreq\".\n", p->name);
369
 
    return -1;
370
 
  }
371
 
  if (!(state & HAS_POLICY)) {
372
 
    cp_log(LOG_ERR, "parse_config_profile(): [Profile] \"%s\" missing required property \"policy\".\n", p->name);
373
 
    return -1;
374
 
  }
375
 
  
376
 
  /* translate max_freq to absolute value if necessary */
377
 
  if (g->has_sysfs && p->sep == '%') {
378
 
    p->max_freq = g->cpu_max_freq * ((float)p->max_freq / 100);
379
 
    cp_log(LOG_INFO, "parse_config_profile(): [Profile] \"%s\" translated max frequency to %d\n", p->name, p->max_freq);
380
 
    /* normalize if necessary */
381
 
    if (p->max_freq > g->cpu_max_freq) {
382
 
      cp_log(LOG_NOTICE, "parse_config_profile(): [Profile] \"%s\" max frequency %d out of range\n", p->name, p->max_freq);
383
 
      p->max_freq = g->cpu_max_freq;
384
 
    }
385
 
  }
386
 
  /* translate min_freq to absolute value if necessary */
387
 
  if (g->has_sysfs && p->sep == '%') {
388
 
    p->min_freq = g->cpu_max_freq * ((float)p->min_freq / 100);
389
 
    cp_log(LOG_INFO, "parse_config_profile(): [Profile] \"%s\" translated min frequency to %d\n", p->name, p->min_freq);
390
 
    /* normalize if necessary */
391
 
    if (p->min_freq < g->cpu_min_freq) {
392
 
      cp_log(LOG_NOTICE, "parse_config_profile(): [Profile] \"%s\" min frequency %d out of range\n", p->name, p->min_freq);
393
 
      p->min_freq = g->cpu_min_freq;
394
 
    }
395
 
  }
396
 
 
397
 
  return 0;
398
 
}
399
 
 
400
 
/*
401
 
 * parses a [Rule] section
402
 
 *
403
 
 * Returns -1 if required properties are missing, 0 otherwise
404
 
 */
405
 
int parse_config_rule (FILE *config, rule *r) {
406
 
#define HAS_NAME    1 
407
 
#define HAS_PROFILE 2
408
 
int state = 0;
409
 
char buf[256];
410
 
 
411
 
  /* reset profile ref */
412
 
  r->prof = 0;
413
 
 
414
 
  /* initialize battery_interval */
415
 
  r->bat = (battery_interval *) malloc(sizeof(battery_interval));
416
 
  r->bat->min = 101;
417
 
  r->bat->max = -1;
418
 
  
419
 
  /* initialize cpu_interval */
420
 
  r->cpu = (cpu_interval *) malloc(sizeof(cpu_interval));
421
 
  r->cpu->min = 101;    /* so we won't ever trigger them... */
422
 
  r->cpu->max = -1;
423
 
 
424
 
  /* initialize cpu_nice_scale to DEFAULT_NICE_SCALE */
425
 
  r->cpu_nice_scale = DEFAULT_NICE_SCALE;
426
 
  
427
 
  while (!feof(config)) {
428
 
    char *clean;
429
 
    char *name;
430
 
    char *value;
431
 
 
432
 
    if (!fgets(buf, 255, config))
433
 
      break;
434
 
 
435
 
    clean = strip_comments_line(buf);
436
 
 
437
 
    if (!clean[0]) /* returned an empty line */
438
 
      continue;
439
 
 
440
 
    clean = clean_config_line(clean);
441
 
 
442
 
    if (!clean[0]) /* returned an empty line */
443
 
      break;
444
 
 
445
 
    name = strtok(clean, "=");
446
 
    value = strtok(NULL, "");
447
 
 
448
 
    /* empty value: skip */
449
 
    if (value == NULL)
450
 
      continue;
451
 
 
452
 
    if (strcmp(name,"name") == 0) {
453
 
      strncpy(r->name, value, 255);
454
 
      r->name[254] = 0;
455
 
      state |= HAS_NAME;
456
 
    } else if (strcmp(name,"ac") == 0) {
457
 
      r->ac = strcmp(value,"on") == 0 ? 1:0;
458
 
    } else if (strcmp(name,"battery_interval") == 0) {
459
 
      r->bat->min = atoi(strtok(value,"-"));
460
 
      r->bat->max = atoi(strtok(NULL,""));
461
 
    } else if (strcmp(name,"cpu_interval") == 0) {
462
 
      r->cpu->min = atoi(strtok(value,"-"));
463
 
      r->cpu->max = atoi(strtok(NULL,""));
464
 
    } else if (strcmp(name,"cpu_nice_scale") == 0) {
465
 
      r->cpu_nice_scale = atof(value);
466
 
      if (r->cpu_nice_scale<=0) {
467
 
        cp_log(LOG_ERR, "parse_config_rule(): [Rule] invalid \"cpu_nice_scale\" value: %f.\n", r->cpu_nice_scale);
468
 
        return -1;
469
 
      }
470
 
    } else if (strcmp(name,"delay_cycles") == 0) {
471
 
      r->delay_cycles = atoi(value);
472
 
      if (r->delay_cycles<0) {
473
 
        cp_log(LOG_ERR, "parse_config_rule(): [Rule] invalid \"delay_cycles\" value: %d.\n", r->delay_cycles);
474
 
        return -1;
475
 
      }
476
 
    } else if (strcmp(name,"programs") == 0) {
477
 
      /* create program list */
478
 
      char *t_prog;
479
 
      r->program_list = string_list_new();
480
 
      t_prog = strtok(value,",");
481
 
      do {
482
 
        struct string_node *temp;
483
 
        
484
 
        if (t_prog == NULL)
485
 
          continue;
486
 
        
487
 
        temp = string_node_new();
488
 
        strncpy(temp->string, t_prog, 255);
489
 
        temp->string[254] = 0;
490
 
 
491
 
        string_list_append(r->program_list, temp);
492
 
        cp_log(LOG_DEBUG, "parse_config_rule(): read program: %s\n", temp->string);
493
 
      } while ((t_prog = strtok(NULL,",")) != NULL);
494
 
 
495
 
    } else if (strcmp(name, "profile") == 0) {
496
 
      strncpy(r->profile_name, value, 255);
497
 
      r->profile_name[254] = 0;
498
 
      state |= HAS_PROFILE;
499
 
    } else {
500
 
      cp_log(LOG_WARNING, "WARNING: [Rule] skipping unknown config option \"%s\"\n", name);
501
 
    }
502
 
  }
503
 
 
504
 
  if (!(state & HAS_NAME)) {
505
 
    cp_log(LOG_ERR, "parse_config_rule(): [Rule] missing required property \"name\".\n");
506
 
    return -1;
507
 
  }
508
 
 
509
 
  if (!(state & HAS_PROFILE)) {
510
 
    cp_log(LOG_ERR, "parse_config_rule(): [Rule] \"%s\" missing required property \"profile\".\n", 
511
 
                 r->name);
512
 
    return -1;
513
 
  }
514
 
 
515
 
  return 0;
516
 
}
517
 
 
518
 
/* char *clean_config_line (char *str)
519
 
 *
520
 
 * Removes trailing blanks and CR off the string str
521
 
 *
522
 
 * Returns a pointer to the cleaned string.
523
 
 * WARNING: it modifies the input string!
524
 
 * 
525
 
 */
526
 
char *clean_config_line (char *str) {
527
 
int i = 0;
528
 
 
529
 
  /* remove white spaces at the beginning */
530
 
  while (isspace(str[0])) {
531
 
    str++;
532
 
  }
533
 
 
534
 
  /* remove end line white space */
535
 
  i = strlen(str) - 1;
536
 
  while (i >= 0 && isspace(str[i])) {
537
 
    str[i] = 0;
538
 
    i--;
539
 
  }
540
 
 
541
 
  return str;
542
 
}
543
 
 
544
 
/* char *strip_comments_line (char *str)
545
 
 *
546
 
 * Removes comments off the string str
547
 
 *
548
 
 * Returns a pointer to the cleaned string.
549
 
 * WARNING: it modifies the input string!
550
 
 * 
551
 
 */
552
 
char *strip_comments_line (char *str) {
553
 
int i;
554
 
 
555
 
  /* remove comment */
556
 
  for (i = strlen(str); i >= 0; i--) {
557
 
    if (str[i] == '#') {
558
 
      str[i] = 0;
559
 
    }
560
 
  }
561
 
 
562
 
  return str;
563
 
}
564
 
 
565
 
/* void free_config(general *g)
566
 
 *
567
 
 * Frees the structures allocated.
568
 
 *
569
 
 */
570
 
void free_config(general *g) {
571
 
  profile *p_iter = 0L, *p_temp = 0L;
572
 
  rule *r_iter = 0L, *r_temp = 0L;
573
 
  
574
 
  /* cleanup config structs */
575
 
  r_iter = g->rules;
576
 
  while (r_iter != NULL) {
577
 
    r_temp = r_iter;
578
 
    r_iter = r_iter->next;
579
 
    
580
 
      cp_log(LOG_DEBUG, "free_config(): freeing rule %s.\n", r_temp->name);
581
 
      cp_log(LOG_DEBUG, "free_config(): freeing battery interval %d-%d.\n", r_temp->bat->min, r_temp->bat->max);
582
 
    
583
 
    free(r_temp->bat);
584
 
    
585
 
      cp_log(LOG_DEBUG, "free_config(): freeing cpu interval %d-%d.\n", r_temp->cpu->min, r_temp->cpu->max);
586
 
    
587
 
    free(r_temp->cpu);
588
 
    r_temp->bat = 0L;
589
 
    r_temp->cpu = 0L;
590
 
    
591
 
      cp_log(LOG_DEBUG, "free_config(): freeing program list.\n");
592
 
    
593
 
    if (r_temp->program_list) {
594
 
      string_list_free_sublist(r_temp->program_list, r_temp->program_list->first);
595
 
      free(r_temp->program_list);
596
 
    }
597
 
    
598
 
    free(r_temp);
599
 
  }
600
 
  g->rules = 0L;
601
 
  
602
 
  p_iter = g->profiles;
603
 
  while (p_iter != NULL) {
604
 
    p_temp = p_iter;
605
 
    p_iter = p_iter->next;
606
 
    cp_log(LOG_DEBUG, "free_config(): freeing profile %s.\n", p_temp->name);
607
 
    free(p_temp);
608
 
  }
609
 
  g->profiles = 0L;
610
 
 
611
 
  /* clean other values */
612
 
  g->poll_interval = DEFAULT_POLL;
613
 
  g->has_sysfs = 0;
614
 
  g->acpi_workaround = 0;
615
 
  g->cpu_min_freq = 0;
616
 
  g->cpu_max_freq = 0;
617
 
  
618
 
  if (!g->log_level_overridden)
619
 
    g->log_level = DEFAULT_VERBOSITY;
620
 
  
621
 
}