"Fossies" - the Fresh Open Source Software Archive

Member "userinfo-2.5/src/modules/mail.c" (15 Jan 2015, 7153 Bytes) of package /linux/privat/userinfo-2.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mail.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4_vs_2.5.

    1 /*
    2     Copyright (C) 2001-2015 Ben Kibbey <bjk@luxsci.net>
    3 
    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.
    8 
    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.
   13 
   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
   17 */
   18 #ifdef HAVE_CONFIG_H
   19 #include <config.h>
   20 #endif
   21 
   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>
   29 
   30 #ifdef HAVE_FCNTL_H
   31 #include <fcntl.h>
   32 #endif
   33 
   34 #ifdef HAVE_STRING_H
   35 #include <string.h>
   36 #endif
   37 
   38 #ifdef HAVE_LIMITS_H
   39 #include <limits.h>
   40 #ifndef LINE_MAX
   41 #ifdef _POSIX2_LINE_MAX
   42 #define LINE_MAX _POSIX2_LINE_MAX
   43 #else
   44 #define LINE_MAX 2048
   45 #endif
   46 #endif
   47 #endif
   48 
   49 #ifdef HAVE_SYS_MMAN_H
   50 #include <sys/mman.h>
   51 #endif
   52 
   53 #ifdef HAVE_ERR_H
   54 #include <err.h>
   55 #endif
   56 
   57 #ifdef HAVE_PATHS_H
   58 #include <paths.h>
   59 #endif
   60 #ifndef _PATH_MAILDIR
   61 #define _PATH_MAILDIR       "/var/mail"
   62 #endif
   63 
   64 #ifndef HAVE_ERR_H
   65 #include "../err.c"
   66 #endif
   67 
   68 #ifndef HAVE_STRSEP
   69 #include "../strsep.c"
   70 #endif
   71 
   72 #ifdef WITH_DMALLOC
   73 #include <dmalloc.h>
   74 #endif
   75 
   76 #define MAIL_OPTION_ORDER   "smrfa"
   77 #define MAIL_OPTION_STRING  "Mfrsam"
   78 
   79 static char options[6];     /* NULL terminated. */
   80 static char *aliasbuf;
   81 static char **strings;
   82 
   83 void add_string(char ***, const char *);
   84 char *stamp(time_t, const char *);
   85 char *safe_strncat(char *, const char *, size_t);
   86 
   87 void ui_module_init(int *chainable)
   88 {
   89     *chainable = 0;
   90 }
   91 
   92 void ui_module_exit()
   93 {
   94     if (aliasbuf)
   95     munmap(aliasbuf, strlen(aliasbuf));
   96 
   97     aliasbuf = NULL;
   98 }
   99 
  100 /* Remove characters (rm) from string (str). */
  101 static char *stripstr(char *str, char *rm)
  102 {
  103     static char buf[LINE_MAX];
  104     char *orm;
  105     int i = 0;
  106 
  107     if (rm == NULL || str == NULL)
  108     return str;
  109 
  110     while (*str) {
  111     orm = rm;
  112 
  113     while (*orm) {
  114         if (*str == *orm) {
  115         str++;
  116         continue;
  117         }
  118 
  119         orm++;
  120     }
  121 
  122     buf[i++] = *str++;
  123     }
  124 
  125     buf[i] = '\0';
  126     return buf;
  127 }
  128 
  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)
  133 {
  134     char t[LINE_MAX];
  135     static char aliases[LINE_MAX], *p;
  136     static int firstrun;
  137     int i, n;
  138     struct stat st;
  139     char m[2] = { multi, '\0' };
  140     int fd;
  141 
  142     aliases[0] = '\0';
  143 
  144     if ((!aliasbuf && firstrun) || aliasbuf == MAP_FAILED)
  145     return "!";
  146 
  147     if (!aliasbuf) {
  148     firstrun = 1;
  149 
  150     if (stat(ALIAS_FILE, &st) == -1)
  151         return "!";
  152 
  153     if ((fd = open(ALIAS_FILE, O_RDONLY)) == -1)
  154         return "!";
  155 
  156     if ((aliasbuf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd,
  157                  0)) == MAP_FAILED) {
  158         warn("%s", "mmap()");
  159             close (fd);
  160         return "!";
  161     }
  162 
  163     close(fd);
  164     }
  165 
  166     for (i = n = 0; aliasbuf[i]; i++) {
  167     char *last, *name, *tmp;
  168 
  169     while (aliasbuf[i] != '\n')
  170         t[n++] = aliasbuf[i++];
  171 
  172     t[n] = 0;
  173     n = 0;
  174 
  175     if (t[0] == '#' || t[0] == '\0')
  176         continue;
  177 
  178     last = t;
  179 
  180     if ((name = strsep(&last, ":")) == NULL)
  181         continue;
  182 
  183     if (strcmp(user, name) == 0) {
  184         while ((tmp = strsep(&last, ",")) != NULL) {
  185         tmp = stripstr(tmp, " \n\t");
  186 
  187         safe_strncat(aliases, tmp, sizeof(aliases));
  188         safe_strncat(aliases, m, sizeof(aliases));
  189         }
  190 
  191         continue;
  192     }
  193 
  194     while ((tmp = strsep(&last, ",")) != NULL) {
  195         tmp = stripstr(tmp, " \n\t");
  196 
  197         if (strcmp(user, tmp) == 0) {
  198         safe_strncat(aliases, name, sizeof(aliases));
  199         safe_strncat(aliases, m, sizeof(aliases));
  200         }
  201     }
  202     }
  203 
  204     if (aliases[0] == '\0')
  205     return "-";
  206     else
  207     aliases[strlen(aliases) - 1] = '\0';
  208 
  209     p = aliases;
  210     return p;
  211 }
  212 
  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)
  216 {
  217     FILE *fp;
  218     char buf[LINE_MAX], *s;
  219     static char buf2[LINE_MAX];
  220     int n = 0;
  221     char m[2] = { multi, '\0' };
  222 
  223     snprintf(buf2, sizeof(buf2), "%s/.forward", dir);
  224 
  225     if ((fp = fopen(buf2, "r")) == NULL) {
  226     if (errno == ENOENT)
  227         return "-";
  228     else
  229         return "!";
  230     }
  231 
  232     buf2[0] = '\0';
  233 
  234     while ((s = fgets(buf, sizeof(buf), fp)) != NULL) {
  235     if (buf[0] == '\n')
  236         continue;
  237 
  238     if (buf[strlen(buf) - 1] == '\n')
  239         buf[strlen(buf) - 1] = '\0';
  240 
  241     if (n++)
  242         safe_strncat(buf2, m, sizeof(buf2));
  243 
  244     safe_strncat(buf2, buf, sizeof(buf2));
  245     }
  246 
  247     fclose(fp);
  248 
  249     if (!n)
  250     return "-";
  251 
  252     s = buf2;
  253     return s;
  254 }
  255 
  256 /* /var/mail/username folder size in bytes. */
  257 static char *foldersize(struct stat *st)
  258 {
  259     static char str[33], *p;
  260 
  261     snprintf(str, sizeof(str), "%lu", (unsigned long) st->st_size);
  262     p = str;
  263     return p;
  264 }
  265 
  266 /* This is output if the -h command line option is passed to the main program.
  267  */
  268 void ui_module_help()
  269 {
  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");
  276 }
  277 
  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)
  281 {
  282     char *p = options;
  283     int gotstat = 0;
  284     struct stat st;
  285     char folder[PATH_MAX];
  286 
  287     strings = *s;
  288     folder[0] = '\0';
  289     snprintf(folder, sizeof(folder), "%s/%s", _PATH_MAILDIR, pw->pw_name);
  290 
  291     if (stat(folder, &st) != -1)
  292     gotstat = 1;
  293 
  294     for (; *p; p++) {
  295     switch (*p) {
  296         case 's':
  297         add_string(&strings, (gotstat) ? foldersize(&st) : "!");
  298         break;
  299         case 'r':
  300         add_string(&strings, (gotstat) ? stamp(st.st_atime, tf) : "!");
  301         break;
  302         case 'm':
  303         add_string(&strings, (gotstat) ? stamp(st.st_mtime, tf) : "!");
  304         break;
  305         case 'f':
  306         add_string(&strings, forwards(pw->pw_dir, multi_char));
  307         break;
  308         case 'a':
  309         add_string(&strings, mail_aliases(pw->pw_name, multi_char));
  310         break;
  311         default:
  312         break;
  313     }
  314     }
  315 
  316     *s = strings;
  317     return EXIT_SUCCESS;
  318 }
  319 
  320 char *ui_module_options_init(char **defaults)
  321 {
  322     *defaults = "M";
  323     return MAIL_OPTION_STRING;
  324 }
  325 
  326 /* Check module option validity. */
  327 int ui_module_options(int argc, char **argv)
  328 {
  329     int opt;
  330     char *p = options;
  331 
  332     while ((opt = getopt(argc, argv, MAIL_OPTION_STRING)) != -1) {
  333     switch (opt) {
  334         case 'M':
  335         strncpy(options, MAIL_OPTION_ORDER, sizeof(options));
  336         return 0;
  337         case 'f':
  338         case 's':
  339         case 'r':
  340         case 'm':
  341         case 'a':
  342         break;
  343         case '?':
  344         warnx("mail: invalid option -- %c", optopt);
  345         default:
  346         return 1;
  347     }
  348 
  349     *p++ = opt;
  350     *p = '\0';
  351     }
  352 
  353     return 0;
  354 }