Print this page
5166 sendmail package should be replaceable
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Toomas Soome <tsoome@me.com>
        
*** 36,47 ****
   * University Acknowledgment- Portions of this document are derived from
   * software developed by the University of California, Berkeley, and its
   * contributors.
   */
  
- #pragma ident   "%Z%%M% %I%     %E% SMI"
- 
  /*
   * mailx -- a modified version of a University of California at Berkeley
   *      mail program
   *
   * Handle name lists.
--- 36,45 ----
*** 51,62 ****
  #include <locale.h>
  
  static struct name      *nalloc(char str[]);
  static int              isfileaddr(char *name);
  static int              lengthof(struct name *name);
! static struct name      *gexpand(struct name *nlist, struct grouphead *gh, int metoo, int arg_ntype);
! static char             *norm(register char *user, register char *ubuf, int nbangs);
  static struct name      *put(struct name *list, struct name *node);
  
  /*
   * Allocate a single element of a name list,
   * initialize its name field to the passed
--- 49,62 ----
  #include <locale.h>
  
  static struct name      *nalloc(char str[]);
  static int              isfileaddr(char *name);
  static int              lengthof(struct name *name);
! static struct name      *gexpand(struct name *nlist, struct grouphead *gh,
!     int metoo, int arg_ntype);
! static char             *norm(register char *user, register char *ubuf,
!     int nbangs);
  static struct name      *put(struct name *list, struct name *node);
  
  /*
   * Allocate a single element of a name list,
   * initialize its name field to the passed
*** 66,82 ****
  static struct name *
  nalloc(char str[])
  {
          register struct name *np;
  
!         np = (struct name *) salloc(sizeof *np);
          np->n_flink = NIL;
          np->n_blink = NIL;
          np->n_type = -1;
          np->n_full = savestr(str);
          np->n_name = skin(np->n_full);
!         return(np);
  }
  
  /*
   * Find the tail of a list and return it.
   */
--- 66,82 ----
  static struct name *
  nalloc(char str[])
  {
          register struct name *np;
  
!         np = (struct name *)salloc(sizeof (*np));
          np->n_flink = NIL;
          np->n_blink = NIL;
          np->n_type = -1;
          np->n_full = savestr(str);
          np->n_name = skin(np->n_full);
!         return (np);
  }
  
  /*
   * Find the tail of a list and return it.
   */
*** 86,99 ****
  {
          register struct name *np;
  
          np = name;
          if (np == NIL)
!                 return(NIL);
          while (np->n_flink != NIL)
                  np = np->n_flink;
!         return(np);
  }
  
  /*
   * Extract a list of names from a line,
   * and make a list of names from it.
--- 86,99 ----
  {
          register struct name *np;
  
          np = name;
          if (np == NIL)
!                 return (NIL);
          while (np->n_flink != NIL)
                  np = np->n_flink;
!         return (np);
  }
  
  /*
   * Extract a list of names from a line,
   * and make a list of names from it.
*** 108,118 ****
          register struct name *top, *np, *t;
          char nbuf[BUFSIZ], abuf[BUFSIZ];
          int comma;
  
          if (line == NOSTR || strlen(line) == 0)
!                 return(NIL);
          comma = docomma(line);
          top = NIL;
          np = NIL;
          cp = line;
          while ((cp = yankword(cp, nbuf, sizeof (nbuf), comma)) != NOSTR) {
--- 108,118 ----
          register struct name *top, *np, *t;
          char nbuf[BUFSIZ], abuf[BUFSIZ];
          int comma;
  
          if (line == NOSTR || strlen(line) == 0)
!                 return (NIL);
          comma = docomma(line);
          top = NIL;
          np = NIL;
          cp = line;
          while ((cp = yankword(cp, nbuf, sizeof (nbuf), comma)) != NOSTR) {
*** 136,146 ****
                  else
                          np->n_flink = t;
                  t->n_blink = np;
                  np = t;
          }
!         return(top);
  }
  
  /*
   * Turn a list of names into a string of the same names.
   */
--- 136,146 ----
                  else
                          np->n_flink = t;
                  t->n_blink = np;
                  np = t;
          }
!         return (top);
  }
  
  /*
   * Turn a list of names into a string of the same names.
   */
*** 151,193 ****
          register int s;
          register char *cp, *top;
          register struct name *p;
  
          if (np == NIL)
!                 return(NOSTR);
          s = 0;
          for (p = np; p != NIL; p = p->n_flink) {
!                 if ((ntype && (p->n_type & GMASK) != ntype)
!                  || (p->n_type & GDEL))
                          continue;
                  s += strlen(p->n_full) + 2;
          }
          if (s == 0)
