Remove DEBUG lines.
[userinfo.git] / src / modules / mail.c
blob73d2cfd05218636b7969dd8f768ba37cc3579b34
1 /*
2 Copyright (C) 2001-2006 Ben Kibbey <bjk@luxsci.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <errno.h>
28 #include <pwd.h>
30 #ifdef HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
34 #ifdef HAVE_STRING_H
35 #include <string.h>
36 #endif
38 #ifdef HAVE_LIMITS_H
39 #include <limits.h>
40 #endif
42 #ifdef HAVE_SYS_MMAN_H
43 #include <sys/mman.h>
44 #endif
46 #ifdef HAVE_ERR_H
47 #include <err.h>
48 #endif
50 #ifdef HAVE_PATHS_H
51 #include <paths.h>
52 #endif
53 #ifndef _PATH_MAILDIR
54 #define _PATH_MAILDIR "/var/mail"
55 #endif
57 #ifndef HAVE_ERR_H
58 #include "../err.c"
59 #endif
61 #ifndef HAVE_STRSEP
62 #include "../strsep.c"
63 #endif
65 #include "common.h"
67 #ifdef WITH_DMALLOC
68 #include <dmalloc.h>
69 #endif
71 #define MAIL_OPTION_ORDER "smrfa"
72 #define MAIL_OPTION_STRING "Mfrsam"
74 static char options[6]; /* NULL terminated. */
75 static char *aliasbuf;
76 static char **strings;
78 void add_string(char ***, const char *);
79 char *stamp(time_t, const char *);
81 void ui_module_init(int *chainable)
83 *chainable = 0;
86 void ui_module_exit()
88 if (aliasbuf)
89 munmap(aliasbuf, strlen(aliasbuf));
91 aliasbuf = NULL;
94 /* Remove characters (rm) from string (str). */
95 static char *stripstr(char *str, char *rm)
97 static char buf[LINE_MAX];
98 char *orm;
99 int i = 0, c;
101 if (rm == NULL || str == NULL)
102 return str;
104 while (*str) {
105 orm = rm;
107 while (*orm) {
108 if (*str == *orm) {
109 c = *str++;
110 continue;
113 c = *orm++;
116 buf[i++] = *str++;
119 buf[i] = '\0';
120 return buf;
123 /* Return a string of mail aliases for the user. Looks in /etc/aliases (or
124 * whatever was specified at compile-time). The file is read into a buffer
125 * only once (mmap(2)). */
126 static char *mail_aliases(const char *user, const int multi)
128 char t[LINE_MAX];
129 static char aliases[LINE_MAX], *p;
130 static int firstrun;
131 int i, n;
132 struct stat st;
133 char m[2] = { multi, '\0' };
134 int fd;
136 aliases[0] = '\0';
138 if ((!aliasbuf && firstrun) || aliasbuf == MAP_FAILED)
139 return "!";
141 if (!aliasbuf) {
142 firstrun = 1;
144 if (stat(ALIAS_FILE, &st) == -1)
145 return "!";
147 if ((fd = open(ALIAS_FILE, O_RDONLY)) == -1)
148 return "!";
150 if ((aliasbuf = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd,
151 0)) == MAP_FAILED) {
152 warn("%s", "mmap()");
153 return "!";
156 close(fd);
159 for (i = n = 0; aliasbuf[i]; i++) {
160 char *last, *name, *tmp;
162 while (aliasbuf[i] != '\n')
163 t[n++] = aliasbuf[i++];
165 t[n] = 0;
166 n = 0;
168 if (t[0] == '#' || t[0] == '\0')
169 continue;
171 last = t;
173 if ((name = strsep(&last, ":")) == NULL)
174 continue;
176 if (strcmp(user, name) == 0) {
177 while ((tmp = strsep(&last, ",")) != NULL) {
178 tmp = stripstr(tmp, " \n\t");
180 safe_strncat(aliases, tmp, sizeof(aliases));
181 safe_strncat(aliases, m, sizeof(aliases));
184 continue;
187 while ((tmp = strsep(&last, ",")) != NULL) {
188 tmp = stripstr(tmp, " \n\t");
190 if (strcmp(user, tmp) == 0) {
191 safe_strncat(aliases, name, sizeof(aliases));
192 safe_strncat(aliases, m, sizeof(aliases));
197 if (aliases[0] == '\0')
198 return "-";
199 else
200 aliases[strlen(aliases) - 1] = '\0';
202 p = aliases;
203 return p;
206 /* Returns a string of forward aliases for the user. Reads ~/.forward if it
207 * exists and is readable. */
208 static char *forwards(const char *dir, const int multi)
210 FILE *fp;
211 char buf[LINE_MAX], *s;
212 static char buf2[LINE_MAX];
213 int n = 0;
214 char m[2] = { multi, '\0' };
216 snprintf(buf2, sizeof(buf2), "%s/.forward", dir);
218 if ((fp = fopen(buf2, "r")) == NULL) {
219 if (errno == ENOENT)
220 return "-";
221 else
222 return "!";
225 buf2[0] = '\0';
227 while ((s = fgets(buf, sizeof(buf), fp)) != NULL) {
228 if (buf[0] == '\n')
229 continue;
231 if (buf[strlen(buf) - 1] == '\n')
232 buf[strlen(buf) - 1] = '\0';
234 if (n++)
235 safe_strncat(buf2, m, sizeof(buf2));
237 safe_strncat(buf2, buf, sizeof(buf2));
240 fclose(fp);
242 if (!n)
243 return "-";
245 s = buf2;
246 return s;
249 /* /var/mail/username folder size in bytes. */
250 static char *foldersize(struct stat st)
252 static char str[33], *p;
254 snprintf(str, sizeof(str), "%lu", (unsigned long) st.st_size);
255 p = str;
256 return p;
259 /* This is output if the -h command line option is passed to the main program.
261 void ui_module_help()
263 printf(" Mail information [-M (-%s)]:\n", MAIL_OPTION_ORDER);
264 printf("\t-f forwarding addresses\t");
265 printf("-a mail aliases\n");
266 printf("\t-r folder access (read) time\t");
267 printf("-m folder modification time\n");
268 printf("\t-s folder size\n\n");
271 /* This is the equivalent to main() only without argc and argv available. */
272 int ui_module_exec(char ***s, const struct passwd *pw, const int multi_char,
273 const int verbose, char *tf)
275 char *p = options;
276 int gotstat = 0;
277 struct stat st;
278 char folder[FILENAME_MAX];
280 strings = *s;
281 folder[0] = '\0';
282 snprintf(folder, sizeof(folder), "%s/%s", _PATH_MAILDIR, pw->pw_name);
284 if (stat(folder, &st) != -1)
285 gotstat = 1;
287 for (; *p; p++) {
288 switch (*p) {
289 case 's':
290 add_string(&strings, (gotstat) ? foldersize(st) : "!");
291 break;
292 case 'r':
293 add_string(&strings, (gotstat) ? stamp(st.st_atime, tf) : "!");
294 break;
295 case 'm':
296 add_string(&strings, (gotstat) ? stamp(st.st_mtime, tf) : "!");
297 break;
298 case 'f':
299 add_string(&strings, forwards(pw->pw_dir, multi_char));
300 break;
301 case 'a':
302 add_string(&strings, mail_aliases(pw->pw_name, multi_char));
303 break;
304 default:
305 break;
309 *s = strings;
310 return EXIT_SUCCESS;
313 char *ui_module_options_init(char **defaults)
315 *defaults = "M";
316 return MAIL_OPTION_STRING;
319 /* Check module option validity. */
320 int ui_module_options(int argc, char **argv)
322 int opt;
323 char *p = options;
325 while ((opt = getopt(argc, argv, MAIL_OPTION_STRING)) != -1) {
326 switch (opt) {
327 case 'M':
328 strncpy(options, MAIL_OPTION_ORDER, sizeof(options));
329 return 0;
330 case 'f':
331 case 's':
332 case 'r':
333 case 'm':
334 case 'a':
335 break;
336 case '?':
337 warnx("mail: invalid option -- %c", optopt);
338 default:
339 return 1;
342 *p++ = opt;
343 *p = '\0';
346 return 0;