Commit | Line | Data |
---|---|---|
761330fe DF |
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 | ||
2ae9f53f | 7 | #ifndef lint |
2fd8b883 | 8 | static char *sccsid = "@(#)names.c 5.2 (Berkeley) %G%"; |
761330fe | 9 | #endif not lint |
65d3742f KS |
10 | |
11 | /* | |
12 | * Mail -- a mail program | |
13 | * | |
14 | * Handle name lists. | |
15 | */ | |
16 | ||
17 | #include "rcv.h" | |
18 | ||
65d3742f KS |
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 | do { | |
160 | for (cp = ap; *cp && any(*cp, " \t,"); cp++) | |
161 | ; | |
162 | if (*cp == '(') { | |
163 | while (*cp && *cp != ')') | |
164 | cp++; | |
165 | if (*cp) | |
166 | cp++; | |
167 | } | |
168 | if (*cp == '\0') | |
169 | return(NOSTR); | |
170 | } while (any(*cp, " \t,(")); | |
171 | for (cp2 = wbuf; *cp && !any(*cp, " \t,("); *cp2++ = *cp++) | |
172 | ; | |
173 | *cp2 = '\0'; | |
174 | return(cp); | |
175 | } | |
176 | ||
177 | /* | |
178 | * Verify that all the users in the list of names are | |
179 | * legitimate. Bitch about and delink those who aren't. | |
180 | */ | |
181 | ||
182 | struct name * | |
183 | verify(names) | |
184 | struct name *names; | |
185 | { | |
186 | register struct name *np, *top, *t, *x; | |
187 | register char *cp; | |
188 | ||
ac57be53 | 189 | #ifdef SENDMAIL |
65d3742f KS |
190 | return(names); |
191 | #else | |
192 | top = names; | |
193 | np = names; | |
194 | while (np != NIL) { | |
195 | if (np->n_type & GDEL) { | |
196 | np = np->n_flink; | |
197 | continue; | |
198 | } | |
199 | for (cp = "!:@^"; *cp; cp++) | |
200 | if (any(*cp, np->n_name)) | |
201 | break; | |
202 | if (*cp != 0) { | |
203 | np = np->n_flink; | |
204 | continue; | |
205 | } | |
206 | cp = np->n_name; | |
207 | while (*cp == '\\') | |
208 | cp++; | |
209 | if (equal(cp, "msgs") || | |
210 | getuserid(cp) != -1) { | |
211 | np = np->n_flink; | |
212 | continue; | |
213 | } | |
214 | fprintf(stderr, "Can't send to %s\n", np->n_name); | |
215 | senderr++; | |
216 | if (np == top) { | |
217 | top = np->n_flink; | |
218 | if (top != NIL) | |
219 | top->n_blink = NIL; | |
220 | np = top; | |
221 | continue; | |
222 | } | |
223 | x = np->n_blink; | |
224 | t = np->n_flink; | |
225 | x->n_flink = t; | |
226 | if (t != NIL) | |
227 | t->n_blink = x; | |
228 | np = t; | |
229 | } | |
230 | return(top); | |
231 | #endif | |
232 | } | |
233 | ||
234 | /* | |
235 | * For each recipient in the passed name list with a / | |
236 | * in the name, append the message to the end of the named file | |
237 | * and remove him from the recipient list. | |
238 | * | |
239 | * Recipients whose name begins with | are piped through the given | |
240 | * program and removed. | |
241 | */ | |
242 | ||
243 | struct name * | |
244 | outof(names, fo, hp) | |
245 | struct name *names; | |
246 | FILE *fo; | |
247 | struct header *hp; | |
248 | { | |
249 | register int c; | |
250 | register struct name *np, *top, *t, *x; | |
251 | long now; | |
252 | char *date, *fname, *shell, *ctime(); | |
253 | FILE *fout, *fin; | |
254 | int ispipe, s, pid; | |
255 | extern char tempEdit[]; | |
256 | ||
257 | top = names; | |
258 | np = names; | |
259 | time(&now); | |
260 | date = ctime(&now); | |
261 | while (np != NIL) { | |
5cf80950 | 262 | if (!isfileaddr(np->n_name) && np->n_name[0] != '|') { |
65d3742f KS |
263 | np = np->n_flink; |
264 | continue; | |
265 | } | |
266 | ispipe = np->n_name[0] == '|'; | |
267 | if (ispipe) | |
268 | fname = np->n_name+1; | |
269 | else | |
270 | fname = expand(np->n_name); | |
271 | ||
272 | /* | |
273 | * See if we have copied the complete message out yet. | |
274 | * If not, do so. | |
275 | */ | |
276 | ||
277 | if (image < 0) { | |
278 | if ((fout = fopen(tempEdit, "a")) == NULL) { | |
279 | perror(tempEdit); | |
280 | senderr++; | |
281 | goto cant; | |
282 | } | |
283 | image = open(tempEdit, 2); | |
284 | unlink(tempEdit); | |
285 | if (image < 0) { | |
286 | perror(tempEdit); | |
287 | senderr++; | |
288 | goto cant; | |
289 | } | |
290 | else { | |
291 | rewind(fo); | |
292 | fprintf(fout, "From %s %s", myname, date); | |
293 | puthead(hp, fout, GTO|GSUBJECT|GCC|GNL); | |
294 | while ((c = getc(fo)) != EOF) | |
295 | putc(c, fout); | |
296 | rewind(fo); | |
297 | putc('\n', fout); | |
298 | fflush(fout); | |
299 | if (ferror(fout)) | |
300 | perror(tempEdit); | |
301 | fclose(fout); | |
302 | } | |
303 | } | |
304 | ||
305 | /* | |
306 | * Now either copy "image" to the desired file | |
307 | * or give it as the standard input to the desired | |
308 | * program as appropriate. | |
309 | */ | |
310 | ||
311 | if (ispipe) { | |
312 | wait(&s); | |
313 | switch (pid = fork()) { | |
314 | case 0: | |
cb9e16fc | 315 | sigchild(); |
c3ca8d0d KS |
316 | sigsys(SIGHUP, SIG_IGN); |
317 | sigsys(SIGINT, SIG_IGN); | |
318 | sigsys(SIGQUIT, SIG_IGN); | |
65d3742f KS |
319 | close(0); |
320 | dup(image); | |
321 | close(image); | |
322 | if ((shell = value("SHELL")) == NOSTR) | |
323 | shell = SHELL; | |
324 | execl(shell, shell, "-c", fname, 0); | |
325 | perror(shell); | |
326 | exit(1); | |
327 | break; | |
328 | ||
329 | case -1: | |
330 | perror("fork"); | |
331 | senderr++; | |
332 | goto cant; | |
333 | } | |
334 | } | |
335 | else { | |
336 | if ((fout = fopen(fname, "a")) == NULL) { | |
337 | perror(fname); | |
338 | senderr++; | |
339 | goto cant; | |
340 | } | |
341 | fin = Fdopen(image, "r"); | |
342 | if (fin == NULL) { | |
343 | fprintf(stderr, "Can't reopen image\n"); | |
344 | fclose(fout); | |
345 | senderr++; | |
346 | goto cant; | |
347 | } | |
348 | rewind(fin); | |
349 | while ((c = getc(fin)) != EOF) | |
350 | putc(c, fout); | |
351 | if (ferror(fout)) | |
352 | senderr++, perror(fname); | |
353 | fclose(fout); | |
354 | fclose(fin); | |
355 | } | |
356 | ||
357 | cant: | |
358 | ||
359 | /* | |
360 | * In days of old we removed the entry from the | |
361 | * the list; now for sake of header expansion | |
362 | * we leave it in and mark it as deleted. | |
363 | */ | |
364 | ||
365 | #ifdef CRAZYWOW | |
366 | if (np == top) { | |
367 | top = np->n_flink; | |
368 | if (top != NIL) | |
369 | top->n_blink = NIL; | |
370 | np = top; | |
371 | continue; | |
372 | } | |
373 | x = np->n_blink; | |
374 | t = np->n_flink; | |
375 | x->n_flink = t; | |
376 | if (t != NIL) | |
377 | t->n_blink = x; | |
378 | np = t; | |
379 | #endif | |
380 | ||
381 | np->n_type |= GDEL; | |
382 | np = np->n_flink; | |
383 | } | |
384 | if (image >= 0) { | |
385 | close(image); | |
386 | image = -1; | |
387 | } | |
388 | return(top); | |
389 | } | |
390 | ||
5cf80950 KS |
391 | /* |
392 | * Determine if the passed address is a local "send to file" address. | |
393 | * If any of the network metacharacters precedes any slashes, it can't | |
394 | * be a filename. We cheat with .'s to allow path names like ./... | |
395 | */ | |
396 | isfileaddr(name) | |
397 | char *name; | |
398 | { | |
399 | register char *cp; | |
400 | extern char *metanet; | |
401 | ||
402 | if (any('@', name)) | |
403 | return(0); | |
1c617162 KS |
404 | if (*name == '+') |
405 | return(1); | |
5cf80950 KS |
406 | for (cp = name; *cp; cp++) { |
407 | if (*cp == '.') | |
408 | continue; | |
409 | if (any(*cp, metanet)) | |
410 | return(0); | |
411 | if (*cp == '/') | |
412 | return(1); | |
413 | } | |
414 | return(0); | |
415 | } | |
416 | ||
65d3742f KS |
417 | /* |
418 | * Map all of the aliased users in the invoker's mailrc | |
419 | * file and insert them into the list. | |
420 | * Changed after all these months of service to recursively | |
421 | * expand names (2/14/80). | |
422 | */ | |
423 | ||
424 | struct name * | |
425 | usermap(names) | |
426 | struct name *names; | |
427 | { | |
428 | register struct name *new, *np, *cp; | |
429 | struct name *getto; | |
430 | struct grouphead *gh; | |
431 | register int metoo; | |
432 | ||
433 | new = NIL; | |
434 | np = names; | |
435 | getto = NIL; | |
436 | metoo = (value("metoo") != NOSTR); | |
437 | while (np != NIL) { | |
438 | if (np->n_name[0] == '\\') { | |
439 | cp = np->n_flink; | |
440 | new = put(new, np); | |
441 | np = cp; | |
442 | continue; | |
443 | } | |
444 | gh = findgroup(np->n_name); | |
445 | cp = np->n_flink; | |
446 | if (gh != NOGRP) | |
447 | new = gexpand(new, gh, metoo, np->n_type); | |
448 | else | |
449 | new = put(new, np); | |
450 | np = cp; | |
451 | } | |
452 | return(new); | |
453 | } | |
454 | ||
455 | /* | |
456 | * Recursively expand a group name. We limit the expansion to some | |
457 | * fixed level to keep things from going haywire. | |
458 | * Direct recursion is not expanded for convenience. | |
459 | */ | |
460 | ||
461 | struct name * | |
462 | gexpand(nlist, gh, metoo, ntype) | |
463 | struct name *nlist; | |
464 | struct grouphead *gh; | |
465 | { | |
466 | struct group *gp; | |
467 | struct grouphead *ngh; | |
468 | struct name *np; | |
469 | static int depth; | |
470 | char *cp; | |
471 | ||
472 | if (depth > MAXEXP) { | |
473 | printf("Expanding alias to depth larger than %d\n", MAXEXP); | |
474 | return(nlist); | |
475 | } | |
476 | depth++; | |
477 | for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) { | |
478 | cp = gp->ge_name; | |
479 | if (*cp == '\\') | |
480 | goto quote; | |
481 | if (strcmp(cp, gh->g_name) == 0) | |
482 | goto quote; | |
483 | if ((ngh = findgroup(cp)) != NOGRP) { | |
484 | nlist = gexpand(nlist, ngh, metoo, ntype); | |
485 | continue; | |
486 | } | |
487 | quote: | |
488 | np = nalloc(cp); | |
489 | np->n_type = ntype; | |
490 | /* | |
491 | * At this point should allow to expand | |
492 | * to self if only person in group | |
493 | */ | |
494 | if (gp == gh->g_list && gp->ge_link == NOGE) | |
495 | goto skip; | |
496 | if (!metoo && strcmp(cp, myname) == 0) | |
497 | np->n_type |= GDEL; | |
498 | skip: | |
499 | nlist = put(nlist, np); | |
500 | } | |
501 | depth--; | |
502 | return(nlist); | |
503 | } | |
504 | ||
505 | ||
506 | ||
507 | /* | |
508 | * Compute the length of the passed name list and | |
509 | * return it. | |
510 | */ | |
511 | ||
512 | lengthof(name) | |
513 | struct name *name; | |
514 | { | |
515 | register struct name *np; | |
516 | register int c; | |
517 | ||
518 | for (c = 0, np = name; np != NIL; c++, np = np->n_flink) | |
519 | ; | |
520 | return(c); | |
521 | } | |
522 | ||
523 | /* | |
524 | * Concatenate the two passed name lists, return the result. | |
525 | */ | |
526 | ||
527 | struct name * | |
528 | cat(n1, n2) | |
529 | struct name *n1, *n2; | |
530 | { | |
531 | register struct name *tail; | |
532 | ||
533 | if (n1 == NIL) | |
534 | return(n2); | |
535 | if (n2 == NIL) | |
536 | return(n1); | |
537 | tail = tailof(n1); | |
538 | tail->n_flink = n2; | |
539 | n2->n_blink = tail; | |
540 | return(n1); | |
541 | } | |
542 | ||
543 | /* | |
544 | * Unpack the name list onto a vector of strings. | |
545 | * Return an error if the name list won't fit. | |
546 | */ | |
547 | ||
548 | char ** | |
549 | unpack(np) | |
550 | struct name *np; | |
551 | { | |
552 | register char **ap, **top; | |
553 | register struct name *n; | |
554 | char *cp; | |
555 | char hbuf[10]; | |
03c98b7d | 556 | int t, extra, metoo, verbose; |
65d3742f KS |
557 | |
558 | n = np; | |
559 | if ((t = lengthof(n)) == 0) | |
560 | panic("No names to unpack"); | |
561 | ||
562 | /* | |
563 | * Compute the number of extra arguments we will need. | |
564 | * We need at least two extra -- one for "mail" and one for | |
565 | * the terminating 0 pointer. Additional spots may be needed | |
566 | * to pass along -r and -f to the host mailer. | |
567 | */ | |
568 | ||
569 | extra = 2; | |
570 | if (rflag != NOSTR) | |
571 | extra += 2; | |
ac57be53 | 572 | #ifdef SENDMAIL |
65d3742f KS |
573 | extra++; |
574 | metoo = value("metoo") != NOSTR; | |
575 | if (metoo) | |
576 | extra++; | |
03c98b7d CL |
577 | verbose = value("verbose") != NOSTR; |
578 | if (verbose) | |
579 | extra++; | |
ac57be53 | 580 | #endif SENDMAIL |
65d3742f KS |
581 | if (hflag) |
582 | extra += 2; | |
583 | top = (char **) salloc((t + extra) * sizeof cp); | |
584 | ap = top; | |
585 | *ap++ = "send-mail"; | |
586 | if (rflag != NOSTR) { | |
587 | *ap++ = "-r"; | |
588 | *ap++ = rflag; | |
589 | } | |
ac57be53 | 590 | #ifdef SENDMAIL |
65d3742f KS |
591 | *ap++ = "-i"; |
592 | if (metoo) | |
593 | *ap++ = "-m"; | |
03c98b7d CL |
594 | if (verbose) |
595 | *ap++ = "-v"; | |
ac57be53 | 596 | #endif SENDMAIL |
65d3742f KS |
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 | } | |
6f63024f | 607 | *ap++ = n->n_name; |
65d3742f KS |
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) | |
20b5c5b1 | 626 | if ((np->n_type & GDEL) == 0 && equal(np->n_name, myname)) { |
65d3742f KS |
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 | ||
03c98b7d CL |
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 | ||
65d3742f | 792 | /* |
03c98b7d CL |
793 | * Delete the given name from a namelist, using the passed |
794 | * function to compare the names. | |
65d3742f | 795 | */ |
65d3742f | 796 | struct name * |
03c98b7d | 797 | delname(np, name, cmpfun) |
65d3742f KS |
798 | register struct name *np; |
799 | char name[]; | |
03c98b7d | 800 | int (* cmpfun)(); |
65d3742f KS |
801 | { |
802 | register struct name *p; | |
803 | ||
804 | for (p = np; p != NIL; p = p->n_flink) | |
03c98b7d | 805 | if ((* cmpfun)(p->n_name, name)) { |
65d3742f KS |
806 | if (p->n_blink == NIL) { |
807 | if (p->n_flink != NIL) | |
808 | p->n_flink->n_blink = NIL; | |
809 | np = p->n_flink; | |
810 | continue; | |
811 | } | |
812 | if (p->n_flink == NIL) { | |
813 | if (p->n_blink != NIL) | |
814 | p->n_blink->n_flink = NIL; | |
815 | continue; | |
816 | } | |
817 | p->n_blink->n_flink = p->n_flink; | |
818 | p->n_flink->n_blink = p->n_blink; | |
819 | } | |
820 | return(np); | |
821 | } | |
822 | ||
823 | /* | |
824 | * Call the given routine on each element of the name | |
825 | * list, replacing said value if need be. | |
826 | */ | |
827 | ||
828 | mapf(np, from) | |
829 | register struct name *np; | |
830 | char *from; | |
831 | { | |
832 | register struct name *p; | |
833 | ||
834 | for (p = np; p != NIL; p = p->n_flink) | |
835 | p->n_name = netmap(p->n_name, from); | |
836 | } | |
837 | ||
838 | /* | |
839 | * Pretty print a name list | |
840 | * Uncomment it if you need it. | |
841 | */ | |
842 | ||
843 | prettyprint(name) | |
844 | struct name *name; | |
845 | { | |
846 | register struct name *np; | |
847 | ||
848 | np = name; | |
849 | while (np != NIL) { | |
850 | fprintf(stderr, "%s(%d) ", np->n_name, np->n_type); | |
851 | np = np->n_flink; | |
852 | } | |
853 | fprintf(stderr, "\n"); | |
854 | } |