Multiple mailbox patch (thanks Ben Kibbey)
[monky] / src / mail.c
1 /*
2  * Conky, a system monitor, based on torsmo
3  *
4  * Any original torsmo code is licensed under the BSD license
5  *
6  * All code written since the fork of torsmo is licensed under the GPL
7  *
8  * Please see COPYING for details
9  *
10  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
11  * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al. (see AUTHORS)
12  * All rights reserved.
13  *
14  * This program is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
25  *
26  *  $Id$
27  */
28
29 #include <sys/stat.h>
30 #include <sys/time.h>
31
32 #include <dirent.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "conky.h"
38
39 char *current_mail_spool;
40
41 void update_mail_count(struct local_mail_s *mail)
42 {
43         struct stat buf;
44
45         if (mail == NULL)
46                 return;
47
48         /* TODO: use that fine file modification notify on Linux 2.4 */
49
50         /* don't check mail so often (9.5s is minimum interval) */
51         if (current_update_time - mail->last_update < 9.5)
52                 return;
53         else
54                 mail->last_update = current_update_time;
55
56         if (stat(mail->box, &buf)) {
57                 static int rep;
58                 if (!rep) {
59                         ERR("can't stat %s: %s", mail->box,
60                             strerror(errno));
61                         rep = 1;
62                 }
63                 return;
64         }
65 #if HAVE_DIRENT_H
66         /* maildir format */
67         if (S_ISDIR(buf.st_mode)) {
68                 DIR *dir;
69                 char *dirname;
70                 struct dirent *dirent;
71
72                 mail->mail_count = mail->new_mail_count = 0;
73                 dirname =
74                     (char *) malloc(sizeof(char) *
75                                     (strlen(mail->box) + 5));
76                 if (!dirname) {
77                         ERR("malloc");
78                         return;
79                 }
80                 strcpy(dirname, mail->box);
81                 strcat(dirname, "/");
82                 /* checking the cur subdirectory */
83                 strcat(dirname, "cur");
84
85                 dir = opendir(dirname);
86                 if (!dir) {
87                         ERR("cannot open directory");
88                         free(dirname);
89                         return;
90                 }
91                 dirent = readdir(dir);
92                 while (dirent) {
93                         /* . and .. are skipped */
94                         if (dirent->d_name[0] != '.') {
95                                 mail->mail_count++;
96                         }
97                         dirent = readdir(dir);
98                 }
99                 closedir(dir);
100
101                 dirname[strlen(dirname) - 3] = '\0';
102                 strcat(dirname, "new");
103
104                 dir = opendir(dirname);
105                 if (!dir) {
106                         ERR("cannot open directory");
107                         free(dirname);
108                         return;
109                 }
110                 dirent = readdir(dir);
111                 while (dirent) {
112                         /* . and .. are skipped */
113                         if (dirent->d_name[0] != '.') {
114                                 mail->new_mail_count++;
115                                 mail->mail_count++;
116                         }
117                         dirent = readdir(dir);
118                 }
119                 closedir(dir);
120
121                 free(dirname);
122                 return;
123         }
124 #endif
125         /* mbox format */
126         if (buf.st_mtime != mail->last_mtime) {
127                 /* yippee, modification time has changed, let's read mail count! */
128                 static int rep;
129                 FILE *fp;
130                 int reading_status = 0;
131
132                 /* could lock here but I don't think it's really worth it because
133                  * this isn't going to write mail spool */
134
135                 mail->new_mail_count = mail->mail_count = 0;
136
137                 fp = open_file(mail->box, &rep);
138                 if (!fp)
139                         return;
140
141                 /* NOTE: adds mail as new if there isn't Status-field at all */
142
143                 while (!feof(fp)) {
144                         char buf[128];
145                         if (fgets(buf, 128, fp) == NULL)
146                                 break;
147
148                         if (strncmp(buf, "From ", 5) == 0) {
149                                 /* ignore MAILER-DAEMON */
150                                 if (strncmp(buf + 5, "MAILER-DAEMON ", 14)
151                                     != 0) {
152                                         mail->mail_count++;
153
154                                         if (reading_status)
155                                                 mail->new_mail_count++;
156                                         else
157                                                 reading_status = 1;
158                                 }
159                         } else {
160                                 if (reading_status
161                                     && strncmp(buf, "X-Mozilla-Status:",
162                                                17) == 0) {
163                                         /* check that mail isn't already read */
164                                         if (strchr(buf + 21, '0'))
165                                                 mail->new_mail_count++;
166
167                                         reading_status = 0;
168                                         continue;
169                                 }
170                                 if (reading_status
171                                     && strncmp(buf, "Status:", 7) == 0) {
172                                         /* check that mail isn't already read */
173                                         if (strchr(buf + 7, 'R') == NULL)
174                                                 mail->new_mail_count++;
175
176                                         reading_status = 0;
177                                         continue;
178                                 }
179                         }
180
181                         /* skip until \n */
182                         while (strchr(buf, '\n') == NULL && !feof(fp))
183                                 fgets(buf, 128, fp);
184                 }
185
186                 fclose(fp);
187
188                 if (reading_status)
189                         mail->new_mail_count++;
190
191                 mail->last_mtime = buf.st_mtime;
192         }
193 }