*** hddtemp.orig 2009-10-02 17:00:28.000000000 +0100 --- hddtemp.c 2009-10-06 11:41:17.000000000 +0100 *************** *** 54,73 **** #include #include ! #ifdef HAVE_NETCAT ! #include "helpers.c" ! # ifndef NETCAT_PATH ! # define NETCAT_PATH "/bin/netcat" # endif ! # ifndef HDDTEMP_PORT ! # define HDDTEMP_PORT "7634" # endif # define DOUBLE_DELIMITER "||" # define SINGLE_DELIMITER "|" - #endif #ifdef HAVE_LIBNOTIFY void --- 54,78 ---- #include #include + #include + #include + #include + #include ! # ifndef HDDTEMP_PORT ! # define HDDTEMP_PORT 7634 # endif ! # ifndef HDDTEMP_BUFFER_SIZE ! # define HDDTEMP_BUFFER_SIZE 1023UL ! # endif ! ! # ifndef MAX_DISKS ! # define MAX_DISKS 200 # endif # define DOUBLE_DELIMITER "||" # define SINGLE_DELIMITER "|" #ifdef HAVE_LIBNOTIFY void *************** *** 177,294 **** #endif } ! ! #ifdef HAVE_NETCAT ! void ! read_disks_netcat (t_chip *chip) { ! char *stdoutput, *stderrput, *cmdline, *tmp, *tmp2, *tmp3; ! gboolean result; ! gint exit_status = 0; ! GError *error = NULL; ! ! t_chipfeature *cf; ! cmdline = g_strdup_printf ("%s localhost %s", NETCAT_PATH, HDDTEMP_PORT); ! //g_printf("cmdline=%s\n", cmdline); ! ! result = g_spawn_command_line_sync ( (const gchar*) cmdline, ! &stdoutput, &stderrput, &exit_status, &error); ! ! if (!result) ! return; ! //g_printf("stdouput=%s\n", stdoutput); ! tmp = str_split (stdoutput, DOUBLE_DELIMITER); ! do { ! //g_printf ("Found token: %s\n", tmp); ! cf = g_new(t_chipfeature, 1); ! ! tmp2 = g_strdup (tmp); ! tmp3 = strtok (tmp2, SINGLE_DELIMITER); ! cf->devicename = g_strdup(tmp3); ! tmp3 = strtok (NULL, SINGLE_DELIMITER); ! cf->name = g_strdup(tmp3); ! g_ptr_array_add(chip->chip_features, cf); ! chip->num_features++; ! g_free (tmp2); } - while ( (tmp = str_split(NULL, DOUBLE_DELIMITER)) ); ! g_free (stdoutput); } ! #else ! void ! read_disks_fallback (t_chip *chip) { ! GError *error; ! GDir *gdir; ! t_chipfeature *chipfeature; ! const gchar* dirname; ! TRACE ("enters read_disks_fallback"); ! /* read from /proc/ide */ ! error = NULL; ! gdir = g_dir_open ("/proc/ide/", 0, &error); ! ! while ( (dirname = g_dir_read_name (gdir))!=NULL ) { ! if ( strncmp (dirname, "hd", 2)==0 || strncmp (dirname, "sd", 2)==0) { ! /* TODO: look, if /dev/dirname exists? */ ! chipfeature = g_new0 (t_chipfeature, 1); ! chipfeature->devicename = g_strconcat ("/dev/", dirname, NULL); ! chipfeature->name = g_strdup(chipfeature->devicename); ! g_ptr_array_add (chip->chip_features, chipfeature); ! chip->num_features++; } } ! g_dir_close (gdir); ! /* FIXME: read SCSI info from where? SATA? */ ! ! TRACE ("leaves read_disks_fallback"); } - void ! read_disks_linux26 (t_chip *chip) { ! GDir *gdir; ! t_chipfeature *chipfeature; ! const gchar* dirname; ! TRACE ("enters read_disks_linux26"); ! /* read from /sys/block */ ! gdir = g_dir_open ("/sys/block/", 0, NULL); ! while ( (dirname = g_dir_read_name (gdir))!=NULL ) { ! /* if ( strncmp (dirname, "ram", 3)!=0 && ! strncmp (dirname, "loop", 4)!=0 && ! strncmp (dirname, "md", 2)!=0 && ! strncmp (dirname, "fd", 2)!=0 && ! strncmp (dirname, "mmc", 3)!=0 && ! strncmp (dirname, "dm-", 3)!=0 ) { */ ! if ( strncmp (dirname, "hd", 2)==0 || ! strncmp (dirname, "sd", 2)==0 ) { ! /* TODO: look, if /dev/dirname exists? */ ! chipfeature = g_new0 (t_chipfeature, 1); ! chipfeature->devicename = g_strconcat ("/dev/", dirname, NULL); /* /proc/ide/hda/model ?? */ ! chipfeature->name = g_strdup(chipfeature->devicename); ! g_ptr_array_add (chip->chip_features, chipfeature); ! chip->num_features++; } - } ! g_dir_close (gdir); ! TRACE ("leaves read_disks_linux26"); } - #endif void remove_unmonitored_drives (t_chip *chip, gboolean *suppressmessage) --- 182,346 ---- #endif } ! /* Function to obtain a socket connected to the hddtemp daemon on the current system. */ ! static int get_hddtemp_socket(void) { ! const int sock_fd = socket(AF_INET, SOCK_STREAM, 0); /* Create an IPv4 socket. */ ! if (sock_fd != -1) ! { ! struct sockaddr_in ip_addr; ! /* Build a binary address for port 7634 on localhost. */ ! memset(&ip_addr, 0x00, sizeof ip_addr); ! ip_addr.sin_family = AF_INET; ! ip_addr.sin_port = htons(HDDTEMP_PORT); ! inet_pton(AF_INET, "127.0.0.1", &ip_addr.sin_addr); ! /* Now connect to the daemon. */ ! if (connect(sock_fd, (struct sockaddr *) &ip_addr, sizeof ip_addr) != 0) ! { ! gchar * msg_txt; ! msg_txt = g_strdup_printf("Connecting socket: %s", g_strerror(errno)); ! /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_txt); */ ! quick_message(msg_txt); ! g_free(msg_txt); ! close(sock_fd); ! return -1; ! } ! } ! else ! { ! gchar * msg_txt; ! msg_txt = g_strdup_printf("Opening socket: %s", g_strerror(errno)); ! /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_txt); */ ! quick_message(msg_txt); ! g_free(msg_txt); } ! return sock_fd; } ! /* This function reads all the bytes of the hddtemp daemon's output, ! places them in a dynamically allocated buffer, which should be freed later, ! and returns the length of the buffer. */ ! static gsize get_hddtemp_text(gchar ** stdoutput) { ! const int sock_fd = get_hddtemp_socket(); ! gsize result_len = 0UL; ! ! TRACE ("enters get_hddtemp_text"); ! ! /* Ensure the socket is valid. */ ! if (sock_fd != -1) ! { ! GIOChannel * const sock = g_io_channel_unix_new(sock_fd); /* Use Glib I/O channel for the socket. */ ! GIOStatus rc; ! GError * err_code = NULL; ! gsize bytes_read = 0UL; ! gchar input_buffer[HDDTEMP_BUFFER_SIZE+1]; ! ! do ! { ! /* Read a buffer of bytes from the socket connected to the hddtemp daemon. */ ! rc = g_io_channel_read_chars(sock, input_buffer, HDDTEMP_BUFFER_SIZE, &bytes_read, &err_code); ! /* The next piece of code should never be executed, but then ... */ ! if (rc == G_IO_STATUS_ERROR) ! { ! gchar * msg_txt; ! msg_txt = g_strdup_printf("Reading socket: %s (%d)", err_code->message, err_code->code); ! /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Reading socket: %s (%d)", err_code->message, err_code->code); */ ! quick_message(msg_txt); ! g_free(msg_txt); ! g_error_free(err_code); ! err_code = NULL; ! break; ! } ! ! /* If we received some bytes in this read, add it to the output string. */ ! if (bytes_read > 0) ! { ! result_len += bytes_read; ! if (*stdoutput == NULL) /* No bytes yet in the string. */ ! { ! *stdoutput = g_strndup(input_buffer, bytes_read); ! } ! else ! { ! gchar * const tmp = *stdoutput; /* Protect the reference to the bytes read previously. */ ! ! /* Add a trailing NUL to the block of bytes. */ ! input_buffer[bytes_read] = '\0'; ! /* Concatenate this block to the bytes we have read previously. */ ! *stdoutput = g_strconcat(tmp, input_buffer, NULL); ! /* Free up the previous bytes. */ ! g_free(tmp); ! } ! } ! } while (rc != G_IO_STATUS_EOF); /* Keep looping until the hddtemp daemon closes the socket. */ ! ! if (g_io_channel_shutdown(sock, TRUE, &err_code) == G_IO_STATUS_ERROR) /* This should always work, but then ... */ ! { ! gchar * msg_txt; ! ! msg_txt = g_strdup_printf("Closing socket: %s (%d)", err_code->message, err_code->code); ! /* g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_txt); */ ! quick_message(msg_txt); ! g_free(msg_txt); ! g_error_free(err_code); ! err_code = NULL; } } ! TRACE ("leaves get_hddtemp_text"); ! /* Return value is the total number of bytes read through the socket. */ ! return result_len; } void ! read_disks(t_chip *chip) { ! gchar * stdoutput = NULL; ! t_chipfeature *cf; ! ! TRACE ("enters read_disks"); ! get_hddtemp_text(&stdoutput); ! ! if (stdoutput != NULL) ! { ! gchar ** string_vec = g_strsplit_set(stdoutput, SINGLE_DELIMITER, MAX_DISKS); ! gint i, max_i = 0; ! while (string_vec[max_i] != NULL) ! { ! ++max_i; } ! for (i = 1; i < max_i; i += 5) ! { ! if (strcmp(string_vec[i+2], "NOS") != 0) ! { ! cf = g_new(t_chipfeature, 1); ! cf->devicename = g_strdup(string_vec[i]); ! cf->name = g_strdup(string_vec[i]+5); /* Trim off "/dev/". */ ! ! g_ptr_array_add(chip->chip_features, cf); ! chip->num_features++; ! } ! } ! ! g_strfreev(string_vec); ! g_free(stdoutput); ! } ! TRACE ("leaves read_disks"); } void remove_unmonitored_drives (t_chip *chip, gboolean *suppressmessage) *************** *** 368,376 **** int initialize_hddtemp (GPtrArray *chips, gboolean *suppressmessage) { ! int generation, major, result, retval; ! struct utsname *p_uname; t_chip *chip; g_assert (chips!=NULL); --- 420,428 ---- int initialize_hddtemp (GPtrArray *chips, gboolean *suppressmessage) { ! int retval; t_chip *chip; + static const sensors_chip_name hdd_chip_name = { "Hard disks", 0, 0, "Hard disks" }; g_assert (chips!=NULL); *************** *** 378,386 **** chip = g_new (t_chip, 1); ! chip->chip_name = (const sensors_chip_name *) ! ( _("Hard disks"), 0, 0, _("Hard disks") ); ! chip->chip_features = g_ptr_array_new (); chip->num_features = 0; chip->description = g_strdup(_("S.M.A.R.T. harddisk temperatures")); --- 430,437 ---- chip = g_new (t_chip, 1); ! chip->chip_name = &hdd_chip_name; ! chip->chip_features = g_ptr_array_new (); chip->num_features = 0; chip->description = g_strdup(_("S.M.A.R.T. harddisk temperatures")); *************** *** 388,417 **** chip->sensorId = g_strdup("Hard disks"); chip->type = HDD; ! p_uname = (struct utsname *) malloc (sizeof(struct utsname)); ! result = uname (p_uname); ! if (result!=0) { ! g_free(p_uname); ! return -1; ! } ! ! generation = atoi ( p_uname->release ); /* this might cause trouble on */ ! major = atoi ( p_uname->release+2 ); /* other systems than Linux! */ ! /* actually, wanted to use build time configuration therefore */ ! ! /* Note: This is actually supposed to be carried out by ifdef HAVE_LINUX ! and major/minor number stuff from compile time*/ ! #ifdef HAVE_NETCAT ! read_disks_netcat (chip); ! #else ! if (strcmp(p_uname->sysname, "Linux")==0 && major>=5) ! read_disks_linux26 (chip); ! else ! read_disks_fallback (chip); /* hopefully, that's a safe variant */ ! #endif ! ! g_free(p_uname); remove_unmonitored_drives (chip, suppressmessage); DBG ("numfeatures=%d\n", chip->num_features); if ( chip->num_features>0 ) { /* if (1) */ --- 439,447 ---- chip->sensorId = g_strdup("Hard disks"); chip->type = HDD; ! read_disks(chip); + /* This next call should no longer be necessary. */ remove_unmonitored_drives (chip, suppressmessage); DBG ("numfeatures=%d\n", chip->num_features); if ( chip->num_features>0 ) { /* if (1) */ *************** *** 433,449 **** double get_hddtemp_value (char* disk, gboolean *suppressmessage) { ! gchar *standard_output, *standard_error; ! gchar *cmd_line, *msg_text; ! #ifndef HAVE_LIBNOTIFY ! gchar *checktext; ! #endif ! gint exit_status=0; ! double value; ! gboolean result, nevershowagain; ! GError *error; ! ! gchar *tmp, *tmp2, *tmp3; if (suppressmessage!=NULL) nevershowagain = *suppressmessage; --- 463,472 ---- double get_hddtemp_value (char* disk, gboolean *suppressmessage) { ! gchar * standard_output = NULL; ! gsize bytes_read; ! double value = ZERO_KELVIN; ! gboolean nevershowagain; if (suppressmessage!=NULL) nevershowagain = *suppressmessage; *************** *** 452,594 **** TRACE ("enters get_hddtemp_value for %s with suppress=%d", disk, nevershowagain); /* *suppressmessage); */ ! #ifdef HAVE_NETCAT ! exit_status = 1; // assume error by default ! cmd_line = g_strdup_printf ( "%s localhost %s", NETCAT_PATH, HDDTEMP_PORT); ! result = g_spawn_command_line_sync ( (const gchar*) cmd_line, ! &standard_output, &standard_error, &exit_status, NULL); ! error = g_new(GError, 1); ! error->message = g_strdup (_("No concrete error detected.\n")); ! if (exit_status==0) { ! tmp3 = "-255"; ! tmp = str_split (standard_output, DOUBLE_DELIMITER); ! do { ! //g_printf ("Found token: %s for disk %s\n", tmp, disk); ! tmp2 = g_strdup (tmp); ! tmp3 = strtok (tmp2, SINGLE_DELIMITER); // device name ! if (strcmp(tmp3, disk)==0) { ! tmp3 = strtok(NULL, SINGLE_DELIMITER); // name ! tmp3 = strdup(strtok(NULL, SINGLE_DELIMITER)); // value ! // tmp3 = strtok(NULL, SINGLE_DELIMITER); // temperature unit ! exit_status = 0; ! g_free(error); ! error = NULL; ! g_free (tmp2); break; } - g_free (tmp2); } - while ( (tmp = str_split(NULL, DOUBLE_DELIMITER)) ); g_free(standard_output); - standard_output = tmp3; } - else - { - error->message = g_strdup (standard_error); - } - - #else - error = NULL; - cmd_line = g_strdup_printf ( "%s -n -q %s", PATH_HDDTEMP, disk); - result = g_spawn_command_line_sync ( (const gchar*) cmd_line, - &standard_output, &standard_error, &exit_status, &error); - #endif - - msg_text = NULL; // wonder if this is still necessary - - DBG ("Exit code %d on %s with stdout of %s.\n", exit_status, disk, standard_output); - - /* filter those with no sensors out */ - if (exit_status==0 && strncmp(disk, "/dev/fd", 6)==0) { /* is returned for floppy disks */ - DBG("exit_status==0 && strncmp(disk, \"/dev/fd\", 6)==0"); - value = 0.0; - } - else if ((exit_status==256 || (standard_error && strlen(standard_error)>0)) - && access (PATH_HDDTEMP, X_OK)==0) /* || strlen(standard_error)>0) */ - { - /* note that this check does only work for some versions of hddtemp. */ - if (!nevershowagain) { - msg_text = g_strdup_printf(_("\"hddtemp\" was not executed correctly, " - "although it is executable. This is most probably due " - "to the disks requiring root privileges to read their " - "temperatures, and \"hddtemp\" not being setuid root." - "\n\n" - "An easy but dirty solution is to run \"chmod u+s %s" - "\" as root user and restart this plugin " - "or its panel.\n\n" - "Calling \"%s\" gave the following error:\n%s\nwith a return value of %d.\n"), - PATH_HDDTEMP, cmd_line, standard_error, exit_status); - - #ifdef HAVE_LIBNOTIFY - //msg_text = g_strconcat(msg_text, _("\nYou can disable these notifications in the settings dialog.\n"); - quick_message_notify (msg_text); - nevershowagain = FALSE; - #else - checktext = g_strdup(_("Suppress this message in future")); - nevershowagain = quick_message_with_checkbox(msg_text, checktext); - #endif - - if (suppressmessage!=NULL) - *suppressmessage = nevershowagain; - } - else { - DBG ("Suppressing dialog with exit_code=256 or output on standard_error"); - } - - value = ZERO_KELVIN; - } - /* else if (strlen(standard_error)>0) { - msg_text = g_strdup_printf (_("An error occurred when executing" - " \"%s\":\n%s"), cmd_line, standard_error); - quick_message (msg_text); - value = ZERO_KELVIN; - } */ - - else if (error && (!result || exit_status!=0)) - { - DBG ("error %s\n", error->message); - if (!nevershowagain) { - msg_text = g_strdup_printf (_("An error occurred when executing" - " \"%s\":\n%s"), cmd_line, error->message); - #ifdef HAVE_LIBNOTIFY - quick_message_notify (msg_text); - nevershowagain = FALSE; - #else - checktext = g_strdup(_("Suppress this message in future")); - nevershowagain = quick_message_with_checkbox (msg_text, checktext); - #endif - - if (suppressmessage!=NULL) - *suppressmessage = nevershowagain; - } - else { - DBG ("Suppressing dialog because of error in g_spawn_cl"); - } - value = 0.0; - } - else if (standard_output && strlen(standard_output) > 0) - { - DBG("got the only useful return value of 0 and value of %s.\n", standard_output); - /* hddtemp does not return floating values, but only integer ones. - So have an easier life with atoi. - FIXME: Use strtod() instead?*/ - value = (double) (atoi ( (const char*) standard_output) ); - } - else { - DBG("No condition applied."); - value = 0.0; - } - - g_free (cmd_line); - g_free (standard_output); - g_free (standard_error); - g_free (msg_text); - #ifndef HAVE_LIBNOTIFY - g_free (checktext); - #endif TRACE ("leaves get_hddtemp_value"); --- 475,503 ---- TRACE ("enters get_hddtemp_value for %s with suppress=%d", disk, nevershowagain); /* *suppressmessage); */ ! bytes_read = get_hddtemp_text(&standard_output); ! if (standard_output != NULL) { ! gchar ** string_vec = g_strsplit_set(standard_output, SINGLE_DELIMITER, MAX_DISKS); ! gint i, max_i = 0; ! ! while (string_vec[max_i] != NULL) ! { ! ++max_i; ! } ! ! for (i = 1; i < max_i; i += 5) ! { ! if (strcmp(string_vec[i], disk) == 0) { ! value = g_strtod(string_vec[i+2], NULL); break; } } + g_strfreev(string_vec); g_free(standard_output); } TRACE ("leaves get_hddtemp_value"); *************** *** 600,606 **** refresh_hddtemp (gpointer chip_feature, gpointer data) { t_chipfeature *cf; - double value; g_assert (chip_feature!=NULL); --- 509,514 ---- *************** *** 608,623 **** cf = (t_chipfeature *) chip_feature; ! value = get_hddtemp_value (cf->devicename, NULL); ! ! /* actually, that's done in the gui part */ ! g_free (cf->formatted_value); ! /* if (scale == FAHRENHEIT) { ! cf->formatted_value = g_strdup_printf(_("%.1f °F"), (float) (value * 9/5 + 32) ); ! } else { // Celsius */ ! cf->formatted_value = g_strdup_printf(_("%.1f °C"), value); ! /* } */ ! cf->raw_value = value; TRACE ("leaves refresh_hddtemp"); } --- 516,522 ---- cf = (t_chipfeature *) chip_feature; ! cf->raw_value = get_hddtemp_value (cf->devicename, NULL); TRACE ("leaves refresh_hddtemp"); }