* Added buffer_text_size option to change the size of the buffer for
authorBrenden Matthews <brenden1@rty.ca>
Mon, 12 Feb 2007 01:03:10 +0000 (01:03 +0000)
committerBrenden Matthews <brenden1@rty.ca>
Mon, 12 Feb 2007 01:03:10 +0000 (01:03 +0000)
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
ChangeLog
doc/config_settings.xml
doc/variables.xml
src/Makefile.am
src/conky.c
src/conky.h
src/mboxscan.c [new file with mode: 0644]
src/mboxscan.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 22c014a..92f698d 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -31,6 +31,9 @@ Bruce Merry <bmerry at cs dot uct dot ac dot za>
 btlee
   linkstatus patch (http://forums.gentoo.org/viewtopic-p-2765647.html#2765647)
 
+calmar <mac at calmar dot ws>
+  mboxscan
+
 dan-h <dan-h at users dot sourceforge dot net>
   adt746x fix
 
index 8d6c2c2..3b8bd5a 100644 (file)
--- 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).
 
index f70a903..cb46811 100644 (file)
 </varlistentry>
 
 <varlistentry>
+       <term><command><option>text_buffer_size</option></command>
+               <option>bytes</option>
+       </term>
+       <listitem>
+               Size of the standard text buffer (default is 1280 bytes).
+               <para></para></listitem>
+</varlistentry>
+
+<varlistentry>
        <term><command><option>maximum_width</option></command>
                <option>pixels</option>
        </term>
index df44c82..a2cca9e 100644 (file)
                <option>(cpuN)</option>
        </term>
        <listitem>
-               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.
        <para></para></listitem>
 </varlistentry>
 
 
 <varlistentry>
        <term>
+               <command><option>mboxscan</option></command>
+               <option>(-n number of messages to print) (-fw from width) (-sw subject width) mbox</option>
+       </term>
+       <listitem>
+               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"}
+       <para></para></listitem>
+</varlistentry>
+
+<varlistentry>
+       <term>
                <command><option>mem</option></command>
        </term>
        <listitem>
index 0429948..3e63d75 100644 (file)
@@ -64,6 +64,8 @@ conky_SOURCES =               \
        $(solaris)              \
        timed_thread.c          \
        timed_thread.h          \
+       mboxscan.c              \
+       mboxscan.h              \
        $(x11)                  \
        $(xmms2) 
 
index 96c39e4..c0fa003 100644 (file)
@@ -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,
@@ -1140,6 +1144,11 @@ struct text_object {
                struct mail_s *mail;
 
                struct {
+                       char *args;
+                       char *output;
+               } mboxscan;
+
+               struct {
                        char *tz;    /* timezone variable */
                        char *fmt;   /* time display formatting */
                } tztime;
@@ -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);
index cccd937..32669de 100644 (file)
@@ -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 (file)
index 0000000..768b222
--- /dev/null
@@ -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 <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <number of messages to print>] [-fw <from width>] [-sw <subject width>] 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: <foo@bar.com> */
+
+                                       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 (file)
index 0000000..1220a24
--- /dev/null
@@ -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_ */