/* $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 <ctype.h>
#include <pwd.h>
#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);
}
syntax highlighted by Code2HTML, v. 0.9.1