diff --git a/plugins/disk/smart-c/smart.c b/plugins/disk/smart-c/smart.c new file mode 100644 index 00000000..ed057360 --- /dev/null +++ b/plugins/disk/smart-c/smart.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2017 Bastiaan van Kesteren - All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2 or v.3. + */ + +#include +#include +#include +#include +#include +#include +#include "common.h" + +static char getitem(char *input, unsigned char item, char *output) +{ + unsigned char i = 0; + unsigned char seperators = 0; + char know_this_seperator = 0; + unsigned char start = 0; + unsigned char stop = 0; + + /* Trim starting spaces */ + while (input[i] == ' ') { + i++; + } + + /* If we're requested to return the very first item... */ + if (seperators == item) { + start = i; + } + + while (input[i] && seperators < item + 1) { + if (input[i] == ' ') { + if (know_this_seperator == 0) { + know_this_seperator = 1; + seperators++; + if (seperators == item + 1) { + stop = i; + break; + } + } + } else if (know_this_seperator) { + know_this_seperator = 0; + if (seperators == item) { + start = i; + } + } else if (input[i] == '\n') { + input[i] = 0; + break; + } + + i++; + } + + if (stop) { + /* Found stop, means we have a start aswell */ + strncpy(output, &input[start], stop - start); + return 1; + } else if (start) { + /* Have a start, no stop. We're returning the last item of the string */ + strcpy(output, &input[start]); + return 1; + } + + return 0; +} + +int smart(int argc, char **argv) +{ + char command[50]; + char output[255]; + char label[25][100]; + char value[25][25]; + unsigned char attribute = 0; + FILE *f; + unsigned int i; + + /* Prepare and execute command */ + snprintf(command, sizeof(command), + "smartctl -A -d ata /dev/%s -n standby", + &basename(argv[0])[6]); + if ((f = popen(command, "r")) == 0) { + return fail("cannot initiate command execution"); + } + + /* Process command output */ + while (fgets(output, sizeof(output), f) != NULL) { + printf("#%s", output); + /* Filter out attribute lines; look for lines starting with an attribute ID */ + if ((output[0] >= '0' && output[0] <= '9') || + (output[0] == ' ' + && (output[1] >= '0' && output[1] <= '9')) + || (output[0] == ' ' && output[1] == ' ' + && (output[2] >= '0' && output[2] <= '9'))) { + /* Now, print the 2nd column (attribute name) and the 10th (raw value) */ + + getitem(output, 1, label[attribute]); + getitem(output, 9, value[attribute]); + attribute++; + if (attribute == 25) { + break; + } + } + } + + /* Close command (this is where we get the exit code! */ + i = WEXITSTATUS(pclose(f)); + if (i == 1 || /* smartctl command did not parse */ + /*i == 2 || *//* smartctl device open failed */ + i == 127) { /* command not found */ + return fail("command execution failed"); + } + + /* Setup for caching */ + snprintf(command, sizeof(command), "/mnt/ram/smart_%s", + &basename(argv[0])[6]); + + if (attribute == 0) { + printf("#Cached attributes\n"); + /* No output from command, try to fetch attribute-list from disk with NaN values */ + if ((f = fopen(command, "r")) == 0) { + return + fail + ("command did not return data, no cached attribute-list"); + return 0; + } + } + + if (argc > 1) { + if (strcmp(argv[1], "config") == 0) { + printf + ("graph_title S.M.A.R.T values for drive %s\n" + "graph_args --base 1000 --lower-limit 0\n" + "graph_vlabel Attribute S.M.A.R.T value\n" + "graph_category disk\n", + &basename(argv[0])[6]); + + if (attribute == 0) { + while (fgets(output, sizeof(output), f) != + NULL) { + for (i = 0; i < strlen(output); + i++) { + if (output[i] == '\n') { + output[i] = '\0'; + break; + } + } + printf("%s.label %s\n", output, + output); + } + fclose(f); + } else { + f = fopen(command, "w"); + do { + attribute--; + printf("%s.label %s\n", + label[attribute], + label[attribute]); + if (f) { + fprintf(f, "%s\n", + label[attribute]); + } + } while (attribute); + + if (f) { + fclose(f); + } + } + printf("standby.label standby\n"); + return 0; + } + } + + /* Asking for a fetch */ + if (attribute == 0) { + /* No data, use cached info */ + while (fgets(output, sizeof(output), f) != NULL) { + for (i = 0; i < strlen(output); i++) { + if (output[i] == '\n') { + output[i] = '\0'; + break; + } + } + printf("%s.value U\n", output); + } + printf("standby.value 1\n"); + fclose(f); + } else { + do { + attribute--; + printf("%s.value %s\n", label[attribute], + value[attribute]); + } while (attribute); + printf("standby.value 0\n"); + } + + return 0; +}