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