Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 272447 | Differences between
and this patch

Collapse All | Expand All

(-)hddtemp.orig (-269 / +168 lines)
Lines 54-73 Link Here
54
#include <sys/utsname.h>
54
#include <sys/utsname.h>
55
55
56
#include <unistd.h>
56
#include <unistd.h>
57
#include <errno.h>
58
#include <sys/types.h>
59
#include <sys/socket.h>
60
#include <arpa/inet.h>
57
61
58
#ifdef HAVE_NETCAT
62
# ifndef HDDTEMP_PORT
59
#include "helpers.c"
63
#  define HDDTEMP_PORT 7634
60
# ifndef NETCAT_PATH
61
#  define NETCAT_PATH "/bin/netcat"
62
# endif
64
# endif
63
65
64
# ifndef HDDTEMP_PORT
66
# ifndef HDDTEMP_BUFFER_SIZE
65
#  define HDDTEMP_PORT "7634"
67
#  define HDDTEMP_BUFFER_SIZE 1023UL
68
# endif
69
70
# ifndef MAX_DISKS
71
#  define MAX_DISKS 200
66
# endif
72
# endif
67
73
68
# define DOUBLE_DELIMITER "||"
74
# define DOUBLE_DELIMITER "||"
69
# define SINGLE_DELIMITER "|"
75
# define SINGLE_DELIMITER "|"
70
#endif
71
76
72
#ifdef HAVE_LIBNOTIFY
77
#ifdef HAVE_LIBNOTIFY
73
void
78
void
Lines 177-294 Link Here
177
#endif
182
#endif
178
}
183
}
179
184
180
185
/* Function to obtain a socket connected to the hddtemp daemon on the current system. */
181
#ifdef HAVE_NETCAT
186
static int get_hddtemp_socket(void)
182
void
183
read_disks_netcat (t_chip *chip)
184
{
187
{
185
    char *stdoutput, *stderrput, *cmdline, *tmp, *tmp2, *tmp3;
188
    const int sock_fd = socket(AF_INET, SOCK_STREAM, 0); /* Create an IPv4 socket. */
186
    gboolean result;
187
    gint exit_status = 0;
188
    GError *error = NULL;
189
189
190
    t_chipfeature *cf;
190
    if (sock_fd != -1)
191
    {
192
        struct sockaddr_in ip_addr;
191
193
192
    cmdline = g_strdup_printf ("%s localhost %s", NETCAT_PATH, HDDTEMP_PORT);
194
        /* Build a binary address for port 7634 on localhost. */
193
    //g_printf("cmdline=%s\n", cmdline);
195
        memset(&ip_addr, 0x00, sizeof ip_addr);
196
        ip_addr.sin_family = AF_INET;
197
        ip_addr.sin_port = htons(HDDTEMP_PORT);
198
        inet_pton(AF_INET, "127.0.0.1", &ip_addr.sin_addr);
194
199
195
    result = g_spawn_command_line_sync ( (const gchar*) cmdline,
200
        /* Now connect to the daemon. */
196
                &stdoutput, &stderrput, &exit_status, &error);
201
        if (connect(sock_fd, (struct sockaddr *) &ip_addr, sizeof ip_addr) != 0)
202
        {
203
            gchar * msg_txt;
197
204
198
    if (!result)
205
            msg_txt = g_strdup_printf("Connecting socket: %s", g_strerror(errno));
199
        return;
206
            /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_txt); */
207
            quick_message(msg_txt);
208
            g_free(msg_txt);
209
            close(sock_fd);
210
            return -1;
211
        }
212
    }
213
    else
214
    {
215
        gchar * msg_txt;
200
216
201
    //g_printf("stdouput=%s\n", stdoutput);
217
        msg_txt = g_strdup_printf("Opening socket: %s", g_strerror(errno));
218
        /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_txt); */
219
        quick_message(msg_txt);
220
        g_free(msg_txt);
221
    }
202
222
203
    tmp = str_split (stdoutput, DOUBLE_DELIMITER);
223
    return sock_fd;
204
    do {
224
}
205
        //g_printf ("Found token: %s\n", tmp);
206
        cf = g_new(t_chipfeature, 1);
