2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
2N/A/* All Rights Reserved */
2N/A
2N/A#include "mt.h"
2N/A#include "uucp.h"
2N/A
2N/A#include <unistd.h>
2N/A#include <string.h>
2N/A#include "sysfiles.h"
2N/A#include <sys/stropts.h>
2N/A
2N/A/*
2N/A * manage systems files (Systems, Devices, and Dialcodes families).
2N/A *
2N/A * also manage new file Devconfig, allows per-device setup.
2N/A * present use is to specify what streams modules to push/pop for
2N/A * AT&T TLI/streams network.
2N/A *
2N/A * TODO:
2N/A * call bsfix()?
2N/A * combine the 3 versions of everything (sys, dev, and dial) into one.
2N/A * allow arbitrary classes of service.
2N/A * need verifysys() for uucheck.
2N/A * nameserver interface?
2N/A * pass sysname (or 0) to getsysline(). (might want reg. exp. or
2N/A * NS processing)
2N/A */
2N/A
2N/A/* private variables */
2N/Astatic void tokenize(void);
2N/Astatic void nameparse(void);
2N/Astatic void setfile(char **, char *);
2N/Astatic void setioctl(char **, char *);
2N/Astatic void scansys(const char *);
2N/Astatic void scancfg(char *, char *);
2N/Astatic void setconfig(void);
2N/Astatic int namematch(const char *label, char *line, const char *name);
2N/Astatic int nextdialers(void);
2N/Astatic int nextdevices(void);
2N/Astatic int nextsystems(void);
2N/Astatic int getaline(FILE *, char *);
2N/A
2N/A/* pointer arrays might be dynamically allocated */
2N/Astatic char *Systems[64]; /* list of Systems files */
2N/Astatic char *Devices[64]; /* list of Devices files */
2N/Astatic char *Dialers[64]; /* list of Dialers files */
2N/Astatic char *Pops[64]; /* list of STREAMS modules to be popped */
2N/Astatic char *Pushes[64]; /* list of STREAMS modules to be pushed */
2N/A
2N/Astatic int nsystems; /* index into list of Systems files */
2N/Astatic int ndevices; /* index into list of Devices files */
2N/Astatic int ndialers; /* index into list of Dialers files */
2N/Astatic int npops; /* index into list of STREAMS modules */
2N/A /* to be popped */
2N/Astatic int npushes; /* index into list of STREAMS modules */
2N/A /* to be pushed */
2N/A
2N/Astatic unsigned connecttime, expecttime;
2N/A
2N/Astatic FILE *fsystems;
2N/Astatic FILE *fdevices;
2N/Astatic FILE *fdialers;
2N/A
2N/A/* this might be dynamically allocated */
2N/A#define NTOKENS 16
2N/Astatic char *tokens[NTOKENS], **tokptr;
2N/A
2N/A/* export these */
2N/Astatic void setservice(const char *service);
2N/Astatic void sysreset(void);
2N/Astatic void devreset(void);
2N/Astatic void dialreset(void);
2N/Astatic void setdevcfg(char *, char *);
2N/Astatic void setservice(const char *);
2N/A
2N/A/* import these */
2N/Aextern char *strsave(const char *);
2N/Astatic int eaccess(char *, mode_t);
2N/A
2N/A/*
2N/A * setservice init's Systems, Devices, Dialers lists from Sysfiles
2N/A */
2N/Astatic void
2N/Asetservice(const char *service)
2N/A{
2N/A setconfig();
2N/A scansys(service);
2N/A}
2N/A
2N/A/*
2N/A * setdevcfg init's Pops, Pushes lists from Devconfig
2N/A */
2N/A
2N/Astatic void
2N/Asetdevcfg(char *service, char *device)
2N/A{
2N/A scancfg(service, device);
2N/A}
2N/A
2N/A/* administrative files access */
2N/Astatic int
2N/Asysaccess(int type)
2N/A{
2N/A char errformat[BUFSIZ];
2N/A
2N/A switch (type) {
2N/A case ACCESS_SYSTEMS:
2N/A return (access(Systems[nsystems], R_OK));
2N/A case ACCESS_DEVICES:
2N/A return (access(Devices[ndevices], R_OK));
2N/A case ACCESS_DIALERS:
2N/A return (access(Dialers[ndialers], R_OK));
2N/A case EACCESS_SYSTEMS:
2N/A return (eaccess(Systems[nsystems], R_OK));
2N/A case EACCESS_DEVICES:
2N/A return (eaccess(Devices[ndevices], R_OK));
2N/A case EACCESS_DIALERS:
2N/A return (eaccess(Dialers[ndialers], R_OK));
2N/A }
2N/A (void) sprintf(errformat, "bad access type %d", type);
2N/A logent(errformat, "sysaccess");
2N/A return (FAIL);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * read Sysfiles, set up lists of Systems/Devices/Dialers file names.
2N/A * allow multiple entries for a given service, allow a service
2N/A * type to describe resources more than once, e.g., systems=foo:baz systems=bar.
2N/A */
2N/Astatic void
2N/Ascansys(const char *service)
2N/A{ FILE *f;
2N/A char *tok, buf[BUFSIZ];
2N/A char **tptr;
2N/A
2N/A /*
2N/A * Release and Initialize previously allocated memory
2N/A * for Systems, Devices and Dialers.
2N/A */
2N/A nsystems = 0;
2N/A tptr = Systems;
2N/A while (*tptr) {
2N/A free(*tptr);
2N/A *tptr = NULL;
2N/A tptr++;
2N/A }
2N/A
2N/A ndevices = 0;
2N/A tptr = Devices;
2N/A while (*tptr) {
2N/A free(*tptr);
2N/A *tptr = NULL;
2N/A tptr++;
2N/A }
2N/A
2N/A ndialers = 0;
2N/A tptr = Dialers;
2N/A while (*tptr) {
2N/A free(*tptr);
2N/A *tptr = NULL;
2N/A tptr++;
2N/A }
2N/A
2N/A if ((f = fopen(SYSFILES, "rF")) != 0) {
2N/A while (getaline(f, buf) > 0) {
2N/A /* got a (logical) line from Sysfiles */
2N/A /* strtok's of this buf continue in tokenize() */
2N/A tok = strtok(buf, " \t");
2N/A if (namematch("service=", tok, service)) {
2N/A tokenize();
2N/A nameparse();
2N/A }
2N/A }
2N/A (void) fclose(f);
2N/A }
2N/A
2N/A /* if didn't find entries in Sysfiles, use defaults */
2N/A if (Systems[0] == NULL) {
2N/A Systems[0] = strsave(SYSTEMS);
2N/A ASSERT(Systems[0] != NULL, "Ct_ALLOCATE", "scansys: Systems",
2N/A 0);
2N/A Systems[1] = NULL;
2N/A }
2N/A if (Devices[0] == NULL) {
2N/A Devices[0] = strsave(DEVICES);
2N/A ASSERT(Devices[0] != NULL, "Ct_ALLOCATE", "scansys: Devices",
2N/A 0);
2N/A Devices[1] = NULL;
2N/A }
2N/A if (Dialers[0] == NULL) {
2N/A Dialers[0] = strsave(DIALERS);
2N/A ASSERT(Dialers[0] != NULL, "Ct_ALLOCATE", "scansys: Dialers",
2N/A 0);
2N/A Dialers[1] = NULL;
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * read Devconfig. allow multiple entries for a given service, allow a service
2N/A * type to describe resources more than once, e.g., push=foo:baz push=bar.
2N/A */
2N/Astatic void
2N/Ascancfg(char *service, char *device)
2N/A{ FILE *f;
2N/A char *tok, buf[BUFSIZ];
2N/A
2N/A /* (re)initialize device-specific information */
2N/A npops = npushes = 0;
2N/A Pops[0] = Pushes[0] = NULL;
2N/A connecttime = CONNECTTIME;
2N/A expecttime = EXPECTTIME;
2N/A
2N/A if ((f = fopen(DEVCONFIG, "rF")) != 0) {
2N/A while (getaline(f, buf) > 0) {
2N/A /* got a (logical) line from Devconfig */
2N/A /* strtok's of this buf continue in tokenize() */
2N/A tok = strtok(buf, " \t");
2N/A if (namematch("service=", tok, service)) {
2N/A tok = strtok((char *)0, " \t");
2N/A if (namematch("device=", tok, device)) {
2N/A tokenize();
2N/A nameparse();
2N/A }
2N/A }
2N/A }
2N/A (void) fclose(f);
2N/A }
2N/A return;
2N/A
2N/A}
2N/A
2N/A/*
2N/A * given a file pointer and buffer, construct logical line in buffer
2N/A * (i.e., concatenate lines ending in '\'). return length of line
2N/A * ASSUMES that buffer is BUFSIZ long!
2N/A */
2N/A
2N/Astatic int
2N/Agetaline(FILE *f, char *line)
2N/A{ char *lptr, *lend;
2N/A
2N/A lptr = line;
2N/A while (fgets(lptr, (line + BUFSIZ) - lptr, f) != NULL) {
2N/A lend = lptr + strlen(lptr);
2N/A if (lend == lptr || lend[-1] != '\n')
2N/A /* empty buf or line too long! */
2N/A break;
2N/A *--lend = '\0'; /* lop off ending '\n' */
2N/A if (lend == line) /* empty line - ignore */
2N/A continue;
2N/A lptr = lend;
2N/A if (lend[-1] != '\\')
2N/A break;
2N/A /* continuation */
2N/A lend[-1] = ' ';
2N/A }
2N/A return (lptr - line);
2N/A}
2N/A
2N/A/*
2N/A * given a label (e.g., "service=", "device="), a name ("cu", "uucico"),
2N/A * and a line: if line begins with the label and if the name appears
2N/A * in a colon-separated list of names following the label, return true;
2N/A * else return false
2N/A */
2N/Astatic int
2N/Anamematch(const char *label, char *line, const char *name)
2N/A{
2N/A char *lend;
2N/A
2N/A if (strncmp(label, line, strlen(label)) != SAME)
2N/A return (FALSE); /* probably a comment line */
2N/A line += strlen(label);
2N/A if (*line == '\0')
2N/A return (FALSE);
2N/A /*
2N/A * can't use strtok() in the following because scansys(),
2N/A * scancfg() do an initializing call to strtok() before
2N/A * coming here and then CONTINUE calling strtok() in tokenize(),
2N/A * after returning from namematch().
2N/A */
2N/A while ((lend = strchr(line, ':')) != NULL) {
2N/A *lend = '\0';
2N/A if (strcmp(line, name) == SAME)
2N/A return (TRUE);
2N/A line = lend+1;
2N/A }
2N/A return (strcmp(line, name) == SAME);
2N/A}
2N/A
2N/A/*
2N/A * tokenize() continues pulling tokens out of a buffer -- the
2N/A * initializing call to strtok must have been made before calling
2N/A * tokenize() -- and starts stuffing 'em into tokptr.
2N/A */
2N/Astatic void
2N/Atokenize(void)
2N/A{
2N/A char *tok;
2N/A
2N/A tokptr = tokens;
2N/A while ((tok = strtok(NULL, " \t")) != NULL) {
2N/A *tokptr++ = tok;
2N/A if (tokptr - tokens >= NTOKENS)
2N/A break;
2N/A }
2N/A *tokptr = NULL;
2N/A}
2N/A
2N/A/*
2N/A * look at top token in array: should be line of the form
2N/A * name=item1:item2:item3...
2N/A * if name is one we recognize, then call set[file|ioctl] to set up
2N/A * corresponding list. otherwise, log bad name.
2N/A */
2N/Astatic void
2N/Anameparse(void)
2N/A{
2N/A char **line, *equals;
2N/A int temp;
2N/A
2N/A#define setuint(a, b, c) a = (((temp = atoi(b)) <= 0) ? (c) : temp)
2N/A
2N/A for (line = tokens; (line - tokens) < NTOKENS && *line; line++) {
2N/A equals = strchr(*line, '=');
2N/A if (equals == NULL)
2N/A continue; /* may be meaningful someday? */
2N/A *equals = '\0';
2N/A /* ignore entry with empty rhs */
2N/A if (*++equals == '\0')
2N/A continue;
2N/A if (strcmp(*line, "systems") == SAME)
2N/A setfile(Systems, equals);
2N/A else if (strcmp(*line, "devices") == SAME)
2N/A setfile(Devices, equals);
2N/A else if (strcmp(*line, "dialers") == SAME)
2N/A setfile(Dialers, equals);
2N/A else if (strcmp(*line, "pop") == SAME)
2N/A setioctl(Pops, equals);
2N/A else if (strcmp(*line, "push") == SAME)
2N/A setioctl(Pushes, equals);
2N/A else if (strcmp(*line, "connecttime") == SAME)
2N/A setuint(connecttime, equals, CONNECTTIME);
2N/A else if (strcmp(*line, "expecttime") == SAME)
2N/A setuint(expecttime, equals, EXPECTTIME);
2N/A else if (strcmp(*line, "msgtime") == SAME)
2N/A continue;
2N/A else {
2N/A char errformat[BUFSIZ];
2N/A
2N/A (void) snprintf(errformat, sizeof (errformat),
2N/A "unrecognized label %s", *line);
2N/A logent(errformat, "Sysfiles|Devconfig");
2N/A }
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * given the list for a particular type (systems, devices,...)
2N/A * and a line of colon-separated files, add 'em to list
2N/A */
2N/A
2N/Astatic void
2N/Asetfile(char **type, char *line)
2N/A{
2N/A char **tptr, *tok;
2N/A char expandpath[BUFSIZ];
2N/A
2N/A if (*line == 0)
2N/A return;
2N/A tptr = type;
2N/A while (*tptr) /* skip over existing entries to */
2N/A tptr++; /* concatenate multiple entries */
2N/A
2N/A for (tok = strtok(line, ":"); tok != NULL; tok = strtok(NULL, ":")) {
2N/A expandpath[0] = '\0';
2N/A if (*tok != '/')
2N/A /* by default, file names are relative to SYSDIR */
2N/A (void) snprintf(expandpath, sizeof (expandpath),
2N/A "%s/", SYSDIR);
2N/A (void) strcat(expandpath, tok);
2N/A if (eaccess(expandpath, R_OK) != 0)
2N/A /* if we can't read it, no point in adding to list */
2N/A continue;
2N/A *tptr = strsave(expandpath);
2N/A ASSERT(*tptr != NULL, "Ct_ALLOCATE", "setfile: tptr", 0);
2N/A tptr++;
2N/A }
2N/A *tptr = NULL;
2N/A}
2N/A
2N/A/*
2N/A * given the list for a particular ioctl (push, pop)
2N/A * and a line of colon-separated modules, add 'em to list
2N/A */
2N/A
2N/Astatic void
2N/Asetioctl(char **type, char *line)
2N/A{
2N/A char **tptr, *tok;
2N/A
2N/A if (*line == 0)
2N/A return;
2N/A tptr = type;
2N/A while (*tptr) /* skip over existing entries to */
2N/A tptr++; /* concatenate multiple entries */
2N/A for (tok = strtok(line, ":"); tok != NULL; tok = strtok(NULL, ":")) {
2N/A *tptr = strsave(tok);
2N/A ASSERT(*tptr != NULL, "Ct_ALLOCATE", "setioctl: tptr", 0);
2N/A tptr++;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * reset Systems files
2N/A */
2N/Astatic void
2N/Asysreset(void)
2N/A{
2N/A if (fsystems)
2N/A (void) fclose(fsystems);
2N/A fsystems = NULL;
2N/A nsystems = 0;
2N/A devreset();
2N/A}
2N/A
2N/A/*
2N/A * reset Devices files
2N/A */
2N/Astatic void
2N/Adevreset(void)
2N/A{
2N/A if (fdevices)
2N/A (void) fclose(fdevices);
2N/A fdevices = NULL;
2N/A ndevices = 0;
2N/A dialreset();
2N/A}
2N/A
2N/A/*
2N/A * reset Dialers files
2N/A */
2N/Astatic void
2N/Adialreset(void)
2N/A{
2N/A if (fdialers)
2N/A (void) fclose(fdialers);
2N/A fdialers = NULL;
2N/A ndialers = 0;
2N/A}
2N/A
2N/A/*
2N/A * get next line from Systems file
2N/A * return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Agetsysline(char *buf, int len)
2N/A{
2N/A if (Systems[0] == NULL)
2N/A /* not initialized via setservice() - use default */
2N/A setservice("uucico");
2N/A
2N/A /* initialize devices and dialers whenever a new line is read */
2N/A /* from systems */
2N/A devreset();
2N/A if (fsystems == NULL)
2N/A if (nextsystems() == FALSE)
2N/A return (FALSE);
2N/A
2N/A for (;;) {
2N/A while (fgets(buf, len, fsystems) != NULL)
2N/A if ((*buf != '#') && (*buf != ' ') &&
2N/A (*buf != '\t') && (*buf != '\n'))
2N/A return (TRUE);
2N/A if (nextsystems() == FALSE)
2N/A return (FALSE);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * move to next systems file. return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Anextsystems(void)
2N/A{
2N/A devreset();
2N/A
2N/A if (fsystems != NULL) {
2N/A (void) fclose(fsystems);
2N/A nsystems++;
2N/A } else {
2N/A nsystems = 0;
2N/A }
2N/A for (; Systems[nsystems] != NULL; nsystems++)
2N/A if ((fsystems = fopen(Systems[nsystems], "rF")) != NULL)
2N/A return (TRUE);
2N/A return (FALSE);
2N/A}
2N/A
2N/A/*
2N/A * get next line from Devices file
2N/A * return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Agetdevline(char *buf, int len)
2N/A{
2N/A if (Devices[0] == NULL)
2N/A /* not initialized via setservice() - use default */
2N/A setservice("uucico");
2N/A
2N/A if (fdevices == NULL)
2N/A if (nextdevices() == FALSE)
2N/A return (FALSE);
2N/A for (;;) {
2N/A if (fgets(buf, len, fdevices) != NULL)
2N/A return (TRUE);
2N/A if (nextdevices() == FALSE)
2N/A return (FALSE);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * move to next devices file. return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Anextdevices(void)
2N/A{
2N/A if (fdevices != NULL) {
2N/A (void) fclose(fdevices);
2N/A ndevices++;
2N/A } else {
2N/A ndevices = 0;
2N/A }
2N/A for (; Devices[ndevices] != NULL; ndevices++)
2N/A if ((fdevices = fopen(Devices[ndevices], "rF")) != NULL)
2N/A return (TRUE);
2N/A return (FALSE);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * get next line from Dialers file
2N/A * return TRUE if successful, FALSE if not
2N/A */
2N/A
2N/Astatic int
2N/Agetdialline(char *buf, int len)
2N/A{
2N/A if (Dialers[0] == NULL)
2N/A /* not initialized via setservice() - use default */
2N/A setservice("uucico");
2N/A
2N/A if (fdialers == NULL)
2N/A if (nextdialers() == FALSE)
2N/A return (FALSE);
2N/A for (;;) {
2N/A if (fgets(buf, len, fdialers) != NULL)
2N/A return (TRUE);
2N/A if (nextdialers() == FALSE)
2N/A return (FALSE);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * move to next dialers file. return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Anextdialers(void)
2N/A{
2N/A if (fdialers) {
2N/A (void) fclose(fdialers);
2N/A ndialers++;
2N/A } else {
2N/A ndialers = 0;
2N/A }
2N/A
2N/A for (; Dialers[ndialers] != NULL; ndialers++)
2N/A if ((fdialers = fopen(Dialers[ndialers], "rF")) != NULL)
2N/A return (TRUE);
2N/A return (FALSE);
2N/A}
2N/A
2N/A/*
2N/A * get next module to be popped
2N/A * return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Agetpop(char *buf, size_t len, int *optional)
2N/A{
2N/A int slen;
2N/A
2N/A if (Pops[0] == NULL || Pops[npops] == NULL)
2N/A return (FALSE);
2N/A
2N/A /* if the module name is enclosed in parentheses, */
2N/A /* is optional. set flag & strip parens */
2N/A slen = strlen(Pops[npops]) - 1;
2N/A if (Pops[npops][0] == '(' && Pops[npops][slen] == ')') {
2N/A *optional = 1;
2N/A len = (slen < len ? slen : len);
2N/A (void) strncpy(buf, &(Pops[npops++][1]), len);
2N/A } else {
2N/A *optional = 0;
2N/A (void) strncpy(buf, Pops[npops++], len);
2N/A }
2N/A buf[len-1] = '\0';
2N/A return (TRUE);
2N/A}
2N/A
2N/A/*
2N/A * get next module to be pushed
2N/A * return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Agetpush(char *buf, size_t len)
2N/A{
2N/A if (Pushes[0] == NULL || Pushes[npushes] == NULL)
2N/A return (FALSE);
2N/A (void) strncpy(buf, Pushes[npushes++], len);
2N/A return (TRUE);
2N/A}
2N/A
2N/A/*
2N/A * pop/push requested modules
2N/A * return TRUE if successful, FALSE if not
2N/A */
2N/Astatic int
2N/Apop_push(int fd)
2N/A{
2N/A char strmod[FMNAMESZ], onstream[FMNAMESZ];
2N/A int optional;
2N/A
2N/A /* check for streams modules to pop */
2N/A while (getpop(strmod, sizeof (strmod), &optional)) {
2N/A DEBUG(5, (optional ?
2N/A (const char *)"pop_push: optionally POPing %s\n" :
2N/A (const char *)"pop_push: POPing %s\n"), strmod);
2N/A if (ioctl(fd, I_LOOK, onstream) == -1) {
2N/A DEBUG(5, "pop_push: I_LOOK on fd %d failed ", fd);
2N/A DEBUG(5, "errno %d\n", errno);
2N/A return (FALSE);
2N/A }
2N/A if (strcmp(strmod, onstream) != SAME) {
2N/A if (optional)
2N/A continue;
2N/A DEBUG(5, "pop_push: I_POP: %s not there\n", strmod);
2N/A return (FALSE);
2N/A }
2N/A if (ioctl(fd, I_POP, 0) == -1) {
2N/A DEBUG(5, "pop_push: I_POP on fd %d failed ", fd);
2N/A DEBUG(5, "errno %d\n", errno);
2N/A return (FALSE);
2N/A }
2N/A }
2N/A
2N/A /* check for streams modules to push */
2N/A while (getpush(strmod, sizeof (strmod))) {
2N/A DEBUG(5, "pop_push: PUSHing %s\n", strmod);
2N/A if (ioctl(fd, I_PUSH, strmod) == -1) {
2N/A DEBUG(5, "pop_push: I_PUSH on fd %d failed ", fd);
2N/A DEBUG(5, "errno %d\n", errno);
2N/A return (FALSE);
2N/A }
2N/A }
2N/A return (TRUE);
2N/A}
2N/A
2N/A#ifndef SMALL
2N/A/*
2N/A * return name of currently open Systems file
2N/A */
2N/Astatic char *
2N/Acurrsys(void)
2N/A{
2N/A return (Systems[nsystems]);
2N/A}
2N/A
2N/A/*
2N/A * return name of currently open Devices file
2N/A */
2N/Astatic char *
2N/Acurrdev(void)
2N/A{
2N/A return (Devices[ndevices]);
2N/A}
2N/A
2N/A/*
2N/A * return name of currently open Dialers file
2N/A */
2N/Astatic char *
2N/Acurrdial(void)
2N/A{
2N/A return (Dialers[ndialers]);
2N/A}
2N/A#endif
2N/A
2N/A/*
2N/A * set configuration parameters provided in Config file
2N/A */
2N/Astatic void
2N/Asetconfig(void)
2N/A{
2N/A FILE *f;
2N/A char buf[BUFSIZ];
2N/A char *tok;
2N/A extern char _ProtoCfg[];
2N/A
2N/A if ((f = fopen(CONFIG, "rF")) != 0) {
2N/A while (getaline(f, buf) > 0) {
2N/A /* got a (logical) line from Config file */
2N/A tok = strtok(buf, " \t");
2N/A if ((tok != NULL) && (*tok != '#')) {
2N/A /* got a token */
2N/A /*
2N/A * this probably should be table driven when
2N/A * the list of configurable parameters grows.
2N/A */
2N/A if (strncmp("Protocol=", tok, strlen("Protocol=")) ==
2N/A SAME) {
2N/A tok += strlen("Protocol=");
2N/A if (*tok != '\0') {
2N/A if (_ProtoCfg[0] != '\0') {
2N/A /*EMPTY*/
2N/A DEBUG(7, "Protocol string %s ",
2N/A tok);
2N/A DEBUG(7, "overrides %s\n",
2N/A _ProtoCfg);
2N/A }
2N/A (void) strcpy(_ProtoCfg, tok);
2N/A }
2N/A } else {
2N/A /*EMPTY*/
2N/A DEBUG(7, "Unknown configuration parameter %s\n",
2N/A tok);
2N/A }
2N/A }
2N/A }
2N/A (void) fclose(f);
2N/A }
2N/A}