!                 return(NOSTR);
          top = (char *)salloc((unsigned)(++s));
          cp = top;
          for (p = np; p != NIL; p = p->n_flink) {
!                 if ((ntype && (p->n_type & GMASK) != ntype)
!                  || (p->n_type & GDEL))
                          continue;
                  cp = copy(p->n_full, cp);
                  *cp++ = ',';
                  *cp++ = ' ';
          }
          *cp = 0;
!         return(top);
  }
  
  struct name *
  outpre(struct name *to)
  {
          register struct name *np;
  
          for (np = to; np; np = np->n_flink)
                  if (isfileaddr(np->n_name))
                          np->n_type |= GDEL;
!         return to;
  }
  
  /*
   * For each recipient in the passed name list with a /
   * in the name, append the message to the end of the named file
--- 151,193 ----
          register int s;
          register char *cp, *top;
          register struct name *p;
  
          if (np == NIL)
!                 return (NOSTR);
          s = 0;
          for (p = np; p != NIL; p = p->n_flink) {
!                 if ((ntype && (p->n_type & GMASK) != ntype) ||
!                     (p->n_type & GDEL))
                          continue;
                  s += strlen(p->n_full) + 2;
          }
          if (s == 0)
!                 return (NOSTR);
          top = (char *)salloc((unsigned)(++s));
          cp = top;
          for (p = np; p != NIL; p = p->n_flink) {
!                 if ((ntype && (p->n_type & GMASK) != ntype) ||
!                     (p->n_type & GDEL))
                          continue;
                  cp = copy(p->n_full, cp);
                  *cp++ = ',';
                  *cp++ = ' ';
          }
          *cp = 0;
!         return (top);
  }
  
  struct name *
  outpre(struct name *to)
  {
          register struct name *np;
  
          for (np = to; np; np = np->n_flink)
                  if (isfileaddr(np->n_name))
                          np->n_type |= GDEL;
!         return (to);
  }
  
  /*
   * For each recipient in the passed name list with a /
   * in the name, append the message to the end of the named file
*** 280,303 ****
                                  sigset(SIGQUIT, SIG_IGN);
                                  close(0);
                                  dup(image);
                                  close(image);
                                  lseek(0, 0L, 0);
!                                 if ((shell = value("SHELL")) == NOSTR || *shell=='\0')
                                          shell = SHELL;
!                                 (void) execlp(shell, shell, "-c", fname, (char *)0);
                                  perror(shell);
                                  exit(1);
                                  break;
  
                          case (pid_t)-1:
                                  perror("fork");
                                  senderr++;
                                  goto cant;
                          }
!                 }
!                 else {
                          if ((fout = fopen(fname, "a")) == NULL) {
                                  perror(fname);
                                  senderr++;
                                  goto cant;
                          }
--- 280,304 ----
                                  sigset(SIGQUIT, SIG_IGN);
                                  close(0);
                                  dup(image);
                                  close(image);
                                  lseek(0, 0L, 0);
!                                 if ((shell = value("SHELL")) == NOSTR ||
!                                     *shell == '\0')
                                          shell = SHELL;
!                                 (void) execlp(shell, shell, "-c", fname,
!                                     (char *)0);
                                  perror(shell);
                                  exit(1);
                                  break;
  
                          case (pid_t)-1:
                                  perror("fork");
                                  senderr++;
                                  goto cant;
                          }
!                 } else {
                          if ((fout = fopen(fname, "a")) == NULL) {
                                  perror(fname);
                                  senderr++;
                                  goto cant;
                          }
*** 310,321 ****
                                  goto cant;
                          }
                          rewind(fin);
  #ifdef preSVr4
                          putc(getc(fin), fout);
!                         while (fgets(line, sizeof line, fin)) {
!                                 if (!strncmp(line, "From ", 5))
                                          putc('>', fout);
                                  fputs(line, fout);
                          }
  #else
                          while ((c = getc(fin)) != EOF)
--- 311,322 ----
                                  goto cant;
                          }
                          rewind(fin);
  #ifdef preSVr4
                          putc(getc(fin), fout);
!                         while (fgets(line, sizeof (line), fin)) {
!                                 if (strncmp(line, "From ", 5) == 0)
                                          putc('>', fout);
                                  fputs(line, fout);
                          }
  #else
                          while ((c = getc(fin)) != EOF)
*** 359,369 ****
          }
          if (image >= 0) {
                  close(image);
                  image = -1;
          }
!         return(nout);
  }
  
  /*
   * Determine if the passed address is a local "send to file" address.
   * If any of the network metacharacters precedes any slashes, it can't
--- 360,370 ----
          }
          if (image >= 0) {
                  close(image);
                  image = -1;
          }
!         return (nout);
  }
  
  /*
   * Determine if the passed address is a local "send to file" address.
   * If any of the network metacharacters precedes any slashes, it can't
*** 376,399 ****
  {
          register char *cp;
          char *fcc = value("fcc");
  
          if (any('@', name))
!                 return(0);
          if (*name == '+')
!                 return(1);
          if (fcc == NOSTR)
!                 return(0);
          for (cp = name; *cp; cp++) {
                  if (*cp == '.')
                          continue;
                  if (any(*cp, metanet))
!                         return(0);
                  if (*cp == '/')
!                         return(1);
          }
!         return(0);
  }
  
  /*
   * Map all of the aliased users in the invoker's mailrc
   * file and insert them into the list.
--- 377,400 ----
  {
          register char *cp;
          char *fcc = value("fcc");
  
          if (any('@', name))
!                 return (0);
          if (*name == '+')
!                 return (1);
          if (fcc == NOSTR)
!                 return (0);
          for (cp = name; *cp; cp++) {
                  if (*cp == '.')
                          continue;
                  if (any(*cp, metanet))
!                         return (0);
                  if (*cp == '/')
!                         return (1);
          }
!         return (0);
  }
  
  /*
   * Map all of the aliased users in the invoker's mailrc
   * file and insert them into the list.
*** 424,434 ****
                          newnames = gexpand(newnames, gh, metoo, np->n_type);
                  else
                          newnames = put(newnames, np);
                  np = cp;
          }
!         return(newnames);
  }
  
  /*
   * Recursively expand a group name.  We limit the expansion to some
   * fixed level to keep things from going haywire.
--- 425,435 ----
                          newnames = gexpand(newnames, gh, metoo, np->n_type);
                  else
                          newnames = put(newnames, np);
                  np = cp;
          }
!         return (newnames);
  }
  
  /*
   * Recursively expand a group name.  We limit the expansion to some
   * fixed level to keep things from going haywire.
*** 446,456 ****
          register char *cp;
  
          if (depth > MAXEXP) {
                  printf(gettext("Expanding alias to depth larger than %d\n"),
                      MAXEXP);
!                 return(nlist);
          }
          depth++;
          for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) {
                  cp = gp->ge_name;
                  if (*cp == '\\')
--- 447,457 ----
          register char *cp;
  
          if (depth > MAXEXP) {
                  printf(gettext("Expanding alias to depth larger than %d\n"),
                      MAXEXP);
!                 return (nlist);
          }
          depth++;
          for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) {
                  cp = gp->ge_name;
                  if (*cp == '\\')
*** 474,484 ****
                          np->n_type |= GDEL;
  skip:
                  nlist = put(nlist, np);
          }
          depth--;
!         return(nlist);
  }
  
  /*
   * Normalize a network name for comparison purposes.
   */
