/* * ali.c -- list nmh mail aliases * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #define ALI_SWITCHES \ X("alias aliasfile", 0, ALIASW) \ X("noalias", -7, NALIASW) \ X("list", 0, LISTSW) \ X("nolist", 0, NLISTSW) \ X("user", 0, USERSW) \ X("nouser", 0, NUSERSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(ALI); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(ALI, switches); #undef X static int pos = 1; extern struct aka *akahead; /* * prototypes */ static void print_aka (char *, int, int); static void print_usr (char *, int); int main (int argc, char **argv) { int i, vecp = 0, inverted = 0, list = 0; int noalias = 0; char *cp, **ap, **argp, buf[BUFSIZ]; /* Really only need to allocate for argc-1, but must allocate at least 1, so go ahead and allocate for argc char pointers. */ char **vec = mh_xmalloc (argc * sizeof (char *)), **arguments; struct aka *ak; if (nmh_init(argv[0], 1)) { return 1; } mts_init (invo_name); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] aliases ...", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version (invo_name); done (0); case ALIASW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((i = alias (cp)) != AK_OK) adios (NULL, "aliasing error in %s - %s", cp, akerror (i)); continue; case NALIASW: noalias++; continue; case LISTSW: list++; continue; case NLISTSW: list = 0; continue; case USERSW: inverted++; continue; case NUSERSW: inverted = 0; continue; } } if (vecp < argc) { vec[vecp++] = cp; } else { /* Should never happen, but try to protect against code changes that could allow it. */ adios (NULL, "too many arguments"); } } if (!noalias) { /* allow Aliasfile: profile entry */ if ((cp = context_find ("Aliasfile"))) { char *dp = NULL; for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) if ((i = alias (*ap)) != AK_OK) adios (NULL, "aliasing error in %s - %s", *ap, akerror (i)); if (dp) free(dp); } alias (AliasFile); } /* * If -user is specified */ if (inverted) { if (vecp == 0) adios (NULL, "usage: %s -user addresses ... (you forgot the addresses)", invo_name); for (i = 0; i < vecp; i++) print_usr (vec[i], list); } else { if (vecp) { /* print specified aliases */ for (i = 0; i < vecp; i++) print_aka (akvalue (vec[i]), list, 0); } else { /* print them all */ for (ak = akahead; ak; ak = ak->ak_next) { printf ("%s: ", ak->ak_name); pos += strlen (ak->ak_name) + 1; print_aka (akresult (ak), list, pos); } } } free (vec); done (0); return 1; } static void print_aka (char *p, int list, int margin) { char c; if (p == NULL) { printf ("\n"); return; } while ((c = *p++)) { switch (c) { case ',': if (*p) { if (list) printf ("\n%*s", margin, ""); else { if (pos >= 68) { printf (",\n "); pos = 2; } else { printf (", "); pos += 2; } } } case 0: break; default: pos++; putchar (c); } } putchar ('\n'); pos = 1; } static void print_usr (char *s, int list) { register char *cp, *pp, *vp; register struct aka *ak; register struct mailname *mp, *np; if ((pp = getname (s)) == NULL) adios (NULL, "no address in \"%s\"", s); if ((mp = getm (pp, NULL, 0, NULL, 0)) == NULL) adios (NULL, "bad address \"%s\"", s); while (getname ("")) continue; vp = NULL; for (ak = akahead; ak; ak = ak->ak_next) { pp = akresult (ak); while ((cp = getname (pp))) { if ((np = getm (cp, NULL, 0, NULL, 0)) == NULL) continue; if (!strcasecmp (mp->m_host ? mp->m_host : "", np->m_host ? np->m_host : "") && !strcasecmp (mp->m_mbox ? mp->m_mbox : "", np->m_mbox ? np->m_mbox : "")) { vp = vp ? add (ak->ak_name, add (",", vp)) : getcpy (ak->ak_name); mnfree (np); while (getname ("")) continue; break; } mnfree (np); } } mnfree (mp); print_aka (vp ? vp : s, list, 0); if (vp) free (vp); }