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: }

Defined functions

cat defined in line 538; used 3 times
cmpdomain defined in line 793; used 1 times
count defined in line 781; used 2 times
delname defined in line 807; used 5 times
detract defined in line 106; used 5 times
elide defined in line 649; used 4 times
extract defined in line 63; used 6 times
gexpand defined in line 472; used 3 times
isfileaddr defined in line 407; used 1 times
lengthof defined in line 523; used 1 times
mapf defined in line 839; used 2 times
mechk defined in line 631; used 1 times
nalloc defined in line 25; used 2 times
nstrcmp defined in line 748; used 2 times
outof defined in line 254; used 2 times
prettyprint defined in line 854; never used
put defined in line 765; used 4 times
tailof defined in line 43; used 1 times
unpack defined in line 559; used 2 times
usermap defined in line 435; used 2 times
verify defined in line 193; used 2 times
yankword defined in line 153; used 3 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1985-11-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2171
Valid CSS Valid XHTML 1.0 Strict