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