207
225
208
        tmp2 = g_strdup (tmp);
226
/* This function reads all the bytes of the hddtemp daemon's output,
209
        tmp3 = strtok (tmp2, SINGLE_DELIMITER);
227
    places them in a dynamically allocated buffer, which should be freed later,
210
        cf->devicename = g_strdup(tmp3);
228
    and returns the length of the buffer. */
211
        tmp3 = strtok (NULL, SINGLE_DELIMITER);
229
static gsize get_hddtemp_text(gchar ** stdoutput)
212
        cf->name = g_strdup(tmp3);
230
{
231
    const int sock_fd = get_hddtemp_socket();
232
    gsize result_len = 0UL;
213
233
214
        g_ptr_array_add(chip->chip_features, cf);
234
    TRACE ("enters get_hddtemp_text");
215
        chip->num_features++;
216
235
217
        g_free (tmp2);
236
    /* Ensure the socket is valid. */
218
    }
237
    if (sock_fd != -1)
219
    while ( (tmp = str_split(NULL, DOUBLE_DELIMITER)) );
238
    {
239
        GIOChannel * const sock = g_io_channel_unix_new(sock_fd); /* Use Glib I/O channel for the socket. */
240
        GIOStatus rc;
241
        GError * err_code = NULL;
242
        gsize bytes_read = 0UL;
243
        gchar input_buffer[HDDTEMP_BUFFER_SIZE+1];
220
244
221
    g_free (stdoutput);
245
        do
222
}
246
        {
247
            /* Read a buffer of bytes from the socket connected to the hddtemp daemon. */
248
            rc = g_io_channel_read_chars(sock, input_buffer, HDDTEMP_BUFFER_SIZE, &bytes_read, &err_code);
223
249
224
#else
250
            /* The next piece of code should never be executed, but then ... */
225
void
251
            if (rc == G_IO_STATUS_ERROR)
226
read_disks_fallback (t_chip *chip)
252
            {
227
{
253
                gchar * msg_txt;
228
    GError *error;
229
    GDir *gdir;
230
    t_chipfeature *chipfeature;
231
    const gchar* dirname;
232
254
233
    TRACE ("enters read_disks_fallback");
255
                msg_txt = g_strdup_printf("Reading socket: %s (%d)", err_code->message, err_code->code);
256
                /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Reading socket: %s (%d)", err_code->message, err_code->code); */
257
                quick_message(msg_txt);
258
                g_free(msg_txt);
259
                g_error_free(err_code);
260
                err_code = NULL;
261
                break;
262
            }
234
263
235
    /* read from /proc/ide */
264
            /* If we received some bytes in this read, add it to the output string. */
236
    error = NULL;
265
            if (bytes_read > 0)
237
    gdir = g_dir_open ("/proc/ide/", 0, &error);
266
            {
267
                result_len += bytes_read;
268
                if (*stdoutput == NULL) /* No bytes yet in the string. */
269
                {
270
                    *stdoutput = g_strndup(input_buffer, bytes_read);
271
                }
272
                else
273
                {
274
                    gchar * const tmp = *stdoutput; /* Protect the reference to the bytes read previously. */
238
275
239
    while ( (dirname = g_dir_read_name (gdir))!=NULL ) {
276
                    /* Add a trailing NUL to the block of bytes. */
240
        if ( strncmp (dirname, "hd", 2)==0 || strncmp (dirname, "sd", 2)==0) {
277
                    input_buffer[bytes_read] = '\0';
241
            /* TODO: look, if /dev/dirname exists? */
278
                    /* Concatenate this block to the bytes we have read previously. */
242
            chipfeature = g_new0 (t_chipfeature, 1);
279
                    *stdoutput = g_strconcat(tmp, input_buffer, NULL);
243
            chipfeature->devicename = g_strconcat ("/dev/", dirname, NULL);
280
                    /* Free up the previous bytes. */
244
            chipfeature->name = g_strdup(chipfeature->devicename);
281
                    g_free(tmp);
245
            g_ptr_array_add (chip->chip_features, chipfeature);
282
                }
246
            chip->num_features++;
283
            }
284
        } while (rc != G_IO_STATUS_EOF); /* Keep looping until the hddtemp daemon closes the socket. */
285
286
        if (g_io_channel_shutdown(sock, TRUE, &err_code) == G_IO_STATUS_ERROR) /* This should always work, but then ... */
287
        {
288
            gchar * msg_txt;
289
290
            msg_txt = g_strdup_printf("Closing socket: %s (%d)", err_code->message, err_code->code);
291
            /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_txt); */
292
            quick_message(msg_txt);
293
            g_free(msg_txt);
294
            g_error_free(err_code);
295
            err_code = NULL;
247
        }
296
        }
248
    }