--- 475,485 ----
                          np->n_type |= GDEL;
  skip:
                  nlist = put(nlist, np);
          }
          depth--;
!         return (nlist);
  }
  
  /*
   * Normalize a network name for comparison purposes.
   */
*** 486,506 ****
  norm(register char *user, register char *ubuf, int nbangs)
  {
          register char *cp;
          int inubuf = 0;
  
!         while (*user++ == '!');
          user--;
          if (!strchr(user, '!')) {
                  snprintf(ubuf, BUFSIZ, "%s!%s", host, user);
                  user = ubuf;
                  inubuf++;
          }
          if (nbangs) {
                  cp = user + strlen(user);
                  while (nbangs--)
!                         while (cp > user && *--cp != '!');
                  user = (cp > user) ? ++cp : cp;
                  /*
                   * Now strip off all Internet-type
                   * hosts.
                   */
--- 487,509 ----
  norm(register char *user, register char *ubuf, int nbangs)
  {
          register char *cp;
          int inubuf = 0;
  
!         while (*user++ == '!')
!                 ;
          user--;
          if (!strchr(user, '!')) {
                  snprintf(ubuf, BUFSIZ, "%s!%s", host, user);
                  user = ubuf;
                  inubuf++;
          }
          if (nbangs) {
                  cp = user + strlen(user);
                  while (nbangs--)
!                         while (cp > user && *--cp != '!')
!                                 ;
                  user = (cp > user) ? ++cp : cp;
                  /*
                   * Now strip off all Internet-type
                   * hosts.
                   */
*** 513,534 ****
                                  user = ubuf;
                          } else
                                  *cp = '\0';
                  }
          }
!         return user;
  }
  
  /*
   * Implement allnet options.
   */
  int 
  samebody(register char *user, register char *addr, int fuzzy)
  {
          char ubuf[BUFSIZ], abuf[BUFSIZ];
          char *allnet = value("allnet");
!         int nbangs = allnet ? !strcmp(allnet, "uucp") ? 2 : 1 : 0;
  
          if (fuzzy && value("fuzzymatch")) {
                  int i;
  
                  (void) strlcpy(ubuf, user, BUFSIZ);
--- 516,537 ----
                                  user = ubuf;
                          } else
                                  *cp = '\0';
                  }
          }
