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