297
    }
249
298
250
    g_dir_close (gdir);
299
    TRACE ("leaves get_hddtemp_text");
251
252
    /* FIXME: read SCSI info from where? SATA?  */
253
300
254
    TRACE ("leaves read_disks_fallback");
301
    /* Return value is the total number of bytes read through the socket. */
302
    return result_len;
255
}
303
}
256
304
257
258
void
305
void
259
read_disks_linux26 (t_chip *chip)
306
read_disks(t_chip *chip)
260
{
307
{
261
    GDir *gdir;
308
    gchar * stdoutput = NULL;
262
    t_chipfeature *chipfeature;
309
    t_chipfeature *cf;
263
    const gchar* dirname;
264
310
265
    TRACE ("enters read_disks_linux26");
311
    TRACE ("enters read_disks");
266
312
267
    /* read from /sys/block */
313
    get_hddtemp_text(&stdoutput);
268
    gdir = g_dir_open ("/sys/block/", 0, NULL);
314
269
    while ( (dirname = g_dir_read_name (gdir))!=NULL ) {
315
    if (stdoutput != NULL)
270
        /* if ( strncmp (dirname, "ram", 3)!=0 &&
316
    {
271
             strncmp (dirname, "loop", 4)!=0 &&
317
        gchar ** string_vec = g_strsplit_set(stdoutput, SINGLE_DELIMITER, MAX_DISKS);
272
             strncmp (dirname, "md", 2)!=0 &&
318
        gint i, max_i = 0;
273
             strncmp (dirname, "fd", 2)!=0 &&
319
274
             strncmp (dirname, "mmc", 3)!=0 &&
320
        while (string_vec[max_i] != NULL)
275
             strncmp (dirname, "dm-", 3)!=0 ) { */
321
        {
276
            if ( strncmp (dirname, "hd", 2)==0 ||
322
            ++max_i;
277
                            strncmp (dirname, "sd", 2)==0 ) {
278
            /* TODO: look, if /dev/dirname exists? */
279
            chipfeature = g_new0 (t_chipfeature, 1);
280
            chipfeature->devicename = g_strconcat ("/dev/", dirname, NULL); /* /proc/ide/hda/model ?? */
281
            chipfeature->name = g_strdup(chipfeature->devicename);
282
            g_ptr_array_add (chip->chip_features, chipfeature);
283
            chip->num_features++;
284
        }
323
        }
285
    }
286
324
287
    g_dir_close (gdir);
325
        for (i = 1; i < max_i; i += 5)
326
        {
327
            if (strcmp(string_vec[i+2], "NOS") != 0)
328
            {
329
                cf = g_new(t_chipfeature, 1);
330
                cf->devicename = g_strdup(string_vec[i]);
331
                cf->name = g_strdup(string_vec[i]+5); /* Trim off "/dev/". */
288
332
289
    TRACE ("leaves read_disks_linux26");
333
                g_ptr_array_add(chip->chip_features, cf);
334
                chip->num_features++;
335
            }
336
        }
337
338
        g_strfreev(string_vec);
339
        g_free(stdoutput);
340
    }
341
342
    TRACE ("leaves read_disks");
290
}
343
}
291
#endif
292
344
293
void
345
void
294
remove_unmonitored_drives (t_chip *chip, gboolean *suppressmessage)
346
remove_unmonitored_drives (t_chip *chip, gboolean *suppressmessage)
Lines 368-376 Link Here
368
int
420
int
369
initialize_hddtemp (GPtrArray *chips, gboolean *suppressmessage)
421
initialize_hddtemp (GPtrArray *chips, gboolean *suppressmessage)
370
{
422
{
371
    int generation, major, result, retval;
423
    int retval;
372
    struct utsname *p_uname;
373
    t_chip *chip;
424
    t_chip *chip;
425
    static const sensors_chip_name hdd_chip_name = { "Hard disks", 0, 0, "Hard disks" };
374
426
375
    g_assert (chips!=NULL);
427
    g_assert (chips!=NULL);
376
428
Lines 378-386 Link Here
378
430
379
    chip = g_new (t_chip, 1);
431
    chip = g_new (t_chip, 1);
380
432
381
    chip->chip_name = (const sensors_chip_name *)
433
    chip->chip_name = &hdd_chip_name;
382
            ( _("Hard disks"), 0, 0, _("Hard disks") );
434
    
383
384
    chip->chip_features = g_ptr_array_new ();
435
    chip->chip_features = g_ptr_array_new ();
385
    chip->num_features = 0;
436
    chip->num_features = 0;
386
    chip->description = g_strdup(_("S.M.A.R.T. harddisk temperatures"));
437
    chip->description = g_strdup(_("S.M.A.R.T. harddisk temperatures"));
Lines 388-417 Link Here
388
    chip->sensorId = g_strdup("Hard disks");
439
    chip->sensorId = g_strdup("Hard disks");
389
    chip->type = HDD;
440
    chip->type = HDD;
390
441
391
    p_uname = (struct utsname *) malloc (sizeof(struct utsname));
442
    read_disks(chip);
392
    result =  uname (p_uname);
393
    if (result!=0) {
394
        g_free(p_uname);
395
        return -1;
396
    }
397
398
    generation = atoi ( p_uname->release ); /* this might cause trouble on */
399
    major = atoi ( p_uname->release+2 );      /* other systems than Linux! */
400
                /* actually, wanted to use build time configuration therefore */
401
402
    /* Note: This is actually supposed to be carried out by ifdef HAVE_LINUX
403
     and major/minor number stuff from compile time*/
404
#ifdef HAVE_NETCAT
405
    read_disks_netcat (chip);
406
#else
407
    if (strcmp(p_uname->sysname, "Linux")==0 && major>=5)
408
        read_disks_linux26 (chip);
409
    else
410
        read_disks_fallback (chip); /* hopefully, that's a safe variant */
411
#endif
412
413
    g_free(p_uname);
414
443
444
    /* This next call should no longer be necessary. */
415
    remove_unmonitored_drives (chip, suppressmessage);
445
    remove_unmonitored_drives (chip, suppressmessage);
416
    DBG  ("numfeatures=%d\n", chip->num_features);
446
    DBG  ("numfeatures=%d\n", chip->num_features);
417
    if ( chip->num_features>0 ) {  /* if (1) */
447
    if ( chip->num_features>0 ) {  /* if (1) */
Lines 433-449 Link Here
433
double
463
double
434
get_hddtemp_value (char* disk, gboolean *suppressmessage)
464
get_hddtemp_value (char* disk, gboolean *suppressmessage)
435
{
465
{
436
    gchar *standard_output, *standard_error;
466
    gchar * standard_output = NULL;
437
    gchar *cmd_line, *msg_text;
467
    gsize bytes_read;
438
#ifndef HAVE_LIBNOTIFY
468
    double value = ZERO_KELVIN;
439
    gchar *checktext;
469
    gboolean nevershowagain;
440
#endif
441
    gint exit_status=0;
442
    double value;
443
    gboolean result, nevershowagain;
444
    GError *error;
445
446
    gchar *tmp, *tmp2, *tmp3;
447
470
448
    if (suppressmessage!=NULL)
471
    if (suppressmessage!=NULL)
449
        nevershowagain = *suppressmessage;
472
        nevershowagain = *suppressmessage;
Lines 452-594 Link Here
452
475
453
    TRACE ("enters get_hddtemp_value for %s with suppress=%d", disk, nevershowagain); /* *suppressmessage); */
476
    TRACE ("enters get_hddtemp_value for %s with suppress=%d", disk, nevershowagain); /* *suppressmessage); */
454
477
455
#ifdef HAVE_NETCAT
478
    bytes_read = get_hddtemp_text(&standard_output);
456
    exit_status = 1; // assume error by default
479
    if (standard_output != NULL)
457
    cmd_line = g_strdup_printf ( "%s localhost %s", NETCAT_PATH, HDDTEMP_PORT);
458
    result = g_spawn_command_line_sync ( (const gchar*) cmd_line,
459
            &standard_output, &standard_error, &exit_status, NULL);
460
    error = g_new(GError, 1);
461
    error->message = g_strdup (_("No concrete error detected.\n"));
462
    if (exit_status==0)
463
    {
480
    {
464
        tmp3 = "-255";
481
        gchar ** string_vec = g_strsplit_set(standard_output, SINGLE_DELIMITER, MAX_DISKS);
465
        tmp = str_split (standard_output, DOUBLE_DELIMITER);
482
        gint i, max_i = 0;
466
        do {
483
467
            //g_printf ("Found token: %s for disk %s\n", tmp, disk);
484
        while (string_vec[max_i] != NULL)
468
            tmp2 = g_strdup (tmp);
485
        {
469
            tmp3 = strtok (tmp2, SINGLE_DELIMITER); // device name
486
            ++max_i;
470
            if (strcmp(tmp3, disk)==0)
487
        }
488
489
        for (i = 1; i < max_i; i += 5)
490
        {
491
            if (strcmp(string_vec[i], disk) == 0)
471
            {
492
            {
472
                tmp3 = strtok(NULL, SINGLE_DELIMITER); // name
493
                value = g_strtod(string_vec[i+2], NULL);
473
                tmp3 = strdup(strtok(NULL, SINGLE_DELIMITER)); // value
474
                // tmp3 = strtok(NULL, SINGLE_DELIMITER); // temperature unit
475
                exit_status = 0;
476
                g_free(error);
477
                error = NULL;
478
                g_free (tmp2);
479
                break;
494
                break;
480
            }
495
            }
481
            g_free (tmp2);
482
        }
496
        }
483
        while ( (tmp = str_split(NULL, DOUBLE_DELIMITER)) );
484
497
498
        g_strfreev(string_vec);
485
        g_free(standard_output);
499
        g_free(standard_output);
486
        standard_output = tmp3;
487
    }
488
    else
489
    {
490
        error->message = g_strdup (standard_error);
491
    }
492
493
#else
494
    error = NULL;
495
    cmd_line = g_strdup_printf ( "%s -n -q %s", PATH_HDDTEMP, disk);
496
    result = g_spawn_command_line_sync ( (const gchar*) cmd_line,
497
            &standard_output, &standard_error, &exit_status, &error);
498
#endif
499
500
    msg_text = NULL; // wonder if this is still necessary
501
502
    DBG ("Exit code %d on %s with stdout of %s.\n", exit_status, disk, standard_output);
503
504
    /* filter those with no sensors out */
505
    if (exit_status==0 && strncmp(disk, "/dev/fd", 6)==0) { /* is returned for floppy disks */
506
        DBG("exit_status==0 && strncmp(disk, \"/dev/fd\", 6)==0");
507
        value = 0.0;
508
    }
500
    }
509
    else if ((exit_status==256 || (standard_error && strlen(standard_error)>0))
510
            && access (PATH_HDDTEMP, X_OK)==0) /* || strlen(standard_error)>0) */
511
    {
512
        /* note that this check does only work for some versions of hddtemp. */
513
        if (!nevershowagain) {
514
            msg_text = g_strdup_printf(_("\"hddtemp\" was not executed correctly, "
515
                            "although it is executable. This is most probably due "
516
                            "to the disks requiring root privileges to read their "
517
                            "temperatures, and \"hddtemp\" not being setuid root."
518
                            "\n\n"
519
                            "An easy but dirty solution is to run \"chmod u+s %s"
520
                            "\" as root user and restart this plugin "
521
                            "or its panel.\n\n"
522
                            "Calling \"%s\" gave the following error:\n%s\nwith a return value of %d.\n"),
523
                            PATH_HDDTEMP, cmd_line, standard_error, exit_status);
524
525
#ifdef HAVE_LIBNOTIFY
526
            //msg_text = g_strconcat(msg_text, _("\nYou can disable these notifications in the settings dialog.\n");
527
            quick_message_notify (msg_text);
528
            nevershowagain = FALSE;
529
#else
530
            checktext = g_strdup(_("Suppress this message in future"));
531
            nevershowagain = quick_message_with_checkbox(msg_text, checktext);
532
#endif
533
534
            if (suppressmessage!=NULL)
535
                *suppressmessage = nevershowagain;
536
        }
537
        else {
538
            DBG  ("Suppressing dialog with exit_code=256 or output on standard_error");
539
        }
540
541
        value = ZERO_KELVIN;
542
    }
543
    /* else if (strlen(standard_error)>0) {
544
        msg_text = g_strdup_printf (_("An error occurred when executing"
545
                                      " \"%s\":\n%s"), cmd_line, standard_error);
546
        quick_message (msg_text);
547
        value = ZERO_KELVIN;
548
    } */
549
550
    else if (error && (!result || exit_status!=0))
551
    {
552
         DBG  ("error %s\n", error->message);
553
        if (!nevershowagain) {
554
            msg_text = g_strdup_printf (_("An error occurred when executing"
555
                                      " \"%s\":\n%s"), cmd_line, error->message);
556
#ifdef HAVE_LIBNOTIFY
557
            quick_message_notify (msg_text);
558
            nevershowagain = FALSE;
559
#else
560
            checktext = g_strdup(_("Suppress this message in future"));
561
            nevershowagain = quick_message_with_checkbox (msg_text, checktext);
562
#endif
563
564
             if (suppressmessage!=NULL)
565
                *suppressmessage = nevershowagain;
566
        }
567
        else {
568
            DBG  ("Suppressing dialog because of error in g_spawn_cl");
569
        }
570
        value = 0.0;
571
    }
572
    else if (standard_output && strlen(standard_output) > 0)
573
    {
574
        DBG("got the only useful return value of 0 and value of %s.\n", standard_output);
575
        /* hddtemp does not return floating values, but only integer ones.
576
          So have an easier life with atoi.
577
          FIXME: Use strtod() instead?*/
578
        value = (double) (atoi ( (const char*) standard_output) );
579
    }
580
    else {
581
        DBG("No condition applied.");
582
        value = 0.0;
583
    }
584
585
    g_free (cmd_line);
586
    g_free (standard_output);
587
    g_free (standard_error);
588
    g_free (msg_text);
589
#ifndef HAVE_LIBNOTIFY
590
    g_free (checktext);
591
#endif
592
501
593
    TRACE ("leaves get_hddtemp_value");
502
    TRACE ("leaves get_hddtemp_value");
594
503
Lines 600-606 Link Here
600
refresh_hddtemp (gpointer chip_feature, gpointer data)
509
refresh_hddtemp (gpointer chip_feature, gpointer data)
601
{
510
{
602
    t_chipfeature *cf;
511
    t_chipfeature *cf;
603
    double value;
604
512
605
    g_assert (chip_feature!=NULL);
513
    g_assert (chip_feature!=NULL);
606
514
Lines 608-623 Link Here
608
516
609
    cf = (t_chipfeature *) chip_feature;
517
    cf = (t_chipfeature *) chip_feature;
610
518
611
    value = get_hddtemp_value (cf->devicename, NULL);
519
    cf->raw_value = get_hddtemp_value (cf->devicename, NULL);
612
613
    /* actually, that's done in the gui part */
614
    g_free (cf->formatted_value);
615
    /*  if (scale == FAHRENHEIT) {
616
        cf->formatted_value = g_strdup_printf(_("%.1f °F"), (float) (value * 9/5 + 32) );
617
    } else { // Celsius  */
618
        cf->formatted_value = g_strdup_printf(_("%.1f °C"), value);
619
    /* } */
620
    cf->raw_value = value;
621
520
622
    TRACE ("leaves refresh_hddtemp");
521
    TRACE ("leaves refresh_hddtemp");
623
}
522
}

Return to bug 272447