From 45acd5c3b9d2449d5087dfc821d6ab476480527c Mon Sep 17 00:00:00 2001 From: Brenden Matthews Date: Mon, 12 Feb 2007 01:03:10 +0000 Subject: [PATCH] * Added buffer_text_size option to change the size of the buffer for things like $exec, $tail, et cetera * Added $mboxscan which lets you display the Subject and From fields from recent email in an mbox file * Disambiguated (is that a word?) $cpu docs git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky1@831 7f574dfc-610e-0410-a909-a81674777703 --- AUTHORS | 3 + ChangeLog | 7 ++ doc/config_settings.xml | 9 ++ doc/variables.xml | 12 +- src/Makefile.am | 2 + src/conky.c | 59 ++++++--- src/conky.h | 1 + src/mboxscan.c | 262 ++++++++++++++++++++++++++++++++++++++++ src/mboxscan.h | 10 ++ 9 files changed, 348 insertions(+), 17 deletions(-) create mode 100644 src/mboxscan.c create mode 100644 src/mboxscan.h diff --git a/AUTHORS b/AUTHORS index 22c014a1..92f698d8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -31,6 +31,9 @@ Bruce Merry btlee linkstatus patch (http://forums.gentoo.org/viewtopic-p-2765647.html#2765647) +calmar + mboxscan + dan-h adt746x fix diff --git a/ChangeLog b/ChangeLog index 8d6c2c2d..3b8bd5a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ # $Id$ +2007-02-11 + * Added buffer_text_size option to change the size of the buffer for + things like $exec, $tail, et cetera + * Added $mboxscan which lets you display the Subject and From fields + from recent email in an mbox file + * Disambiguated (is that a word?) $cpu docs + 2007-01-14 * Fallback to gettimeofday() when clock_gettime () not available (mac os). diff --git a/doc/config_settings.xml b/doc/config_settings.xml index f70a903b..cb468110 100644 --- a/doc/config_settings.xml +++ b/doc/config_settings.xml @@ -172,6 +172,15 @@ + + + + + + Size of the standard text buffer (default is 1280 bytes). + + + diff --git a/doc/variables.xml b/doc/variables.xml index df44c825..a2cca9ed 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -338,7 +338,7 @@ - CPU usage in percents. For SMP machines, the CPU number can be provided as an argument. ${cpu 0} is the total usage, and ${cpu X} (X >= 1) are individual CPUs. + CPU usage in percents. For SMP machines, the CPU number can be provided as an argument. ${cpu cpu0} is the total usage, and ${cpu cpuX} (X >= 1) are individual CPUs. @@ -967,6 +967,16 @@ + + + + + + + Print a summary of recent messages in an mbox format mailbox. mbox parameter is the filename of the mailbox (can be encapsulated using '"', ie. ${mboxscan -n 10 "/home/brenden/some box"} + + + diff --git a/src/Makefile.am b/src/Makefile.am index 04299481..3e63d759 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,6 +64,8 @@ conky_SOURCES = \ $(solaris) \ timed_thread.c \ timed_thread.h \ + mboxscan.c \ + mboxscan.h \ $(x11) \ $(xmms2) diff --git a/src/conky.c b/src/conky.c index 96c39e49..c0fa0039 100644 --- a/src/conky.c +++ b/src/conky.c @@ -322,6 +322,9 @@ static unsigned int max_specials = MAX_SPECIALS_DEFAULT; /* maximum size of config TEXT buffer, i.e. below TEXT line. */ static unsigned int max_user_text = MAX_USER_TEXT_DEFAULT; +/* maximum size of individual text buffers, ie $exec buffer size */ +unsigned int text_buffer_size = TEXT_BUFFER_SIZE; + #ifdef HAVE_ICONV #define CODEPAGE_LENGTH 20 long iconv_selected; @@ -992,6 +995,7 @@ enum text_object_type { OBJ_loadavg, OBJ_machine, OBJ_mails, + OBJ_mboxscan, OBJ_mem, OBJ_membar, OBJ_memgraph, @@ -1139,6 +1143,11 @@ struct text_object { unsigned int cpu_index; struct mail_s *mail; + struct { + char *args; + char *output; + } mboxscan; + struct { char *tz; /* timezone variable */ char *fmt; /* time display formatting */ @@ -1694,7 +1703,7 @@ void *threaded_exec(struct text_object *obj) { char *p2 = obj->data.texeci.buffer; FILE *fp = popen(obj->data.texeci.cmd,"r"); timed_thread_lock (obj->data.texeci.p_timed_thread); - int n2 = fread(p2, 1, TEXT_BUFFER_SIZE, fp); + int n2 = fread(p2, 1, text_buffer_size, fp); (void) pclose(fp); p2[n2] = '\0'; if (n2 && p2[n2 - 1] == '\n') { @@ -1744,6 +1753,10 @@ static void free_text_objects(unsigned int count, struct text_object *objs) free(objs[i].data.tztime.tz); free(objs[i].data.tztime.fmt); break; + case OBJ_mboxscan: + free(objs[i].data.mboxscan.args); + free(objs[i].data.mboxscan.output); + break; case OBJ_imap: free(info.mail); break; @@ -2287,7 +2300,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, } else { obj->data.execi.cmd = strdup(arg + n); obj->data.execi.buffer = - (char *) calloc(1, TEXT_BUFFER_SIZE); + (char *) calloc(1, text_buffer_size); } END OBJ(texeci, 0) unsigned int n; if (!arg || sscanf(arg, "%f %n", &obj->data.texeci.interval, &n) <= 0) { @@ -2299,7 +2312,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, } else { obj->data.texeci.cmd = strdup(arg + n); obj->data.texeci.buffer = - (char *) calloc(1, TEXT_BUFFER_SIZE); + (char *) calloc(1, text_buffer_size); } obj->data.texeci.p_timed_thread = NULL; END OBJ(pre_exec, 0) obj->type = OBJ_text; @@ -2502,7 +2515,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, fp = fopen(buf, "r"); if (fp) { obj->data.tail.logfile = - malloc(TEXT_BUFFER_SIZE); + malloc(text_buffer_size); strcpy(obj->data.tail.logfile, buf); obj->data.tail.wantedlines = n1; obj->data.tail.interval = @@ -2527,7 +2540,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, fp = fopen(buf, "r"); if (fp != NULL) { obj->data.tail.logfile = - malloc(TEXT_BUFFER_SIZE); + malloc(text_buffer_size); strcpy(obj->data.tail.logfile, buf); obj->data.tail.wantedlines = n1; obj->data.tail.interval = n2; @@ -2543,7 +2556,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, ERR("invalid args given for tail"); return NULL; } - obj->data.tail.buffer = malloc(TEXT_BUFFER_SIZE * 20); /* asumming all else worked */ + obj->data.tail.buffer = malloc(text_buffer_size * 20); /* asumming all else worked */ END OBJ(head, 0) char buf[64]; int n1, n2; @@ -2562,7 +2575,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, fp = fopen(buf, "r"); if (fp != NULL) { obj->data.tail.logfile = - malloc(TEXT_BUFFER_SIZE); + malloc(text_buffer_size); strcpy(obj->data.tail.logfile, buf); obj->data.tail.wantedlines = n1; obj->data.tail.interval = @@ -2587,7 +2600,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, fp = fopen(buf, "r"); if (fp != NULL) { obj->data.tail.logfile = - malloc(TEXT_BUFFER_SIZE); + malloc(text_buffer_size); strcpy(obj->data.tail.logfile, buf); obj->data.tail.wantedlines = n1; obj->data.tail.interval = n2; @@ -2603,7 +2616,7 @@ static struct text_object *construct_text_object(const char *s, const char *arg, ERR("invalid args given for head"); return NULL; } - obj->data.tail.buffer = malloc(TEXT_BUFFER_SIZE * 20); /* asumming all else worked */ + obj->data.tail.buffer = malloc(text_buffer_size * 20); /* asumming all else worked */ END OBJ(loadavg, INFO_LOADAVG) int a = 1, b = 2, c = 3, r = 3; if (arg) { r = sscanf(arg, "%d %d %d", &a, &b, &c); @@ -2659,6 +2672,10 @@ static struct text_object *construct_text_object(const char *s, const char *arg, END OBJ(kernel, 0) END OBJ(machine, 0) END OBJ(mails, INFO_MAIL) + END OBJ(mboxscan, 0) + obj->data.mboxscan.args = (char*)malloc(TEXT_BUFFER_SIZE); + obj->data.mboxscan.output = (char*)malloc(text_buffer_size); + strncpy(obj->data.mboxscan.args, arg, TEXT_BUFFER_SIZE); END OBJ(mem, INFO_MEM) END OBJ(memmax, INFO_MEM) END OBJ(memperc, INFO_MEM) @@ -3727,8 +3744,8 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object * } else { char *output = obj->data.execi.buffer; FILE *fp = popen(obj->data.execi.cmd, "r"); - //int length = fread(output, 1, TEXT_BUFFER_SIZE, fp); - int length = fread(output, 1, TEXT_BUFFER_SIZE, fp); + //int length = fread(output, 1, text_buffer_size, fp); + int length = fread(output, 1, text_buffer_size, fp); (void) pclose(fp); output[length] = '\0'; @@ -4164,6 +4181,10 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object * OBJ(mails) { snprintf(p, p_max_size, "%d", cur->mail_count); } + OBJ(mboxscan) { + mbox_scan(obj->data.mboxscan.args, obj->data.mboxscan.output, text_buffer_size); + snprintf(p, p_max_size, "%s", obj->data.mboxscan.output); + } OBJ(new_mails) { snprintf(p, p_max_size, "%d", cur->new_mail_count); } @@ -4677,9 +4698,9 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object * } /* Make sure bsize is at least 1 byte smaller than * the buffer max size. */ - if(bsize > TEXT_BUFFER_SIZE*20 - 1) { - fseek(fp, bsize - TEXT_BUFFER_SIZE*20 - 1, SEEK_CUR); - bsize = TEXT_BUFFER_SIZE*20 - 1; + if(bsize > text_buffer_size*20 - 1) { + fseek(fp, bsize - text_buffer_size*20 - 1, SEEK_CUR); + bsize = text_buffer_size*20 - 1; } bsize = fread(obj->data.tail.buffer, 1, bsize, fp); fclose(fp); @@ -4730,8 +4751,8 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object * obj->data.tail.readlines = iter; /* Make sure nl is at least 1 byte smaller than * the buffer max size. */ - if(nl > TEXT_BUFFER_SIZE*20 - 1) { - nl = TEXT_BUFFER_SIZE*20 - 1; + if(nl > text_buffer_size*20 - 1) { + nl = text_buffer_size*20 - 1; } nl = fread(obj->data.tail.buffer, 1, nl, fp); fclose(fp); @@ -6735,6 +6756,12 @@ else if (strcasecmp(name, a) == 0 || strcasecmp(name, b) == 0) else CONF_ERR; } + CONF("text_buffer_size") { + if (value) + text_buffer_size = atoi(value); + else + CONF_ERR; + } CONF("text") { if (text != original_text) free(text); diff --git a/src/conky.h b/src/conky.h index cccd9376..32669de0 100644 --- a/src/conky.h +++ b/src/conky.h @@ -53,6 +53,7 @@ #define TEXT_BUFFER_SIZE 1280 #define P_MAX_SIZE ((TEXT_BUFFER_SIZE * 4) - 2) +extern unsigned int text_buffer_size; /* maximum number of special things, e.g. fonts, offsets, aligns, etc. */ #define MAX_SPECIALS_DEFAULT 512 diff --git a/src/mboxscan.c b/src/mboxscan.c new file mode 100644 index 00000000..768b2223 --- /dev/null +++ b/src/mboxscan.c @@ -0,0 +1,262 @@ +/* + * $Id$ + * + * Licence: http://www.opensource.org/licenses/bsd-license.php + * author: mac@calmar.ws + * + * Modified for use in Conky by Brenden Matthews + * + * Description: + * scanning from top to bottom on a mbox + * The output as follows: + * F: FROM_LENGHT S: SUBJECT_LENGHT + * (PRINT_MAILS or -n NR times) + */ + +#include "conky.h" +#include +#include +#include +#include +#include +#include "mboxscan.h" + +#define FROM_WIDTH 10 +#define SUBJECT_WIDTH 22 +#define PRINT_MAILS 5 + +struct ring_list { + char *from; + char *subject; + struct ring_list *previous; + struct ring_list *next; +}; + +void mbox_scan(char *args, char *output, size_t max_len) +{ + int i, u, flag; + int from_width, subject_width, print_mails; + char buf[text_buffer_size]; + + char *substr = strstr(args, "-n"); + if (substr) { + if (sscanf(substr, "-n %i", &print_mails) != 1) { + print_mails = PRINT_MAILS; + } + } else { + print_mails = PRINT_MAILS; + } + substr = strstr(args, "-fw"); + if (substr) { + if (sscanf(substr, "-fw %i", &from_width) != 1) { + from_width = FROM_WIDTH; + } + } else { + from_width = FROM_WIDTH; + } + substr = strstr(args, "-sw"); + if (substr) { + if (sscanf(substr, "-sw %i", &subject_width) != 1) { + subject_width = SUBJECT_WIDTH; + } + } else { + subject_width = SUBJECT_WIDTH; + } + char current_mail_spool[text_buffer_size]; + if (args[strlen(args) - 1] == '"') { // encapsulated with "'s + // find first occurrence of " + strncpy(current_mail_spool, args, text_buffer_size); + char *start = strchr(current_mail_spool, '"') + 1; + start[(long)(strrchr(current_mail_spool, '"') - start)] = '\0'; + strncpy(current_mail_spool, start, text_buffer_size); + } else { + char *tmp = strtok(args, " "); + char *start = tmp; + while (tmp) { + tmp = strtok(NULL, " "); + if (tmp) { + start = tmp; + } + } + strncpy(current_mail_spool, start, text_buffer_size); + } + //printf("'%s', %i, %i, %i\n", current_mail_spool, subject_width, from_width, print_mails); + if (strlen(current_mail_spool) < 1) { + CRIT_ERR("Usage: ${mboxscan [-n ] [-fw ] [-sw ] mbox}"); + } + + struct stat statbuf; + + if (stat(current_mail_spool, &statbuf)) { + CRIT_ERR("can't stat %s: %s", current_mail_spool, strerror(errno)); + } + /* end - argument checking */ + + /* build up double-linked ring-list to hold data, while scanning down the mbox */ + struct ring_list *curr, *prev, *start; + + for (i = 0; i < print_mails; i++) { + curr = (struct ring_list *)malloc(sizeof(struct ring_list)); + curr->from = (char *)malloc(sizeof(char[from_width + 1])); + curr->subject = (char *)malloc(sizeof(char[subject_width + 1])); + curr->from[0] = '\0'; + curr->subject[0] = '\0'; + + if (i == 0) + start = curr; + if (i > 0) { + curr->previous = prev; + prev->next = curr; + } + prev = curr; + } + + /* connect end to start for an endless loop-ring */ + start->previous = curr; + curr->next = start; + + /* mbox */ + FILE *fp; + + fp = fopen(current_mail_spool, "r"); + if (!fp) { + return; + } + + flag = 1; /* frist find a "From " to set it to 0 for header-sarchings */ + while (!feof(fp)) { + if (fgets(buf, text_buffer_size, fp) == NULL) + break; + + if (strncmp(buf, "From ", 5) == 0) { + curr = curr->next; + + /* skip until \n */ + while (strchr(buf, '\n') == NULL && !feof(fp)) + fgets(buf, text_buffer_size, fp); + + flag = 0; /* in the headers now */ + continue; + } + + if (flag == 1) { /* in the body, so skip */ + continue; + } + + if (buf[0] == '\n') { + /* beyond the headers now (empty line), skip until \n */ + /* then search for new mail ("From ") */ + while (strchr(buf, '\n') == NULL && !feof(fp)) + fgets(buf, text_buffer_size, fp); + flag = 1; /* in the body now */ + continue; + } + + if ((strncmp(buf, "X-Status: ", 10) == 0) + || (strncmp(buf, "Status: R", 9) == 0)) { + + /* Mail was read or something, so skip that message */ + flag = 1; /* search for next From */ + curr->subject[0] = '0'; + curr->from[0] = '0'; + curr = curr->previous; /* (will get current again on new 'From ' finding) */ + /* Skip until \n */ + while (strchr(buf, '\n') == NULL && !feof(fp)) + fgets(buf, text_buffer_size, fp); + continue; + } + + /* that covers ^From: and ^from: */ + if (strncmp(buf + 1, "rom: ", 5) == 0) { + + i = 0; + u = 6; /* no "From: " string needed, so skip */ + while (1) { + + if (buf[u] == '"') { /* no quotes around names */ + u++; + continue; + } + + if (buf[u] == '<' && i > 1) { /* some are: From: */ + + curr->from[i] = '\0'; + /* skip until \n */ + while (strchr(buf, '\n') == NULL && !feof(fp)) + fgets(buf, text_buffer_size, fp); + break; + } + + if (buf[u] == '\n') { + curr->from[i] = '\0'; + break; + } + + if (buf[u] == '\0') { + curr->from[i] = '\0'; + break; + } + + if (i >= from_width) { + curr->from[i] = '\0'; + /* skip until \n */ + while (strchr(buf, '\n') == NULL && !feof(fp)) + fgets(buf, text_buffer_size, fp); + break; + } + + /* nothing special so just set it */ + curr->from[i++] = buf[u++]; + } + } + + /* that covers ^Subject and ^subject */ + if (strncmp(buf + 1, "ubject: ", 8) == 0) { + + i = 0; + u = 9; /* no "Subject: " string needed, so skip */ + while (1) { + + if (buf[u] == '\n') { + curr->subject[i] = '\0'; + break; + } + if (buf[u] == '\0') { + curr->subject[i] = '\0'; + break; + } + if (i >= subject_width) { + curr->subject[i] = '\0'; + + /* skip until \n */ + while (strchr(buf, '\n') == NULL && !feof(fp)) + fgets(buf, text_buffer_size, fp); + break; + } + + /* nothing special so just set it */ + curr->subject[i++] = buf[u++]; + } + } + + } + + fclose(fp); + + i = print_mails; + output[0] = '\0'; + while (curr->from[0] != '\0') { + snprintf(buf, text_buffer_size, "F: %-*s S: %-*s\n", from_width, curr->from, subject_width, curr->subject); + strncat(output, buf, max_len - strlen(output)); +/* printf("F: %-*s", from_width, curr->from); + printf(" S: %-*s\n", subject_width, curr->subject);*/ + free(curr->from); + free(curr->subject); + struct ring_list *old = curr; + free(old); + curr = curr->previous; + if (--i == 0) { + break; + } + } +} diff --git a/src/mboxscan.h b/src/mboxscan.h new file mode 100644 index 00000000..1220a24d --- /dev/null +++ b/src/mboxscan.h @@ -0,0 +1,10 @@ +/* + * $Id$ + */ + +#ifndef _MBOXSCAN_H_ +#define _MBOXSCAN_H_ + +void mbox_scan(char *args, char *output, size_t max_len); + +#endif /* _MBOXSCAN_H_ */