~jfi/ubuntu/quantal/psensor/new-upstream

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Package Import Robot
  • Author(s): Micah Gersten
  • Date: 2012-01-21 22:41:34 UTC
  • mfrom: (3.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20120121224134-mty23d3917ng5ujd
Tags: 0.6.2.16-1ubuntu1
* Merge from Debian testing.  Remaining changes:
  + Modifed build-dep to add NVidia and Application Indicator support
  + Only add an nvidia-settings build-dep on i386 and amd64

* Add a patch to drop the deprecated g_thread_init() call
  - add debian/patches/drop_g_thread_init.patch
  - add debian/patches/series

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
    Copyright (C) 2010-2011 wpitchoune@gmail.com
3
 
 
4
 
    This program is free software; you can redistribute it and/or modify
5
 
    it under the terms of the GNU General Public License as published by
6
 
    the Free Software Foundation; either version 2 of the License, or
7
 
    (at your option) any later version.
8
 
 
9
 
    This program is distributed in the hope that it will be useful,
10
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
    GNU General Public License for more details.
13
 
 
14
 
    You should have received a copy of the GNU General Public License
15
 
    along with this program; if not, write to the Free Software
16
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
 
    02110-1301 USA
18
 
*/
19
 
 
 
2
 * Copyright (C) 2010-2011 jeanfi@gmail.com
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; either version 2 of the
 
7
 * License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
 * 02110-1301 USA
 
18
 */
20
19
#include <locale.h>
21
 
#include <libintl.h>
22
 
#define _(str) gettext(str)
23
20
 
24
21
#include <getopt.h>
25
22
#include <stdio.h>
26
23
#include <stdlib.h>
27
24
#include <string.h>
28
25
#include <unistd.h>
 
26
#include <sys/stat.h>
 
27
#include <sys/types.h>
29
28
 
30
29
#include <gtk/gtk.h>
31
30
 
32
 
#include <sensors/sensors.h>
33
 
#include <sensors/error.h>
34
 
 
35
31
#include "config.h"
36
32
 
37
33
#include "cfg.h"
42
38
#include "ui_color.h"
43
39
#include "lmsensor.h"
44
40
#include "ui_pref.h"
 
41
#include "ui_graph.h"
 
42
#include "ui_status.h"
 
43
 
 
44
#ifdef HAVE_UNITY
 
45
#include "ui_unity.h"
 
46
#endif
45
47
 
46
48
#ifdef HAVE_NVIDIA
47
49
#include "nvidia.h"
48
50
#endif
49
51
 
 
52
#ifdef HAVE_LIBATIADL
 
53
#include "amd.h"
 
54
#endif
 
55
 
50
56
#ifdef HAVE_REMOTE_SUPPORT
51
57
#include "rsensor.h"
52
58
#endif
53
59
 
54
 
#if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
55
60
#include "ui_appindicator.h"
56
 
#endif
57
61
 
58
62
#ifdef HAVE_LIBNOTIFY
59
63
#include "ui_notify.h"
60
64
#endif
61
65
 
 
66
#ifdef HAVE_GTOP
 
67
#include "cpu.h"
 
68
#endif
 
69
 
62
70
#include "compat.h"
63
71
 
64
72
static const char *program_name;
65
73
 
66
 
void print_version()
 
74
static void print_version()
67
75
{
68
76
        printf("psensor %s\n", VERSION);
69
 
        printf(_("Copyright (C) %s wpitchoune@gmail.com\n\
70
 
License GPLv2: GNU GPL version 2 or later \
71
 
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n\
72
 
This is free software: you are free to change and redistribute it.\n\
73
 
There is NO WARRANTY, to the extent permitted by law.\n"),
 
77
        printf(_("Copyright (C) %s jeanfi@gmail.com\n"
 
78
                 "License GPLv2: GNU GPL version 2 or later "
 
79
                 "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
 
80
                 "This is free software: you are free to change and "
 
81
                 " redistribute it.\n"
 
82
                 "There is NO WARRANTY, to the extent permitted by law.\n"),
74
83
               "2010-2011");
75
84
}
76
85
 
77
 
void print_help()
 
86
static void print_help()
78
87
{
79
88
        printf(_("Usage: %s [OPTION]...\n"), program_name);
80
89
 
82
91
               "including temperatures and fan speeds."));
83
92
 
84
93
        puts("");
85
 
        puts("Options:");
86
 
        puts(_("\
87
 
  -h, --help          display this help and exit\n\
88
 
  -v, --version       display version information and exit"));
89
 
 
90
 
        puts("");
91
 
 
92
 
        puts(_("\
93
 
  -u, --url=URL       \
94
 
the URL of the psensor-server, example: http://hostname:3131"));
 
94
        puts(_("Options:"));
 
95
        puts(_("  -h, --help          display this help and exit\n"
 
96
               "  -v, --version       display version information and exit"));
 
97
 
 
98
        puts("");
 
99
 
 
100
        puts(_("  -u, --url=URL       "
 
101
               "the URL of the psensor-server, example: http://hostname:3131"));
 
102
 
 
103
        puts("");
 
104
 
 
105
        puts(_("  -d, --debug=LEVEL   "
 
106
               "set the debug level, integer between 0 and 3"));
95
107
 
96
108
        puts("");
97
109
 
100
112
        printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
101
113
}
102
114
 
103
 
static void
104
 
cb_preferences(gpointer data, guint callback_action, GtkWidget *item)
105
 
{
106
 
        ui_pref_dialog_run((struct ui_psensor *)data);
107
 
}
108
 
 
109
 
static GtkItemFactoryEntry menu_items[] = {
110
 
        {"/Preferences",
111
 
         NULL, cb_preferences, 0, "<Item>"},
112
 
 
113
 
        {"/sep1",
114
 
         NULL, NULL, 0, "<Separator>"},
115
 
 
116
 
        {"/Quit",
117
 
         "", ui_psensor_exit, 0, "<StockItem>", GTK_STOCK_QUIT},
118
 
};
119
 
 
120
 
static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
121
 
 
122
115
/*
123
116
  Updates the size of the sensor values if different than the
124
117
  configuration.
140
133
        }
141
134
}
142
135
 
 
136
static void log_measures(struct psensor **sensors)
 
137
{
 
138
        if (log_level == LOG_DEBUG)
 
139
                while (*sensors) {
 
140
                        log_debug("Measure: %s %.2f",
 
141
                                   (*sensors)->name,
 
142
                                   psensor_get_current_value(*sensors));
 
143
 
 
144
                        sensors++;
 
145
                }
 
146
}
 
147
 
143
148
void update_psensor_measures(struct ui_psensor *ui)
144
149
{
145
150
        struct psensor **sensors = ui->sensors;
146
151
        struct config *cfg = ui->config;
147
152
 
148
153
        while (1) {
149
 
                gdk_threads_enter();
 
154
                g_mutex_lock(ui->sensors_mutex);
150
155
 
151
156
                if (!sensors)
152
157
                        return;
160
165
#ifdef HAVE_NVIDIA
161
166
                nvidia_psensor_list_update(sensors);
162
167
#endif
163
 
 
164
 
                gdk_threads_leave();
 
168
#ifdef HAVE_LIBATIADL
 
169
                amd_psensor_list_update(sensors);
 
170
#endif
 
171
 
 
172
                log_measures(sensors);
 
173
 
 
174
                g_mutex_unlock(ui->sensors_mutex);
165
175
 
166
176
                sleep(cfg->sensor_update_interval);
167
177
        }
168
178
}
169
179
 
 
180
static void indicators_update(struct ui_psensor *ui)
 
181
{
 
182
        struct psensor **sensor_cur = ui->sensors;
 
183
        unsigned int attention = 0;
 
184
 
 
185
        while (*sensor_cur) {
 
186
                struct psensor *s = *sensor_cur;
 
187
 
 
188
                if (s->alarm_enabled && s->alarm_raised) {
 
189
                        attention = 1;
 
190
                        break;
 
191
                }
 
192
 
 
193
                sensor_cur++;
 
194
        }
 
195
 
 
196
#if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
 
197
        if (is_appindicator_supported())
 
198
                ui_appindicator_update(ui, attention);
 
199
#endif
 
200
 
 
201
        if (is_status_supported())
 
202
                ui_status_update(ui, attention);
 
203
}
 
204
 
170
205
gboolean ui_refresh_thread(gpointer data)
171
206
{
172
207
        struct config *cfg;
176
211
        ret = TRUE;
177
212
        cfg = ui->config;
178
213
 
179
 
        gdk_threads_enter();
 
214
        g_mutex_lock(ui->sensors_mutex);
180
215
 
181
216
        graph_update(ui->sensors, ui->w_graph, ui->config);
182
217
 
183
 
        ui_sensorlist_update(ui->ui_sensorlist);
184
 
 
185
 
#if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
186
 
        ui_appindicator_update(ui);
 
218
        ui_sensorlist_update(ui);
 
219
 
 
220
        if (is_appindicator_supported() || is_status_supported())
 
221
                indicators_update(ui);
 
222
 
 
223
#ifdef HAVE_UNITY
 
224
        ui_unity_launcher_entry_update(ui->sensors,
 
225
                                       !cfg->unity_launcher_count_disabled);
187
226
#endif
188
227
 
189
228
        if (ui->graph_update_interval != cfg->graph_update_interval) {
191
230
                ret = FALSE;
192
231
        }
193
232
 
194
 
        gdk_threads_leave();
 
233
        g_mutex_unlock(ui->sensors_mutex);
195
234
 
196
235
        if (ret == FALSE)
197
236
                g_timeout_add(1000 * ui->graph_update_interval,
200
239
        return ret;
201
240
}
202
241
 
203
 
gboolean
204
 
on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
205
 
{
206
 
        struct ui_psensor *ui_psensor = (struct ui_psensor *)data;
207
 
 
208
 
        graph_update(ui_psensor->sensors,
209
 
                     ui_psensor->w_graph, ui_psensor->config);
210
 
 
211
 
        return FALSE;
212
 
}
213
 
 
214
242
void cb_alarm_raised(struct psensor *sensor, void *data)
215
243
{
216
244
#ifdef HAVE_LIBNOTIFY
219
247
#endif
220
248
}
221
249
 
222
 
void associate_colors(struct psensor **sensors)
 
250
static void associate_colors(struct psensor **sensors)
223
251
{
224
252
        /* number of uniq colors */
225
253
#define COLORS_COUNT 8
254
282
        }
255
283
}
256
284
 
257
 
void associate_cb_alarm_raised(struct psensor **sensors, struct ui_psensor *ui)
 
285
static void
 
286
associate_cb_alarm_raised(struct psensor **sensors, struct ui_psensor *ui)
258
287
{
259
288
        struct psensor **sensor_cur = sensors;
260
289
        while (*sensor_cur) {
277
306
        }
278
307
}
279
308
 
280
 
void associate_preferences(struct psensor **sensors)
 
309
static void associate_preferences(struct psensor **sensors)
281
310
{
282
311
        struct psensor **sensor_cur = sensors;
283
312
        while (*sensor_cur) {
295
324
        }
296
325
}
297
326
 
298
 
GtkWidget *ui_get_popupmenu(gpointer data)
299
 
{
300
 
        GtkItemFactory *item_factory;
301
 
        GtkWidget *menu;
302
 
 
303
 
        item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
304
 
        gtk_item_factory_create_items(item_factory,
305
 
                                      nmenu_items, menu_items, data);
306
 
        menu = gtk_item_factory_get_widget(item_factory, "<main>");
307
 
 
308
 
        return menu;
309
 
}
310
 
 
311
 
int on_graph_clicked(GtkWidget *widget, GdkEventButton *event, gpointer data)
312
 
{
313
 
        GtkWidget *menu;
314
 
 
315
 
        if (event->type != GDK_BUTTON_PRESS)
316
 
                return FALSE;
317
 
 
318
 
        menu = ui_get_popupmenu(data);
319
 
 
320
 
        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
321
 
                       event->button, event->time);
322
 
 
323
 
        return TRUE;
324
 
}
325
 
 
326
 
 
327
 
GtkWidget *create_graph_widget(struct ui_psensor * ui)
328
 
{
329
 
        GtkWidget *w_graph;
330
 
 
331
 
        w_graph = gtk_drawing_area_new();
332
 
 
333
 
        g_signal_connect(G_OBJECT(w_graph),
334
 
                         "expose-event", G_CALLBACK(on_expose_event), ui);
335
 
 
336
 
        gtk_widget_add_events(w_graph, GDK_BUTTON_PRESS_MASK);
337
 
        gtk_signal_connect(GTK_OBJECT(w_graph),
338
 
                           "button_press_event",
339
 
                           (GCallback) on_graph_clicked, ui);
340
 
 
341
 
        return w_graph;
342
 
}
343
 
 
344
 
void ui_main_box_create(struct ui_psensor *ui)
345
 
{
346
 
        struct config *cfg;
347
 
        GtkWidget *w_sensorlist;
348
 
 
349
 
        cfg = ui->config;
350
 
 
351
 
        if (ui->main_box) {
352
 
                ui_sensorlist_create_widget(ui->ui_sensorlist);
353
 
 
354
 
                gtk_container_remove(GTK_CONTAINER(ui->main_window),
355
 
                                     ui->main_box);
356
 
 
357
 
                ui->w_graph = create_graph_widget(ui);
358
 
                ui->w_sensorlist = ui->ui_sensorlist->widget;
359
 
        }
360
 
 
361
 
        if (cfg->sensorlist_position == SENSORLIST_POSITION_RIGHT
362
 
            || cfg->sensorlist_position == SENSORLIST_POSITION_LEFT)
363
 
                ui->main_box = gtk_hpaned_new();
364
 
        else
365
 
                ui->main_box = gtk_vpaned_new();
366
 
 
367
 
        w_sensorlist = gtk_scrolled_window_new(NULL, NULL);
368
 
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w_sensorlist),
369
 
                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
370
 
        gtk_container_add(GTK_CONTAINER(w_sensorlist),
371
 
                          ui->ui_sensorlist->widget);
372
 
 
373
 
        gtk_container_add(GTK_CONTAINER(ui->main_window), ui->main_box);
374
 
 
375
 
        if (cfg->sensorlist_position == SENSORLIST_POSITION_RIGHT
376
 
            || cfg->sensorlist_position == SENSORLIST_POSITION_BOTTOM) {
377
 
                gtk_paned_pack1(GTK_PANED(ui->main_box),
378
 
                                GTK_WIDGET(ui->w_graph), TRUE, TRUE);
379
 
                gtk_paned_pack2(GTK_PANED(ui->main_box),
380
 
                                w_sensorlist, FALSE, TRUE);
381
 
        } else {
382
 
                gtk_paned_pack1(GTK_PANED(ui->main_box),
383
 
                                w_sensorlist, FALSE, TRUE);
384
 
                gtk_paned_pack2(GTK_PANED(ui->main_box),
385
 
                                GTK_WIDGET(ui->w_graph), TRUE, TRUE);
386
 
        }
387
 
 
388
 
        gtk_widget_show_all(ui->main_box);
 
327
static void log_init()
 
328
{
 
329
        char *home, *path, *dir;
 
330
 
 
331
        home = getenv("HOME");
 
332
 
 
333
        if (!home)
 
334
                return ;
 
335
 
 
336
        dir = malloc(strlen(home)+1+strlen(".psensor")+1);
 
337
        sprintf(dir, "%s/%s", home, ".psensor");
 
338
        mkdir(dir, 0777);
 
339
 
 
340
        path = malloc(strlen(dir)+1+strlen("log")+1);
 
341
        sprintf(path, "%s/%s", dir, "log");
 
342
 
 
343
        log_open(path);
 
344
 
 
345
        free(dir);
 
346
        free(path);
389
347
}
390
348
 
391
349
static struct option long_options[] = {
392
350
        {"version", no_argument, 0, 'v'},
393
351
        {"help", no_argument, 0, 'h'},
394
352
        {"url", required_argument, 0, 'u'},
 
353
        {"debug", required_argument, 0, 'd'},
395
354
        {0, 0, 0, 0}
396
355
};
397
356
 
 
357
static gboolean initial_window_show(gpointer data)
 
358
{
 
359
        struct ui_psensor *ui;
 
360
 
 
361
        log_debug("initial_window_show()");
 
362
 
 
363
        ui = (struct ui_psensor *)data;
 
364
 
 
365
        log_debug("is_status_supported: %d", is_status_supported());
 
366
        log_debug("is_appindicator_supported: %d",
 
367
                   is_appindicator_supported());
 
368
        log_debug("hide_on_startup: %d", ui->config->hide_on_startup);
 
369
 
 
370
        if (!ui->config->hide_on_startup
 
371
            || (!is_appindicator_supported() && !is_status_supported()))
 
372
                ui_window_show(ui);
 
373
 
 
374
        ui_window_update(ui);
 
375
 
 
376
        return FALSE;
 
377
}
 
378
 
398
379
int main(int argc, char **argv)
399
380
{
400
381
        struct ui_psensor ui;
401
382
        GError *error;
402
383
        GThread *thread;
403
 
        int err, optc;
 
384
        int optc, cmdok;
404
385
        char *url = NULL;
405
 
        int cmdok = 1;
406
386
 
407
387
        program_name = argv[0];
408
388
 
413
393
        textdomain(PACKAGE);
414
394
#endif
415
395
 
416
 
        while ((optc = getopt_long(argc, argv, "vhu:", long_options,
 
396
        cmdok = 1;
 
397
        while ((optc = getopt_long(argc, argv, "vhd:u:", long_options,
417
398
                                   NULL)) != -1) {
418
399
                switch (optc) {
419
400
                case 'u':
426
407
                case 'v':
427
408
                        print_version();
428
409
                        exit(EXIT_SUCCESS);
 
410
                case 'd':
 
411
                        log_level = atoi(optarg);
 
412
                        log_printf(LOG_INFO, _("Enables debug mode."));
 
413
                        break;
429
414
                default:
430
415
                        cmdok = 0;
431
416
                        break;
438
423
                exit(EXIT_FAILURE);
439
424
        }
440
425
 
441
 
        g_thread_init(NULL);
 
426
        log_init();
 
427
 
442
428
        gdk_threads_init();
443
 
        gdk_threads_enter();
444
 
 
445
 
        gtk_init(&argc, &argv);
446
 
 
447
 
#ifdef HAVE_LIBNOTIFY
448
 
        ui.notification_last_time = NULL;
449
 
#endif
 
429
        /* gdk_threads_enter(); */
 
430
 
 
431
        gtk_init(NULL, NULL);
 
432
 
 
433
        ui.sensors_mutex = g_mutex_new();
450
434
 
451
435
        config_init();
452
436
 
453
437
        ui.config = config_load();
454
438
 
455
 
        err = lmsensor_init();
456
 
        if (!err) {
457
 
                fprintf(stderr, _("ERROR: lmsensor init failure: %s\n"),
458
 
                        sensors_strerror(err));
459
 
                exit(EXIT_FAILURE);
460
 
        }
 
439
        psensor_init();
461
440
 
462
441
        if (url) {
463
442
#ifdef HAVE_REMOTE_SUPPORT
469
448
                exit(EXIT_FAILURE);
470
449
#endif
471
450
        } else {
472
 
#ifdef HAVE_NVIDIA
473
 
                struct psensor **tmp;
474
 
 
475
 
                tmp = get_all_sensors(600);
476
 
                ui.sensors = nvidia_psensor_list_add(tmp, 600);
477
 
 
478
 
                if (tmp != ui.sensors)
479
 
                        free(tmp);
480
 
#else
481
451
                ui.sensors = get_all_sensors(600);
 
452
#ifdef HAVE_NVIDIA
 
453
                ui.sensors = nvidia_psensor_list_add(ui.sensors, 600);
 
454
#endif
 
455
#ifdef HAVE_LIBATIADL
 
456
                ui.sensors = amd_psensor_list_add(ui.sensors, 600);
 
457
#endif
 
458
#ifdef HAVE_GTOP
 
459
                ui.sensors = cpu_psensor_list_add(ui.sensors, 600);
482
460
#endif
483
461
        }
484
462
 
486
464
        associate_colors(ui.sensors);
487
465
        associate_cb_alarm_raised(ui.sensors, &ui);
488
466
 
 
467
#if !defined(HAVE_APPINDICATOR) && !defined(HAVE_APPINDICATOR_029)
 
468
        ui_status_init(&ui);
 
469
#endif
 
470
 
489
471
        /* main window */
490
 
        ui.main_window = ui_window_create(&ui);
491
 
        ui.main_box = NULL;
 
472
        ui_window_create(&ui);
 
473
        ui.sensor_box = NULL;
492
474
 
493
475
        /* drawing box */
494
 
        ui.w_graph = create_graph_widget(&ui);
 
476
        ui.w_graph = ui_graph_create(&ui);
495
477
 
496
478
        /* sensor list */
497
 
        ui.ui_sensorlist = ui_sensorlist_create(ui.sensors);
498
 
 
499
 
        ui_main_box_create(&ui);
500
 
 
501
 
        gtk_widget_show_all(ui.main_window);
 
479
        ui_sensorlist_create(&ui);
502
480
 
503
481
        thread = g_thread_create((GThreadFunc) update_psensor_measures,
504
482
                                 &ui, TRUE, &error);
514
492
        ui_appindicator_init(&ui);
515
493
#endif
516
494
 
 
495
        /*
 
496
         * show the window as soon as all gtk events have been processed
 
497
         * in order to ensure that the status icon is attempted to be
 
498
         * drawn before. If not, there is no way to detect that it is
 
499
         * visible.
 
500
        */
 
501
        g_idle_add((GSourceFunc)initial_window_show, &ui);
 
502
 
 
503
        gdk_notify_startup_complete();
 
504
 
517
505
        /* main loop */
518
506
        gtk_main();
519
507
 
520
 
        sensors_cleanup();
 
508
        g_mutex_lock(ui.sensors_mutex);
 
509
 
 
510
        psensor_cleanup();
 
511
 
 
512
#ifdef HAVE_NVIDIA
 
513
        nvidia_cleanup();
 
514
#endif
 
515
#ifdef HAVE_LIBATIADL
 
516
        amd_cleanup();
 
517
#endif
 
518
#ifdef HAVE_REMOTE_SUPPORT
 
519
        rsensor_cleanup();
 
520
#endif
521
521
 
522
522
        psensor_list_free(ui.sensors);
523
 
 
524
 
        gdk_threads_leave();
 
523
        ui.sensors = NULL;
 
524
 
 
525
#if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
 
526
        ui_appindicator_cleanup();
 
527
#endif
 
528
 
 
529
        ui_status_cleanup();
 
530
 
 
531
        g_mutex_unlock(ui.sensors_mutex);
 
532
 
 
533
        config_cleanup();
 
534
 
 
535
        log_close();
525
536
 
526
537
        return 0;
527
538
}