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 |
116f92bd | 8 | static char *sccsid = "@(#)names.c 5.3 (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 | ||
116f92bd | 159 | cp = ap; |
65d3742f | 160 | do { |
116f92bd S |
161 | while (*cp && any(*cp, " \t,")) |
162 | cp++; | |
65d3742f | 163 | if (*cp == '(') { |
116f92bd S |
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 | } | |
65d3742f KS |
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 | ||
ac57be53 | 200 | #ifdef SENDMAIL |
65d3742f KS |
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) { | |
5cf80950 | 273 | if (!isfileaddr(np->n_name) && np->n_name[0] != '|') { |
65d3742f KS |
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: | |
cb9e16fc | 326 | sigchild(); |
c3ca8d0d KS |
327 | sigsys(SIGHUP, SIG_IGN); |
328 | sigsys(SIGINT, SIG_IGN); | |
329 | sigsys(SIGQUIT, SIG_IGN); | |
65d3742f KS |
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 | ||
5cf80950 KS |
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); | |
1c617162 KS |
415 | if (*name == '+') |
416 | return(1); | |
5cf80950 KS |
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 | ||
65d3742f KS |
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]; | |
03c98b7d | 567 | int t, extra, metoo, verbose; |
65d3742f KS |
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; | |
ac57be53 | 583 | #ifdef SENDMAIL |
65d3742f KS |
584 | extra++; |
585 | metoo = value("metoo") != NOSTR; | |
586 | if (metoo) | |
587 | extra++; | |
03c98b7d CL |
588 | verbose = value("verbose") != NOSTR; |
589 | if (verbose) | |
590 | extra++; | |
ac57be53 | 591 | #endif SENDMAIL |
65d3742f KS |
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 | } | |
ac57be53 | 601 | #ifdef SENDMAIL |
65d3742f KS |
602 | *ap++ = "-i"; |
603 | if (metoo) | |
604 | *ap++ = "-m"; | |
03c98b7d CL |
605 | if (verbose) |
606 | *ap++ = "-v"; | |
ac57be53 | 607 | #endif SENDMAIL |
65d3742f KS |
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 | } | |
6f63024f | 618 | *ap++ = n->n_name; |
65d3742f KS |
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) | |
20b5c5b1 | 637 | if ((np->n_type & GDEL) == 0 && equal(np->n_name, myname)) { |
65d3742f KS |
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 | ||
03c98b7d CL |
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 | ||
65d3742f | 803 | /* |
03c98b7d CL |
804 | * Delete the given name from a namelist, using the passed |
805 | * function to compare the names. | |
65d3742f | 806 | */ |
65d3742f | 807 | struct name * |
03c98b7d | 808 | delname(np, name, cmpfun) |
65d3742f KS |
809 | register struct name *np; |
810 | char name[]; | |
03c98b7d | 811 | int (* cmpfun)(); |
65d3742f KS |
812 | { |
813 | register struct name *p; | |
814 | ||
815 | for (p = np; p != NIL; p = p->n_flink) | |
03c98b7d | 816 | if ((* cmpfun)(p->n_name, name)) { |
65d3742f KS |
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 | } |