!         return (user);
  }
  
  /*
   * Implement allnet options.
   */
  int
  samebody(register char *user, register char *addr, int fuzzy)
  {
          char ubuf[BUFSIZ], abuf[BUFSIZ];
          char *allnet = value("allnet");
!         int nbangs = allnet ? (strcmp(allnet, "uucp") == 0) ? 2 : 1 : 0;
  
          if (fuzzy && value("fuzzymatch")) {
                  int i;
  
                  (void) strlcpy(ubuf, user, BUFSIZ);
*** 539,549 ****
                          abuf[i] = tolower(abuf[i]);
                  return (strstr(abuf, ubuf) != NOSTR);
          }
          user = norm(user, ubuf, nbangs);
          addr = norm(addr, abuf, nbangs);
!         return strcmp(user, addr) == 0;
  }
  
  /*
   * Compute the length of the passed name list and
   * return it.
--- 542,552 ----
                          abuf[i] = tolower(abuf[i]);
                  return (strstr(abuf, ubuf) != NOSTR);
          }
          user = norm(user, ubuf, nbangs);
          addr = norm(addr, abuf, nbangs);
!         return (strcmp(user, addr) == 0);
  }
  
  /*
   * Compute the length of the passed name list and
   * return it.
*** 554,564 ****
          register struct name *np;
          register int c;
  
          for (c = 0, np = name; np != NIL; c++, np = np->n_flink)
                  ;
!         return(c);
  }
  
  /*
   * Concatenate the two passed name lists, return the result.
   */
--- 557,567 ----
          register struct name *np;
          register int c;
  
          for (c = 0, np = name; np != NIL; c++, np = np->n_flink)
                  ;
!         return (c);
  }
  
  /*
   * Concatenate the two passed name lists, return the result.
   */
*** 567,583 ****
  cat(struct name *n1, struct name *n2)
  {
          register struct name *tail;
  
          if (n1 == NIL)
!                 return(n2);
          if (n2 == NIL)
!                 return(n1);
          tail = tailof(n1);
          tail->n_flink = n2;
          n2->n_blink = tail;
!         return(n1);
  }
  
  /*
   * Unpack the name list onto a vector of strings.
   * Return an error if the name list won't fit.
--- 570,586 ----
  cat(struct name *n1, struct name *n2)
  {
          register struct name *tail;
  
          if (n1 == NIL)
!                 return (n2);
          if (n2 == NIL)
!                 return (n1);
          tail = tailof(n1);
          tail->n_flink = n2;
          n2->n_blink = tail;
!         return (n1);
  }
  
  /*
   * Unpack the name list onto a vector of strings.
   * Return an error if the name list won't fit.
*** 605,654 ****
  
          extra = 2;
  
          if (rflag != NOSTR)
                  extra += 2;
- #ifdef SENDMAIL
          extra++;
          metoo = value("metoo") != NOSTR;
          if (metoo)
                  extra++;
          verbose = value("verbose") != NOSTR;
          if (verbose)
                  extra++;
          if (hflag)
                  extra += 2;
! #endif /* SENDMAIL */
!         top = (char **) salloc((t + extra) * sizeof (char *));
          ap = top;
!         *ap++ = "mail";
          if (rflag != NOSTR) {
                  *ap++ = "-r";
                  *ap++ = rflag;
          }
- #ifdef SENDMAIL
          *ap++ = "-i";
          if (metoo)
                  *ap++ = "-m";
          if (verbose)
                  *ap++ = "-v";
          if (hflag) {
                  *ap++ = "-h";
                  snprintf(hbuf, sizeof (hbuf), "%d", hflag);
                  *ap++ = savestr(hbuf);
          }
