17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 246c83d09fSrobbin * Copyright 2001 Sun Microsystems, Inc. All rights reserved. 256c83d09fSrobbin * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 286c83d09fSrobbin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 296c83d09fSrobbin /* All Rights Reserved */ 306c83d09fSrobbin 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 337c478bd9Sstevel@tonic-gate * The Regents of the University of California 347c478bd9Sstevel@tonic-gate * All Rights Reserved 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 377c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 387c478bd9Sstevel@tonic-gate * contributors. 397c478bd9Sstevel@tonic-gate */ 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 437c478bd9Sstevel@tonic-gate * mail program 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate * Handle name lists. 467c478bd9Sstevel@tonic-gate */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include "rcv.h" 497c478bd9Sstevel@tonic-gate #include <locale.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static struct name *nalloc(char str[]); 527c478bd9Sstevel@tonic-gate static int isfileaddr(char *name); 537c478bd9Sstevel@tonic-gate static int lengthof(struct name *name); 54287247a8SAlexander Pyhalov static struct name *gexpand(struct name *nlist, struct grouphead *gh, 55287247a8SAlexander Pyhalov int metoo, int arg_ntype); 56287247a8SAlexander Pyhalov static char *norm(register char *user, register char *ubuf, 57287247a8SAlexander Pyhalov int nbangs); 587c478bd9Sstevel@tonic-gate static struct name *put(struct name *list, struct name *node); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * Allocate a single element of a name list, 627c478bd9Sstevel@tonic-gate * initialize its name field to the passed 637c478bd9Sstevel@tonic-gate * name and return it. 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static struct name * 677c478bd9Sstevel@tonic-gate nalloc(char str[]) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate register struct name *np; 707c478bd9Sstevel@tonic-gate 71287247a8SAlexander Pyhalov np = (struct name *)salloc(sizeof (*np)); 727c478bd9Sstevel@tonic-gate np->n_flink = NIL; 737c478bd9Sstevel@tonic-gate np->n_blink = NIL; 747c478bd9Sstevel@tonic-gate np->n_type = -1; 757c478bd9Sstevel@tonic-gate np->n_full = savestr(str); 767c478bd9Sstevel@tonic-gate np->n_name = skin(np->n_full); 777c478bd9Sstevel@tonic-gate return (np); 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Find the tail of a list and return it. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate struct name * 857c478bd9Sstevel@tonic-gate tailof(struct name *name) 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate register struct name *np; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate np = name; 907c478bd9Sstevel@tonic-gate if (np == NIL) 917c478bd9Sstevel@tonic-gate return (NIL); 927c478bd9Sstevel@tonic-gate while (np->n_flink != NIL) 937c478bd9Sstevel@tonic-gate np = np->n_flink; 947c478bd9Sstevel@tonic-gate return (np); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * Extract a list of names from a line, 997c478bd9Sstevel@tonic-gate * and make a list of names from it. 1007c478bd9Sstevel@tonic-gate * Return the list or NIL if none found. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate struct name * 1047c478bd9Sstevel@tonic-gate extract(char line[], int arg_ntype) 1057c478bd9Sstevel@tonic-gate { 1067c478bd9Sstevel@tonic-gate short ntype = (short)arg_ntype; 1077c478bd9Sstevel@tonic-gate register char *cp; 1087c478bd9Sstevel@tonic-gate register struct name *top, *np, *t; 1097c478bd9Sstevel@tonic-gate char nbuf[BUFSIZ], abuf[BUFSIZ]; 1107c478bd9Sstevel@tonic-gate int comma; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (line == NOSTR || strlen(line) == 0) 1137c478bd9Sstevel@tonic-gate return (NIL); 1147c478bd9Sstevel@tonic-gate comma = docomma(line); 1157c478bd9Sstevel@tonic-gate top = NIL; 1167c478bd9Sstevel@tonic-gate np = NIL; 1177c478bd9Sstevel@tonic-gate cp = line; 1187c478bd9Sstevel@tonic-gate while ((cp = yankword(cp, nbuf, sizeof (nbuf), comma)) != NOSTR) { 1197c478bd9Sstevel@tonic-gate if (np != NIL && equal(nbuf, "at")) { 1207c478bd9Sstevel@tonic-gate nstrcpy(abuf, sizeof (abuf), nbuf); 1217c478bd9Sstevel@tonic-gate if ((cp = yankword(cp, nbuf, sizeof (nbuf), 1227c478bd9Sstevel@tonic-gate comma)) == NOSTR) { 1237c478bd9Sstevel@tonic-gate nstrcpy(nbuf, sizeof (nbuf), abuf); 1247c478bd9Sstevel@tonic-gate goto normal; 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate snprintf(abuf, sizeof (abuf), "%s@%s", np->n_name, 1277c478bd9Sstevel@tonic-gate nbuf); 1287c478bd9Sstevel@tonic-gate np->n_name = savestr(abuf); 1297c478bd9Sstevel@tonic-gate continue; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate normal: 1327c478bd9Sstevel@tonic-gate t = nalloc(nbuf); 1337c478bd9Sstevel@tonic-gate t->n_type = ntype; 1347c478bd9Sstevel@tonic-gate if (top == NIL) 1357c478bd9Sstevel@tonic-gate top = t; 1367c478bd9Sstevel@tonic-gate else 1377c478bd9Sstevel@tonic-gate np->n_flink = t; 1387c478bd9Sstevel@tonic-gate t->n_blink = np; 1397c478bd9Sstevel@tonic-gate np = t; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate return (top); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Turn a list of names into a string of the same names. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate char * 1497c478bd9Sstevel@tonic-gate detract(register struct name *np, int ntype) 1507c478bd9Sstevel@tonic-gate { 1517c478bd9Sstevel@tonic-gate register int s; 1527c478bd9Sstevel@tonic-gate register char *cp, *top; 1537c478bd9Sstevel@tonic-gate register struct name *p; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate if (np == NIL) 1567c478bd9Sstevel@tonic-gate return (NOSTR); 1577c478bd9Sstevel@tonic-gate s = 0; 1587c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) { 159287247a8SAlexander Pyhalov if ((ntype && (p->n_type & GMASK) != ntype) || 160287247a8SAlexander Pyhalov (p->n_type & GDEL)) 1617c478bd9Sstevel@tonic-gate continue; 1627c478bd9Sstevel@tonic-gate s += strlen(p->n_full) + 2; 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate if (s == 0) 1657c478bd9Sstevel@tonic-gate return (NOSTR); 1667c478bd9Sstevel@tonic-gate top = (char *)salloc((unsigned)(++s)); 1677c478bd9Sstevel@tonic-gate cp = top; 1687c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) { 169287247a8SAlexander Pyhalov if ((ntype && (p->n_type & GMASK) != ntype) || 170287247a8SAlexander Pyhalov (p->n_type & GDEL)) 1717c478bd9Sstevel@tonic-gate continue; 1727c478bd9Sstevel@tonic-gate cp = copy(p->n_full, cp); 1737c478bd9Sstevel@tonic-gate *cp++ = ','; 1747c478bd9Sstevel@tonic-gate *cp++ = ' '; 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate *cp = 0; 1777c478bd9Sstevel@tonic-gate return (top); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate struct name * 1817c478bd9Sstevel@tonic-gate outpre(struct name *to) 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate register struct name *np; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate for (np = to; np; np = np->n_flink) 1867c478bd9Sstevel@tonic-gate if (isfileaddr(np->n_name)) 1877c478bd9Sstevel@tonic-gate np->n_type |= GDEL; 188287247a8SAlexander Pyhalov return (to); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * For each recipient in the passed name list with a / 1937c478bd9Sstevel@tonic-gate * in the name, append the message to the end of the named file 194*5422785dSRobert Mustacchi * and remove them from the recipient list. 1957c478bd9Sstevel@tonic-gate * 1967c478bd9Sstevel@tonic-gate * Recipients whose name begins with | are piped through the given 1977c478bd9Sstevel@tonic-gate * program and removed. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate int 2017c478bd9Sstevel@tonic-gate outof(struct name *names, FILE *fo) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate register int c; 2047c478bd9Sstevel@tonic-gate register struct name *np; 2057c478bd9Sstevel@tonic-gate time_t now; 2067c478bd9Sstevel@tonic-gate char *date, *fname, *shell; 2077c478bd9Sstevel@tonic-gate FILE *fout, *fin; 2087c478bd9Sstevel@tonic-gate int ispipe; 2097c478bd9Sstevel@tonic-gate int nout = 0; 2107c478bd9Sstevel@tonic-gate int fd = 0; 2117c478bd9Sstevel@tonic-gate #ifdef preSVr4 2127c478bd9Sstevel@tonic-gate char line[BUFSIZ]; 2137c478bd9Sstevel@tonic-gate #endif 2147c478bd9Sstevel@tonic-gate 215*5422785dSRobert Mustacchi if (value("expandaddr") == NOSTR) 216*5422785dSRobert Mustacchi return (nout); 217*5422785dSRobert Mustacchi 2187c478bd9Sstevel@tonic-gate for (np = names; np != NIL; np = np->n_flink) { 2197c478bd9Sstevel@tonic-gate if (!isfileaddr(np->n_name) && np->n_name[0] != '|') 2207c478bd9Sstevel@tonic-gate continue; 2217c478bd9Sstevel@tonic-gate nout++; 2227c478bd9Sstevel@tonic-gate ispipe = np->n_name[0] == '|'; 2237c478bd9Sstevel@tonic-gate if (ispipe) 2247c478bd9Sstevel@tonic-gate fname = np->n_name+1; 2257c478bd9Sstevel@tonic-gate else 2267c478bd9Sstevel@tonic-gate fname = safeexpand(np->n_name); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * See if we have copied the complete message out yet. 2307c478bd9Sstevel@tonic-gate * If not, do so. 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate if (image < 0) { 2347c478bd9Sstevel@tonic-gate fd = open(tempEdit, O_CREAT|O_EXCL|O_APPEND|O_WRONLY, 2357c478bd9Sstevel@tonic-gate 0600); 2367c478bd9Sstevel@tonic-gate if ((fd < 0) && (errno == EEXIST)) { 2377c478bd9Sstevel@tonic-gate if ((fd = open(tempEdit, O_APPEND|O_WRONLY, 2387c478bd9Sstevel@tonic-gate 0600)) < 0) { 2397c478bd9Sstevel@tonic-gate perror(tempEdit); 2407c478bd9Sstevel@tonic-gate senderr++; 2417c478bd9Sstevel@tonic-gate goto cant; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate if ((fout = fdopen(fd, "a")) == NULL) { 2457c478bd9Sstevel@tonic-gate perror(tempEdit); 2467c478bd9Sstevel@tonic-gate senderr++; 2477c478bd9Sstevel@tonic-gate goto cant; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate image = open(tempEdit, O_RDWR); 2507c478bd9Sstevel@tonic-gate unlink(tempEdit); 2517c478bd9Sstevel@tonic-gate if (image < 0) { 2527c478bd9Sstevel@tonic-gate perror(tempEdit); 2537c478bd9Sstevel@tonic-gate senderr++; 2547c478bd9Sstevel@tonic-gate goto cant; 2557c478bd9Sstevel@tonic-gate } else { 2567c478bd9Sstevel@tonic-gate rewind(fo); 2577c478bd9Sstevel@tonic-gate time(&now); 2587c478bd9Sstevel@tonic-gate date = ctime(&now); 2597c478bd9Sstevel@tonic-gate fprintf(fout, "From %s %s", myname, date); 2607c478bd9Sstevel@tonic-gate while ((c = getc(fo)) != EOF) 2617c478bd9Sstevel@tonic-gate putc(c, fout); 2627c478bd9Sstevel@tonic-gate rewind(fo); 2637c478bd9Sstevel@tonic-gate fflush(fout); 2647c478bd9Sstevel@tonic-gate if (fferror(fout)) 2657c478bd9Sstevel@tonic-gate perror(tempEdit); 2667c478bd9Sstevel@tonic-gate fclose(fout); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * Now either copy "image" to the desired file 2727c478bd9Sstevel@tonic-gate * or give it as the standard input to the desired 2737c478bd9Sstevel@tonic-gate * program as appropriate. 2747c478bd9Sstevel@tonic-gate */ 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (ispipe) { 2777c478bd9Sstevel@tonic-gate wait((int *)NULL); 2787c478bd9Sstevel@tonic-gate switch (fork()) { 2797c478bd9Sstevel@tonic-gate case 0: 2807c478bd9Sstevel@tonic-gate sigchild(); 2817c478bd9Sstevel@tonic-gate sigset(SIGHUP, SIG_IGN); 2827c478bd9Sstevel@tonic-gate sigset(SIGINT, SIG_IGN); 2837c478bd9Sstevel@tonic-gate sigset(SIGQUIT, SIG_IGN); 2847c478bd9Sstevel@tonic-gate close(0); 2857c478bd9Sstevel@tonic-gate dup(image); 2867c478bd9Sstevel@tonic-gate close(image); 2877c478bd9Sstevel@tonic-gate lseek(0, 0L, 0); 288287247a8SAlexander Pyhalov if ((shell = value("SHELL")) == NOSTR || 289287247a8SAlexander Pyhalov *shell == '\0') 2907c478bd9Sstevel@tonic-gate shell = SHELL; 291287247a8SAlexander Pyhalov (void) execlp(shell, shell, "-c", fname, 292287247a8SAlexander Pyhalov (char *)0); 2937c478bd9Sstevel@tonic-gate perror(shell); 2947c478bd9Sstevel@tonic-gate exit(1); 2957c478bd9Sstevel@tonic-gate break; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate case (pid_t)-1: 2987c478bd9Sstevel@tonic-gate perror("fork"); 2997c478bd9Sstevel@tonic-gate senderr++; 3007c478bd9Sstevel@tonic-gate goto cant; 3017c478bd9Sstevel@tonic-gate } 302287247a8SAlexander Pyhalov } else { 3037c478bd9Sstevel@tonic-gate if ((fout = fopen(fname, "a")) == NULL) { 3047c478bd9Sstevel@tonic-gate perror(fname); 3057c478bd9Sstevel@tonic-gate senderr++; 3067c478bd9Sstevel@tonic-gate goto cant; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate fin = Fdopen(image, "r"); 3097c478bd9Sstevel@tonic-gate if (fin == NULL) { 3107c478bd9Sstevel@tonic-gate fprintf(stderr, 3117c478bd9Sstevel@tonic-gate gettext("Can't reopen image\n")); 3127c478bd9Sstevel@tonic-gate fclose(fout); 3137c478bd9Sstevel@tonic-gate senderr++; 3147c478bd9Sstevel@tonic-gate goto cant; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate rewind(fin); 3177c478bd9Sstevel@tonic-gate #ifdef preSVr4 3187c478bd9Sstevel@tonic-gate putc(getc(fin), fout); 319287247a8SAlexander Pyhalov while (fgets(line, sizeof (line), fin)) { 320287247a8SAlexander Pyhalov if (strncmp(line, "From ", 5) == 0) 3217c478bd9Sstevel@tonic-gate putc('>', fout); 3227c478bd9Sstevel@tonic-gate fputs(line, fout); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate #else 3257c478bd9Sstevel@tonic-gate while ((c = getc(fin)) != EOF) 3267c478bd9Sstevel@tonic-gate putc(c, fout); 3277c478bd9Sstevel@tonic-gate #endif 3287c478bd9Sstevel@tonic-gate putc('\n', fout); 3297c478bd9Sstevel@tonic-gate fflush(fout); 3307c478bd9Sstevel@tonic-gate if (fferror(fout)) 3317c478bd9Sstevel@tonic-gate senderr++, perror(fname); 3327c478bd9Sstevel@tonic-gate fclose(fout); 3337c478bd9Sstevel@tonic-gate fclose(fin); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate cant: 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * In days of old we removed the entry from the 3387c478bd9Sstevel@tonic-gate * the list; now for sake of header expansion 3397c478bd9Sstevel@tonic-gate * we leave it in and mark it as deleted. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate #ifdef CRAZYWOW 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate register struct name *t, *x; 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate if (np == top) { 3477c478bd9Sstevel@tonic-gate top = np->n_flink; 3487c478bd9Sstevel@tonic-gate if (top != NIL) 3497c478bd9Sstevel@tonic-gate top->n_blink = NIL; 3507c478bd9Sstevel@tonic-gate np = top; 3517c478bd9Sstevel@tonic-gate continue; 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate x = np->n_blink; 3547c478bd9Sstevel@tonic-gate t = np->n_flink; 3557c478bd9Sstevel@tonic-gate x->n_flink = t; 3567c478bd9Sstevel@tonic-gate if (t != NIL) 3577c478bd9Sstevel@tonic-gate t->n_blink = x; 3587c478bd9Sstevel@tonic-gate np = t; 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate #endif 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate np->n_type |= GDEL; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate if (image >= 0) { 3657c478bd9Sstevel@tonic-gate close(image); 3667c478bd9Sstevel@tonic-gate image = -1; 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate return (nout); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * Determine if the passed address is a local "send to file" address. 3737c478bd9Sstevel@tonic-gate * If any of the network metacharacters precedes any slashes, it can't 3747c478bd9Sstevel@tonic-gate * be a filename. We cheat with .'s to allow path names like ./... 3757c478bd9Sstevel@tonic-gate * If "fcc" has been unset, then short-circuit those tests, but not 3767c478bd9Sstevel@tonic-gate * the +... test. 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate static int 3797c478bd9Sstevel@tonic-gate isfileaddr(char *name) 3807c478bd9Sstevel@tonic-gate { 3817c478bd9Sstevel@tonic-gate register char *cp; 3827c478bd9Sstevel@tonic-gate char *fcc = value("fcc"); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate if (any('@', name)) 3857c478bd9Sstevel@tonic-gate return (0); 3867c478bd9Sstevel@tonic-gate if (*name == '+') 3877c478bd9Sstevel@tonic-gate return (1); 3887c478bd9Sstevel@tonic-gate if (fcc == NOSTR) 3897c478bd9Sstevel@tonic-gate return (0); 3907c478bd9Sstevel@tonic-gate for (cp = name; *cp; cp++) { 3917c478bd9Sstevel@tonic-gate if (*cp == '.') 3927c478bd9Sstevel@tonic-gate continue; 3937c478bd9Sstevel@tonic-gate if (any(*cp, metanet)) 3947c478bd9Sstevel@tonic-gate return (0); 3957c478bd9Sstevel@tonic-gate if (*cp == '/') 3967c478bd9Sstevel@tonic-gate return (1); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate return (0); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Map all of the aliased users in the invoker's mailrc 4037c478bd9Sstevel@tonic-gate * file and insert them into the list. 4047c478bd9Sstevel@tonic-gate * Changed after all these months of service to recursively 4057c478bd9Sstevel@tonic-gate * expand names (2/14/80). 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate struct name * 4097c478bd9Sstevel@tonic-gate usermap(struct name *names) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate register struct name *newnames, *np, *cp; 4127c478bd9Sstevel@tonic-gate struct grouphead *gh; 4137c478bd9Sstevel@tonic-gate register int metoo; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate newnames = NIL; 4167c478bd9Sstevel@tonic-gate np = names; 4177c478bd9Sstevel@tonic-gate metoo = (value("metoo") != NOSTR); 4187c478bd9Sstevel@tonic-gate while (np != NIL) { 4197c478bd9Sstevel@tonic-gate if (np->n_name[0] == '\\') { 4207c478bd9Sstevel@tonic-gate cp = np->n_flink; 4217c478bd9Sstevel@tonic-gate newnames = put(newnames, np); 4227c478bd9Sstevel@tonic-gate np = cp; 4237c478bd9Sstevel@tonic-gate continue; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate gh = findgroup(np->n_name); 4267c478bd9Sstevel@tonic-gate cp = np->n_flink; 4277c478bd9Sstevel@tonic-gate if (gh != NOGRP) 4287c478bd9Sstevel@tonic-gate newnames = gexpand(newnames, gh, metoo, np->n_type); 4297c478bd9Sstevel@tonic-gate else 4307c478bd9Sstevel@tonic-gate newnames = put(newnames, np); 4317c478bd9Sstevel@tonic-gate np = cp; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate return (newnames); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * Recursively expand a group name. We limit the expansion to some 4387c478bd9Sstevel@tonic-gate * fixed level to keep things from going haywire. 4397c478bd9Sstevel@tonic-gate * Direct recursion is not expanded for convenience. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate static struct name * 4437c478bd9Sstevel@tonic-gate gexpand(struct name *nlist, struct grouphead *gh, int metoo, int arg_ntype) 4447c478bd9Sstevel@tonic-gate { 4457c478bd9Sstevel@tonic-gate short ntype = (short)arg_ntype; 4467c478bd9Sstevel@tonic-gate struct mgroup *gp; 4477c478bd9Sstevel@tonic-gate struct grouphead *ngh; 4487c478bd9Sstevel@tonic-gate struct name *np; 4497c478bd9Sstevel@tonic-gate static int depth; 4507c478bd9Sstevel@tonic-gate register char *cp; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (depth > MAXEXP) { 4537c478bd9Sstevel@tonic-gate printf(gettext("Expanding alias to depth larger than %d\n"), 4547c478bd9Sstevel@tonic-gate MAXEXP); 4557c478bd9Sstevel@tonic-gate return (nlist); 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate depth++; 4587c478bd9Sstevel@tonic-gate for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) { 4597c478bd9Sstevel@tonic-gate cp = gp->ge_name; 4607c478bd9Sstevel@tonic-gate if (*cp == '\\') 4617c478bd9Sstevel@tonic-gate goto quote; 4627c478bd9Sstevel@tonic-gate if (strcmp(cp, gh->g_name) == 0) 4637c478bd9Sstevel@tonic-gate goto quote; 4647c478bd9Sstevel@tonic-gate if ((ngh = findgroup(cp)) != NOGRP) { 4657c478bd9Sstevel@tonic-gate nlist = gexpand(nlist, ngh, metoo, ntype); 4667c478bd9Sstevel@tonic-gate continue; 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate quote: 4697c478bd9Sstevel@tonic-gate np = nalloc(cp); 4707c478bd9Sstevel@tonic-gate np->n_type = ntype; 4717c478bd9Sstevel@tonic-gate /* 4727c478bd9Sstevel@tonic-gate * At this point should allow to expand 4737c478bd9Sstevel@tonic-gate * to self if only person in group 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate if (gp == gh->g_list && gp->ge_link == NOGE) 4767c478bd9Sstevel@tonic-gate goto skip; 4777c478bd9Sstevel@tonic-gate if (!metoo && samebody(myname, gp->ge_name, FALSE)) 4787c478bd9Sstevel@tonic-gate np->n_type |= GDEL; 4797c478bd9Sstevel@tonic-gate skip: 4807c478bd9Sstevel@tonic-gate nlist = put(nlist, np); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate depth--; 4837c478bd9Sstevel@tonic-gate return (nlist); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * Normalize a network name for comparison purposes. 4887c478bd9Sstevel@tonic-gate */ 4897c478bd9Sstevel@tonic-gate static char * 4907c478bd9Sstevel@tonic-gate norm(register char *user, register char *ubuf, int nbangs) 4917c478bd9Sstevel@tonic-gate { 4927c478bd9Sstevel@tonic-gate register char *cp; 4937c478bd9Sstevel@tonic-gate int inubuf = 0; 4947c478bd9Sstevel@tonic-gate 495287247a8SAlexander Pyhalov while (*user++ == '!') 496287247a8SAlexander Pyhalov ; 4977c478bd9Sstevel@tonic-gate user--; 4987c478bd9Sstevel@tonic-gate if (!strchr(user, '!')) { 4997c478bd9Sstevel@tonic-gate snprintf(ubuf, BUFSIZ, "%s!%s", host, user); 5007c478bd9Sstevel@tonic-gate user = ubuf; 5017c478bd9Sstevel@tonic-gate inubuf++; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate if (nbangs) { 5047c478bd9Sstevel@tonic-gate cp = user + strlen(user); 5057c478bd9Sstevel@tonic-gate while (nbangs--) 506287247a8SAlexander Pyhalov while (cp > user && *--cp != '!') 507287247a8SAlexander Pyhalov ; 5087c478bd9Sstevel@tonic-gate user = (cp > user) ? ++cp : cp; 5097c478bd9Sstevel@tonic-gate /* 5107c478bd9Sstevel@tonic-gate * Now strip off all Internet-type 5117c478bd9Sstevel@tonic-gate * hosts. 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate if ((cp = strchr(user, '%')) == NOSTR) 5147c478bd9Sstevel@tonic-gate cp = strchr(user, '@'); 5157c478bd9Sstevel@tonic-gate if (cp != NOSTR) { 5167c478bd9Sstevel@tonic-gate if (!inubuf) { 5177c478bd9Sstevel@tonic-gate strncpy(ubuf, user, cp - user); 5187c478bd9Sstevel@tonic-gate ubuf[cp - user] = '\0'; 5197c478bd9Sstevel@tonic-gate user = ubuf; 5207c478bd9Sstevel@tonic-gate } else 5217c478bd9Sstevel@tonic-gate *cp = '\0'; 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } 524287247a8SAlexander Pyhalov return (user); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * Implement allnet options. 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate int 5317c478bd9Sstevel@tonic-gate samebody(register char *user, register char *addr, int fuzzy) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate char ubuf[BUFSIZ], abuf[BUFSIZ]; 5347c478bd9Sstevel@tonic-gate char *allnet = value("allnet"); 535287247a8SAlexander Pyhalov int nbangs = allnet ? (strcmp(allnet, "uucp") == 0) ? 2 : 1 : 0; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate if (fuzzy && value("fuzzymatch")) { 5387c478bd9Sstevel@tonic-gate int i; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate (void) strlcpy(ubuf, user, BUFSIZ); 5417c478bd9Sstevel@tonic-gate for (i = 0; ubuf[i]; i++) 5427c478bd9Sstevel@tonic-gate ubuf[i] = tolower(ubuf[i]); 5437c478bd9Sstevel@tonic-gate (void) strlcpy(abuf, addr, BUFSIZ); 5447c478bd9Sstevel@tonic-gate for (i = 0; abuf[i]; i++) 5457c478bd9Sstevel@tonic-gate abuf[i] = tolower(abuf[i]); 5467c478bd9Sstevel@tonic-gate return (strstr(abuf, ubuf) != NOSTR); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate user = norm(user, ubuf, nbangs); 5497c478bd9Sstevel@tonic-gate addr = norm(addr, abuf, nbangs); 550287247a8SAlexander Pyhalov return (strcmp(user, addr) == 0); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate /* 5547c478bd9Sstevel@tonic-gate * Compute the length of the passed name list and 5557c478bd9Sstevel@tonic-gate * return it. 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate static int 5587c478bd9Sstevel@tonic-gate lengthof(struct name *name) 5597c478bd9Sstevel@tonic-gate { 5607c478bd9Sstevel@tonic-gate register struct name *np; 5617c478bd9Sstevel@tonic-gate register int c; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate for (c = 0, np = name; np != NIL; c++, np = np->n_flink) 5647c478bd9Sstevel@tonic-gate ; 5657c478bd9Sstevel@tonic-gate return (c); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * Concatenate the two passed name lists, return the result. 5707c478bd9Sstevel@tonic-gate */ 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate struct name * 5737c478bd9Sstevel@tonic-gate cat(struct name *n1, struct name *n2) 5747c478bd9Sstevel@tonic-gate { 5757c478bd9Sstevel@tonic-gate register struct name *tail; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (n1 == NIL) 5787c478bd9Sstevel@tonic-gate return (n2); 5797c478bd9Sstevel@tonic-gate if (n2 == NIL) 5807c478bd9Sstevel@tonic-gate return (n1); 5817c478bd9Sstevel@tonic-gate tail = tailof(n1); 5827c478bd9Sstevel@tonic-gate tail->n_flink = n2; 5837c478bd9Sstevel@tonic-gate n2->n_blink = tail; 5847c478bd9Sstevel@tonic-gate return (n1); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* 5887c478bd9Sstevel@tonic-gate * Unpack the name list onto a vector of strings. 5897c478bd9Sstevel@tonic-gate * Return an error if the name list won't fit. 5907c478bd9Sstevel@tonic-gate */ 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate char ** 5937c478bd9Sstevel@tonic-gate unpack(struct name *np) 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate register char **ap, **top; 5967c478bd9Sstevel@tonic-gate register struct name *n; 5977c478bd9Sstevel@tonic-gate char hbuf[10]; 5987c478bd9Sstevel@tonic-gate int t, extra, metoo, verbose; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate n = np; 6017c478bd9Sstevel@tonic-gate if ((t = lengthof(n)) == 0) 6027c478bd9Sstevel@tonic-gate panic("No names to unpack"); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* 605*5422785dSRobert Mustacchi * Compute the number of extra arguments we will need. We need at least 606*5422785dSRobert Mustacchi * 3 extra -- one for "mail", one for a terminating -- to stop sendmail 607*5422785dSRobert Mustacchi * option processing, and one for the terminating 0 pointer. 608*5422785dSRobert Mustacchi * 609*5422785dSRobert Mustacchi * Additional spots may be needed to pass along -r and -f to the host 610*5422785dSRobert Mustacchi * mailer. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate 613*5422785dSRobert Mustacchi extra = 3; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate if (rflag != NOSTR) 6167c478bd9Sstevel@tonic-gate extra += 2; 6177c478bd9Sstevel@tonic-gate extra++; 6187c478bd9Sstevel@tonic-gate metoo = value("metoo") != NOSTR; 6197c478bd9Sstevel@tonic-gate if (metoo) 6207c478bd9Sstevel@tonic-gate extra++; 6217c478bd9Sstevel@tonic-gate verbose = value("verbose") != NOSTR; 6227c478bd9Sstevel@tonic-gate if (verbose) 6237c478bd9Sstevel@tonic-gate extra++; 6247c478bd9Sstevel@tonic-gate if (hflag) 6257c478bd9Sstevel@tonic-gate extra += 2; 6267c478bd9Sstevel@tonic-gate top = (char **)salloc((t + extra) * sizeof (char *)); 6277c478bd9Sstevel@tonic-gate ap = top; 628287247a8SAlexander Pyhalov *ap++ = "sendmail"; 6297c478bd9Sstevel@tonic-gate if (rflag != NOSTR) { 6307c478bd9Sstevel@tonic-gate *ap++ = "-r"; 6317c478bd9Sstevel@tonic-gate *ap++ = rflag; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate *ap++ = "-i"; 6347c478bd9Sstevel@tonic-gate if (metoo) 6357c478bd9Sstevel@tonic-gate *ap++ = "-m"; 6367c478bd9Sstevel@tonic-gate if (verbose) 6377c478bd9Sstevel@tonic-gate *ap++ = "-v"; 6387c478bd9Sstevel@tonic-gate if (hflag) { 6397c478bd9Sstevel@tonic-gate *ap++ = "-h"; 6407c478bd9Sstevel@tonic-gate snprintf(hbuf, sizeof (hbuf), "%d", hflag); 6417c478bd9Sstevel@tonic-gate *ap++ = savestr(hbuf); 6427c478bd9Sstevel@tonic-gate } 643*5422785dSRobert Mustacchi *ap++ = "--"; 6447c478bd9Sstevel@tonic-gate while (n != NIL) { 6457c478bd9Sstevel@tonic-gate if (n->n_type & GDEL) { 6467c478bd9Sstevel@tonic-gate n = n->n_flink; 6477c478bd9Sstevel@tonic-gate continue; 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate *ap++ = n->n_name; 6507c478bd9Sstevel@tonic-gate n = n->n_flink; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate *ap = NOSTR; 6537c478bd9Sstevel@tonic-gate return (top); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * See if the user named himself as a destination 6587c478bd9Sstevel@tonic-gate * for outgoing mail. If so, set the global flag 6597c478bd9Sstevel@tonic-gate * selfsent so that we avoid removing his mailbox. 6607c478bd9Sstevel@tonic-gate */ 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate void 6637c478bd9Sstevel@tonic-gate mechk(struct name *names) 6647c478bd9Sstevel@tonic-gate { 6657c478bd9Sstevel@tonic-gate register struct name *np; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate for (np = names; np != NIL; np = np->n_flink) 6687c478bd9Sstevel@tonic-gate if ((np->n_type & GDEL) == 0 && 6697c478bd9Sstevel@tonic-gate samebody(np->n_name, myname, FALSE)) { 6707c478bd9Sstevel@tonic-gate selfsent++; 6717c478bd9Sstevel@tonic-gate return; 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * Remove all of the duplicates from the passed name list by 6777c478bd9Sstevel@tonic-gate * insertion sorting them, then checking for dups. 6787c478bd9Sstevel@tonic-gate * Return the head of the new list. 6797c478bd9Sstevel@tonic-gate */ 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate struct name * 6827c478bd9Sstevel@tonic-gate elide(struct name *names) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate register struct name *np, *t, *newnames; 6857c478bd9Sstevel@tonic-gate struct name *x; 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (names == NIL) 6887c478bd9Sstevel@tonic-gate return (NIL); 6897c478bd9Sstevel@tonic-gate newnames = names; 6907c478bd9Sstevel@tonic-gate np = names; 6917c478bd9Sstevel@tonic-gate np = np->n_flink; 6927c478bd9Sstevel@tonic-gate if (np != NIL) 6937c478bd9Sstevel@tonic-gate np->n_blink = NIL; 6947c478bd9Sstevel@tonic-gate newnames->n_flink = NIL; 6957c478bd9Sstevel@tonic-gate while (np != NIL) { 6967c478bd9Sstevel@tonic-gate t = newnames; 6977c478bd9Sstevel@tonic-gate while (strcmp(t->n_name, np->n_name) < 0) { 6987c478bd9Sstevel@tonic-gate if (t->n_flink == NIL) 6997c478bd9Sstevel@tonic-gate break; 7007c478bd9Sstevel@tonic-gate t = t->n_flink; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate /* 7047c478bd9Sstevel@tonic-gate * If we ran out of t's, put the new entry after 7057c478bd9Sstevel@tonic-gate * the current value of t. 7067c478bd9Sstevel@tonic-gate */ 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (strcmp(t->n_name, np->n_name) < 0) { 7097c478bd9Sstevel@tonic-gate t->n_flink = np; 7107c478bd9Sstevel@tonic-gate np->n_blink = t; 7117c478bd9Sstevel@tonic-gate t = np; 7127c478bd9Sstevel@tonic-gate np = np->n_flink; 7137c478bd9Sstevel@tonic-gate t->n_flink = NIL; 7147c478bd9Sstevel@tonic-gate continue; 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate /* 7187c478bd9Sstevel@tonic-gate * Otherwise, put the new entry in front of the 7197c478bd9Sstevel@tonic-gate * current t. If at the front of the list, 7207c478bd9Sstevel@tonic-gate * the new guy becomes the new head of the list. 7217c478bd9Sstevel@tonic-gate */ 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate if (t == newnames) { 7247c478bd9Sstevel@tonic-gate t = np; 7257c478bd9Sstevel@tonic-gate np = np->n_flink; 7267c478bd9Sstevel@tonic-gate t->n_flink = newnames; 7277c478bd9Sstevel@tonic-gate newnames->n_blink = t; 7287c478bd9Sstevel@tonic-gate t->n_blink = NIL; 7297c478bd9Sstevel@tonic-gate newnames = t; 7307c478bd9Sstevel@tonic-gate continue; 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate /* 7347c478bd9Sstevel@tonic-gate * The normal case -- we are inserting into the 7357c478bd9Sstevel@tonic-gate * middle of the list. 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate x = np; 7397c478bd9Sstevel@tonic-gate np = np->n_flink; 7407c478bd9Sstevel@tonic-gate x->n_flink = t; 7417c478bd9Sstevel@tonic-gate x->n_blink = t->n_blink; 7427c478bd9Sstevel@tonic-gate t->n_blink->n_flink = x; 7437c478bd9Sstevel@tonic-gate t->n_blink = x; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * Now the list headed up by new is sorted. 7487c478bd9Sstevel@tonic-gate * Go through it and remove duplicates. 7497c478bd9Sstevel@tonic-gate * Remember the best "type" among all the 7507c478bd9Sstevel@tonic-gate * duplicates of a name. 7517c478bd9Sstevel@tonic-gate */ 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate np = newnames; 7547c478bd9Sstevel@tonic-gate while (np != NIL) { 7557c478bd9Sstevel@tonic-gate int type; 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate t = np; 7587c478bd9Sstevel@tonic-gate type = np->n_type; 7597c478bd9Sstevel@tonic-gate while (t->n_flink != NIL && 7607c478bd9Sstevel@tonic-gate strcmp(np->n_name, t->n_flink->n_name) == 0) { 7617c478bd9Sstevel@tonic-gate t = t->n_flink; 7627c478bd9Sstevel@tonic-gate /* "To" before "Cc" before "Bcc" */ 7637c478bd9Sstevel@tonic-gate if (t->n_type < type) 7647c478bd9Sstevel@tonic-gate type = t->n_type; 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate if (t == np || t == NIL) { 7677c478bd9Sstevel@tonic-gate np = np->n_flink; 7687c478bd9Sstevel@tonic-gate continue; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* 7727c478bd9Sstevel@tonic-gate * Now t points to the last entry with the same name 7737c478bd9Sstevel@tonic-gate * as np. Make np point beyond t. 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate np->n_flink = t->n_flink; 7777c478bd9Sstevel@tonic-gate if (t->n_flink != NIL) 7787c478bd9Sstevel@tonic-gate t->n_flink->n_blink = np; 7797c478bd9Sstevel@tonic-gate np->n_type = type; 7807c478bd9Sstevel@tonic-gate np = np->n_flink; 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate return (newnames); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * Put another node onto a list of names and return 7877c478bd9Sstevel@tonic-gate * the list. 7887c478bd9Sstevel@tonic-gate */ 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate static struct name * 7917c478bd9Sstevel@tonic-gate put(struct name *list, struct name *node) 7927c478bd9Sstevel@tonic-gate { 7937c478bd9Sstevel@tonic-gate node->n_flink = list; 7947c478bd9Sstevel@tonic-gate node->n_blink = NIL; 7957c478bd9Sstevel@tonic-gate if (list != NIL) 7967c478bd9Sstevel@tonic-gate list->n_blink = node; 7977c478bd9Sstevel@tonic-gate return (node); 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * Delete the given name from a namelist. 8037c478bd9Sstevel@tonic-gate */ 8047c478bd9Sstevel@tonic-gate struct name * 8057c478bd9Sstevel@tonic-gate delname(register struct name *np, char name[]) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate register struct name *p; 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) 8107c478bd9Sstevel@tonic-gate if (samebody(name, p->n_name, FALSE)) { 8117c478bd9Sstevel@tonic-gate if (p->n_blink == NIL) { 8127c478bd9Sstevel@tonic-gate if (p->n_flink != NIL) 8137c478bd9Sstevel@tonic-gate p->n_flink->n_blink = NIL; 8147c478bd9Sstevel@tonic-gate np = p->n_flink; 8157c478bd9Sstevel@tonic-gate continue; 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate if (p->n_flink == NIL) { 8187c478bd9Sstevel@tonic-gate if (p->n_blink != NIL) 8197c478bd9Sstevel@tonic-gate p->n_blink->n_flink = NIL; 8207c478bd9Sstevel@tonic-gate continue; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate p->n_blink->n_flink = p->n_flink; 8237c478bd9Sstevel@tonic-gate p->n_flink->n_blink = p->n_blink; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate return (np); 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate /* 8297c478bd9Sstevel@tonic-gate * Call the given routine on each element of the name 8307c478bd9Sstevel@tonic-gate * list, replacing said value if need be. 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate void 8347c478bd9Sstevel@tonic-gate mapf(register struct name *np, char *from) 8357c478bd9Sstevel@tonic-gate { 8367c478bd9Sstevel@tonic-gate register struct name *p; 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate if (debug) fprintf(stderr, "mapf %lx, %s\n", (long)np, from); 8397c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) 8407c478bd9Sstevel@tonic-gate if ((p->n_type & GDEL) == 0) { 8417c478bd9Sstevel@tonic-gate p->n_name = netmap(p->n_name, from); 8427c478bd9Sstevel@tonic-gate p->n_full = splice(p->n_name, p->n_full); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate if (debug) fprintf(stderr, "mapf %s done\n", from); 8457c478bd9Sstevel@tonic-gate } 846