Logo Search packages:      
Sourcecode: mailavenger version File versions  Download package

aliascheck.c

/* $Id$ */

/*
 *
 * Copyright (C) 2004 David Mazieres (dm@uun.org)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */

#include "avutil.h"
#include "db.h"
#include <ctype.h>
#include <pwd.h>
#include "getopt_long.h"

int check_alias_dbm (const char *file, const char *user, int map);

char *progname;

static inline int
checkfile (const char *file)
{
  struct stat sb;
  if (stat (file, &sb) || !S_ISREG (sb.st_mode))
    return -1;
  return 0;
}

static char *
dotqmail (const char *user, int nchop)
{
  static const char dqm[] = ".qmail-";
  static const char def[] = "default";
  char *p;
  char *res;

  res = xmalloc (sizeof (dqm) + sizeof (def) + strlen (user));
  strcpy (res, dqm);
  strcat (res, user);

  for (p = res + strlen (res); nchop > 0; nchop--) {
    *p = '\0';
    p = strrchr (res, '-');
    if (!p || !*p)
      return NULL;
  }
  if (*p)
    strcpy (p + 1, def);
  return res;
}

int
check_alias_qmail (const char *alias, const char *user)
{
  struct passwd *pw;
  char *p;
  int i;

  if (!(pw = getpwnam (alias))) {
    fprintf (stderr, "%s: no such user\n", alias);
    return 2;
  }
  if (chdir (pw->pw_dir)) {
    fprintf (stderr, "cannot chdir %s: %s\n", pw->pw_dir, strerror (errno));
    return 2;
  }

  for (i = 0; (p = dotqmail (user, i)); i++) {
    /* printf ("trying %s\n", p); */
    if (!checkfile (p)) {
      printf ("%s/%s\n", pw->pw_dir, p);
      free (p);
      return 0;
    }
    free (p);
  }
  
  return 1;
}

void db_fatal (int err, const char *) __attribute__ ((noreturn));
void
db_fatal (int err, const char *msg)
{
  if (msg)
    fprintf (stderr, "%s: %s\n", msg, db_strerror (err));
  else
    fprintf (stderr, "%s\n", db_strerror (err));
  exit (2);
}

int
check_alias (const char *file, const char *user, int map)
{
  int err;
  DB *db;
  DBT k, v;

  err = db_create (&db, NULL, 0);
  if (err) {
    fprintf (stderr, "db_create: %s\n", db_strerror (err));
    return check_alias_dbm (file, user, map);
  }
  err = db->open (db, NULL, file, NULL, DB_UNKNOWN, DB_RDONLY, 0666);
  if (err) {
    db->close (db, 0);
    return check_alias_dbm (file, user, map);
  }

  bzero (&k, sizeof (k));
  bzero (&v, sizeof (v));

  if (!map) {
    k.data = "@";
    k.size = 2;
    err = db->get (db, NULL, &k, &v, 0);
    if (err) {
      if (err != DB_NOTFOUND)
      fprintf (stderr, "%s: %s\n", file, db_strerror (err));
      else
      fprintf (stderr, "%s: incomplete/corrupted alias database\n", file);
      db->close (db, 0);
      return 2;
    }
  }

  k.data = (char *) user;
  k.size = strlen (user);
  if (!map)
    k.size++;

  err = db->get (db, NULL, &k, &v, 0);
  if (err == DB_NOTFOUND) {
    db->close (db, 0);
    return 1;
  }
  else if (err) {
    db->close (db, 0);
    fprintf (stderr, "%s: %s\n", file, db_strerror (err));
    return 2;
  }
  printf ("%.*s\n", (int) v.size, (char *) v.data);
  db->close (db, 0);
  return 0;
}

static void usage (void) __attribute__ ((noreturn));
static void
usage (void)
{
  fprintf (stderr, "usage: %s [--nopwd] name alias-file\n"
         "       %s --map [--case] key map-file\n"
         "       %s --qmail [--nopwd] name alias-user\n",
         progname, progname, progname);
  exit (1);
}

int
main (int argc, char **argv)
{
  int mode = 0;
  int opt_nopwd = 0;
  int opt_map = 0;
  int opt_case = 0;
  struct option o[] = {
    { "version", no_argument, &mode, 'v' },
    { "qmail", no_argument, &mode, 'q' },
    { "nopwd", no_argument, &opt_nopwd, 1 },
    { "map", no_argument, &opt_map, 1 },
    { "case", no_argument, &opt_case, 1 },
    { NULL, 0, NULL, 0 }
  };
  int c;
  char *p, *q, *user, *alias = NULL;
  int ret;

  progname = strrchr (argv[0], '/');
  if (progname)
    progname++;
  else
    progname = argv[0];

  while ((c = getopt_long (argc, argv, "+", o, NULL)) != -1)
    switch (c) {
    case 0:
      break;
    default:
      usage ();
    }

  if (optind + 2 == argc)
    alias = argv[optind+1];
  else if (optind + 1 != argc)
    usage ();

  if (opt_map) {
    opt_nopwd = 1;
    if (mode == 'q' || !alias)
      usage ();
  }

  if (mode == 'v')
    version (progname, 1);

  p = argv[optind];
  q = user = xmalloc (strlen (p) + 1);
  if (opt_case)
    strcpy (q, p);
  else
    while ((*q++ = tolower (*p++)))
      ;

  if (mode == 'q') {
    if (!alias)
      alias = "alias";
    ret = check_alias_qmail (alias, user);
  }
  else {
    if (!alias && !checkfile ("/etc/mail/aliases.db"))
      alias = "/etc/mail/aliases.db";
    if (!alias && !checkfile ("/etc/aliases.db"))
      alias = "/etc/aliases.db";
    ret = check_alias (alias, user, opt_map);
    if (ret == 2)
      fprintf (stderr, "%s: bad alias file\n", alias);
  }

  if (ret && !opt_nopwd && getpwnam (user)) {
    printf ("%s\n", user);
    exit (0);
  }

  exit (ret);
}

Generated by  Doxygen 1.6.0   Back to index