#include "mt.h"
#include "uucp.h"
#include <unistd.h>
#include <string.h>
#include "sysfiles.h"
#include <sys/stropts.h>
static void tokenize(void);
static void nameparse(void);
static void setfile(char **, char *);
static void setioctl(char **, char *);
static void scansys(const char *);
static void scancfg(char *, char *);
static void setconfig(void);
static int namematch(const char *label, char *line, const char *name);
static int nextdialers(void);
static int nextdevices(void);
static int nextsystems(void);
static int getaline(FILE *, char *);
static char *Systems[64];
static char *Devices[64];
static char *Dialers[64];
static char *Pops[64];
static char *Pushes[64];
static int nsystems;
static int ndevices;
static int ndialers;
static int npops;
static int npushes;
static unsigned connecttime, expecttime;
static FILE *fsystems;
static FILE *fdevices;
static FILE *fdialers;
#define NTOKENS 16
static char *tokens[NTOKENS], **tokptr;
static void setservice(const char *service);
static void sysreset(void);
static void devreset(void);
static void dialreset(void);
static void setdevcfg(char *, char *);
static void setservice(const char *);
extern char *strsave(const char *);
static int eaccess(char *, mode_t);
static void
setservice(const char *service)
{
setconfig();
scansys(service);
}
static void
setdevcfg(char *service, char *device)
{
scancfg(service, device);
}
static int
sysaccess(int type)
{
char errformat[BUFSIZ];
switch (type) {
case ACCESS_SYSTEMS:
return (access(Systems[nsystems], R_OK));
case ACCESS_DEVICES:
return (access(Devices[ndevices], R_OK));
case ACCESS_DIALERS:
return (access(Dialers[ndialers], R_OK));
case EACCESS_SYSTEMS:
return (eaccess(Systems[nsystems], R_OK));
case EACCESS_DEVICES:
return (eaccess(Devices[ndevices], R_OK));
case EACCESS_DIALERS:
return (eaccess(Dialers[ndialers], R_OK));
}
(void) sprintf(errformat, "bad access type %d", type);
logent(errformat, "sysaccess");
return (FAIL);
}
static void
scansys(const char *service)
{ FILE *f;
char *tok, buf[BUFSIZ];
char **tptr;
nsystems = 0;
tptr = Systems;
while (*tptr) {
free(*tptr);
*tptr = NULL;
tptr++;
}
ndevices = 0;
tptr = Devices;
while (*tptr) {
free(*tptr);
*tptr = NULL;
tptr++;
}
ndialers = 0;
tptr = Dialers;
while (*tptr) {
free(*tptr);
*tptr = NULL;
tptr++;
}
if ((f = fopen(SYSFILES, "rF")) != 0) {
while (getaline(f, buf) > 0) {
tok = strtok(buf, " \t");
if (namematch("service=", tok, service)) {
tokenize();
nameparse();
}
}
(void) fclose(f);
}
if (Systems[0] == NULL) {
Systems[0] = strsave(SYSTEMS);
ASSERT(Systems[0] != NULL, "Ct_ALLOCATE", "scansys: Systems",
0);
Systems[1] = NULL;
}
if (Devices[0] == NULL) {
Devices[0] = strsave(DEVICES);
ASSERT(Devices[0] != NULL, "Ct_ALLOCATE", "scansys: Devices",
0);
Devices[1] = NULL;
}
if (Dialers[0] == NULL) {
Dialers[0] = strsave(DIALERS);
ASSERT(Dialers[0] != NULL, "Ct_ALLOCATE", "scansys: Dialers",
0);
Dialers[1] = NULL;
}
}
static void
scancfg(char *service, char *device)
{ FILE *f;
char *tok, buf[BUFSIZ];
npops = npushes = 0;
Pops[0] = Pushes[0] = NULL;
connecttime = CONNECTTIME;
expecttime = EXPECTTIME;
if ((f = fopen(DEVCONFIG, "rF")) != 0) {
while (getaline(f, buf) > 0) {
tok = strtok(buf, " \t");
if (namematch("service=", tok, service)) {
tok = strtok((char *)0, " \t");
if (namematch("device=", tok, device)) {
tokenize();
nameparse();
}
}
}
(void) fclose(f);
}
return;
}
static int
getaline(FILE *f, char *line)
{ char *lptr, *lend;
lptr = line;
while (fgets(lptr, (line + BUFSIZ) - lptr, f) != NULL) {
lend = lptr + strlen(lptr);
if (lend == lptr || lend[-1] != '\n')
break;
*--lend = '\0';
if (lend == line)
continue;
lptr = lend;
if (lend[-1] != '\\')
break;
lend[-1] = ' ';
}
return (lptr - line);
}
static int
namematch(const char *label, char *line, const char *name)
{
char *lend;
if (strncmp(label, line, strlen(label)) != SAME)
return (FALSE);
line += strlen(label);
if (*line == '\0')
return (FALSE);
while ((lend = strchr(line, ':')) != NULL) {
*lend = '\0';
if (strcmp(line, name) == SAME)
return (TRUE);
line = lend+1;
}
return (strcmp(line, name) == SAME);
}
static void
tokenize(void)
{
char *tok;
tokptr = tokens;
while ((tok = strtok(NULL, " \t")) != NULL) {
*tokptr++ = tok;
if (tokptr - tokens >= NTOKENS)
break;
}
*tokptr = NULL;
}
static void
nameparse(void)
{
char **line, *equals;
int temp;
#define setuint(a, b, c) a = (((temp = atoi(b)) <= 0) ? (c) : temp)
for (line = tokens; (line - tokens) < NTOKENS && *line; line++) {
equals = strchr(*line, '=');
if (equals == NULL)
continue;
*equals = '\0';
if (*++equals == '\0')
continue;
if (strcmp(*line, "systems") == SAME)
setfile(Systems, equals);
else if (strcmp(*line, "devices") == SAME)
setfile(Devices, equals);
else if (strcmp(*line, "dialers") == SAME)
setfile(Dialers, equals);
else if (strcmp(*line, "pop") == SAME)
setioctl(Pops, equals);
else if (strcmp(*line, "push") == SAME)
setioctl(Pushes, equals);
else if (strcmp(*line, "connecttime") == SAME)
setuint(connecttime, equals, CONNECTTIME);
else if (strcmp(*line, "expecttime") == SAME)
setuint(expecttime, equals, EXPECTTIME);
else if (strcmp(*line, "msgtime") == SAME)
continue;
else {
char errformat[BUFSIZ];
(void) snprintf(errformat, sizeof (errformat),
"unrecognized label %s", *line);
logent(errformat, "Sysfiles|Devconfig");
}
}
}
static void
setfile(char **type, char *line)
{
char **tptr, *tok;
char expandpath[BUFSIZ];
if (*line == 0)
return;
tptr = type;
while (*tptr)
tptr++;
for (tok = strtok(line, ":"); tok != NULL; tok = strtok(NULL, ":")) {
expandpath[0] = '\0';
if (*tok != '/')
(void) snprintf(expandpath, sizeof (expandpath),
"%s/", SYSDIR);
(void) strcat(expandpath, tok);
if (eaccess(expandpath, R_OK) != 0)
continue;
*tptr = strsave(expandpath);
ASSERT(*tptr != NULL, "Ct_ALLOCATE", "setfile: tptr", 0);
tptr++;
}
*tptr = NULL;
}
static void
setioctl(char **type, char *line)
{
char **tptr, *tok;
if (*line == 0)
return;
tptr = type;
while (*tptr)
tptr++;
for (tok = strtok(line, ":"); tok != NULL; tok = strtok(NULL, ":")) {
*tptr = strsave(tok);
ASSERT(*tptr != NULL, "Ct_ALLOCATE", "setioctl: tptr", 0);
tptr++;
}
}
static void
sysreset(void)
{
if (fsystems)
(void) fclose(fsystems);
fsystems = NULL;
nsystems = 0;
devreset();
}
static void
devreset(void)
{
if (fdevices)
(void) fclose(fdevices);
fdevices = NULL;
ndevices = 0;
dialreset();
}
static void
dialreset(void)
{
if (fdialers)
(void) fclose(fdialers);
fdialers = NULL;
ndialers = 0;
}
static int
getsysline(char *buf, int len)
{
if (Systems[0] == NULL)
setservice("uucico");
devreset();
if (fsystems == NULL)
if (nextsystems() == FALSE)
return (FALSE);
for (;;) {
while (fgets(buf, len, fsystems) != NULL)
if ((*buf != '#') && (*buf != ' ') &&
(*buf != '\t') && (*buf != '\n'))
return (TRUE);
if (nextsystems() == FALSE)
return (FALSE);
}
}
static int
nextsystems(void)
{
devreset();
if (fsystems != NULL) {
(void) fclose(fsystems);
nsystems++;
} else {
nsystems = 0;
}
for (; Systems[nsystems] != NULL; nsystems++)
if ((fsystems = fopen(Systems[nsystems], "rF")) != NULL)
return (TRUE);
return (FALSE);
}
static int
getdevline(char *buf, int len)
{
if (Devices[0] == NULL)
setservice("uucico");
if (fdevices == NULL)
if (nextdevices() == FALSE)
return (FALSE);
for (;;) {
if (fgets(buf, len, fdevices) != NULL)
return (TRUE);
if (nextdevices() == FALSE)
return (FALSE);
}
}
static int
nextdevices(void)
{
if (fdevices != NULL) {
(void) fclose(fdevices);
ndevices++;
} else {
ndevices = 0;
}
for (; Devices[ndevices] != NULL; ndevices++)
if ((fdevices = fopen(Devices[ndevices], "rF")) != NULL)
return (TRUE);
return (FALSE);
}
static int
getdialline(char *buf, int len)
{
if (Dialers[0] == NULL)
setservice("uucico");
if (fdialers == NULL)
if (nextdialers() == FALSE)
return (FALSE);
for (;;) {
if (fgets(buf, len, fdialers) != NULL)
return (TRUE);
if (nextdialers() == FALSE)
return (FALSE);
}
}
static int
nextdialers(void)
{
if (fdialers) {
(void) fclose(fdialers);
ndialers++;
} else {
ndialers = 0;
}
for (; Dialers[ndialers] != NULL; ndialers++)
if ((fdialers = fopen(Dialers[ndialers], "rF")) != NULL)
return (TRUE);
return (FALSE);
}
static int
getpop(char *buf, size_t len, int *optional)
{
int slen;
if (Pops[0] == NULL || Pops[npops] == NULL)
return (FALSE);
slen = strlen(Pops[npops]) - 1;
if (Pops[npops][0] == '(' && Pops[npops][slen] == ')') {
*optional = 1;
len = (slen < len ? slen : len);
(void) strncpy(buf, &(Pops[npops++][1]), len);
} else {
*optional = 0;
(void) strncpy(buf, Pops[npops++], len);
}
buf[len-1] = '\0';
return (TRUE);
}
static int
getpush(char *buf, size_t len)
{
if (Pushes[0] == NULL || Pushes[npushes] == NULL)
return (FALSE);
(void) strncpy(buf, Pushes[npushes++], len);
return (TRUE);
}
static int
pop_push(int fd)
{
char strmod[FMNAMESZ], onstream[FMNAMESZ];
int optional;
while (getpop(strmod, sizeof (strmod), &optional)) {
DEBUG(5, (optional ?
(const char *)"pop_push: optionally POPing %s\n" :
(const char *)"pop_push: POPing %s\n"), strmod);
if (ioctl(fd, I_LOOK, onstream) == -1) {
DEBUG(5, "pop_push: I_LOOK on fd %d failed ", fd);
DEBUG(5, "errno %d\n", errno);
return (FALSE);
}
if (strcmp(strmod, onstream) != SAME) {
if (optional)
continue;
DEBUG(5, "pop_push: I_POP: %s not there\n", strmod);
return (FALSE);
}
if (ioctl(fd, I_POP, 0) == -1) {
DEBUG(5, "pop_push: I_POP on fd %d failed ", fd);
DEBUG(5, "errno %d\n", errno);
return (FALSE);
}
}
while (getpush(strmod, sizeof (strmod))) {
DEBUG(5, "pop_push: PUSHing %s\n", strmod);
if (ioctl(fd, I_PUSH, strmod) == -1) {
DEBUG(5, "pop_push: I_PUSH on fd %d failed ", fd);
DEBUG(5, "errno %d\n", errno);
return (FALSE);
}
}
return (TRUE);
}
#ifndef SMALL
static char *
currsys(void)
{
return (Systems[nsystems]);
}
static char *
currdev(void)
{
return (Devices[ndevices]);
}
static char *
currdial(void)
{
return (Dialers[ndialers]);
}
#endif
static void
setconfig(void)
{
FILE *f;
char buf[BUFSIZ];
char *tok;
extern char _ProtoCfg[];
if ((f = fopen(CONFIG, "rF")) != 0) {
while (getaline(f, buf) > 0) {
tok = strtok(buf, " \t");
if ((tok != NULL) && (*tok != '#')) {
if (strncmp("Protocol=", tok, strlen("Protocol=")) ==
SAME) {
tok += strlen("Protocol=");
if (*tok != '\0') {
if (_ProtoCfg[0] != '\0') {
DEBUG(7, "Protocol string %s ",
tok);
DEBUG(7, "overrides %s\n",
_ProtoCfg);
}
(void) strcpy(_ProtoCfg, tok);
}
} else {
DEBUG(7, "Unknown configuration parameter %s\n",
tok);
}
}
}
(void) fclose(f);
}
}