1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright (c) 1985-2001 by Sun Microsystems, Inc. 28*7c478bd9Sstevel@tonic-gate * All rights reserved. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 33*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 34*7c478bd9Sstevel@tonic-gate * All Rights Reserved 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 37*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 38*7c478bd9Sstevel@tonic-gate * contributors. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 45*7c478bd9Sstevel@tonic-gate * mail program 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * Handle name lists. 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #include "rcv.h" 51*7c478bd9Sstevel@tonic-gate #include <locale.h> 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate static struct name *nalloc(char str[]); 54*7c478bd9Sstevel@tonic-gate static int isfileaddr(char *name); 55*7c478bd9Sstevel@tonic-gate static int lengthof(struct name *name); 56*7c478bd9Sstevel@tonic-gate static struct name *gexpand(struct name *nlist, struct grouphead *gh, int metoo, int arg_ntype); 57*7c478bd9Sstevel@tonic-gate static char *norm(register char *user, register char *ubuf, int nbangs); 58*7c478bd9Sstevel@tonic-gate static struct name *put(struct name *list, struct name *node); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* 61*7c478bd9Sstevel@tonic-gate * Allocate a single element of a name list, 62*7c478bd9Sstevel@tonic-gate * initialize its name field to the passed 63*7c478bd9Sstevel@tonic-gate * name and return it. 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate static struct name * 67*7c478bd9Sstevel@tonic-gate nalloc(char str[]) 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate register struct name *np; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate np = (struct name *) salloc(sizeof *np); 72*7c478bd9Sstevel@tonic-gate np->n_flink = NIL; 73*7c478bd9Sstevel@tonic-gate np->n_blink = NIL; 74*7c478bd9Sstevel@tonic-gate np->n_type = -1; 75*7c478bd9Sstevel@tonic-gate np->n_full = savestr(str); 76*7c478bd9Sstevel@tonic-gate np->n_name = skin(np->n_full); 77*7c478bd9Sstevel@tonic-gate return(np); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * Find the tail of a list and return it. 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate struct name * 85*7c478bd9Sstevel@tonic-gate tailof(struct name *name) 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate register struct name *np; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate np = name; 90*7c478bd9Sstevel@tonic-gate if (np == NIL) 91*7c478bd9Sstevel@tonic-gate return(NIL); 92*7c478bd9Sstevel@tonic-gate while (np->n_flink != NIL) 93*7c478bd9Sstevel@tonic-gate np = np->n_flink; 94*7c478bd9Sstevel@tonic-gate return(np); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * Extract a list of names from a line, 99*7c478bd9Sstevel@tonic-gate * and make a list of names from it. 100*7c478bd9Sstevel@tonic-gate * Return the list or NIL if none found. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate struct name * 104*7c478bd9Sstevel@tonic-gate extract(char line[], int arg_ntype) 105*7c478bd9Sstevel@tonic-gate { 106*7c478bd9Sstevel@tonic-gate short ntype = (short)arg_ntype; 107*7c478bd9Sstevel@tonic-gate register char *cp; 108*7c478bd9Sstevel@tonic-gate register struct name *top, *np, *t; 109*7c478bd9Sstevel@tonic-gate char nbuf[BUFSIZ], abuf[BUFSIZ]; 110*7c478bd9Sstevel@tonic-gate int comma; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate if (line == NOSTR || strlen(line) == 0) 113*7c478bd9Sstevel@tonic-gate return(NIL); 114*7c478bd9Sstevel@tonic-gate comma = docomma(line); 115*7c478bd9Sstevel@tonic-gate top = NIL; 116*7c478bd9Sstevel@tonic-gate np = NIL; 117*7c478bd9Sstevel@tonic-gate cp = line; 118*7c478bd9Sstevel@tonic-gate while ((cp = yankword(cp, nbuf, sizeof (nbuf), comma)) != NOSTR) { 119*7c478bd9Sstevel@tonic-gate if (np != NIL && equal(nbuf, "at")) { 120*7c478bd9Sstevel@tonic-gate nstrcpy(abuf, sizeof (abuf), nbuf); 121*7c478bd9Sstevel@tonic-gate if ((cp = yankword(cp, nbuf, sizeof (nbuf), 122*7c478bd9Sstevel@tonic-gate comma)) == NOSTR) { 123*7c478bd9Sstevel@tonic-gate nstrcpy(nbuf, sizeof (nbuf), abuf); 124*7c478bd9Sstevel@tonic-gate goto normal; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate snprintf(abuf, sizeof (abuf), "%s@%s", np->n_name, 127*7c478bd9Sstevel@tonic-gate nbuf); 128*7c478bd9Sstevel@tonic-gate np->n_name = savestr(abuf); 129*7c478bd9Sstevel@tonic-gate continue; 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate normal: 132*7c478bd9Sstevel@tonic-gate t = nalloc(nbuf); 133*7c478bd9Sstevel@tonic-gate t->n_type = ntype; 134*7c478bd9Sstevel@tonic-gate if (top == NIL) 135*7c478bd9Sstevel@tonic-gate top = t; 136*7c478bd9Sstevel@tonic-gate else 137*7c478bd9Sstevel@tonic-gate np->n_flink = t; 138*7c478bd9Sstevel@tonic-gate t->n_blink = np; 139*7c478bd9Sstevel@tonic-gate np = t; 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate return(top); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * Turn a list of names into a string of the same names. 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate char * 149*7c478bd9Sstevel@tonic-gate detract(register struct name *np, int ntype) 150*7c478bd9Sstevel@tonic-gate { 151*7c478bd9Sstevel@tonic-gate register int s; 152*7c478bd9Sstevel@tonic-gate register char *cp, *top; 153*7c478bd9Sstevel@tonic-gate register struct name *p; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if (np == NIL) 156*7c478bd9Sstevel@tonic-gate return(NOSTR); 157*7c478bd9Sstevel@tonic-gate s = 0; 158*7c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) { 159*7c478bd9Sstevel@tonic-gate if ((ntype && (p->n_type & GMASK) != ntype) 160*7c478bd9Sstevel@tonic-gate || (p->n_type & GDEL)) 161*7c478bd9Sstevel@tonic-gate continue; 162*7c478bd9Sstevel@tonic-gate s += strlen(p->n_full) + 2; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate if (s == 0) 165*7c478bd9Sstevel@tonic-gate return(NOSTR); 166*7c478bd9Sstevel@tonic-gate top = (char *)salloc((unsigned)(++s)); 167*7c478bd9Sstevel@tonic-gate cp = top; 168*7c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) { 169*7c478bd9Sstevel@tonic-gate if ((ntype && (p->n_type & GMASK) != ntype) 170*7c478bd9Sstevel@tonic-gate || (p->n_type & GDEL)) 171*7c478bd9Sstevel@tonic-gate continue; 172*7c478bd9Sstevel@tonic-gate cp = copy(p->n_full, cp); 173*7c478bd9Sstevel@tonic-gate *cp++ = ','; 174*7c478bd9Sstevel@tonic-gate *cp++ = ' '; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate *cp = 0; 177*7c478bd9Sstevel@tonic-gate return(top); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate struct name * 181*7c478bd9Sstevel@tonic-gate outpre(struct name *to) 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate register struct name *np; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate for (np = to; np; np = np->n_flink) 186*7c478bd9Sstevel@tonic-gate if (isfileaddr(np->n_name)) 187*7c478bd9Sstevel@tonic-gate np->n_type |= GDEL; 188*7c478bd9Sstevel@tonic-gate return to; 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* 192*7c478bd9Sstevel@tonic-gate * For each recipient in the passed name list with a / 193*7c478bd9Sstevel@tonic-gate * in the name, append the message to the end of the named file 194*7c478bd9Sstevel@tonic-gate * and remove him from the recipient list. 195*7c478bd9Sstevel@tonic-gate * 196*7c478bd9Sstevel@tonic-gate * Recipients whose name begins with | are piped through the given 197*7c478bd9Sstevel@tonic-gate * program and removed. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate int 201*7c478bd9Sstevel@tonic-gate outof(struct name *names, FILE *fo) 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate register int c; 204*7c478bd9Sstevel@tonic-gate register struct name *np; 205*7c478bd9Sstevel@tonic-gate time_t now; 206*7c478bd9Sstevel@tonic-gate char *date, *fname, *shell; 207*7c478bd9Sstevel@tonic-gate FILE *fout, *fin; 208*7c478bd9Sstevel@tonic-gate int ispipe; 209*7c478bd9Sstevel@tonic-gate int nout = 0; 210*7c478bd9Sstevel@tonic-gate int fd = 0; 211*7c478bd9Sstevel@tonic-gate #ifdef preSVr4 212*7c478bd9Sstevel@tonic-gate char line[BUFSIZ]; 213*7c478bd9Sstevel@tonic-gate #endif 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate for (np = names; np != NIL; np = np->n_flink) { 216*7c478bd9Sstevel@tonic-gate if (!isfileaddr(np->n_name) && np->n_name[0] != '|') 217*7c478bd9Sstevel@tonic-gate continue; 218*7c478bd9Sstevel@tonic-gate nout++; 219*7c478bd9Sstevel@tonic-gate ispipe = np->n_name[0] == '|'; 220*7c478bd9Sstevel@tonic-gate if (ispipe) 221*7c478bd9Sstevel@tonic-gate fname = np->n_name+1; 222*7c478bd9Sstevel@tonic-gate else 223*7c478bd9Sstevel@tonic-gate fname = safeexpand(np->n_name); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * See if we have copied the complete message out yet. 227*7c478bd9Sstevel@tonic-gate * If not, do so. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate if (image < 0) { 231*7c478bd9Sstevel@tonic-gate fd = open(tempEdit, O_CREAT|O_EXCL|O_APPEND|O_WRONLY, 232*7c478bd9Sstevel@tonic-gate 0600); 233*7c478bd9Sstevel@tonic-gate if ((fd < 0) && (errno == EEXIST)) { 234*7c478bd9Sstevel@tonic-gate if ((fd = open(tempEdit, O_APPEND|O_WRONLY, 235*7c478bd9Sstevel@tonic-gate 0600)) < 0) { 236*7c478bd9Sstevel@tonic-gate perror(tempEdit); 237*7c478bd9Sstevel@tonic-gate senderr++; 238*7c478bd9Sstevel@tonic-gate goto cant; 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate if ((fout = fdopen(fd, "a")) == NULL) { 242*7c478bd9Sstevel@tonic-gate perror(tempEdit); 243*7c478bd9Sstevel@tonic-gate senderr++; 244*7c478bd9Sstevel@tonic-gate goto cant; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate image = open(tempEdit, O_RDWR); 247*7c478bd9Sstevel@tonic-gate unlink(tempEdit); 248*7c478bd9Sstevel@tonic-gate if (image < 0) { 249*7c478bd9Sstevel@tonic-gate perror(tempEdit); 250*7c478bd9Sstevel@tonic-gate senderr++; 251*7c478bd9Sstevel@tonic-gate goto cant; 252*7c478bd9Sstevel@tonic-gate } else { 253*7c478bd9Sstevel@tonic-gate rewind(fo); 254*7c478bd9Sstevel@tonic-gate time(&now); 255*7c478bd9Sstevel@tonic-gate date = ctime(&now); 256*7c478bd9Sstevel@tonic-gate fprintf(fout, "From %s %s", myname, date); 257*7c478bd9Sstevel@tonic-gate while ((c = getc(fo)) != EOF) 258*7c478bd9Sstevel@tonic-gate putc(c, fout); 259*7c478bd9Sstevel@tonic-gate rewind(fo); 260*7c478bd9Sstevel@tonic-gate fflush(fout); 261*7c478bd9Sstevel@tonic-gate if (fferror(fout)) 262*7c478bd9Sstevel@tonic-gate perror(tempEdit); 263*7c478bd9Sstevel@tonic-gate fclose(fout); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* 268*7c478bd9Sstevel@tonic-gate * Now either copy "image" to the desired file 269*7c478bd9Sstevel@tonic-gate * or give it as the standard input to the desired 270*7c478bd9Sstevel@tonic-gate * program as appropriate. 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate if (ispipe) { 274*7c478bd9Sstevel@tonic-gate wait((int *)NULL); 275*7c478bd9Sstevel@tonic-gate switch (fork()) { 276*7c478bd9Sstevel@tonic-gate case 0: 277*7c478bd9Sstevel@tonic-gate sigchild(); 278*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, SIG_IGN); 279*7c478bd9Sstevel@tonic-gate sigset(SIGINT, SIG_IGN); 280*7c478bd9Sstevel@tonic-gate sigset(SIGQUIT, SIG_IGN); 281*7c478bd9Sstevel@tonic-gate close(0); 282*7c478bd9Sstevel@tonic-gate dup(image); 283*7c478bd9Sstevel@tonic-gate close(image); 284*7c478bd9Sstevel@tonic-gate lseek(0, 0L, 0); 285*7c478bd9Sstevel@tonic-gate if ((shell = value("SHELL")) == NOSTR || *shell=='\0') 286*7c478bd9Sstevel@tonic-gate shell = SHELL; 287*7c478bd9Sstevel@tonic-gate (void) execlp(shell, shell, "-c", fname, (char *)0); 288*7c478bd9Sstevel@tonic-gate perror(shell); 289*7c478bd9Sstevel@tonic-gate exit(1); 290*7c478bd9Sstevel@tonic-gate break; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate case (pid_t)-1: 293*7c478bd9Sstevel@tonic-gate perror("fork"); 294*7c478bd9Sstevel@tonic-gate senderr++; 295*7c478bd9Sstevel@tonic-gate goto cant; 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate else { 299*7c478bd9Sstevel@tonic-gate if ((fout = fopen(fname, "a")) == NULL) { 300*7c478bd9Sstevel@tonic-gate perror(fname); 301*7c478bd9Sstevel@tonic-gate senderr++; 302*7c478bd9Sstevel@tonic-gate goto cant; 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate fin = Fdopen(image, "r"); 305*7c478bd9Sstevel@tonic-gate if (fin == NULL) { 306*7c478bd9Sstevel@tonic-gate fprintf(stderr, 307*7c478bd9Sstevel@tonic-gate gettext("Can't reopen image\n")); 308*7c478bd9Sstevel@tonic-gate fclose(fout); 309*7c478bd9Sstevel@tonic-gate senderr++; 310*7c478bd9Sstevel@tonic-gate goto cant; 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate rewind(fin); 313*7c478bd9Sstevel@tonic-gate #ifdef preSVr4 314*7c478bd9Sstevel@tonic-gate putc(getc(fin), fout); 315*7c478bd9Sstevel@tonic-gate while (fgets(line, sizeof line, fin)) { 316*7c478bd9Sstevel@tonic-gate if (!strncmp(line, "From ", 5)) 317*7c478bd9Sstevel@tonic-gate putc('>', fout); 318*7c478bd9Sstevel@tonic-gate fputs(line, fout); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate #else 321*7c478bd9Sstevel@tonic-gate while ((c = getc(fin)) != EOF) 322*7c478bd9Sstevel@tonic-gate putc(c, fout); 323*7c478bd9Sstevel@tonic-gate #endif 324*7c478bd9Sstevel@tonic-gate putc('\n', fout); 325*7c478bd9Sstevel@tonic-gate fflush(fout); 326*7c478bd9Sstevel@tonic-gate if (fferror(fout)) 327*7c478bd9Sstevel@tonic-gate senderr++, perror(fname); 328*7c478bd9Sstevel@tonic-gate fclose(fout); 329*7c478bd9Sstevel@tonic-gate fclose(fin); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate cant: 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * In days of old we removed the entry from the 334*7c478bd9Sstevel@tonic-gate * the list; now for sake of header expansion 335*7c478bd9Sstevel@tonic-gate * we leave it in and mark it as deleted. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate #ifdef CRAZYWOW 339*7c478bd9Sstevel@tonic-gate { 340*7c478bd9Sstevel@tonic-gate register struct name *t, *x; 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate if (np == top) { 343*7c478bd9Sstevel@tonic-gate top = np->n_flink; 344*7c478bd9Sstevel@tonic-gate if (top != NIL) 345*7c478bd9Sstevel@tonic-gate top->n_blink = NIL; 346*7c478bd9Sstevel@tonic-gate np = top; 347*7c478bd9Sstevel@tonic-gate continue; 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate x = np->n_blink; 350*7c478bd9Sstevel@tonic-gate t = np->n_flink; 351*7c478bd9Sstevel@tonic-gate x->n_flink = t; 352*7c478bd9Sstevel@tonic-gate if (t != NIL) 353*7c478bd9Sstevel@tonic-gate t->n_blink = x; 354*7c478bd9Sstevel@tonic-gate np = t; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate #endif 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate np->n_type |= GDEL; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate if (image >= 0) { 361*7c478bd9Sstevel@tonic-gate close(image); 362*7c478bd9Sstevel@tonic-gate image = -1; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate return(nout); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * Determine if the passed address is a local "send to file" address. 369*7c478bd9Sstevel@tonic-gate * If any of the network metacharacters precedes any slashes, it can't 370*7c478bd9Sstevel@tonic-gate * be a filename. We cheat with .'s to allow path names like ./... 371*7c478bd9Sstevel@tonic-gate * If "fcc" has been unset, then short-circuit those tests, but not 372*7c478bd9Sstevel@tonic-gate * the +... test. 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate static int 375*7c478bd9Sstevel@tonic-gate isfileaddr(char *name) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate register char *cp; 378*7c478bd9Sstevel@tonic-gate char *fcc = value("fcc"); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate if (any('@', name)) 381*7c478bd9Sstevel@tonic-gate return(0); 382*7c478bd9Sstevel@tonic-gate if (*name == '+') 383*7c478bd9Sstevel@tonic-gate return(1); 384*7c478bd9Sstevel@tonic-gate if (fcc == NOSTR) 385*7c478bd9Sstevel@tonic-gate return(0); 386*7c478bd9Sstevel@tonic-gate for (cp = name; *cp; cp++) { 387*7c478bd9Sstevel@tonic-gate if (*cp == '.') 388*7c478bd9Sstevel@tonic-gate continue; 389*7c478bd9Sstevel@tonic-gate if (any(*cp, metanet)) 390*7c478bd9Sstevel@tonic-gate return(0); 391*7c478bd9Sstevel@tonic-gate if (*cp == '/') 392*7c478bd9Sstevel@tonic-gate return(1); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate return(0); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * Map all of the aliased users in the invoker's mailrc 399*7c478bd9Sstevel@tonic-gate * file and insert them into the list. 400*7c478bd9Sstevel@tonic-gate * Changed after all these months of service to recursively 401*7c478bd9Sstevel@tonic-gate * expand names (2/14/80). 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate struct name * 405*7c478bd9Sstevel@tonic-gate usermap(struct name *names) 406*7c478bd9Sstevel@tonic-gate { 407*7c478bd9Sstevel@tonic-gate register struct name *newnames, *np, *cp; 408*7c478bd9Sstevel@tonic-gate struct grouphead *gh; 409*7c478bd9Sstevel@tonic-gate register int metoo; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate newnames = NIL; 412*7c478bd9Sstevel@tonic-gate np = names; 413*7c478bd9Sstevel@tonic-gate metoo = (value("metoo") != NOSTR); 414*7c478bd9Sstevel@tonic-gate while (np != NIL) { 415*7c478bd9Sstevel@tonic-gate if (np->n_name[0] == '\\') { 416*7c478bd9Sstevel@tonic-gate cp = np->n_flink; 417*7c478bd9Sstevel@tonic-gate newnames = put(newnames, np); 418*7c478bd9Sstevel@tonic-gate np = cp; 419*7c478bd9Sstevel@tonic-gate continue; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate gh = findgroup(np->n_name); 422*7c478bd9Sstevel@tonic-gate cp = np->n_flink; 423*7c478bd9Sstevel@tonic-gate if (gh != NOGRP) 424*7c478bd9Sstevel@tonic-gate newnames = gexpand(newnames, gh, metoo, np->n_type); 425*7c478bd9Sstevel@tonic-gate else 426*7c478bd9Sstevel@tonic-gate newnames = put(newnames, np); 427*7c478bd9Sstevel@tonic-gate np = cp; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate return(newnames); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* 433*7c478bd9Sstevel@tonic-gate * Recursively expand a group name. We limit the expansion to some 434*7c478bd9Sstevel@tonic-gate * fixed level to keep things from going haywire. 435*7c478bd9Sstevel@tonic-gate * Direct recursion is not expanded for convenience. 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate static struct name * 439*7c478bd9Sstevel@tonic-gate gexpand(struct name *nlist, struct grouphead *gh, int metoo, int arg_ntype) 440*7c478bd9Sstevel@tonic-gate { 441*7c478bd9Sstevel@tonic-gate short ntype = (short)arg_ntype; 442*7c478bd9Sstevel@tonic-gate struct mgroup *gp; 443*7c478bd9Sstevel@tonic-gate struct grouphead *ngh; 444*7c478bd9Sstevel@tonic-gate struct name *np; 445*7c478bd9Sstevel@tonic-gate static int depth; 446*7c478bd9Sstevel@tonic-gate register char *cp; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (depth > MAXEXP) { 449*7c478bd9Sstevel@tonic-gate printf(gettext("Expanding alias to depth larger than %d\n"), 450*7c478bd9Sstevel@tonic-gate MAXEXP); 451*7c478bd9Sstevel@tonic-gate return(nlist); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate depth++; 454*7c478bd9Sstevel@tonic-gate for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) { 455*7c478bd9Sstevel@tonic-gate cp = gp->ge_name; 456*7c478bd9Sstevel@tonic-gate if (*cp == '\\') 457*7c478bd9Sstevel@tonic-gate goto quote; 458*7c478bd9Sstevel@tonic-gate if (strcmp(cp, gh->g_name) == 0) 459*7c478bd9Sstevel@tonic-gate goto quote; 460*7c478bd9Sstevel@tonic-gate if ((ngh = findgroup(cp)) != NOGRP) { 461*7c478bd9Sstevel@tonic-gate nlist = gexpand(nlist, ngh, metoo, ntype); 462*7c478bd9Sstevel@tonic-gate continue; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate quote: 465*7c478bd9Sstevel@tonic-gate np = nalloc(cp); 466*7c478bd9Sstevel@tonic-gate np->n_type = ntype; 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * At this point should allow to expand 469*7c478bd9Sstevel@tonic-gate * to self if only person in group 470*7c478bd9Sstevel@tonic-gate */ 471*7c478bd9Sstevel@tonic-gate if (gp == gh->g_list && gp->ge_link == NOGE) 472*7c478bd9Sstevel@tonic-gate goto skip; 473*7c478bd9Sstevel@tonic-gate if (!metoo && samebody(myname, gp->ge_name, FALSE)) 474*7c478bd9Sstevel@tonic-gate np->n_type |= GDEL; 475*7c478bd9Sstevel@tonic-gate skip: 476*7c478bd9Sstevel@tonic-gate nlist = put(nlist, np); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate depth--; 479*7c478bd9Sstevel@tonic-gate return(nlist); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate /* 483*7c478bd9Sstevel@tonic-gate * Normalize a network name for comparison purposes. 484*7c478bd9Sstevel@tonic-gate */ 485*7c478bd9Sstevel@tonic-gate static char * 486*7c478bd9Sstevel@tonic-gate norm(register char *user, register char *ubuf, int nbangs) 487*7c478bd9Sstevel@tonic-gate { 488*7c478bd9Sstevel@tonic-gate register char *cp; 489*7c478bd9Sstevel@tonic-gate int inubuf = 0; 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate while (*user++ == '!'); 492*7c478bd9Sstevel@tonic-gate user--; 493*7c478bd9Sstevel@tonic-gate if (!strchr(user, '!')) { 494*7c478bd9Sstevel@tonic-gate snprintf(ubuf, BUFSIZ, "%s!%s", host, user); 495*7c478bd9Sstevel@tonic-gate user = ubuf; 496*7c478bd9Sstevel@tonic-gate inubuf++; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate if (nbangs) { 499*7c478bd9Sstevel@tonic-gate cp = user + strlen(user); 500*7c478bd9Sstevel@tonic-gate while (nbangs--) 501*7c478bd9Sstevel@tonic-gate while (cp > user && *--cp != '!'); 502*7c478bd9Sstevel@tonic-gate user = (cp > user) ? ++cp : cp; 503*7c478bd9Sstevel@tonic-gate /* 504*7c478bd9Sstevel@tonic-gate * Now strip off all Internet-type 505*7c478bd9Sstevel@tonic-gate * hosts. 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate if ((cp = strchr(user, '%')) == NOSTR) 508*7c478bd9Sstevel@tonic-gate cp = strchr(user, '@'); 509*7c478bd9Sstevel@tonic-gate if (cp != NOSTR) { 510*7c478bd9Sstevel@tonic-gate if (!inubuf) { 511*7c478bd9Sstevel@tonic-gate strncpy(ubuf, user, cp - user); 512*7c478bd9Sstevel@tonic-gate ubuf[cp - user] = '\0'; 513*7c478bd9Sstevel@tonic-gate user = ubuf; 514*7c478bd9Sstevel@tonic-gate } else 515*7c478bd9Sstevel@tonic-gate *cp = '\0'; 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate return user; 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* 522*7c478bd9Sstevel@tonic-gate * Implement allnet options. 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate int 525*7c478bd9Sstevel@tonic-gate samebody(register char *user, register char *addr, int fuzzy) 526*7c478bd9Sstevel@tonic-gate { 527*7c478bd9Sstevel@tonic-gate char ubuf[BUFSIZ], abuf[BUFSIZ]; 528*7c478bd9Sstevel@tonic-gate char *allnet = value("allnet"); 529*7c478bd9Sstevel@tonic-gate int nbangs = allnet ? !strcmp(allnet, "uucp") ? 2 : 1 : 0; 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate if (fuzzy && value("fuzzymatch")) { 532*7c478bd9Sstevel@tonic-gate int i; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate (void) strlcpy(ubuf, user, BUFSIZ); 535*7c478bd9Sstevel@tonic-gate for (i = 0; ubuf[i]; i++) 536*7c478bd9Sstevel@tonic-gate ubuf[i] = tolower(ubuf[i]); 537*7c478bd9Sstevel@tonic-gate (void) strlcpy(abuf, addr, BUFSIZ); 538*7c478bd9Sstevel@tonic-gate for (i = 0; abuf[i]; i++) 539*7c478bd9Sstevel@tonic-gate abuf[i] = tolower(abuf[i]); 540*7c478bd9Sstevel@tonic-gate return (strstr(abuf, ubuf) != NOSTR); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate user = norm(user, ubuf, nbangs); 543*7c478bd9Sstevel@tonic-gate addr = norm(addr, abuf, nbangs); 544*7c478bd9Sstevel@tonic-gate return strcmp(user, addr) == 0; 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate /* 548*7c478bd9Sstevel@tonic-gate * Compute the length of the passed name list and 549*7c478bd9Sstevel@tonic-gate * return it. 550*7c478bd9Sstevel@tonic-gate */ 551*7c478bd9Sstevel@tonic-gate static int 552*7c478bd9Sstevel@tonic-gate lengthof(struct name *name) 553*7c478bd9Sstevel@tonic-gate { 554*7c478bd9Sstevel@tonic-gate register struct name *np; 555*7c478bd9Sstevel@tonic-gate register int c; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate for (c = 0, np = name; np != NIL; c++, np = np->n_flink) 558*7c478bd9Sstevel@tonic-gate ; 559*7c478bd9Sstevel@tonic-gate return(c); 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate /* 563*7c478bd9Sstevel@tonic-gate * Concatenate the two passed name lists, return the result. 564*7c478bd9Sstevel@tonic-gate */ 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate struct name * 567*7c478bd9Sstevel@tonic-gate cat(struct name *n1, struct name *n2) 568*7c478bd9Sstevel@tonic-gate { 569*7c478bd9Sstevel@tonic-gate register struct name *tail; 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate if (n1 == NIL) 572*7c478bd9Sstevel@tonic-gate return(n2); 573*7c478bd9Sstevel@tonic-gate if (n2 == NIL) 574*7c478bd9Sstevel@tonic-gate return(n1); 575*7c478bd9Sstevel@tonic-gate tail = tailof(n1); 576*7c478bd9Sstevel@tonic-gate tail->n_flink = n2; 577*7c478bd9Sstevel@tonic-gate n2->n_blink = tail; 578*7c478bd9Sstevel@tonic-gate return(n1); 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* 582*7c478bd9Sstevel@tonic-gate * Unpack the name list onto a vector of strings. 583*7c478bd9Sstevel@tonic-gate * Return an error if the name list won't fit. 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate char ** 587*7c478bd9Sstevel@tonic-gate unpack(struct name *np) 588*7c478bd9Sstevel@tonic-gate { 589*7c478bd9Sstevel@tonic-gate register char **ap, **top; 590*7c478bd9Sstevel@tonic-gate register struct name *n; 591*7c478bd9Sstevel@tonic-gate char hbuf[10]; 592*7c478bd9Sstevel@tonic-gate int t, extra, metoo, verbose; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate n = np; 595*7c478bd9Sstevel@tonic-gate if ((t = lengthof(n)) == 0) 596*7c478bd9Sstevel@tonic-gate panic("No names to unpack"); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * Compute the number of extra arguments we will need. 600*7c478bd9Sstevel@tonic-gate * We need at least 2 extra -- one for "mail" and one for 601*7c478bd9Sstevel@tonic-gate * the terminating 0 pointer. 602*7c478bd9Sstevel@tonic-gate * Additional spots may be needed to pass along -r and -f to 603*7c478bd9Sstevel@tonic-gate * the host mailer. 604*7c478bd9Sstevel@tonic-gate */ 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate extra = 2; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate if (rflag != NOSTR) 609*7c478bd9Sstevel@tonic-gate extra += 2; 610*7c478bd9Sstevel@tonic-gate #ifdef SENDMAIL 611*7c478bd9Sstevel@tonic-gate extra++; 612*7c478bd9Sstevel@tonic-gate metoo = value("metoo") != NOSTR; 613*7c478bd9Sstevel@tonic-gate if (metoo) 614*7c478bd9Sstevel@tonic-gate extra++; 615*7c478bd9Sstevel@tonic-gate verbose = value("verbose") != NOSTR; 616*7c478bd9Sstevel@tonic-gate if (verbose) 617*7c478bd9Sstevel@tonic-gate extra++; 618*7c478bd9Sstevel@tonic-gate if (hflag) 619*7c478bd9Sstevel@tonic-gate extra += 2; 620*7c478bd9Sstevel@tonic-gate #endif SENDMAIL 621*7c478bd9Sstevel@tonic-gate top = (char **) salloc((t + extra) * sizeof (char *)); 622*7c478bd9Sstevel@tonic-gate ap = top; 623*7c478bd9Sstevel@tonic-gate *ap++ = "mail"; 624*7c478bd9Sstevel@tonic-gate if (rflag != NOSTR) { 625*7c478bd9Sstevel@tonic-gate *ap++ = "-r"; 626*7c478bd9Sstevel@tonic-gate *ap++ = rflag; 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate #ifdef SENDMAIL 629*7c478bd9Sstevel@tonic-gate *ap++ = "-i"; 630*7c478bd9Sstevel@tonic-gate if (metoo) 631*7c478bd9Sstevel@tonic-gate *ap++ = "-m"; 632*7c478bd9Sstevel@tonic-gate if (verbose) 633*7c478bd9Sstevel@tonic-gate *ap++ = "-v"; 634*7c478bd9Sstevel@tonic-gate if (hflag) { 635*7c478bd9Sstevel@tonic-gate *ap++ = "-h"; 636*7c478bd9Sstevel@tonic-gate snprintf(hbuf, sizeof (hbuf), "%d", hflag); 637*7c478bd9Sstevel@tonic-gate *ap++ = savestr(hbuf); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate #endif SENDMAIL 640*7c478bd9Sstevel@tonic-gate while (n != NIL) { 641*7c478bd9Sstevel@tonic-gate if (n->n_type & GDEL) { 642*7c478bd9Sstevel@tonic-gate n = n->n_flink; 643*7c478bd9Sstevel@tonic-gate continue; 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate *ap++ = n->n_name; 646*7c478bd9Sstevel@tonic-gate n = n->n_flink; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate *ap = NOSTR; 649*7c478bd9Sstevel@tonic-gate return(top); 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate /* 653*7c478bd9Sstevel@tonic-gate * See if the user named himself as a destination 654*7c478bd9Sstevel@tonic-gate * for outgoing mail. If so, set the global flag 655*7c478bd9Sstevel@tonic-gate * selfsent so that we avoid removing his mailbox. 656*7c478bd9Sstevel@tonic-gate */ 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate void 659*7c478bd9Sstevel@tonic-gate mechk(struct name *names) 660*7c478bd9Sstevel@tonic-gate { 661*7c478bd9Sstevel@tonic-gate register struct name *np; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate for (np = names; np != NIL; np = np->n_flink) 664*7c478bd9Sstevel@tonic-gate if ((np->n_type & GDEL) == 0 && 665*7c478bd9Sstevel@tonic-gate samebody(np->n_name, myname, FALSE)) { 666*7c478bd9Sstevel@tonic-gate selfsent++; 667*7c478bd9Sstevel@tonic-gate return; 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate /* 672*7c478bd9Sstevel@tonic-gate * Remove all of the duplicates from the passed name list by 673*7c478bd9Sstevel@tonic-gate * insertion sorting them, then checking for dups. 674*7c478bd9Sstevel@tonic-gate * Return the head of the new list. 675*7c478bd9Sstevel@tonic-gate */ 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate struct name * 678*7c478bd9Sstevel@tonic-gate elide(struct name *names) 679*7c478bd9Sstevel@tonic-gate { 680*7c478bd9Sstevel@tonic-gate register struct name *np, *t, *newnames; 681*7c478bd9Sstevel@tonic-gate struct name *x; 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate if (names == NIL) 684*7c478bd9Sstevel@tonic-gate return(NIL); 685*7c478bd9Sstevel@tonic-gate newnames = names; 686*7c478bd9Sstevel@tonic-gate np = names; 687*7c478bd9Sstevel@tonic-gate np = np->n_flink; 688*7c478bd9Sstevel@tonic-gate if (np != NIL) 689*7c478bd9Sstevel@tonic-gate np->n_blink = NIL; 690*7c478bd9Sstevel@tonic-gate newnames->n_flink = NIL; 691*7c478bd9Sstevel@tonic-gate while (np != NIL) { 692*7c478bd9Sstevel@tonic-gate t = newnames; 693*7c478bd9Sstevel@tonic-gate while (strcmp(t->n_name, np->n_name) < 0) { 694*7c478bd9Sstevel@tonic-gate if (t->n_flink == NIL) 695*7c478bd9Sstevel@tonic-gate break; 696*7c478bd9Sstevel@tonic-gate t = t->n_flink; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * If we ran out of t's, put the new entry after 701*7c478bd9Sstevel@tonic-gate * the current value of t. 702*7c478bd9Sstevel@tonic-gate */ 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate if (strcmp(t->n_name, np->n_name) < 0) { 705*7c478bd9Sstevel@tonic-gate t->n_flink = np; 706*7c478bd9Sstevel@tonic-gate np->n_blink = t; 707*7c478bd9Sstevel@tonic-gate t = np; 708*7c478bd9Sstevel@tonic-gate np = np->n_flink; 709*7c478bd9Sstevel@tonic-gate t->n_flink = NIL; 710*7c478bd9Sstevel@tonic-gate continue; 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * Otherwise, put the new entry in front of the 715*7c478bd9Sstevel@tonic-gate * current t. If at the front of the list, 716*7c478bd9Sstevel@tonic-gate * the new guy becomes the new head of the list. 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate if (t == newnames) { 720*7c478bd9Sstevel@tonic-gate t = np; 721*7c478bd9Sstevel@tonic-gate np = np->n_flink; 722*7c478bd9Sstevel@tonic-gate t->n_flink = newnames; 723*7c478bd9Sstevel@tonic-gate newnames->n_blink = t; 724*7c478bd9Sstevel@tonic-gate t->n_blink = NIL; 725*7c478bd9Sstevel@tonic-gate newnames = t; 726*7c478bd9Sstevel@tonic-gate continue; 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate /* 730*7c478bd9Sstevel@tonic-gate * The normal case -- we are inserting into the 731*7c478bd9Sstevel@tonic-gate * middle of the list. 732*7c478bd9Sstevel@tonic-gate */ 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate x = np; 735*7c478bd9Sstevel@tonic-gate np = np->n_flink; 736*7c478bd9Sstevel@tonic-gate x->n_flink = t; 737*7c478bd9Sstevel@tonic-gate x->n_blink = t->n_blink; 738*7c478bd9Sstevel@tonic-gate t->n_blink->n_flink = x; 739*7c478bd9Sstevel@tonic-gate t->n_blink = x; 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate /* 743*7c478bd9Sstevel@tonic-gate * Now the list headed up by new is sorted. 744*7c478bd9Sstevel@tonic-gate * Go through it and remove duplicates. 745*7c478bd9Sstevel@tonic-gate * Remember the best "type" among all the 746*7c478bd9Sstevel@tonic-gate * duplicates of a name. 747*7c478bd9Sstevel@tonic-gate */ 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate np = newnames; 750*7c478bd9Sstevel@tonic-gate while (np != NIL) { 751*7c478bd9Sstevel@tonic-gate int type; 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate t = np; 754*7c478bd9Sstevel@tonic-gate type = np->n_type; 755*7c478bd9Sstevel@tonic-gate while (t->n_flink!=NIL && 756*7c478bd9Sstevel@tonic-gate strcmp(np->n_name, t->n_flink->n_name) == 0) { 757*7c478bd9Sstevel@tonic-gate t = t->n_flink; 758*7c478bd9Sstevel@tonic-gate /* "To" before "Cc" before "Bcc" */ 759*7c478bd9Sstevel@tonic-gate if (t->n_type < type) 760*7c478bd9Sstevel@tonic-gate type = t->n_type; 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate if (t == np || t == NIL) { 763*7c478bd9Sstevel@tonic-gate np = np->n_flink; 764*7c478bd9Sstevel@tonic-gate continue; 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate /* 768*7c478bd9Sstevel@tonic-gate * Now t points to the last entry with the same name 769*7c478bd9Sstevel@tonic-gate * as np. Make np point beyond t. 770*7c478bd9Sstevel@tonic-gate */ 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate np->n_flink = t->n_flink; 773*7c478bd9Sstevel@tonic-gate if (t->n_flink != NIL) 774*7c478bd9Sstevel@tonic-gate t->n_flink->n_blink = np; 775*7c478bd9Sstevel@tonic-gate np->n_type = type; 776*7c478bd9Sstevel@tonic-gate np = np->n_flink; 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate return(newnames); 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate /* 782*7c478bd9Sstevel@tonic-gate * Put another node onto a list of names and return 783*7c478bd9Sstevel@tonic-gate * the list. 784*7c478bd9Sstevel@tonic-gate */ 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate static struct name * 787*7c478bd9Sstevel@tonic-gate put(struct name *list, struct name *node) 788*7c478bd9Sstevel@tonic-gate { 789*7c478bd9Sstevel@tonic-gate node->n_flink = list; 790*7c478bd9Sstevel@tonic-gate node->n_blink = NIL; 791*7c478bd9Sstevel@tonic-gate if (list != NIL) 792*7c478bd9Sstevel@tonic-gate list->n_blink = node; 793*7c478bd9Sstevel@tonic-gate return(node); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate /* 798*7c478bd9Sstevel@tonic-gate * Delete the given name from a namelist. 799*7c478bd9Sstevel@tonic-gate */ 800*7c478bd9Sstevel@tonic-gate struct name * 801*7c478bd9Sstevel@tonic-gate delname(register struct name *np, char name[]) 802*7c478bd9Sstevel@tonic-gate { 803*7c478bd9Sstevel@tonic-gate register struct name *p; 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) 806*7c478bd9Sstevel@tonic-gate if (samebody(name, p->n_name, FALSE)) { 807*7c478bd9Sstevel@tonic-gate if (p->n_blink == NIL) { 808*7c478bd9Sstevel@tonic-gate if (p->n_flink != NIL) 809*7c478bd9Sstevel@tonic-gate p->n_flink->n_blink = NIL; 810*7c478bd9Sstevel@tonic-gate np = p->n_flink; 811*7c478bd9Sstevel@tonic-gate continue; 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate if (p->n_flink == NIL) { 814*7c478bd9Sstevel@tonic-gate if (p->n_blink != NIL) 815*7c478bd9Sstevel@tonic-gate p->n_blink->n_flink = NIL; 816*7c478bd9Sstevel@tonic-gate continue; 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate p->n_blink->n_flink = p->n_flink; 819*7c478bd9Sstevel@tonic-gate p->n_flink->n_blink = p->n_blink; 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate return(np); 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * Call the given routine on each element of the name 826*7c478bd9Sstevel@tonic-gate * list, replacing said value if need be. 827*7c478bd9Sstevel@tonic-gate */ 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate void 830*7c478bd9Sstevel@tonic-gate mapf(register struct name *np, char *from) 831*7c478bd9Sstevel@tonic-gate { 832*7c478bd9Sstevel@tonic-gate register struct name *p; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if (debug) fprintf(stderr, "mapf %lx, %s\n", (long)np, from); 835*7c478bd9Sstevel@tonic-gate for (p = np; p != NIL; p = p->n_flink) 836*7c478bd9Sstevel@tonic-gate if ((p->n_type & GDEL) == 0) { 837*7c478bd9Sstevel@tonic-gate p->n_name = netmap(p->n_name, from); 838*7c478bd9Sstevel@tonic-gate p->n_full = splice(p->n_name, p->n_full); 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate if (debug) fprintf(stderr, "mapf %s done\n", from); 841*7c478bd9Sstevel@tonic-gate } 842