d11bd0f01ada079ea70af08ed65c5eeeb2232d4c
[monky] / src / mboxscan.c
1 /*
2  * $Id$
3  * 
4  * Licence: http://www.opensource.org/licenses/bsd-license.php
5  * author: mac@calmar.ws
6  * 
7  * Modified for use in Conky by Brenden Matthews
8  *
9  * Description:
10  * scanning from top to bottom on a mbox
11  * The output as follows:
12  * F: FROM_LENGHT S: SUBJECT_LENGHT
13  * (PRINT_MAILS or -n NR times)
14  */
15
16 #include "conky.h"
17 #include <sys/stat.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "mboxscan.h"
23
24 #define FROM_WIDTH 10
25 #define SUBJECT_WIDTH 22
26 #define PRINT_MAILS 5
27
28 struct ring_list {
29         char *from;
30         char *subject;
31         struct ring_list *previous;
32         struct ring_list *next;
33 };
34
35 void mbox_scan(char *args, char *output, size_t max_len)
36 {
37         int i, u, flag;
38         int from_width, subject_width, print_mails;
39         char buf[text_buffer_size];
40
41         char *substr = strstr(args, "-n");
42         if (substr) {
43                 if (sscanf(substr, "-n %i", &print_mails) != 1) {
44                         print_mails = PRINT_MAILS;
45                 }
46         } else {
47                 print_mails = PRINT_MAILS;
48         }
49         substr = strstr(args, "-fw");
50         if (substr) {
51                 if (sscanf(substr, "-fw %i", &from_width) != 1) {
52                         from_width = FROM_WIDTH;
53                 }
54         } else {
55                 from_width = FROM_WIDTH;
56         }
57         substr = strstr(args, "-sw");
58         if (substr) {
59                 if (sscanf(substr, "-sw %i", &subject_width) != 1) {
60                         subject_width = SUBJECT_WIDTH;
61                 }
62         } else {
63                 subject_width = SUBJECT_WIDTH;
64         }
65         char current_mail_spool[text_buffer_size];
66         if (args[strlen(args) - 1] == '"') { // encapsulated with "'s
67                 // find first occurrence of "
68                 strncpy(current_mail_spool, args, text_buffer_size);
69                 char *start = strchr(current_mail_spool, '"') + 1;
70                 start[(long)(strrchr(current_mail_spool, '"') - start)] = '\0';
71                 strncpy(current_mail_spool, start, text_buffer_size);
72         } else {
73                 char *tmp = strtok(args, " ");
74                 char *start = tmp;
75                 while (tmp) {
76                         tmp = strtok(NULL, " ");
77                         if (tmp) {
78                                 start = tmp;
79                         }
80                 }
81                 strncpy(current_mail_spool, start, text_buffer_size);
82         }
83         //printf("'%s', %i, %i, %i\n", current_mail_spool, subject_width, from_width, print_mails);
84         if (strlen(current_mail_spool) < 1) {
85                 CRIT_ERR("Usage: ${mboxscan [-n <number of messages to print>] [-fw <from width>] [-sw <subject width>] mbox}");
86         }
87
88         struct stat statbuf;
89
90         if (stat(current_mail_spool, &statbuf)) {
91                 CRIT_ERR("can't stat %s: %s", current_mail_spool, strerror(errno));
92         }
93         /* end - argument checking */
94
95         /* build up double-linked ring-list to hold data, while scanning down the mbox */
96         struct ring_list *curr=0, *prev=0, *start=0;
97
98         for (i = 0; i < print_mails; i++) {
99                 curr = (struct ring_list *)malloc(sizeof(struct ring_list));
100                 curr->from = (char *)malloc(sizeof(char[from_width + 1]));
101                 curr->subject = (char *)malloc(sizeof(char[subject_width + 1]));
102                 curr->from[0] = '\0';
103                 curr->subject[0] = '\0';
104
105                 if (i == 0)
106                         start = curr;
107                 if (i > 0) {
108                         curr->previous = prev;
109                         prev->next = curr;
110                 }
111                 prev = curr;
112         }
113
114         /* connect end to start for an endless loop-ring */
115         start->previous = curr;
116         curr->next = start;
117
118         /* mbox */
119         FILE *fp;
120
121         fp = fopen(current_mail_spool, "r");
122         if (!fp) {
123                 return;
124         }
125
126         flag = 1;               /* frist find a "From " to set it to 0 for header-sarchings */
127         while (!feof(fp)) {
128                 if (fgets(buf, text_buffer_size, fp) == NULL)
129                         break;
130
131                 if (strncmp(buf, "From ", 5) == 0) {
132                         curr = curr->next;
133
134                         /* skip until \n */
135                         while (strchr(buf, '\n') == NULL && !feof(fp))
136                                 fgets(buf, text_buffer_size, fp);
137
138                         flag = 0;       /* in the headers now */
139                         continue;
140                 }
141
142                 if (flag == 1) {        /* in the body, so skip */
143                         continue;
144                 }
145
146                 if (buf[0] == '\n') {
147                         /* beyond the headers now (empty line), skip until \n */
148                         /* then search for new mail ("From ") */
149                         while (strchr(buf, '\n') == NULL && !feof(fp))
150                                 fgets(buf, text_buffer_size, fp);
151                         flag = 1;       /* in the body now */
152                         continue;
153                 }
154
155                 if ((strncmp(buf, "X-Status: ", 10) == 0)
156                     || (strncmp(buf, "Status: R", 9) == 0)) {
157
158                         /* Mail was read or something, so skip that message */
159                         flag = 1;       /* search for next From */
160                         curr->subject[0] = '0';
161                         curr->from[0] = '0';
162                         curr = curr->previous;  /* (will get current again on new 'From ' finding) */
163                         /* Skip until \n */
164                         while (strchr(buf, '\n') == NULL && !feof(fp))
165                                 fgets(buf, text_buffer_size, fp);
166                         continue;
167                 }
168
169                 /* that covers ^From: and ^from: */
170                 if (strncmp(buf + 1, "rom: ", 5) == 0) {
171
172                         i = 0;
173                         u = 6;  /* no "From: " string needed, so skip */
174                         while (1) {
175
176                                 if (buf[u] == '"') {    /* no quotes around names */
177                                         u++;
178                                         continue;
179                                 }
180
181                                 if (buf[u] == '<' && i > 1) {   /* some are: From: <foo@bar.com> */
182
183                                         curr->from[i] = '\0';
184                                         /* skip until \n */
185                                         while (strchr(buf, '\n') == NULL && !feof(fp))
186                                                 fgets(buf, text_buffer_size, fp);
187                                         break;
188                                 }
189
190                                 if (buf[u] == '\n') {
191                                         curr->from[i] = '\0';
192                                         break;
193                                 }
194
195                                 if (buf[u] == '\0') {
196                                         curr->from[i] = '\0';
197                                         break;
198                                 }
199
200                                 if (i >= from_width) {
201                                         curr->from[i] = '\0';
202                                         /* skip until \n */
203                                         while (strchr(buf, '\n') == NULL && !feof(fp))
204                                                 fgets(buf, text_buffer_size, fp);
205                                         break;
206                                 }
207
208                                 /* nothing special so just set it */
209                                 curr->from[i++] = buf[u++];
210                         }
211                 }
212
213                 /* that covers ^Subject and ^subject */
214                 if (strncmp(buf + 1, "ubject: ", 8) == 0) {
215
216                         i = 0;
217                         u = 9;  /* no "Subject: " string needed, so skip */
218                         while (1) {
219
220                                 if (buf[u] == '\n') {
221                                         curr->subject[i] = '\0';
222                                         break;
223                                 }
224                                 if (buf[u] == '\0') {
225                                         curr->subject[i] = '\0';
226                                         break;
227                                 }
228                                 if (i >= subject_width) {
229                                         curr->subject[i] = '\0';
230
231                                         /* skip until \n */
232                                         while (strchr(buf, '\n') == NULL && !feof(fp))
233                                                 fgets(buf, text_buffer_size, fp);
234                                         break;
235                                 }
236
237                                 /* nothing special so just set it */
238                                 curr->subject[i++] = buf[u++];
239                         }
240                 }
241
242         }
243
244         fclose(fp);
245
246         i = print_mails;
247         output[0] = '\0';
248         while (curr->from[0] != '\0') {
249                 snprintf(buf, text_buffer_size, "F: %-*s S: %-*s\n", from_width, curr->from, subject_width, curr->subject);
250                 strncat(output, buf, max_len - strlen(output));
251 /*              printf("F: %-*s", from_width, curr->from);
252                 printf(" S: %-*s\n", subject_width, curr->subject);*/
253                 free(curr->from);
254                 free(curr->subject);
255                 struct ring_list *old = curr;
256                 free(old);
257                 curr = curr->previous;
258                 if (--i == 0) {
259                         break;
260                 }
261         }
262 }