- #endif /* SENDMAIL */
          while (n != NIL) {
                  if (n->n_type & GDEL) {
                          n = n->n_flink;
                          continue;
                  }
                  *ap++ = n->n_name;
                  n = n->n_flink;
          }
          *ap = NOSTR;
!         return(top);
  }
  
  /*
   * See if the user named himself as a destination
   * for outgoing mail.  If so, set the global flag
--- 608,653 ----
  
          extra = 2;
  
          if (rflag != NOSTR)
                  extra += 2;
          extra++;
          metoo = value("metoo") != NOSTR;
          if (metoo)
                  extra++;
          verbose = value("verbose") != NOSTR;
          if (verbose)
                  extra++;
          if (hflag)
                  extra += 2;
!         top = (char **)salloc((t + extra) * sizeof (char *));
          ap = top;
!         *ap++ = "sendmail";
          if (rflag != NOSTR) {
                  *ap++ = "-r";
                  *ap++ = rflag;
          }
          *ap++ = "-i";
          if (metoo)
                  *ap++ = "-m";
          if (verbose)
                  *ap++ = "-v";
          if (hflag) {
                  *ap++ = "-h";
                  snprintf(hbuf, sizeof (hbuf), "%d", hflag);
                  *ap++ = savestr(hbuf);
          }
          while (n != NIL) {
                  if (n->n_type & GDEL) {
                          n = n->n_flink;
                          continue;
                  }
                  *ap++ = n->n_name;
                  n = n->n_flink;
          }
          *ap = NOSTR;
!         return (top);
  }
  
  /*
   * See if the user named himself as a destination
   * for outgoing mail.  If so, set the global flag
*** 679,689 ****
  {
          register struct name *np, *t, *newnames;
          struct name *x;
  
          if (names == NIL)
!                 return(NIL);
          newnames = names;
          np = names;
          np = np->n_flink;
          if (np != NIL)
                  np->n_blink = NIL;
--- 678,688 ----
  {
          register struct name *np, *t, *newnames;
          struct name *x;
  
          if (names == NIL)
!                 return (NIL);
          newnames = names;
          np = names;
          np = np->n_flink;
          if (np != NIL)
                  np->n_blink = NIL;
*** 750,760 ****
          while (np != NIL) {
                  int type;
  
                  t = np;
                  type = np->n_type;
!                 while (t->n_flink!=NIL &&
                      strcmp(np->n_name, t->n_flink->n_name) == 0) {
                          t = t->n_flink;
                          /* "To" before "Cc" before "Bcc" */
                          if (t->n_type < type)
                                  type = t->n_type;
--- 749,759 ----
          while (np != NIL) {
                  int type;
  
                  t = np;
                  type = np->n_type;
!                 while (t->n_flink != NIL &&
                      strcmp(np->n_name, t->n_flink->n_name) == 0) {
                          t = t->n_flink;
                          /* "To" before "Cc" before "Bcc" */
                          if (t->n_type < type)
                                  type = t->n_type;
*** 773,783 ****
                  if (t->n_flink != NIL)
                          t->n_flink->n_blink = np;
                  np->n_type = type;
                  np = np->n_flink;
          }
!         return(newnames);
  }
  
  /*
   * Put another node onto a list of names and return
   * the list.
--- 772,782 ----
                  if (t->n_flink != NIL)
                          t->n_flink->n_blink = np;
                  np->n_type = type;
                  np = np->n_flink;
          }
!         return (newnames);
  }
  
  /*
   * Put another node onto a list of names and return
   * the list.
*** 788,798 ****
  {
          node->n_flink = list;
          node->n_blink = NIL;
          if (list != NIL)
                  list->n_blink = node;
!         return(node);
  }
  
  
  /*
   * Delete the given name from a namelist.
--- 787,797 ----
  {
          node->n_flink = list;
          node->n_blink = NIL;
          if (list != NIL)
                  list->n_blink = node;
!         return (node);
  }
  
  
  /*
   * Delete the given name from a namelist.
*** 816,826 ****
                                  continue;
                          }
                          p->n_blink->n_flink = p->n_flink;
                          p->n_flink->n_blink = p->n_blink;
                  }
!         return(np);
  }
  
  /*
   * Call the given routine on each element of the name
   * list, replacing said value if need be.
--- 815,825 ----
                                  continue;
                          }
                          p->n_blink->n_flink = p->n_flink;
                          p->n_flink->n_blink = p->n_blink;
                  }
!         return (np);
  }
  
  /*
   * Call the given routine on each element of the name
   * list, replacing said value if need be.