/*
 * find destination
 */

#include <stdio.h>
#include <grp.h>
#include "mail.h"

extern int DestSub;
extern char *strchr(), *getarg(), **alias();

struct group *getgrnam();

#define   BACKOUT()   fprintf(stderr, "Too many adressees\n");\
         strcpy(xbuf, oldtobuf);\
         goto out
char   *
finddest(strng, oldtobuf)
char   *strng;         /* map to list of addressees */
char   *oldtobuf;      /* substitution string for '%' */
{
   char   *sp, sbuf[TOSIZE], *tp, tbuf[TOSIZE], *xp, xbuf[TOSIZE], *cp;
   char   **pal;
   int   delta, i;
   struct   group   *pgrp;

   /* Substitute each '%' by previous list of addressees */
   for (sp = strng, xp = xbuf; *sp; ) {
      if (*sp == '%') {
         if (((xp - xbuf) + strlen(oldtobuf) + 1) > TOSIZE) {
            BACKOUT();
         }
         tp = oldtobuf;
         while (*xp++ = *tp++);
         --xp;
         ++sp;
      }
      else
	{
         /* room for string so far, + next character, + '\0' ? */
         if ((xp - xbuf + 2) > TOSIZE) {
            BACKOUT();
         }
         *xp++ = *sp++;
      }
   }
   *xp = '\0';

   /* Expand shell metacharacter expressions */
   strcpy(sbuf, xbuf);
   if (expand(sbuf, EX_ANY) == NULL) {
      /* BACKOUT() -- expand() failed to execute echo(1) */
      strcpy(xbuf, oldtobuf);
      goto out;
   }
   else {
      /* indicate that there was a substitution */
      if (!equal(sbuf, xbuf)) {
         DestSub++;
      }
   }

   /* Now expand aliases and groups */
   tp = sbuf;
   xp = xbuf;
   while ((tp = getarg(tbuf, tp)) != NULL) {
      if (equal(tbuf, "-g")) {
         /* Get name of group */
         if ((tp = getarg(tbuf, tp)) == NULL)
            break;

         /* Translate group to group members */
         if ((pgrp = getgrnam(tbuf)) == NULL) {
            fprintf(stderr, "Unknown group %s\n", tbuf);
            continue;
         }

         /* Make sure translation fits */
         delta = 1;   /* leave room for null terminator */
         for (i = 0; pgrp->gr_mem[i] && pgrp->gr_mem[i][0]; i++)
            delta += strlen(pgrp->gr_mem[i]) + 1;
         if (xp - xbuf + delta > TOSIZE) {
            BACKOUT();
         }

         /* Replace name by its members */
         for (i = 0; pgrp->gr_mem[i] && pgrp->gr_mem[i][0]; i++) {
            if (xp != xbuf)
               *xp++ = ' ';
            for (cp = pgrp->gr_mem[i]; *xp++ = *cp++; )
               ;
            --xp;
         }
         DestSub += i;
      }
      else {
         for (pal = alias(tbuf, 0); cp = *pal; pal++) {
            delta = ((xp != xbuf) ? 1 : 0) + strlen(cp);
            if (xp - xbuf + delta > (TOSIZE - 1)) {
               BACKOUT();
            }
            if (xp != xbuf)
               *xp++ = ' ';
            while (*xp++ = *cp++);
            --xp;
         }
      }
   }
   *xp = '\0';
out:
   /* Eliminate new lines from result */
   if ((xp = strchr(xbuf, '\n')) != NULL)
      *xp = '\0';
   return xbuf;
}
