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