Changed follow-symlink option -l to -L.
[userinfo.git] / src / modules / mail.c
blobf7c0b6be07f6aaadc371a9e40eec23353b75c6cb
1 /* $Id: mail.c,v 1.4 2006-01-21 22:56:04 bjk Exp $ */
2 /*
3 Copyright (C) 2001-2005 Ben Kibbey <bjk@arbornet.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <errno.h>
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include "mail.h"
32 #ifndef HAVE_ERR_H
33 #include "../err.c"
34 #endif
36 #ifndef HAVE_STRSEP
37 #include "../strsep.c"
38 #endif
40 void ui_module_init(int *chainable)
42 #ifdef DEBUG
43 fprintf(stderr, "%s: ui_module_init()\n", __FILE__);
44 #endif
46 *chainable = 0;
47 return;
50 void ui_module_exit()
52 #ifdef DEBUG
53 fprintf(stderr, "%s: ui_module_exit()\n", __FILE__);
54 #endif
56 if (aliasbuf)
57 munmap(aliasbuf, strlen(aliasbuf));
59 aliasbuf = NULL;
60 return;
63 /* Remove characters (rm) from string (str). */
64 static char *stripstr(char *str, char *rm)
66 static char buf[LINE_MAX];
67 char *orm;
68 int i = 0, c;
70 if (rm == NULL || str == NULL)
71 return str;
73 while (*str) {
74 orm = rm;
76 while (*orm) {
77 if (*str == *orm) {
78 c = *str++;
79 continue;
82 c = *orm++;
85 buf[i++] = *str++;
88 buf[i] = '\0';
89 return buf;
92 /* Return a string of mail aliases for the user. Looks in /etc/aliases (or
93 * whatever was specified at compile-time). The file is read into a buffer
94 * only once (mmap(2)). */
95 static char *mail_aliases(const char *user, const int multi)
97 char t[LINE_MAX];
98 static char aliases[LINE_MAX], *p;
99 static int firstrun;
100 int i, n;
101 struct stat st;
102 char m[2] = { multi, '\0' };
103 int fd;
105 aliases[0] = '\0';
107 if ((!aliasbuf && firstrun) || aliasbuf == MAP_FAILED)
108 return "!";
110 if (!aliasbuf) {
111 firstrun = 1;
113 if (stat(ALIAS_FILE, &st) == -1)
114 return "!";
116 if ((fd = open(ALIAS_FILE, O_RDONLY)) == -1)
117 return "!";
119 if ((aliasbuf = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd,
120 0)) == MAP_FAILED) {
121 warn("%s", "mmap()");
122 return "!";
125 close(fd);
128 for (i = n = 0; aliasbuf[i]; i++) {
129 char *last, *name, *tmp;
131 while (aliasbuf[i] != '\n')
132 t[n++] = aliasbuf[i++];
134 t[n] = 0;
135 n = 0;
137 if (t[0] == '#' || t[0] == '\0')
138 continue;
140 last = t;
142 if ((name = strsep(&last, ":")) == NULL)
143 continue;
145 if (strcmp(user, name) == 0) {
146 while ((tmp = strsep(&last, ",")) != NULL) {
147 tmp = stripstr(tmp, " \n\t");
149 strncat(aliases, tmp, sizeof(aliases));
150 strncat(aliases, m, sizeof(aliases));
153 continue;
156 while ((tmp = strsep(&last, ",")) != NULL) {
157 tmp = stripstr(tmp, " \n\t");
159 if (strcmp(user, tmp) == 0) {
160 strncat(aliases, name, sizeof(aliases));
161 strncat(aliases, m, sizeof(aliases));
166 if (aliases[0] == '\0')
167 return "-";
168 else
169 aliases[strlen(aliases) - 1] = '\0';
171 p = aliases;
172 return p;
175 /* Returns a string of forward aliases for the user. Reads ~/.forward if it
176 * exists and is readable. */
177 static char *forwards(const char *dir, const int multi)
179 FILE *fp;
180 char buf[LINE_MAX], *s;
181 static char buf2[FILENAME_MAX];
182 int n = 0;
183 char m[2] = { multi, '\0' };
185 buf[0] = buf2[0] = '\0';
186 snprintf(buf2, sizeof(buf2), "%s/.forward", dir);
188 if ((fp = fopen(buf2, "r")) == NULL) {
189 if (errno == ENOENT)
190 return "-";
191 else
192 return "!";
195 buf2[0] = '\0';
197 while ((s = fgets(buf, sizeof(buf), fp)) != NULL) {
198 if (buf[0] == '\n')
199 continue;
201 if (buf[strlen(buf) - 1] == '\n')
202 buf[strlen(buf) - 1] = '\0';
204 if (n++)
205 strncat(buf2, m, sizeof(buf2));
207 strncat(buf2, buf, sizeof(buf2));
210 fclose(fp);
212 if (!n)
213 return "-";
215 s = buf2;
216 return s;
219 /* /var/mail/username folder size in bytes. */
220 static char *foldersize(struct stat st)
222 static char str[33], *p;
224 str[0] = '\0';
226 snprintf(str, sizeof(str), "%lu", (unsigned long) st.st_size);
227 p = str;
228 return p;
231 /* This is output if the -h command line option is passed to the main program.
233 void ui_module_help()
235 #ifdef DEBUG
236 fprintf(stderr, "%s: ui_module_help()\n", __FILE__);
237 #endif
239 printf(" Mail information [-M (-%s)]:\n", MAIL_OPTION_ORDER);
240 printf("\t-f forwarding addresses\t");
241 printf("-a mail aliases\n");
242 printf("\t-r folder access (read) time\t");
243 printf("-m folder modification time\n");
244 printf("\t-s folder size\n\n");
245 return;
248 /* This is the equivalent to main() only without argc and argv available. */
249 int ui_module_exec(char ***s, const struct passwd *pw, const int multi_char,
250 const int verbose, char *tf)
252 char *p = options;
253 int gotstat = 0;
254 struct stat st;
255 char folder[FILENAME_MAX];
257 strings = *s;
258 folder[0] = '\0';
259 snprintf(folder, sizeof(folder), "%s/%s", _PATH_MAILDIR, pw->pw_name);
261 if (stat(folder, &st) != -1)
262 gotstat = 1;
264 while (*p) {
265 switch (*p) {
266 case 's':
267 add_string(&strings, (gotstat) ? foldersize(st) : "!");
268 break;
269 case 'r':
270 add_string(&strings, (gotstat) ? stamp(st.st_atime, tf) : "!");
271 break;
272 case 'm':
273 add_string(&strings, (gotstat) ? stamp(st.st_mtime, tf) : "!");
274 break;
275 case 'f':
276 add_string(&strings, forwards(pw->pw_dir, multi_char));
277 break;
278 case 'a':
279 add_string(&strings, mail_aliases(pw->pw_name, multi_char));
280 break;
281 default:
282 break;
285 p++;
288 *s = strings;
289 return EXIT_SUCCESS;
292 char *ui_module_options_init(char **defaults)
294 *defaults = "M";
295 return MAIL_OPTION_STRING;
298 /* Check module option validity. */
299 int ui_module_options(int argc, char **argv)
301 int opt;
302 char *p = options;
304 #ifdef DEBUG
305 fprintf(stderr, "%s: ui_module_options()\n", __FILE__);
306 #endif
308 while ((opt = getopt(argc, argv, MAIL_OPTION_STRING)) != -1) {
309 switch (opt) {
310 case 'f':
311 case 's':
312 case 'r':
313 case 'm':
314 case 'a':
315 case 'M':
316 break;
317 case '?':
318 warnx("mail: invalid option -- %c", optopt);
319 default:
320 return 1;
324 * This option '-M' sets all available options for this module.
326 if (opt == 'M') {
327 strncpy(options, MAIL_OPTION_ORDER, sizeof(options));
328 break;
331 *p++ = opt;
332 *p = '\0';
335 return 0;