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