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(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
,
158 warn("%s", "mmap()");
166 for (i
= n
= 0; aliasbuf
[i
]; i
++) {
167 char *last
, *name
, *tmp
;
169 while (aliasbuf
[i
] != '\n')
170 t
[n
++] = aliasbuf
[i
++];
175 if (t
[0] == '#' || t
[0] == '\0')
180 if ((name
= strsep(&last
, ":")) == NULL
)
183 if (strcmp(user
, name
) == 0) {
184 while ((tmp
= strsep(&last
, ",")) != NULL
) {
185 tmp
= stripstr(tmp
, " \n\t");
187 safe_strncat(aliases
, tmp
, sizeof(aliases
));
188 safe_strncat(aliases
, m
, sizeof(aliases
));
194 while ((tmp
= strsep(&last
, ",")) != NULL
) {
195 tmp
= stripstr(tmp
, " \n\t");
197 if (strcmp(user
, tmp
) == 0) {
198 safe_strncat(aliases
, name
, sizeof(aliases
));
199 safe_strncat(aliases
, m
, sizeof(aliases
));
204 if (aliases
[0] == '\0')
207 aliases
[strlen(aliases
) - 1] = '\0';
213 /* Returns a string of forward aliases for the user. Reads ~/.forward if it
214 * exists and is readable. */
215 static char *forwards(const char *dir
, const int multi
)
218 char buf
[LINE_MAX
], *s
;
219 static char buf2
[LINE_MAX
];
221 char m
[2] = { multi
, '\0' };
223 snprintf(buf2
, sizeof(buf2
), "%s/.forward", dir
);
225 if ((fp
= fopen(buf2
, "r")) == NULL
) {
234 while ((s
= fgets(buf
, sizeof(buf
), fp
)) != NULL
) {
238 if (buf
[strlen(buf
) - 1] == '\n')
239 buf
[strlen(buf
) - 1] = '\0';
242 safe_strncat(buf2
, m
, sizeof(buf2
));
244 safe_strncat(buf2
, buf
, sizeof(buf2
));
256 /* /var/mail/username folder size in bytes. */
257 static char *foldersize(struct stat
*st
)
259 static char str
[33], *p
;
261 snprintf(str
, sizeof(str
), "%lu", (unsigned long) st
->st_size
);
266 /* This is output if the -h command line option is passed to the main program.
268 void ui_module_help()
270 printf(" Mail information [-M (-%s)]:\n", MAIL_OPTION_ORDER
);
271 printf("\t-f forwarding addresses\t");
272 printf("-a mail aliases\n");
273 printf("\t-r folder access (read) time\t");
274 printf("-m folder modification time\n");
275 printf("\t-s folder size\n\n");
278 /* This is the equivalent to main() only without argc and argv available. */
279 int ui_module_exec(char ***s
, const struct passwd
*pw
, const int multi_char
,
280 const int verbose
, char *tf
)
285 char folder
[PATH_MAX
];
289 snprintf(folder
, sizeof(folder
), "%s/%s", _PATH_MAILDIR
, pw
->pw_name
);
291 if (stat(folder
, &st
) != -1)
297 add_string(&strings
, (gotstat
) ? foldersize(&st
) : "!");
300 add_string(&strings
, (gotstat
) ? stamp(st
.st_atime
, tf
) : "!");
303 add_string(&strings
, (gotstat
) ? stamp(st
.st_mtime
, tf
) : "!");
306 add_string(&strings
, forwards(pw
->pw_dir
, multi_char
));
309 add_string(&strings
, mail_aliases(pw
->pw_name
, multi_char
));
320 char *ui_module_options_init(char **defaults
)
323 return MAIL_OPTION_STRING
;
326 /* Check module option validity. */
327 int ui_module_options(int argc
, char **argv
)
332 while ((opt
= getopt(argc
, argv
, MAIL_OPTION_STRING
)) != -1) {
335 strncpy(options
, MAIL_OPTION_ORDER
, sizeof(options
));
344 warnx("mail: invalid option -- %c", optopt
);