xref: /titanic_44/usr/src/lib/libnsl/dial/sysfiles.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include "uucp.h"
34 #include <rpc/trace.h>
35 
36 #include <unistd.h>
37 #include "sysfiles.h"
38 #include <sys/stropts.h>
39 
40 /*
41  * manage systems files (Systems, Devices, and Dialcodes families).
42  *
43  * also manage new file Devconfig, allows per-device setup.
44  * present use is to specify what streams modules to push/pop for
45  * AT&T TLI/streams network.
46  *
47  * TODO:
48  *	call bsfix()?
49  *	combine the 3 versions of everything (sys, dev, and dial) into one.
50  *	allow arbitrary classes of service.
51  *	need verifysys() for uucheck.
52  *	nameserver interface?
53  *	pass sysname (or 0) to getsysline().  (might want reg. exp. or NS processing
54  */
55 
56 /* private variables */
57 static void tokenize(), nameparse(), setfile(), setioctl(),
58 	scansys(), scancfg(), setconfig();
59 #if defined(__STDC__)
60 static int namematch(const char *label, char *line, char *name);
61 #else
62 static int namematch();
63 #endif
64 static int nextdialers(), nextdevices(), nextsystems(), getline();
65 
66 /* pointer arrays might be dynamically allocated */
67 static char *Systems[64];	/* list of Systems files */
68 static char *Devices[64];	/* list of Devices files */
69 static char *Dialers[64];	/* list of Dialers files */
70 static char *Pops[64];		/* list of STREAMS modules to be popped */
71 static char *Pushes[64];	/* list of STREAMS modules to be pushed */
72 
73 static int nsystems;		/* index into list of Systems files */
74 static int ndevices;		/* index into list of Devices files */
75 static int ndialers;		/* index into list of Dialers files */
76 static int npops;		/* index into list of STREAMS modules */
77 							/*to be popped */
78 static int npushes;		/* index into list of STREAMS modules */
79 							/*to be pushed */
80 
81 GLOBAL unsigned connecttime, expecttime, msgtime;
82 
83 static FILE *fsystems;
84 static FILE *fdevices;
85 static FILE *fdialers;
86 
87 /* this might be dynamically allocated */
88 #define NTOKENS 16
89 static char *tokens[NTOKENS], **tokptr;
90 
91 /* export these */
92 #if defined(__STDC__)
93 EXTERN void setservice(const char *service);
94 #else
95 EXTERN void setservice();
96 #endif
97 EXTERN void sysreset(), devreset(), dialreset(), setdevcfg(), setservice();
98 
99 /* import these */
100 extern char *strcpy(), *strtok(), *strchr(), *strsave();
101 EXTERN int eaccess();
102 
103 /*
104  * setservice init's Systems, Devices, Dialers lists from Sysfiles
105  */
106 GLOBAL void
107 setservice(service)
108 #if defined(__STDC__)
109 const char *service;
110 #else
111 char *service;
112 #endif
113 {
114 	trace1(TR_setservice, 0);
115 	setconfig();
116 	scansys(service);
117 	trace1(TR_setservice, 1);
118 	return;
119 }
120 
121 /*
122  * setdevcfg init's Pops, Pushes lists from Devconfig
123  */
124 
125 GLOBAL void
126 setdevcfg(service, device)
127 char *service, *device;
128 {
129 	trace1(TR_setdevcfg, 0);
130 	scancfg(service, device);
131 	trace1(TR_setdevcfg, 1);
132 	return;
133 }
134 
135 /*	administrative files access */
136 GLOBAL int
137 sysaccess(type)
138 int type;
139 {
140 	int dummy;
141 
142 	trace2(TR_sysaccess, 0, type);
143 	switch (type) {
144 
145 	case ACCESS_SYSTEMS:
146 		trace1(TR_sysaccess, 1);
147 		return (access(Systems[nsystems], R_OK));
148 	case ACCESS_DEVICES:
149 		trace1(TR_sysaccess, 1);
150 		return (access(Devices[ndevices], R_OK));
151 	case ACCESS_DIALERS:
152 		trace1(TR_sysaccess, 1);
153 		return (access(Dialers[ndialers], R_OK));
154 	case EACCESS_SYSTEMS:
155 		dummy = eaccess(Systems[nsystems], R_OK);
156 		trace1(TR_sysaccess, 1);
157 		return (dummy);
158 	case EACCESS_DEVICES:
159 		dummy = eaccess(Devices[ndevices], R_OK);
160 		trace1(TR_sysaccess, 1);
161 		return (dummy);
162 	case EACCESS_DIALERS:
163 		dummy = eaccess(Dialers[ndialers], R_OK);
164 		trace1(TR_sysaccess, 1);
165 		return (dummy);
166 	default: {
167 		char errformat[BUFSIZ];
168 
169 		(void) sprintf(errformat, "bad access type %d", type);
170 		logent(errformat, "sysaccess");
171 		trace1(TR_sysaccess, 1);
172 		return (FAIL);
173 	}
174 	}
175 }
176 
177 
178 /*
179  * read Sysfiles, set up lists of Systems/Devices/Dialers file names.
180  * allow multiple entries for a given service, allow a service
181  * type to describe resources more than once, e.g., systems=foo:baz systems=bar.
182  */
183 static void
184 scansys(service)
185 char *service;
186 {	FILE *f;
187 	char *tok, buf[BUFSIZ];
188 
189 	trace1(TR_scansys, 0);
190 	Systems[0] = Devices[0] = Dialers[0] = NULL;
191 	if ((f = fopen(SYSFILES, "r")) != 0) {
192 		while (getline(f, buf) > 0) {
193 			/* got a (logical) line from Sysfiles */
194 			/* strtok's of this buf continue in tokenize() */
195 			tok = strtok(buf, " \t");
196 			if (namematch("service=", tok, service)) {
197 				tokenize();
198 				nameparse();
199 			}
200 		}
201 		(void) fclose(f);
202 	}
203 
204 	/* if didn't find entries in Sysfiles, use defaults */
205 	if (Systems[0] == NULL) {
206 		Systems[0] = strsave(SYSTEMS);
207 		ASSERT(Systems[0] != NULL, "Ct_ALLOCATE", "scansys: Systems", 0);
208 		Systems[1] = NULL;
209 	}
210 	if (Devices[0] == NULL) {
211 		Devices[0] = strsave(DEVICES);
212 		ASSERT(Devices[0] != NULL, "Ct_ALLOCATE", "scansys: Devices", 0);
213 		Devices[1] = NULL;
214 	}
215 	if (Dialers[0] == NULL) {
216 		Dialers[0] = strsave(DIALERS);
217 		ASSERT(Dialers[0] != NULL, "Ct_ALLOCATE", "scansys: Dialers", 0);
218 		Dialers[1] = NULL;
219 	}
220 	trace1(TR_scansys, 1);
221 	return;
222 }
223 
224 
225 /*
226  * read Devconfig.  allow multiple entries for a given service, allow a service
227  * type to describe resources more than once, e.g., push=foo:baz push=bar.
228  */
229 static void
230 scancfg(service, device)
231 char *service, *device;
232 {	FILE *f;
233 	char *tok, buf[BUFSIZ];
234 
235 	/* (re)initialize device-specific information */
236 	trace1(TR_scancfg, 0);
237 	npops = npushes = 0;
238 	Pops[0] = Pushes[0] = NULL;
239 	connecttime = CONNECTTIME;
240 	expecttime = EXPECTTIME;
241 	msgtime = MSGTIME;
242 
243 	if ((f = fopen(DEVCONFIG, "r")) != 0) {
244 		while (getline(f, buf) > 0) {
245 			/* got a (logical) line from Devconfig */
246 			/* strtok's of this buf continue in tokenize() */
247 			tok = strtok(buf, " \t");
248 			if (namematch("service=", tok, service)) {
249 				tok = strtok((char *)0, " \t");
250 				if (namematch("device=", tok, device)) {
251 					tokenize();
252 					nameparse();
253 				}
254 			}
255 		}
256 		(void) fclose(f);
257 	}
258 	trace1(TR_scancfg, 1);
259 	return;
260 
261 }
262 
263 /*
264  *  given a file pointer and buffer, construct logical line in buffer
265  *  (i.e., concatenate lines ending in '\').  return length of line
266  *  ASSUMES that buffer is BUFSIZ long!
267  */
268 
269 static int
270 getline(f, line)
271 FILE *f;
272 char *line;
273 {	char *lptr, *lend;
274 
275 	trace1(TR_getline, 0);
276 	lptr = line;
277 	while (fgets(lptr, (line + BUFSIZ) - lptr, f) != NULL) {
278 		lend = lptr + strlen(lptr);
279 		if (lend == lptr || lend[-1] != '\n')
280 			/* empty buf or line too long! */
281 			break;
282 		*--lend = '\0'; /* lop off ending '\n' */
283 		if (lend == line) /* empty line - ignore */
284 			continue;
285 		lptr = lend;
286 		if (lend[-1] != '\\')
287 			break;
288 		/* continuation */
289 		lend[-1] = ' ';
290 	}
291 	trace1(TR_getline, 1);
292 	return (lptr - line);
293 }
294 
295 /*
296  * given a label (e.g., "service=", "device="), a name ("cu", "uucico"),
297  *  and a line:  if line begins with the label and if the name appears
298  * in a colon-separated list of names following the label, return true;
299  * else return false
300  */
301 #if defined(__STDC__)
302 static int
303 namematch(const char *label, char *line, char *name)
304 #else
305 static int
306 namematch(label, line, name)
307 char *label, *line, *name;
308 #endif
309 {	char *lend;
310 
311 	trace1(TR_namematch, 0);
312 	if (strncmp(label, line, strlen(label)) != SAME) {
313 		trace1(TR_namematch, 1);
314 		return (FALSE);	/* probably a comment line */
315 	}
316 	line += strlen(label);
317 	if (*line == '\0') {
318 		trace1(TR_namematch, 1);
319 		return (FALSE);
320 	}
321 	/*
322 	 * can't use strtok() in the following because scansys(),
323 	 * scancfg() do an initializing call to strtok() before
324 	 * coming here and then CONTINUE calling strtok() in tokenize(),
325 	 * after returning from namematch().
326 	 */
327 	while ((lend = strchr(line, ':')) != NULL) {
328 		*lend = '\0';
329 		if (strcmp(line, name) == SAME) {
330 			trace1(TR_namematch, 1);
331 			return (TRUE);
332 		}
333 		line = lend+1;
334 	}
335 	trace1(TR_namematch, 1);
336 	return (strcmp(line, name) == SAME);
337 }
338 
339 /*
340  * tokenize() continues pulling tokens out of a buffer -- the
341  * initializing call to strtok must have been made before calling
342  * tokenize() -- and starts stuffing 'em into tokptr.
343  */
344 static void
345 tokenize()
346 {	char *tok;
347 
348 	trace1(TR_tokenize, 0);
349 	tokptr = tokens;
350 	while ((tok = strtok((char *) NULL, " \t")) != NULL) {
351 		*tokptr++ = tok;
352 		if (tokptr - tokens >= NTOKENS)
353 			break;
354 	}
355 	*tokptr = NULL;
356 	trace1(TR_tokenize, 1);
357 	return;
358 }
359 
360 /*
361  * look at top token in array: should be line of the form
362  *	name=item1:item2:item3...
363  * if name is one we recognize, then call set[file|ioctl] to set up
364  * corresponding list.  otherwise, log bad name.
365  */
366 static void
367 nameparse()
368 {	char **line, *equals;
369 	int temp;
370 
371 #define setuint(a,b,c) a = (((temp = atoi(b)) <= 0) ? (c) : temp)
372 
373 	trace1(TR_nameparse, 0);
374 	for (line = tokens; (line - tokens) < NTOKENS && *line; line++) {
375 		equals = strchr(*line, '=');
376 		if (equals == NULL)
377 			continue;	/* may be meaningful someday? */
378 		*equals = '\0';
379 		/* ignore entry with empty rhs */
380 		if (*++equals == '\0')
381 			continue;
382 		if (strcmp(*line, "systems") == SAME)
383 			setfile(Systems, equals);
384 		else if (strcmp(*line, "devices") == SAME)
385 			setfile(Devices, equals);
386 		else if (strcmp(*line, "dialers") == SAME)
387 			setfile(Dialers, equals);
388 		else if (strcmp(*line, "pop") == SAME)
389 			setioctl(Pops, equals);
390 		else if (strcmp(*line, "push") == SAME)
391 			setioctl(Pushes, equals);
392 		else if (strcmp(*line, "connecttime") == SAME)
393 			setuint(connecttime, equals, CONNECTTIME);
394 		else if (strcmp(*line, "expecttime") == SAME)
395 			setuint(expecttime, equals, EXPECTTIME);
396 		else if (strcmp(*line, "msgtime") == SAME)
397 			setuint(msgtime, equals, MSGTIME);
398 		else {
399 			char errformat[BUFSIZ];
400 
401 			(void) sprintf(errformat,"unrecognized label %s",*line);
402 			logent(errformat, "Sysfiles|Devconfig");
403 		}
404 	}
405 	trace1(TR_nameparse, 1);
406 	return;
407 }
408 
409 /*
410  * given the list for a particular type (systems, devices,...)
411  * and a line of colon-separated files, add 'em to list
412  */
413 
414 static void
415 setfile(type, line)
416 char **type, *line;
417 {	char **tptr, *tok;
418 	char expandpath[BUFSIZ];
419 
420 	trace1(TR_setfile, 0);
421 	if (*line == 0) {
422 		trace1(TR_setfile, 1);
423 		return;
424 	}
425 	tptr = type;
426 	while (*tptr)		/* skip over existing entries to*/
427 		tptr++;		/* concatenate multiple entries */
428 
429 	for (tok = strtok(line, ":"); tok != NULL;
430 	tok = strtok((char *) NULL, ":")) {
431 		expandpath[0] = '\0';
432 		if (*tok != '/')
433 			/* by default, file names are relative to SYSDIR */
434 			sprintf(expandpath, "%s/", SYSDIR);
435 		strcat(expandpath, tok);
436 		if (eaccess(expandpath, R_OK) != 0)
437 			/* if we can't read it, no point in adding to list */
438 			continue;
439 		*tptr = strsave(expandpath);
440 		ASSERT(*tptr != NULL, "Ct_ALLOCATE", "setfile: tptr", 0);
441 		tptr++;
442 	}
443 	trace1(TR_setfile, 1);
444 	return;
445 }
446 
447 /*
448  * given the list for a particular ioctl (push, pop)
449  * and a line of colon-separated modules, add 'em to list
450  */
451 
452 static void
453 setioctl(type, line)
454 char **type, *line;
455 {	char **tptr, *tok;
456 
457 	trace1(TR_setioctl, 0);
458 	if (*line == 0) {
459 		trace1(TR_setioctl, 1);
460 		return;
461 	}
462 	tptr = type;
463 	while (*tptr)		/* skip over existing entries to*/
464 		tptr++;		/* concatenate multiple entries */
465 	for (tok = strtok(line, ":"); tok != NULL;
466 	tok = strtok((char *) NULL, ":")) {
467 		*tptr = strsave(tok);
468 		ASSERT(*tptr != NULL, "Ct_ALLOCATE", "setioctl: tptr", 0);
469 		tptr++;
470 	}
471 	trace1(TR_setioctl, 1);
472 	return;
473 }
474 
475 /*
476  * reset Systems files
477  */
478 GLOBAL void
479 sysreset()
480 {
481 	trace1(TR_sysreset, 0);
482 	if (fsystems)
483 		fclose(fsystems);
484 	fsystems = NULL;
485 	nsystems = 0;
486 	devreset();
487 	trace1(TR_sysreset, 1);
488 	return;
489 }
490 
491 /*
492  * reset Devices files
493  */
494 GLOBAL void
495 devreset()
496 {
497 	trace1(TR_devreset, 0);
498 	if (fdevices)
499 		fclose(fdevices);
500 	fdevices = NULL;
501 	ndevices = 0;
502 	dialreset();
503 	trace1(TR_devreset, 1);
504 	return;
505 }
506 
507 /*
508  * reset Dialers files
509  */
510 GLOBAL void
511 dialreset()
512 {
513 	trace1(TR_dialreset, 0);
514 	if (fdialers)
515 		fclose(fdialers);
516 	fdialers = NULL;
517 	ndialers = 0;
518 	trace1(TR_dialreset, 1);
519 	return;
520 }
521 
522 /*
523  * get next line from Systems file
524  * return TRUE if successful, FALSE if not
525  */
526 GLOBAL int
527 getsysline(char *buf, int len)
528 {
529 	trace2(TR_getsysline, 0, len);
530 	if (Systems[0] == NULL)
531 		/* not initialized via setservice() - use default */
532 		setservice("uucico");
533 
534 	/* initialize devices and dialers whenever a new line is read */
535 	/* from systems */
536 	devreset();
537 	if (fsystems == NULL)
538 		if (nextsystems() == FALSE) {
539 			trace1(TR_getsysline, 1);
540 			return (FALSE);
541 		}
542 
543 	for (;;) {
544 		while (fgets(buf, len, fsystems) != NULL)
545 			if ((*buf != '#') && (*buf != ' ') &&
546 			(*buf != '\t') && (*buf != '\n')) {
547 			trace1(TR_getsysline, 1);
548 			return (TRUE);
549 		}
550 		if (nextsystems() == FALSE) {
551 			trace1(TR_getsysline, 1);
552 			return (FALSE);
553 		}
554 	}
555 }
556 
557 /*
558  * move to next systems file.  return TRUE if successful, FALSE if not
559  */
560 static int
561 nextsystems()
562 {
563 	trace1(TR_nextsystems, 0);
564 	devreset();
565 
566 	if (fsystems != NULL) {
567 		(void) fclose(fsystems);
568 		nsystems++;
569 	} else {
570 		nsystems = 0;
571 	}
572 	for (; Systems[nsystems] != NULL; nsystems++)
573 		if ((fsystems = fopen(Systems[nsystems], "r")) != NULL) {
574 			trace1(TR_nextsystems, 1);
575 			return (TRUE);
576 		}
577 	trace1(TR_nextsystems, 1);
578 	return (FALSE);
579 }
580 
581 /*
582  * get next line from Devices file
583  * return TRUE if successful, FALSE if not
584  */
585 GLOBAL int
586 getdevline(char *buf, int len)
587 {
588 	trace2(TR_getdevline, 0, len);
589 	if (Devices[0] == NULL)
590 		/* not initialized via setservice() - use default */
591 		setservice("uucico");
592 
593 	if (fdevices == NULL)
594 		if (nextdevices() == FALSE) {
595 			trace1(TR_getdevline, 1);
596 			return (FALSE);
597 		}
598 	for (;;) {
599 		if (fgets(buf, len, fdevices) != NULL) {
600 			trace1(TR_getdevline, 1);
601 			return (TRUE);
602 		}
603 		if (nextdevices() == FALSE) {
604 			trace1(TR_getdevline, 1);
605 			return (FALSE);
606 		}
607 	}
608 }
609 
610 /*
611  * move to next devices file.  return TRUE if successful, FALSE if not
612  */
613 static int
614 nextdevices()
615 {
616 	trace1(TR_nextdevices, 0);
617 	if (fdevices != NULL) {
618 		(void) fclose(fdevices);
619 		ndevices++;
620 	} else {
621 		ndevices = 0;
622 	}
623 	for (; Devices[ndevices] != NULL; ndevices++)
624 		if ((fdevices = fopen(Devices[ndevices], "r")) != NULL) {
625 			trace1(TR_nextdevices, 1);
626 			return (TRUE);
627 		}
628 	trace1(TR_nextdevices, 1);
629 	return (FALSE);
630 }
631 
632 
633 /*
634  * get next line from Dialers file
635  * return TRUE if successful, FALSE if not
636  */
637 
638 GLOBAL int
639 getdialline(char *buf, int len)
640 {
641 	trace2(TR_getdialline, 0, len);
642 	if (Dialers[0] == NULL)
643 		/* not initialized via setservice() - use default */
644 		setservice("uucico");
645 
646 	if (fdialers == NULL)
647 		if (nextdialers() == FALSE) {
648 			trace1(TR_getdialline, 1);
649 			return (FALSE);
650 		}
651 	for (;;) {
652 		if (fgets(buf, len, fdialers) != NULL) {
653 			trace1(TR_getdialline, 1);
654 			return (TRUE);
655 		}
656 		if (nextdialers() == FALSE) {
657 			trace1(TR_getdialline, 1);
658 			return (FALSE);
659 		}
660 	}
661 }
662 
663 /*
664  * move to next dialers file.  return TRUE if successful, FALSE if not
665  */
666 static int
667 nextdialers()
668 {
669 	trace1(TR_nextdialers, 0);
670 	if (fdialers) {
671 		(void) fclose(fdialers);
672 		ndialers++;
673 	} else {
674 		ndialers = 0;
675 	}
676 
677 	for (; Dialers[ndialers] != NULL; ndialers++)
678 		if ((fdialers = fopen(Dialers[ndialers], "r")) != NULL) {
679 			trace1(TR_nextdialers, 1);
680 			return (TRUE);
681 		}
682 	trace1(TR_nextdialers, 1);
683 	return (FALSE);
684 }
685 
686 /*
687  * get next module to be popped
688  * return TRUE if successful, FALSE if not
689  */
690 static int
691 getpop(buf, len, optional)
692 char *buf;
693 size_t len;
694 int *optional;
695 {
696 	int slen;
697 
698 	trace2(TR_getpop, 0, len);
699 	if (Pops[0] == NULL || Pops[npops] == NULL) {
700 		trace1(TR_getpop, 1);
701 		return (FALSE);
702 	}
703 
704 	/*	if the module name is enclosed in parentheses,	*/
705 	/*	is optional. set flag & strip parens		*/
706 	slen = strlen(Pops[npops]) - 1;
707 	if (Pops[npops][0] == '('  && Pops[npops][slen] == ')') {
708 		*optional = 1;
709 		len = (slen < len ? slen : len);
710 		strncpy(buf, &(Pops[npops++][1]), len);
711 	} else {
712 		*optional = 0;
713 		strncpy(buf, Pops[npops++], len);
714 	}
715 	buf[len-1] = '\0';
716 	trace1(TR_getpop, 1);
717 	return (TRUE);
718 }
719 
720 /*
721  * get next module to be pushed
722  * return TRUE if successful, FALSE if not
723  */
724 static int
725 getpush(buf, len)
726 char *buf;
727 size_t len;
728 {
729 	trace2(TR_getpush, 0, len);
730 	if (Pushes[0] == NULL || Pushes[npushes] == NULL) {
731 		trace1(TR_getpush, 1);
732 		return (FALSE);
733 	}
734 	strncpy(buf, Pushes[npushes++], len);
735 	trace1(TR_getpush, 1);
736 	return (TRUE);
737 }
738 
739 /*
740  * pop/push requested modules
741  * return TRUE if successful, FALSE if not
742  */
743 GLOBAL int
744 pop_push(fd)
745 int fd;
746 {
747 	char	strmod[FMNAMESZ], onstream[FMNAMESZ];
748 	int		optional;
749 
750 	trace2(TR_pop_push, 0, fd);
751 	/*	check for streams modules to pop	*/
752 	while (getpop(strmod, sizeof(strmod), &optional)) {
753 		DEBUG(5, (optional ?
754 			(const char *)"pop_push: optionally POPing %s\n"
755 			   : (const char *)"pop_push: POPing %s\n"), strmod);
756 		if (ioctl(fd, I_LOOK, onstream) == -1) {
757 			DEBUG(5, "pop_push: I_LOOK on fd %d failed ", fd);
758 			DEBUG(5, "errno %d\n", errno);
759    			trace1(TR_pop_push, 1);
760 			return (FALSE);
761 		}
762 		if (strcmp(strmod, onstream) != SAME) {
763 			if (optional)
764 				continue;
765 			DEBUG(5, "pop_push: I_POP: %s not there\n", strmod);
766 			trace1(TR_pop_push, 1);
767 			return (FALSE);
768 		}
769 		if (ioctl(fd, I_POP, 0) == -1) {
770 			DEBUG(5, "pop_push: I_POP on fd %d failed ", fd);
771 			DEBUG(5, "errno %d\n", errno);
772 			trace1(TR_pop_push, 1);
773 			return (FALSE);
774 		}
775 	}
776 
777 	/*	check for streams modules to push	*/
778 	while (getpush(strmod, sizeof(strmod))) {
779 		DEBUG(5, "pop_push: PUSHing %s\n", strmod);
780 		if (ioctl(fd, I_PUSH, strmod) == -1) {
781 			DEBUG(5, "pop_push: I_PUSH on fd %d failed ", fd);
782 			DEBUG(5, "errno %d\n", errno);
783 			trace1(TR_pop_push, 1);
784 			return (FALSE);
785 		}
786 	}
787 	trace1(TR_pop_push, 1);
788 	return (TRUE);
789 }
790 
791 /*
792  * 	return name of currently open Systems file
793  */
794 GLOBAL char *
795 currsys()
796 {
797 	trace1(TR_currsys, 0);
798 	trace1(TR_currsys, 1);
799 	return (Systems[nsystems]);
800 }
801 
802 /*
803  * 	return name of currently open Devices file
804  */
805 GLOBAL char *
806 currdev()
807 {
808 	trace1(TR_currdev, 0);
809 	trace1(TR_currdev, 1);
810 	return (Devices[ndevices]);
811 }
812 
813 /*
814  * 	return name of currently open Dialers file
815  */
816 GLOBAL char *
817 currdial()
818 {
819 	trace1(TR_currdial, 0);
820 	trace1(TR_currdial, 1);
821 	return (Dialers[ndialers]);
822 }
823 
824 /*
825  * set configuration parameters provided in Config file
826  */
827 static void
828 setconfig()
829 {
830 	FILE *f;
831 	char buf[BUFSIZ];
832 	char *tok;
833 	extern char _ProtoCfg[];
834 
835 	trace1(TR_setconfig, 0);
836 	if ((f = fopen(CONFIG, "r")) != 0) {
837 	while (getline(f, buf) > 0) {
838 		/* got a (logical) line from Config file */
839 		tok = strtok(buf, " \t");
840 		if ((tok != NULL) && (*tok != '#')) {
841 			/* got a token */
842 
843 			/* this probably should be table driven when
844 		 	* the list of configurable parameters grows.
845 		 	*/
846 			if (strncmp("Protocol=", tok, strlen("Protocol=")) == SAME) {
847 				tok += strlen("Protocol=");
848 				if (*tok != '\0') {
849 					if (_ProtoCfg[0] != '\0') {
850 						/*EMPTY*/
851 						DEBUG(7, "Protocol string %s ", tok);
852 						DEBUG(7, "overrides %s\n", _ProtoCfg);
853 					}
854 					strcpy(_ProtoCfg, tok);
855 				}
856 			} else {
857 				/*EMPTY*/
858 				DEBUG(7, "Unknown configuration parameter %s\n", tok);
859 			}
860 		}
861 	}
862 	(void) fclose(f);
863 	}
864 	trace1(TR_setconfig, 1);
865 }
866