00b10a9c2b1db4f88de3f4d404b077f8a5684090
[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 static time_t last_mail_mtime;
42 static double last_mail_update;
43
44 void update_mail_count()
45 {
46         struct stat buf;
47
48         if (current_mail_spool == NULL)
49                 return;
50
51         /* TODO: use that fine file modification notify on Linux 2.4 */
52
53         /* don't check mail so often (9.5s is minimum interval) */
54         if (current_update_time - last_mail_update < 9.5)
55                 return;
56         else
57                 last_mail_update = current_update_time;
58
59         if (stat(current_mail_spool, &buf)) {
60                 static int rep;
61                 if (!rep) {
62                         ERR("can't stat %s: %s", current_mail_spool,
63                             strerror(errno));
64                         rep = 1;
65                 }
66                 return;
67         }
68 #if HAVE_DIRENT_H
69         /* maildir format */
70         if (S_ISDIR(buf.st_mode)) {
71                 DIR *dir;
72                 char *dirname;
73                 struct dirent *dirent;
74                 info.mail_count = 0;
75                 info.new_mail_count = 0;
76
77                 dirname =
78                     (char *) malloc(sizeof(char) *
79                                     (strlen(current_mail_spool) + 5));
80                 if (!dirname) {
81                         ERR("malloc");
82                         return;
83                 }
84                 strcpy(dirname, current_mail_spool);
85                 strcat(dirname, "/");
86                 /* checking the cur subdirectory */
87                 strcat(dirname, "cur");
88
89                 dir = opendir(dirname);
90                 if (!dir) {
91                         ERR("cannot open directory");
92                         free(dirname);
93                         return;
94                 }
95                 dirent = readdir(dir);
96                 while (dirent) {
97                         /* . and .. are skipped */
98                         if (dirent->d_name[0] != '.') {
99                                 info.mail_count++;
100                         }
101                         dirent = readdir(dir);
102                 }
103                 closedir(dir);
104
105                 dirname[strlen(dirname) - 3] = '\0';
106                 strcat(dirname, "new");
107
108                 dir = opendir(dirname);
109                 if (!dir) {
110                         ERR("cannot open directory");
111                         free(dirname);
112                         return;
113                 }
114                 dirent = readdir(dir);
115                 while (dirent) {
116                         /* . and .. are skipped */
117                         if (dirent->d_name[0] != '.') {
118                                 info.new_mail_count++;
119                                 info.mail_count++;
120                         }
121                         dirent = readdir(dir);
122                 }
123                 closedir(dir);
124
125                 free(dirname);
126                 return;
127         }
128 #endif
129         /* mbox format */
130         if (buf.st_mtime != last_mail_mtime) {
131                 /* yippee, modification time has changed, let's read mail count! */
132                 static int rep;
133                 FILE *fp;
134                 int reading_status = 0;
135
136                 /* could lock here but I don't think it's really worth it because
137                  * this isn't going to write mail spool */
138
139                 info.new_mail_count = 0;
140                 info.mail_count = 0;
141
142                 fp = open_file(current_mail_spool, &rep);
143                 if (!fp)
144                         return;
145
146                 /* NOTE: adds mail as new if there isn't Status-field at all */
147
148                 while (!feof(fp)) {
149                         char buf[128];
150                         if (fgets(buf, 128, fp) == NULL)
151                                 break;
152
153                         if (strncmp(buf, "From ", 5) == 0) {
154                                 /* ignore MAILER-DAEMON */
155                                 if (strncmp(buf + 5, "MAILER-DAEMON ", 14)
156                                     != 0) {
157                                         info.mail_count++;
158
159                                         if (reading_status)
160                                                 info.new_mail_count++;
161                                         else
162                                                 reading_status = 1;
163                                 }
164                         } else {
165                                 if (reading_status
166                                     && strncmp(buf, "X-Mozilla-Status:",
167                                                17) == 0) {
168                                         /* check that mail isn't already read */
169                                         if (strchr(buf + 21, '0'))
170                                                 info.new_mail_count++;
171
172                                         reading_status = 0;
173                                         continue;
174                                 }
175                                 if (reading_status
176                                     && strncmp(buf, "Status:", 7) == 0) {
177                                         /* check that mail isn't already read */
178                                         if (strchr(buf + 7, 'R') == NULL)
179                                                 info.new_mail_count++;
180
181                                         reading_status = 0;
182                                         continue;
183                                 }
184                         }
185
186                         /* skip until \n */
187                         while (strchr(buf, '\n') == NULL && !feof(fp))
188                                 fgets(buf, 128, fp);
189                 }
190
191                 fclose(fp);
192
193                 if (reading_status)
194                         info.new_mail_count++;
195
196                 last_mail_mtime = buf.st_mtime;
197         }
198 }