NetBSD/gnu/libexec/uucp/v2.c

653 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* v2.c
Read V2 configuration files. Much of this file is identical to bnu.c,
and they really should be partially merged.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o AIRS, P.O. Box 520, Waltham, MA 02254.
$Log: v2.c,v $
Revision 1.1.1.1 1993/03/21 09:45:37 cgd
initial import of 386bsd-0.1 sources
Revision 1.15 1992/03/12 19:54:43 ian
Debugging based on types rather than number
Revision 1.14 1992/03/10 21:47:39 ian
Added protocol command for ports
Revision 1.13 1992/03/04 02:09:36 ian
Jeff Putsch: infinite loop when parsing time string
Revision 1.12 1992/02/24 20:36:27 ian
Roberto Biancardi: skip spaces after strtok (NULL, "")
Revision 1.11 1992/02/08 03:54:18 ian
Include <string.h> only in <uucp.h>, added 1992 copyright
Revision 1.10 1992/01/15 07:06:29 ian
Set configuration directory in Makefile rather than sysdep.h
Revision 1.9 1992/01/05 04:30:45 ian
Set chat script correctly
Revision 1.8 1991/12/28 03:49:23 ian
Added HAVE_MEMFNS and HAVE_BFNS; changed uses of memset to bzero
Revision 1.7 1991/12/01 19:35:38 ian
David Nugent: read V2 and BNU files by default even with TAYLOR_CONFIG
Revision 1.6 1991/11/26 01:04:04 ian
Marty Shannon: initialize ireliable for BNU and V2 configuration files
Revision 1.5 1991/11/14 03:20:13 ian
Added seven-bit and reliable commands to help when selecting protocols
Revision 1.4 1991/11/13 20:38:00 ian
Added TCP port type for connections over TCP
Revision 1.3 1991/11/11 16:59:05 ian
Eliminate fread_port_info, allow NULL pflock arg to ffind_port
Revision 1.2 1991/09/19 02:22:44 ian
Chip Salzenberg's patch to allow ";retrytime" at the end of a time string
Revision 1.1 1991/09/10 19:40:31 ian
Initial revision
*/
#include "uucp.h"
#if HAVE_V2_CONFIG
#if USE_RCS_ID
char v2_rcsid[] = "$Id: v2.c,v 1.1.1.1 1993/03/21 09:45:37 cgd Exp $";
#endif
#include <errno.h>
#include "port.h"
#include "sysdep.h"
/* Whether to use V2 configuration files. */
boolean fV2 = TRUE;
/* A little routine to add a grade and a time string to a system. */
static void uvadd_time P((struct ssysteminfo *q, int bgrade,
const char *ztime, int cretry));
static void
uvadd_time (q, bgrade, ztime, cretry)
struct ssysteminfo *q;
int bgrade;
const char *ztime;
int cretry;
{
char *zset;
zset = (char *) alloca (strlen (ztime) + 20);
if (cretry == 0)
sprintf (zset, "%c%s", bgrade, ztime);
else
sprintf (zset, "%c%s;%d", bgrade, ztime, cretry);
uadd_string (&q->ztime, zset, ' ');
}
/* Read V2 system information. This means reading the L.sys file and
the USERFILE file. */
void
uv2_read_systems (pc, ppas)
int *pc;
struct ssysteminfo **ppas;
{
int calc;
char ab[sizeof OLDCONFIGLIB + sizeof V2_SYSTEMS - 1];
FILE *e;
char *zline;
*pc = 0;
*ppas = NULL;
calc = 0;
/* Read the L.sys file first. */
sprintf (ab, "%s%s", OLDCONFIGLIB, V2_SYSTEMS);
e = fopen (ab, "r");
if (e == NULL)
{
ulog (LOG_ERROR, "fopen (%s): %s", ab, strerror (errno));
return;
}
while ((zline = zfgets (e, FALSE)) != NULL)
{
char *ztok;
int i, cretry;
struct ssysteminfo *qset;
char *zsemi, *zslash;
zline[strcspn (zline, "#\n")] = '\0';
ztok = strtok (zline, " \t");
if (ztok == NULL)
{
xfree ((pointer) zline);
continue;
}
DEBUG_MESSAGE1 (DEBUG_CONFIG,
"uv2_read_systems: Reading system %s", ztok);
/* See if we already have information for this system. */
for (i = 0; i < *pc; i++)
if (strcmp ((*ppas)[i].zname, ztok) == 0)
break;
if (i >= *pc)
{
if (*pc >= calc)
{
calc += 10;
*ppas = ((struct ssysteminfo *)
xrealloc ((pointer) *ppas,
calc * sizeof (struct ssysteminfo)));
}
qset = &(*ppas)[*pc];
(*pc)++;
}
else
{
struct ssysteminfo **pq;
for (pq = &(*ppas)[i].qalternate;
*pq != NULL;
pq = &(*pq)->qalternate)
;
*pq = (struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo));
qset = *pq;
}
uset_system_defaults (qset);
qset->zname = ztok;
/* Get the time string. */
ztok = strtok ((char *) NULL, " \t");
if (ztok == NULL)
continue;
/* The format of the time string appears to be time/grade,
time/grade;retry. A missing grade is taken as 'z'. */
cretry = 0;
zsemi = strchr (ztok, ';');
if (zsemi != NULL)
{
*zsemi = '\0';
cretry = atoi (zsemi + 1);
}
qset->ztime = NULL;
while (TRUE)
{
char *zcomma;
zcomma = strchr (ztok, ',');
if (zcomma != NULL)
*zcomma = '\0';
zslash = strchr (ztok, '/');
if (zslash == NULL || zslash[1] == '\0')
uvadd_time (qset, BGRADE_LOW, ztok, cretry);
else
{
*zslash = '\0';
uvadd_time (qset, zslash[1], ztok, cretry);
}
if (zcomma == NULL)
break;
ztok = zcomma + 1;
}
/* Get the devices entry. */
qset->zport = strtok ((char *) NULL, " \t");
if (qset->zport != NULL)
{
/* Get the speed entry. This is the baud rate to use. */
ztok = strtok ((char *) NULL, " \t");
#if HAVE_TCP
/* If the port is "TCP", we set up a system specific port.
The baud rate becomes the service number and the phone
number becomes the address (which is still stored in
qsys->zphone). */
if (strcmp (qset->zport, "TCP") == 0)
{
qset->zport = NULL;
qset->qport = ((struct sport *)
xmalloc (sizeof (struct sport)));
qset->qport->zname = "TCP";
qset->qport->ttype = PORTTYPE_TCP;
qset->qport->zprotocols = NULL;
qset->qport->cproto_params = 0;
qset->qport->qproto_params = NULL;
qset->qport->ireliable = (RELIABLE_ENDTOEND
| RELIABLE_RELIABLE
| RELIABLE_EIGHT
| RELIABLE_SPECIFIED);
qset->qport->zlockname = NULL;
qset->qport->u.stcp.o = -1;
if (ztok == NULL)
qset->qport->u.stcp.zport = "uucp";
else
qset->qport->u.stcp.zport = ztok;
}
#endif /* HAVE_TCP */
if (ztok != NULL)
{
qset->ibaud = atol (ztok);
/* Get the phone number. */
qset->zphone = strtok ((char *) NULL, " \t");
/* The rest of the line is the login script. */
if (qset->zphone != NULL)
{
qset->schat.zchat = strtok ((char *) NULL, "");
qset->schat.zchat += strspn (qset->schat.zchat, " \t");
}
}
}
}
(void) fclose (e);
/* Now read USERFILE and L.cmds to get permissions. We can't fully
handle USERFILE since that specifies permissions based on local
users which we do not support. */
{
char abuserfile[sizeof OLDCONFIGLIB + sizeof V2_USERFILE - 1];
sprintf (abuserfile, "%s%s", OLDCONFIGLIB, V2_USERFILE);
e = fopen (abuserfile, "r");
if (e == NULL)
ulog (LOG_ERROR, "fopen (%s): %s", abuserfile, strerror (errno));
else
{
boolean *affound;
boolean fothercallback;
char *zother;
affound = (boolean *) alloca (*pc * sizeof (boolean));
bzero (affound, *pc * sizeof (boolean));
fothercallback = FALSE;
zother = NULL;
while ((zline = zfgets (e, FALSE)) != NULL)
{
char *ztok, *zcomma, *zfiles, *zset;
boolean fcallback;
zline[strcspn (zline, "#\n")] = '\0';
/* The first field is username,machinename */
ztok = strtok (zline, " \t");
if (ztok == NULL)
{
xfree ((pointer) zline);
continue;
}
zcomma = strchr (ztok, ',');
if (zcomma == NULL)
{
xfree ((pointer) zline);
continue;
}
*zcomma++ = '\0';
/* The rest of the line is the list of directories, expect
that if the first directory is "c" we must call the
system back. */
zfiles = strtok ((char *) NULL, "");
zfiles += strspn (zfiles, " \t");
fcallback = FALSE;
if (*zfiles == 'c'
&& (zfiles[1] == '\0'
|| zfiles[1] == ' '
|| zfiles[1] == '\t'))
{
fcallback = TRUE;
++zfiles;
}
zset = NULL;
for (zfiles = strtok (zfiles, " \t");
zfiles != NULL;
zfiles = strtok ((char *) NULL, " \t"))
uadd_string (&zset, zfiles, ' ');
if (*ztok == '\0')
{
/* There is no user name. If this is the first entry
with no user name, then this line specifies the
directories which may be sent by local request
for login names which are not listed otherwise. */
if (zother == NULL)
{
zother = zset;
fothercallback = fcallback;
}
}
else if (*zcomma == '\0')
{
int i;
/* There is no system name. This entry specifies
permissions based on the login name. We must add
an alternate to each system specifying what to do
when this login name is used. */
for (i = 0; i < *pc; i++)
{
struct ssysteminfo *q;
if ((*ppas)[i].zcalled_login != NULL
&& strcmp ((*ppas)[i].zcalled_login, "ANY") != 0)
continue;
(*ppas)[i].zcalled_login = "ANY";
q = ((struct ssysteminfo *)
xmalloc (sizeof (struct ssysteminfo)));
*q = (*ppas)[i];
q->qalternate = (*ppas)[i].qalternate;
(*ppas)[i].qalternate = q;
q->zcalled_login = xstrdup (ztok);
q->fcallback = fcallback;
q->zremote_send = q->zremote_receive = zset;
}
}
else
{
int i;
struct ssysteminfo *q;
/* Both the login name and the machine name were
listed; require the machine to be logged in under
this name. This is not fully backward compatible,
and perhaps should be changed. On the other hand,
it is more useful. */
for (i = 0; i < *pc; i++)
if (strcmp ((*ppas)->zname, zcomma) == 0)
break;
if (i >= *pc)
{
/* We don't warn about systems which don't already
exist, since they may appear in sample
USERFILES. */
xfree ((pointer) zline);
continue;
}
affound[i] = TRUE;
for (q = &(*ppas)[i]; q != NULL; q = q->qalternate)
{
q->zcalled_login = xstrdup (ztok);
q->zlocal_send = q->zlocal_receive = zset;
q->zremote_send = q->zremote_receive = zset;
q->fcallback = fcallback;
}
}
xfree ((pointer) zline);
}
(void) fclose (e);
if (zother != NULL)
{
int i;
for (i = 0; i < *pc; i++)
{
struct ssysteminfo *q;
if (affound[i])
continue;
q = &(*ppas)[i];
if (q->zcalled_login != NULL
&& strcmp (q->zcalled_login, "ANY") != 0)
continue;
q->zlocal_send = q->zlocal_receive = zother;
q->fcallback = fothercallback;
}
}
}
}
/* Now we must read L.cmds to determine which commands may be
executed. */
{
char abcmds[sizeof OLDCONFIGLIB + sizeof V2_CMDS - 1];
sprintf (abcmds, "%s%s", OLDCONFIGLIB, V2_CMDS);
e = fopen (abcmds, "r");
if (e == NULL)
ulog (LOG_ERROR, "fopen (%s): %s", abcmds, strerror (errno));
else
{
char *zcmds;
int i;
struct ssysteminfo *q;
zline = zfgets (e, FALSE);
zline[strcspn (zline, "#\n")] = '\0';
if (strncmp (zline, "PATH=", sizeof "PATH=" - 1) == 0)
{
char *z;
zline += sizeof "PATH=" - 1;
while ((z = strchr (zline, ':')) != NULL)
*z = ' ';
for (i = 0; i < *pc; i++)
for (q = &(*ppas)[i]; q != NULL; q = q->qalternate)
q->zpath = zline;
zline = zfgets (e, FALSE);
}
zcmds = NULL;
while (zline != NULL)
{
zline[strcspn (zline, "#\n")] = '\0';
uadd_string (&zcmds, zline, ' ');
xfree ((pointer) zline);
zline = zfgets (e, FALSE);
}
(void) fclose (e);
for (i = 0; i < *pc; i++)
for (q = &(*ppas)[i]; q != NULL; q = q->qalternate)
q->zcmds = zcmds;
}
}
}
/* Find a port with a given name and speed in the file L-devices and
lock it. If found and locked, fill in the structure pointed at by
qport. Set *pffound to TRUE if a port was found but could not be
locked. */
boolean
fv2_find_port (zname, ibaud, ihighbaud, qport, pflock, pffound)
const char *zname;
long ibaud;
long ihighbaud;
struct sport *qport;
boolean (*pflock) P((struct sport *, boolean fin));
boolean *pffound;
{
char ab[sizeof OLDCONFIGLIB + sizeof V2_DEVICES - 1];
FILE *e;
char *zline;
sprintf (ab, "%s%s", OLDCONFIGLIB, V2_DEVICES);
e = fopen (ab, "r");
if (e == NULL)
{
ulog (LOG_ERROR, "fopen (%s): %s", ab, strerror (errno));
return FALSE;
}
while ((zline = zfgets (e, FALSE)) != NULL)
{
char *ztok, *zdevice, *zdial_device;
long ilow, ihigh;
zline[strcspn (zline, "#\n")] = '\0';
/* An entry in L-devices is type device dial-device baud. */
ztok = strtok (zline, " \t");
if (ztok == NULL)
{
xfree ((pointer) zline);
continue;
}
if (zname != NULL
&& strcmp (zname, ztok) != 0)
{
xfree ((pointer) zline);
continue;
}
qport->zname = ztok;
zdevice = strtok ((char *) NULL, " \t");
if (zdevice == NULL)
{
xfree ((pointer) zline);
continue;
}
zdial_device = strtok ((char *) NULL, " \t");
if (zdial_device == NULL)
{
xfree ((pointer) zline);
continue;
}
if (strcmp (zdial_device, "-") == 0)
zdial_device = NULL;
ztok = strtok ((char *) NULL, " \t");
if (ztok == NULL)
{
xfree ((pointer) zline);
continue;
}
ilow = strtol (ztok, &ztok, 10);
if (ilow == 0)
ihigh = 38400L;
else
{
if (*ztok == '-')
ihigh = atol (ztok + 1);
else
ihigh = ilow;
}
if (ibaud != 0
&& (ihighbaud < ilow || ibaud > ihigh))
{
xfree ((pointer) zline);
continue;
}
/* We have found a matching port. We now fill in the sport
structure so that we can try to lock it. */
qport->zprotocols = NULL;
qport->cproto_params = 0;
qport->qproto_params = NULL;
qport->ireliable = 0;
qport->zlockname = NULL;
if (strcmp (qport->zname, "DIR") == 0)
{
qport->ttype = PORTTYPE_DIRECT;
qport->u.sdirect.zdevice = zdevice;
qport->u.sdirect.ibaud = ilow;
#ifdef SYSDEP_DIRECT_INIT
SYSDEP_DIRECT_INIT (&qport->u.sdirect.s);
#endif
}
else
{
qport->ttype = PORTTYPE_MODEM;
qport->u.smodem.zdevice = zdevice;
qport->u.smodem.zdial_device = zdial_device;
if (ilow != ihigh)
qport->u.smodem.ibaud = 0;
else
qport->u.smodem.ibaud = ilow;
qport->u.smodem.ilowbaud = ilow;
qport->u.smodem.ihighbaud = ihigh;
qport->u.smodem.fcarrier = TRUE;
qport->u.smodem.zdialer = strtok ((char *) NULL, "");
qport->u.smodem.zdialer += strspn (qport->u.smodem.zdialer,
" \t");
qport->u.smodem.qdialer = NULL;
#ifdef SYSDEP_MODEM_INIT
SYSDEP_MODEM_INIT (&qport->u.smodem.s);
#endif
}
if (pffound != NULL)
*pffound = TRUE;
if (pflock != NULL
&& ! (*pflock) (qport, FALSE))
{
xfree ((pointer) zline);
continue;
}
(void) fclose (e);
return TRUE;
}
(void) fclose (e);
return FALSE;
}
#endif /* HAVE_V2_CONFIG */