Split conky.h into several smaller header files
[monky] / src / mail.c
1 /* Conky, a system monitor, based on torsmo
2  *
3  * Any original torsmo code is licensed under the BSD license
4  *
5  * All code written since the fork of torsmo is licensed under the GPL
6  *
7  * Please see COPYING for details
8  *
9  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
10  * Copyright (c) 2005-2008 Brenden Matthews, Philip Kovacs, et. al.
11  *      (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 #include <sys/stat.h>
29 #include <sys/time.h>
30
31 #include <dirent.h>
32 #include <errno.h>
33
34 #include "conky.h"
35
36 char *current_mail_spool;
37
38 void update_mail_count(struct local_mail_s *mail)
39 {
40         struct stat st;
41
42         if (mail == NULL) {
43                 return;
44         }
45
46         /* TODO: use that fine file modification notify on Linux 2.4 */
47
48         /* don't check mail so often (9.5s is minimum interval) */
49         if (current_update_time - mail->last_update < 9.5) {
50                 return;
51         } else {
52                 mail->last_update = current_update_time;
53         }
54
55         if (stat(mail->box, &st)) {
56                 static int rep;
57
58                 if (!rep) {
59                         ERR("can't stat %s: %s", mail->box, strerror(errno));
60                         rep = 1;
61                 }
62                 return;
63         }
64 #if HAVE_DIRENT_H
65         /* maildir format */
66         if (S_ISDIR(st.st_mode)) {
67                 DIR *dir;
68                 char *dirname;
69                 struct dirent *dirent;
70
71                 mail->mail_count = mail->new_mail_count = 0;
72                 dirname = (char *) malloc(sizeof(char) * (strlen(mail->box) + 5));
73                 if (!dirname) {
74                         ERR("malloc");
75                         return;
76                 }
77                 strcpy(dirname, mail->box);
78                 strcat(dirname, "/");
79                 /* checking the cur subdirectory */
80                 strcat(dirname, "cur");
81
82                 dir = opendir(dirname);
83                 if (!dir) {
84                         ERR("cannot open directory");
85                         free(dirname);
86                         return;
87                 }
88                 dirent = readdir(dir);
89                 while (dirent) {
90                         /* . and .. are skipped */
91                         if (dirent->d_name[0] != '.') {
92                                 mail->mail_count++;
93                         }
94                         dirent = readdir(dir);
95                 }
96                 closedir(dir);
97
98                 dirname[strlen(dirname) - 3] = '\0';
99                 strcat(dirname, "new");
100
101                 dir = opendir(dirname);
102                 if (!dir) {
103                         ERR("cannot open directory");
104                         free(dirname);
105                         return;
106                 }
107                 dirent = readdir(dir);
108                 while (dirent) {
109                         /* . and .. are skipped */
110                         if (dirent->d_name[0] != '.') {
111                                 mail->new_mail_count++;
112                                 mail->mail_count++;
113                         }
114                         dirent = readdir(dir);
115                 }
116                 closedir(dir);
117
118                 free(dirname);
119                 return;
120         }
121 #endif
122         /* mbox format */
123         if (st.st_mtime != mail->last_mtime) {
124                 /* yippee, modification time has changed, let's read mail count! */
125                 static int rep;
126                 FILE *fp;
127                 int reading_status = 0;
128
129                 /* could lock here but I don't think it's really worth it because
130                  * this isn't going to write mail spool */
131
132                 mail->new_mail_count = mail->mail_count = 0;
133
134                 fp = open_file(mail->box, &rep);
135                 if (!fp) {
136                         return;
137                 }
138
139                 /* NOTE: adds mail as new if there isn't Status-field at all */
140
141                 while (!feof(fp)) {
142                         char buf[128];
143
144                         if (fgets(buf, 128, fp) == NULL) {
145                                 break;
146                         }
147
148                         if (strncmp(buf, "From ", 5) == 0) {
149                                 /* ignore MAILER-DAEMON */
150                                 if (strncmp(buf + 5, "MAILER-DAEMON ", 14) != 0) {
151                                         mail->mail_count++;
152
153                                         if (reading_status) {
154                                                 mail->new_mail_count++;
155                                         } else {
156                                                 reading_status = 1;
157                                         }
158                                 }
159                         } else {
160                                 if (reading_status
161                                                 && strncmp(buf, "X-Mozilla-Status:", 17) == 0) {
162                                         /* check that mail isn't already read */
163                                         if (strchr(buf + 21, '0')) {
164                                                 mail->new_mail_count++;
165                                         }
166
167                                         reading_status = 0;
168                                         continue;
169                                 }
170                                 if (reading_status && strncmp(buf, "Status:", 7) == 0) {
171                                         /* check that mail isn't already read */
172                                         if (strchr(buf + 7, 'R') == NULL) {
173                                                 mail->new_mail_count++;
174                                         }
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
187                 fclose(fp);
188
189                 if (reading_status) {
190                         mail->new_mail_count++;
191                 }
192
193                 mail->last_mtime = st.st_mtime;
194         }
195 }