2 Copyright (C) 2001-2013 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
25 #include <sys/types.h>
41 #ifdef _POSIX2_LINE_MAX
42 #define LINE_MAX _POSIX2_LINE_MAX
49 #ifdef HAVE_SYS_MMAN_H
61 #define _PATH_MAILDIR "/var/mail"
69 #include "../strsep.c"
76 #define MAIL_OPTION_ORDER "smrfa"
77 #define MAIL_OPTION_STRING "Mfrsam"
79 static char options
[6]; /* NULL terminated. */
80 static char *aliasbuf
;
81 static char **strings
;
83 void add_string(char ***, const char *);
84 char *stamp(time_t, const char *);
85 char *safe_strncat(char *, const char *, size_t);
87 void ui_module_init(int *chainable
)
95 munmap(aliasbuf
, strlen(aliasbuf
));
100 /* Remove characters (rm) from string (str). */
101 static char *stripstr(char *str
, char *rm
)
103 static char buf
[LINE_MAX
];
107 if (rm
== NULL
|| str
== NULL
)
129 /* Return a string of mail aliases for the user. Looks in /etc/aliases (or
130 * whatever was specified at compile-time). The file is read into a buffer
131 * only once (mmap(2)). */
132 static char *mail_aliases(const char *user
, const int multi
)
135 static char aliases
[LINE_MAX
], *p
;
139 char m
[2] = { multi
, '\0' };
144 if ((!aliasbuf
&& firstrun
) || aliasbuf
== MAP_FAILED
)
150 if (stat(ALIAS_FILE
, &st
) == -1)
153 if ((fd
= open(ALIAS_FILE
, O_RDONLY
)) == -1)
156 if ((aliasbuf
= mmap(0, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
,
158 warn("%s", "mmap()");
165 for (i
= n
= 0; aliasbuf
[i
]; i
++) {
166 char *last
, *name
, *tmp
;
168 while (aliasbuf
[i
] != '\n')
169 t
[n
++] = aliasbuf
[i
++];
174 if (t
[0] == '#' || t
[0] == '\0')
179 if ((name
= strsep(&last
, ":")) == NULL
)
182 if (strcmp(user
, name
) == 0) {
183 while ((tmp
= strsep(&last
, ",")) != NULL
) {
184 tmp
= stripstr(tmp
, " \n\t");
186 safe_strncat(aliases
, tmp
, sizeof(aliases
));
187 safe_strncat(aliases
, m
, sizeof(aliases
));
193 while ((tmp
= strsep(&last
, ",")) != NULL
) {
194 tmp
= stripstr(tmp
, " \n\t");
196 if (strcmp(user
, tmp
) == 0) {
197 safe_strncat(aliases
, name
, sizeof(aliases
));
198 safe_strncat(aliases
, m
, sizeof(aliases
));
203 if (aliases
[0] == '\0')
206 aliases
[strlen(aliases
) - 1] = '\0';
212 /* Returns a string of forward aliases for the user. Reads ~/.forward if it
213 * exists and is readable. */
214 static char *forwards(const char *dir
, const int multi
)
217 char buf
[LINE_MAX
], *s
;
218 static char buf2
[LINE_MAX
];
220 char m
[2] = { multi
, '\0' };
222 snprintf(buf2
, sizeof(buf2
), "%s/.forward", dir
);
224 if ((fp
= fopen(buf2
, "r")) == NULL
) {
233 while ((s
= fgets(buf
, sizeof(buf
), fp
)) != NULL
) {
237 if (buf
[strlen(buf
) - 1] == '\n')
238 buf
[strlen(buf
) - 1] = '\0';
241 safe_strncat(buf2
, m
, sizeof(buf2
));
243 safe_strncat(buf2
, buf
, sizeof(buf2
));
255 /* /var/mail/username folder size in bytes. */
256 static char *foldersize(struct stat st
)
258 static char str
[33], *p
;
260 snprintf(str
, sizeof(str
), "%lu", (unsigned long) st
.st_size
);
265 /* This is output if the -h command line option is passed to the main program.
267 void ui_module_help()
269 printf(" Mail information [-M (-%s)]:\n", MAIL_OPTION_ORDER
);
270 printf("\t-f forwarding addresses\t");
271 printf("-a mail aliases\n");
272 printf("\t-r folder access (read) time\t");
273 printf("-m folder modification time\n");
274 printf("\t-s folder size\n\n");
277 /* This is the equivalent to main() only without argc and argv available. */
278 int ui_module_exec(char ***s
, const struct passwd
*pw
, const int multi_char
,
279 const int verbose
, char *tf
)
284 char folder
[PATH_MAX
];
288 snprintf(folder
, sizeof(folder
), "%s/%s", _PATH_MAILDIR
, pw
->pw_name
);
290 if (stat(folder
, &st
) != -1)
296 add_string(&strings
, (gotstat
) ? foldersize(st
) : "!");
299 add_string(&strings
, (gotstat
) ? stamp(st
.st_atime
, tf
) : "!");
302 add_string(&strings
, (gotstat
) ? stamp(st
.st_mtime
, tf
) : "!");
305 add_string(&strings
, forwards(pw
->pw_dir
, multi_char
));
308 add_string(&strings
, mail_aliases(pw
->pw_name
, multi_char
));
319 char *ui_module_options_init(char **defaults
)
322 return MAIL_OPTION_STRING
;
325 /* Check module option validity. */
326 int ui_module_options(int argc
, char **argv
)
331 while ((opt
= getopt(argc
, argv
, MAIL_OPTION_STRING
)) != -1) {
334 strncpy(options
, MAIL_OPTION_ORDER
, sizeof(options
));
343 warnx("mail: invalid option -- %c", optopt
);