Fix compile time warning.
[userinfo.git] / src / modules / mail.c
blobe82cfd73a27e9c29001aeac3b0ed687aba0c223d
1 /*
2 Copyright (C) 2001-2011 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 02110-1301 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 #ifdef WITH_DMALLOC
66 #include <dmalloc.h>
67 #endif
69 #define MAIL_OPTION_ORDER "smrfa"
70 #define MAIL_OPTION_STRING "Mfrsam"
72 static char options[6]; /* NULL terminated. */
73 static char *aliasbuf;
74 static char **strings;
76 void add_string(char ***, const char *);
77 char *stamp(time_t, const char *);
78 char *safe_strncat(char *, const char *, size_t);
80 void ui_module_init(int *chainable)
82 *chainable = 0;
85 void ui_module_exit()
87 if (aliasbuf)
88 munmap(aliasbuf, strlen(aliasbuf));
90 aliasbuf = NULL;
93 /* Remove characters (rm) from string (str). */
94 static char *stripstr(char *str, char *rm)
96 static char buf[LINE_MAX];
97 char *orm;
98 int i = 0;
100 if (rm == NULL || str == NULL)
101 return str;
103 while (*str) {
104 orm = rm;
106 while (*orm) {
107 if (*str == *orm) {
108 str++;
109 continue;
112 orm++;
115 buf[i++] = *str++;
118 buf[i] = '\0';
119 return buf;
122 /* Return a string of mail aliases for the user. Looks in /etc/aliases (or
123 * whatever was specified at compile-time). The file is read into a buffer
124 * only once (mmap(2)). */
125 static char *mail_aliases(const char *user, const int multi)
127 char t[LINE_MAX];
128 static char aliases[LINE_MAX], *p;
129 static int firstrun;
130 int i, n;
131 struct stat st;
132 char m[2] = { multi, '\0' };
133 int fd;
135 aliases[0] = '\0';
137 if ((!aliasbuf && firstrun) || aliasbuf == MAP_FAILED)
138 return "!";
140 if (!aliasbuf) {
141 firstrun = 1;
143 if (stat(ALIAS_FILE, &st) == -1)
144 return "!";
146 if ((fd = open(ALIAS_FILE, O_RDONLY)) == -1)
147 return "!";
149 if ((aliasbuf = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd,
150 0)) == MAP_FAILED) {
151 warn("%s", "mmap()");
152 return "!";
155 close(fd);
158 for (i = n = 0; aliasbuf[i]; i++) {
159 char *last, *name, *tmp;
161 while (aliasbuf[i] != '\n')
162 t[n++] = aliasbuf[i++];
164 t[n] = 0;
165 n = 0;
167 if (t[0] == '#' || t[0] == '\0')
168 continue;
170 last = t;
172 if ((name = strsep(&last, ":")) == NULL)
173 continue;
175 if (strcmp(user, name) == 0) {
176 while ((tmp = strsep(&last, ",")) != NULL) {
177 tmp = stripstr(tmp, " \n\t");
179 safe_strncat(aliases, tmp, sizeof(aliases));
180 safe_strncat(aliases, m, sizeof(aliases));
183 continue;
186 while ((tmp = strsep(&last, ",")) != NULL) {
187 tmp = stripstr(tmp, " \n\t");
189 if (strcmp(user, tmp) == 0) {
190 safe_strncat(aliases, name, sizeof(aliases));
191 safe_strncat(aliases, m, sizeof(aliases));
196 if (aliases[0] == '\0')
197 return "-";
198 else
199 aliases[strlen(aliases) - 1] = '\0';
201 p = aliases;
202 return p;
205 /* Returns a string of forward aliases for the user. Reads ~/.forward if it
206 * exists and is readable. */
207 static char *forwards(const char *dir, const int multi)
209 FILE *fp;
210 char buf[LINE_MAX], *s;
211 static char buf2[LINE_MAX];
212 int n = 0;
213 char m[2] = { multi, '\0' };
215 snprintf(buf2, sizeof(buf2), "%s/.forward", dir);
217 if ((fp = fopen(buf2, "r")) == NULL) {
218 if (errno == ENOENT)
219 return "-";
220 else
221 return "!";
224 buf2[0] = '\0';
226 while ((s = fgets(buf, sizeof(buf), fp)) != NULL) {
227 if (buf[0] == '\n')
228 continue;
230 if (buf[strlen(buf) - 1] == '\n')
231 buf[strlen(buf) - 1] = '\0';
233 if (n++)
234 safe_strncat(buf2, m, sizeof(buf2));
236 safe_strncat(buf2, buf, sizeof(buf2));
239 fclose(fp);
241 if (!n)
242 return "-";
244 s = buf2;
245 return s;
248 /* /var/mail/username folder size in bytes. */
249 static char *foldersize(struct stat st)
251 static char str[33], *p;
253 snprintf(str, sizeof(str), "%lu", (unsigned long) st.st_size);
254 p = str;
255 return p;
258 /* This is output if the -h command line option is passed to the main program.
260 void ui_module_help()
262 printf(" Mail information [-M (-%s)]:\n", MAIL_OPTION_ORDER);
263 printf("\t-f forwarding addresses\t");
264 printf("-a mail aliases\n");
265 printf("\t-r folder access (read) time\t");
266 printf("-m folder modification time\n");
267 printf("\t-s folder size\n\n");
270 /* This is the equivalent to main() only without argc and argv available. */
271 int ui_module_exec(char ***s, const struct passwd *pw, const int multi_char,
272 const int verbose, char *tf)
274 char *p = options;
275 int gotstat = 0;
276 struct stat st;
277 char folder[PATH_MAX];
279 strings = *s;
280 folder[0] = '\0';
281 snprintf(folder, sizeof(folder), "%s/%s", _PATH_MAILDIR, pw->pw_name);
283 if (stat(folder, &st) != -1)
284 gotstat = 1;
286 for (; *p; p++) {
287 switch (*p) {
288 case 's':
289 add_string(&strings, (gotstat) ? foldersize(st) : "!");
290 break;
291 case 'r':
292 add_string(&strings, (gotstat) ? stamp(st.st_atime, tf) : "!");
293 break;
294 case 'm':
295 add_string(&strings, (gotstat) ? stamp(st.st_mtime, tf) : "!");
296 break;
297 case 'f':
298 add_string(&strings, forwards(pw->pw_dir, multi_char));
299 break;
300 case 'a':
301 add_string(&strings, mail_aliases(pw->pw_name, multi_char));
302 break;
303 default:
304 break;
308 *s = strings;
309 return EXIT_SUCCESS;
312 char *ui_module_options_init(char **defaults)
314 *defaults = "M";
315 return MAIL_OPTION_STRING;
318 /* Check module option validity. */
319 int ui_module_options(int argc, char **argv)
321 int opt;
322 char *p = options;
324 while ((opt = getopt(argc, argv, MAIL_OPTION_STRING)) != -1) {
325 switch (opt) {
326 case 'M':
327 strncpy(options, MAIL_OPTION_ORDER, sizeof(options));
328 return 0;
329 case 'f':
330 case 's':
331 case 'r':
332 case 'm':
333 case 'a':
334 break;
335 case '?':
336 warnx("mail: invalid option -- %c", optopt);
337 default:
338 return 1;
341 *p++ = opt;
342 *p = '\0';
345 return 0;