/* $Id: aliascheck.c,v 1.8 2004/10/27 05:56:59 dm Exp $ */ /* * * 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 #include #include "getopt_long.h" int check_alias_dbm (const char *file, const char *user); 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 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); } err = db->open (db, NULL, file, NULL, DB_UNKNOWN, DB_RDONLY, 0666); if (err) { db->close (db, 0); return check_alias_dbm (file, user); } bzero (&k, sizeof (k)); bzero (&v, sizeof (v)); 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) + 1; 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 --qmail [--nopwd] name alias-user\n", progname, progname); exit (1); } int main (int argc, char **argv) { int mode = 0; int opt_nopwd = 0; struct option o[] = { { "version", no_argument, &mode, 'v' }, { "qmail", no_argument, &mode, 'q' }, { "nopwd", no_argument, &opt_nopwd, 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 (mode == 'v') version (progname, 1); if (optind + 2 == argc) alias = argv[optind+1]; else if (optind + 1 != argc) usage (); p = argv[optind]; q = user = xmalloc (strlen (p) + 1); 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); 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); }