1798 lines
44 KiB
C
1798 lines
44 KiB
C
/* sysinf.c
|
||
Functions to read system information for the UUCP package.
|
||
|
||
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: sysinf.c,v $
|
||
Revision 1.1.1.1 1993/03/21 09:45:37 cgd
|
||
initial import of 386bsd-0.1 sources
|
||
|
||
Revision 1.24 1992/04/02 22:51:09 ian
|
||
Add gcc 2.0 format checking to ulog, and fixed discovered problems
|
||
|
||
Revision 1.23 1992/03/30 04:49:10 ian
|
||
Niels Baggesen: added debugging types abnormal and uucp-proto
|
||
|
||
Revision 1.22 1992/03/28 21:47:55 ian
|
||
David J. MacKenzie: allow backslash to quote newline in config files
|
||
|
||
Revision 1.21 1992/03/28 20:31:55 ian
|
||
Franc,ois Pinard: allow a name to be given to an alternate
|
||
|
||
Revision 1.20 1992/03/24 17:18:33 ian
|
||
Fixed handling of alternates in file-wide defaults
|
||
|
||
Revision 1.19 1992/03/16 04:30:57 ian
|
||
Permit a retry time for the time and timegrade commands
|
||
|
||
Revision 1.18 1992/03/13 16:17:42 ian
|
||
Chip Salzenberg: set default login chat script timeout to 10 seconds
|
||
|
||
Revision 1.17 1992/03/12 19:54:43 ian
|
||
Debugging based on types rather than number
|
||
|
||
Revision 1.16 1992/03/09 20:14:37 ian
|
||
Ted Lindgreen: added max-remote-debug command
|
||
|
||
Revision 1.15 1992/03/07 02:56:30 ian
|
||
Rewrote time routines
|
||
|
||
Revision 1.14 1992/03/03 06:06:48 ian
|
||
T. William Wells: don't complain about missing configuration files
|
||
|
||
Revision 1.13 1992/02/23 19:50:50 ian
|
||
Handle READ and WRITE in Permissions correctly
|
||
|
||
Revision 1.12 1992/02/08 03:54:18 ian
|
||
Include <string.h> only in <uucp.h>, added 1992 copyright
|
||
|
||
Revision 1.11 1992/01/13 05:17:30 ian
|
||
Mike Park: wrong number of arguments to ulog call
|
||
|
||
Revision 1.10 1992/01/07 15:23:50 ian
|
||
Niels Baggesen: allocate number of protocol parameters correctly
|
||
|
||
Revision 1.9 1991/12/28 03:49:23 ian
|
||
Added HAVE_MEMFNS and HAVE_BFNS; changed uses of memset to bzero
|
||
|
||
Revision 1.8 1991/12/23 05:15:54 ian
|
||
David Nugent: set debugging level for a specific system
|
||
|
||
Revision 1.7 1991/12/17 17:08:02 ian
|
||
Marc Unangst: allow true and false for boolean strings as documented
|
||
|
||
Revision 1.6 1991/12/15 04:17:11 ian
|
||
Added chat-seven-bit command to control parity bit stripping
|
||
|
||
Revision 1.5 1991/12/15 03:42:33 ian
|
||
Added tprocess_chat_cmd for all chat commands, and added CMDTABTYPE_PREFIX
|
||
|
||
Revision 1.4 1991/11/13 20:38:00 ian
|
||
Added TCP port type for connections over TCP
|
||
|
||
Revision 1.3 1991/11/12 19:47:04 ian
|
||
Add called-chat set of commands to run a chat script on an incoming call
|
||
|
||
Revision 1.2 1991/11/11 23:47:24 ian
|
||
Added chat-program to run a program to do a chat script
|
||
|
||
Revision 1.1 1991/09/10 19:40:31 ian
|
||
Initial revision
|
||
|
||
*/
|
||
|
||
#include "uucp.h"
|
||
|
||
#if USE_RCS_ID
|
||
char sysinf_rcsid[] = "$Id: sysinf.c,v 1.1.1.1 1993/03/21 09:45:37 cgd Exp $";
|
||
#endif
|
||
|
||
#include <ctype.h>
|
||
#include <errno.h>
|
||
|
||
#include "port.h"
|
||
#include "system.h"
|
||
#include "uutime.h"
|
||
|
||
/* Whether we accept calls from unknown systems. */
|
||
boolean fUnknown_ok = FALSE;
|
||
|
||
/* Information we hold for an unknown system. */
|
||
struct ssysteminfo sUnknown;
|
||
|
||
/* Information we hold for the local system. */
|
||
struct ssysteminfo sLocalsys;
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
|
||
/* I don't find the system file format used by either V2 or BNU UUCP
|
||
very intuitive, so I've developed my own format. This replaces the
|
||
files L.sys and USERFILE for V2, and Systems and Permissions for
|
||
BNU. The complete format is described in a separate document. */
|
||
|
||
/* Some local functions. */
|
||
static void uiset_clear P((boolean falternate));
|
||
|
||
/* Set when we read the first line of a new file, to indicate that a
|
||
new set of defaults should be gathered. */
|
||
static boolean fIfirst;
|
||
|
||
/* This structure holds system information as it is gathered. */
|
||
static struct ssysteminfo sIhold;
|
||
|
||
/* Default information. */
|
||
static struct ssysteminfo sIdefault;
|
||
|
||
/* The name of the next system. */
|
||
static char *zInext_system;
|
||
|
||
/* The list of alternates to draw from. */
|
||
static struct ssysteminfo *qIalternates;
|
||
|
||
/* Whether to use default alternates. */
|
||
static boolean fIdefault_alternates;
|
||
|
||
/* There are several commands for which we want to take the default if
|
||
provided, but we don't want to add to the default. For example,
|
||
each system can have multiple time specifications (using different
|
||
grades), which is implemented by adding each new time specification
|
||
to the previous ones. We want to allow default time specifications.
|
||
However, if a system has time specifications, we don't want to add
|
||
its time specifications to the default ones. We handle this with a
|
||
set of boolean variables which we set to tell the adding functions
|
||
to ignore any existing entry; when an entry has been added, the
|
||
boolean variable is cleared. */
|
||
static boolean fIclear_alias;
|
||
static boolean fIclear_alternate;
|
||
static boolean fIclear_time;
|
||
static boolean fIclear_calltimegrade;
|
||
static boolean fIclear_call_local_size;
|
||
static boolean fIclear_call_remote_size;
|
||
static boolean fIclear_called_local_size;
|
||
static boolean fIclear_called_remote_size;
|
||
static boolean fIclear_port;
|
||
static boolean fIclear_chat_fail;
|
||
static boolean fIclear_proto_param;
|
||
static boolean fIclear_called_chat_fail;
|
||
|
||
/* Local functions needed to parse the system information file. */
|
||
|
||
#define CMDTABFN(z) \
|
||
static enum tcmdtabret z P((int, char **, pointer, const char *))
|
||
|
||
CMDTABFN (ticlear);
|
||
CMDTABFN (tisystem);
|
||
CMDTABFN (tialias);
|
||
CMDTABFN (tialternate);
|
||
CMDTABFN (titime);
|
||
CMDTABFN (titimegrade);
|
||
CMDTABFN (ticall_local_size);
|
||
CMDTABFN (ticall_remote_size);
|
||
CMDTABFN (ticalled_local_size);
|
||
CMDTABFN (ticalled_remote_size);
|
||
CMDTABFN (titimetable);
|
||
CMDTABFN (tiport);
|
||
CMDTABFN (tichat);
|
||
CMDTABFN (ticalled_login);
|
||
CMDTABFN (tiproto_param);
|
||
CMDTABFN (tirequest);
|
||
CMDTABFN (titransfer);
|
||
|
||
#undef CMDTABFN
|
||
|
||
/* The commands accepted from the system information file. */
|
||
|
||
static const struct scmdtab asIcmds[] =
|
||
{
|
||
{ "#", CMDTABTYPE_FN | 1, NULL, ticlear },
|
||
{ "system", CMDTABTYPE_FN | 2, NULL, tisystem },
|
||
{ "alias", CMDTABTYPE_FN | 2, NULL, tialias },
|
||
{ "alternate", CMDTABTYPE_FN | 0, NULL, tialternate },
|
||
{ "default-alternates", CMDTABTYPE_BOOLEAN,
|
||
(pointer) &fIdefault_alternates, NULL },
|
||
{ "time", CMDTABTYPE_FN | 0, NULL, titime },
|
||
{ "timegrade", CMDTABTYPE_FN | 0, (pointer) &sIhold.ztime, titimegrade },
|
||
{ "call-timegrade", CMDTABTYPE_FN | 3, (pointer) &sIhold.zcalltimegrade,
|
||
titimegrade },
|
||
{ "call-local-size", CMDTABTYPE_FN | 3, NULL, ticall_local_size },
|
||
{ "call-remote-size", CMDTABTYPE_FN | 3, NULL, ticall_remote_size },
|
||
{ "called-local-size", CMDTABTYPE_FN | 3, NULL, ticalled_local_size },
|
||
{ "called-remote-size", CMDTABTYPE_FN | 3, NULL, ticalled_remote_size },
|
||
{ "timetable", CMDTABTYPE_FN | 3, NULL, titimetable },
|
||
{ "baud", CMDTABTYPE_LONG, (pointer) &sIhold.ibaud, NULL },
|
||
{ "speed", CMDTABTYPE_LONG, (pointer) &sIhold.ibaud, NULL },
|
||
{ "port", CMDTABTYPE_FN | 0, NULL, tiport },
|
||
{ "phone", CMDTABTYPE_STRING, (pointer) &sIhold.zphone, NULL },
|
||
{ "address", CMDTABTYPE_STRING, (pointer) &sIhold.zphone, NULL },
|
||
{ "chat", CMDTABTYPE_PREFIX | 0, (pointer) &sIhold.schat, tichat },
|
||
{ "call-login", CMDTABTYPE_STRING, (pointer) &sIhold.zcall_login, NULL },
|
||
{ "call-password", CMDTABTYPE_STRING, (pointer) &sIhold.zcall_password,
|
||
NULL },
|
||
{ "called-login", CMDTABTYPE_FN | 0, NULL, ticalled_login },
|
||
{ "callback", CMDTABTYPE_BOOLEAN, (pointer) &sIhold.fcallback, NULL },
|
||
{ "sequence", CMDTABTYPE_BOOLEAN, (pointer) &sIhold.fsequence, NULL },
|
||
{ "protocol", CMDTABTYPE_STRING, (pointer) &sIhold.zprotocols, NULL },
|
||
{ "protocol-parameter", CMDTABTYPE_FN | 0, NULL, tiproto_param },
|
||
{ "called-chat", CMDTABTYPE_PREFIX | 0, (pointer) &sIhold.scalled_chat,
|
||
tichat },
|
||
#if DEBUG > 1
|
||
{ "debug", CMDTABTYPE_FN | 0, (pointer) &sIhold.idebug, tidebug_parse },
|
||
{ "max-remote-debug", CMDTABTYPE_FN | 0,
|
||
(pointer) &sIhold.imax_remote_debug, tidebug_parse },
|
||
#endif
|
||
{ "call-request", CMDTABTYPE_BOOLEAN, (pointer) &sIhold.fcall_request,
|
||
NULL },
|
||
{ "called-request", CMDTABTYPE_BOOLEAN, (pointer) &sIhold.fcalled_request,
|
||
NULL },
|
||
{ "request", CMDTABTYPE_FN | 2, NULL, tirequest },
|
||
{ "call-transfer", CMDTABTYPE_BOOLEAN, (pointer) &sIhold.fcall_transfer,
|
||
NULL },
|
||
{ "called-transfer", CMDTABTYPE_BOOLEAN,
|
||
(pointer) &sIhold.fcalled_transfer, NULL },
|
||
{ "transfer", CMDTABTYPE_FN | 2, NULL, titransfer },
|
||
{ "local-send", CMDTABTYPE_FULLSTRING, (pointer) &sIhold.zlocal_send,
|
||
NULL },
|
||
{ "remote-send", CMDTABTYPE_FULLSTRING, (pointer) &sIhold.zremote_send,
|
||
NULL },
|
||
{ "local-receive", CMDTABTYPE_FULLSTRING,
|
||
(pointer) &sIhold.zlocal_receive, NULL },
|
||
{ "remote-receive", CMDTABTYPE_FULLSTRING,
|
||
(pointer) &sIhold.zremote_receive, NULL },
|
||
{ "command-path", CMDTABTYPE_FULLSTRING, (pointer) &sIhold.zpath, NULL },
|
||
{ "commands", CMDTABTYPE_FULLSTRING, (pointer) &sIhold.zcmds, NULL },
|
||
{ "free-space", CMDTABTYPE_LONG, (pointer) &sIhold.cfree_space, NULL },
|
||
{ "forwardto", CMDTABTYPE_FULLSTRING, (pointer) &sIhold.zforwardto, NULL },
|
||
{ "forward-to", CMDTABTYPE_FULLSTRING, (pointer) &sIhold.zforwardto, NULL },
|
||
{ "pubdir", CMDTABTYPE_STRING, (pointer) &sIhold.zpubdir, NULL },
|
||
{ "myname", CMDTABTYPE_STRING, (pointer) &sIhold.zlocalname, NULL },
|
||
{ NULL, 0, NULL, NULL }
|
||
};
|
||
|
||
/* This is called for the first line of each file. It clears the
|
||
defaults, so that each file has a different set. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticlear (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
fIfirst = TRUE;
|
||
return CMDTABRET_FREE_AND_EXIT;
|
||
}
|
||
|
||
/* Process the system command. We store away the system name and exit
|
||
out of processing commands to let the main loop handle it. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tisystem (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
const char *z;
|
||
|
||
/* System names may only contain alphanumeric characters,
|
||
underscores, dashes and dots, and they may not begin with a dot,
|
||
at least for now. */
|
||
for (z = argv[1]; *z != '\0'; z++)
|
||
{
|
||
if (! isalnum (BUCHAR (*z))
|
||
&& *z != '_'
|
||
&& *z != '-'
|
||
&& (*z != '.' || z == argv[1]))
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s %s: Illegal character in system name",
|
||
zerr, argv[0], argv[1]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
}
|
||
|
||
if (strlen (argv[1]) > cSysdep_max_name_len)
|
||
{
|
||
ulog (LOG_ERROR, "System name \"%s\" too long (max %d)", argv[1],
|
||
cSysdep_max_name_len);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
zInext_system = argv[1];
|
||
|
||
DEBUG_MESSAGE1 (DEBUG_CONFIG,
|
||
"tisystem: Reading system %s", zInext_system);
|
||
|
||
return CMDTABRET_EXIT;
|
||
}
|
||
|
||
/* Process the alias command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tialias (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
if (fIclear_alias)
|
||
{
|
||
sIhold.zalias = NULL;
|
||
fIclear_alias = FALSE;
|
||
}
|
||
uadd_string (&sIhold.zalias, argv[1], ' ');
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* Process the alternate command. The current information is in
|
||
sIhold. We link this onto a chain of alternates starting at
|
||
sIalternate. We then set up sIhold with the defaults for the next
|
||
alternate. qIalternates holds the list of alternates for the
|
||
file-wide defaults, and we use to set up sIhold. We also call
|
||
uiset_clear to set all the fIclear_* variables so that commands
|
||
like ``time'' know that they should ignore any existing entry. */
|
||
|
||
static struct ssysteminfo sIalternate;
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tialternate (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
if (fIclear_alternate)
|
||
{
|
||
sIalternate = sIhold;
|
||
fIclear_alternate = FALSE;
|
||
}
|
||
else
|
||
{
|
||
struct ssysteminfo *qnew;
|
||
struct ssysteminfo **pq;
|
||
|
||
qnew = (struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo));
|
||
*qnew = sIhold;
|
||
for (pq = &sIalternate.qalternate; *pq != NULL; pq = &(*pq)->qalternate)
|
||
;
|
||
*pq = qnew;
|
||
sIhold = sIalternate;
|
||
sIhold.qalternate = NULL;
|
||
}
|
||
|
||
/* Clear the name of the next alternate. */
|
||
sIhold.zalternate = NULL;
|
||
|
||
/* Now, if there is a default alternate to base this on, we must
|
||
override everything not changed before the first ``alternate''
|
||
command to the default alternate. */
|
||
if (fIdefault_alternates
|
||
&& qIalternates != NULL)
|
||
{
|
||
if (qIalternates->zalternate != NULL)
|
||
sIhold.zalternate = qIalternates->zalternate;
|
||
|
||
#define TEST(x) \
|
||
if (sIhold.x == sIdefault.x) \
|
||
sIhold.x = qIalternates->x;
|
||
|
||
TEST (ztime);
|
||
TEST (zcalltimegrade);
|
||
TEST (zcall_local_size);
|
||
TEST (zcall_remote_size);
|
||
TEST (zcalled_local_size);
|
||
TEST (zcalled_remote_size);
|
||
TEST (ibaud);
|
||
TEST (zport);
|
||
TEST (qport);
|
||
TEST (zphone);
|
||
TEST (schat.zchat);
|
||
TEST (schat.zprogram);
|
||
TEST (schat.ctimeout);
|
||
TEST (schat.zfail);
|
||
TEST (zcall_login);
|
||
TEST (zcalled_login);
|
||
TEST (fcallback);
|
||
TEST (zprotocols);
|
||
TEST (cproto_params);
|
||
TEST (qproto_params);
|
||
TEST (scalled_chat.zchat);
|
||
TEST (scalled_chat.zprogram);
|
||
TEST (scalled_chat.ctimeout);
|
||
TEST (scalled_chat.zfail);
|
||
#if DEBUG > 1
|
||
TEST (idebug);
|
||
TEST (imax_remote_debug);
|
||
#endif
|
||
TEST (fcall_request);
|
||
TEST (fcalled_request);
|
||
TEST (fcall_transfer);
|
||
TEST (fcalled_transfer);
|
||
TEST (zlocal_send);
|
||
TEST (zcalled_local_send);
|
||
TEST (zremote_send);
|
||
TEST (zcalled_remote_send);
|
||
TEST (zlocal_receive);
|
||
TEST (zcalled_local_receive);
|
||
TEST (zremote_receive);
|
||
TEST (zcalled_remote_receive);
|
||
TEST (zpath);
|
||
TEST (zcmds);
|
||
TEST (cfree_space);
|
||
TEST (zforwardto);
|
||
TEST (zpubdir);
|
||
TEST (zlocalname);
|
||
|
||
#undef TEST
|
||
|
||
qIalternates = qIalternates->qalternate;
|
||
}
|
||
|
||
/* If there is a name for this alternate, put it in. */
|
||
if (argc > 1)
|
||
sIhold.zalternate = xstrdup (argv[1]);
|
||
|
||
uiset_clear (TRUE);
|
||
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* Process the time command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
titime (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
char *pznew[4];
|
||
char ab[2];
|
||
|
||
pznew[0] = argv[0];
|
||
ab[0] = 'z';
|
||
ab[1] = '\0';
|
||
pznew[1] = ab;
|
||
pznew[2] = argv[1];
|
||
if (argc > 2)
|
||
pznew[3] = argv[2];
|
||
|
||
return titimegrade (argc + 1, pznew, (pointer) &sIhold.ztime, zerr);
|
||
}
|
||
|
||
/* Process the timegrade and the call-timegrade commands. */
|
||
|
||
static enum tcmdtabret
|
||
titimegrade (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
char **pztime = (char **) pvar;
|
||
int clen;
|
||
char *z;
|
||
|
||
if (argc < 3 || argc > 4)
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: Wrong number of arguments", zerr, argv[0]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
if (argv[1][1] != '\0' || ! FGRADE_LEGAL (argv[1][0]))
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: Illegal grade '%s'", zerr, argv[0],
|
||
argv[1]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* We should probably check whether the time string is legal. A
|
||
timegrade string is a single character grade, then a time string,
|
||
then an optional semicolon and a retry time. */
|
||
|
||
clen = strlen (argv[2]) + 2;
|
||
if (argc > 3)
|
||
clen += strlen (argv[3]) + 1;
|
||
z = (char *) alloca (clen);
|
||
*z = argv[1][0];
|
||
strcpy (z + 1, argv[2]);
|
||
if (argc > 3)
|
||
{
|
||
strcat (z, ";");
|
||
strcat (z, argv[3]);
|
||
}
|
||
|
||
if (pztime == &sIhold.ztime)
|
||
{
|
||
if (fIclear_time)
|
||
{
|
||
*pztime = NULL;
|
||
fIclear_time = FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (fIclear_calltimegrade)
|
||
{
|
||
*pztime = NULL;
|
||
fIclear_calltimegrade = FALSE;
|
||
}
|
||
}
|
||
|
||
uadd_string (pztime, z, ' ');
|
||
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* Add a size command. */
|
||
|
||
static enum tcmdtabret tiadd_size P((int argc, char **argv,
|
||
const char *zerr, boolean *pf,
|
||
char **pz));
|
||
|
||
static enum tcmdtabret
|
||
tiadd_size (argc, argv, zerr, pf, pz)
|
||
int argc;
|
||
char **argv;
|
||
const char *zerr;
|
||
boolean *pf;
|
||
char **pz;
|
||
{
|
||
long cbytes;
|
||
char *zend;
|
||
char *zarg;
|
||
|
||
cbytes = strtol (argv[1], &zend, 10);
|
||
if (*zend != '\0')
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: Bad number", zerr, argv[0]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* We should check the legality of the time string here. */
|
||
|
||
if (*pf)
|
||
{
|
||
*pz = NULL;
|
||
*pf = FALSE;
|
||
}
|
||
|
||
zarg = (char *) alloca (strlen (argv[2]) + 20);
|
||
sprintf (zarg, "%ld %s", cbytes, argv[2]);
|
||
|
||
uadd_string (pz, zarg, ' ');
|
||
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* Process the call-local-size command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticall_local_size (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
return tiadd_size (argc, argv, zerr, &fIclear_call_local_size,
|
||
&sIhold.zcall_local_size);
|
||
}
|
||
|
||
/* Process the call-remote-size command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticall_remote_size (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
return tiadd_size (argc, argv, zerr, &fIclear_call_remote_size,
|
||
&sIhold.zcall_remote_size);
|
||
}
|
||
|
||
/* Process the called-local-size command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticalled_local_size (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
return tiadd_size (argc, argv, zerr, &fIclear_called_local_size,
|
||
&sIhold.zcalled_local_size);
|
||
}
|
||
|
||
/* Process the called-remote-size command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticalled_remote_size (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
return tiadd_size (argc, argv, zerr, &fIclear_called_remote_size,
|
||
&sIhold.zcalled_remote_size);
|
||
}
|
||
|
||
/* Process the timetable command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
titimetable (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
uaddtimetable (argv[1], argv[2]);
|
||
return CMDTABRET_CONTINUE;
|
||
}
|
||
|
||
/* Process the port command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tiport (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
if (argc < 2)
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: Wrong number of arguments", zerr, argv[0]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
if (fIclear_port)
|
||
{
|
||
sIhold.zport = NULL;
|
||
sIhold.qport = NULL;
|
||
fIclear_port = FALSE;
|
||
}
|
||
|
||
if (argc > 2)
|
||
{
|
||
enum tcmdtabret tret;
|
||
|
||
if (sIhold.zport != NULL)
|
||
{
|
||
ulog (LOG_ERROR,
|
||
"%s: %s: Ignoring port specification following port name",
|
||
zerr, argv[0]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
tret = tprocess_port_cmd (argc - 1, argv + 1, (pointer) &sIhold.qport,
|
||
zerr);
|
||
if (sIhold.qport != NULL && sIhold.qport->zname == NULL)
|
||
{
|
||
char *zname;
|
||
|
||
if (sIhold.zname == NULL)
|
||
sIhold.qport->zname = "default system file port";
|
||
else
|
||
{
|
||
zname = (char *) alloca (strlen (sIhold.zname)
|
||
+ sizeof "system port");
|
||
sprintf (zname, "system %s port", sIhold.zname);
|
||
sIhold.qport->zname = xstrdup (zname);
|
||
}
|
||
}
|
||
|
||
#if DEBUG > 1
|
||
if (sIhold.qport != NULL)
|
||
DEBUG_MESSAGE2 (DEBUG_CONFIG,
|
||
"tiport: Command %s to port %s", argv[1],
|
||
sIhold.qport->zname);
|
||
#endif
|
||
|
||
return tret;
|
||
}
|
||
else
|
||
{
|
||
if (sIhold.qport != NULL)
|
||
{
|
||
ulog (LOG_ERROR,
|
||
"%s: %s: Ignoring port name following port specification",
|
||
zerr, argv[0]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
sIhold.zport = argv[1];
|
||
|
||
return CMDTABRET_CONTINUE;
|
||
}
|
||
}
|
||
|
||
/* Process one of the chat commands. We have a special version for
|
||
systems just so that we clear out the chat failure strings. It
|
||
would be nice if there were a cleaner way to do this. */
|
||
|
||
static enum tcmdtabret
|
||
tichat (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
if (strcmp (argv[0], "chat-fail") == 0)
|
||
{
|
||
if (fIclear_chat_fail)
|
||
{
|
||
sIhold.schat.zfail = NULL;
|
||
fIclear_chat_fail = FALSE;
|
||
}
|
||
}
|
||
else if (strcmp (argv[0], "called-chat-fail") == 0)
|
||
{
|
||
if (fIclear_called_chat_fail)
|
||
{
|
||
sIhold.scalled_chat.zfail = NULL;
|
||
fIclear_called_chat_fail = FALSE;
|
||
}
|
||
}
|
||
|
||
return tprocess_chat_cmd (argc, argv, pvar, zerr);
|
||
}
|
||
|
||
/* Process the called-login command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticalled_login (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
if (argc < 2)
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: Wrong number of arguments", zerr, argv[0]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
sIhold.zcalled_login = argv[1];
|
||
|
||
if (argc > 2)
|
||
uadd_validate (argv[1], argc - 2, (const char **) argv + 2);
|
||
|
||
return CMDTABRET_CONTINUE;
|
||
}
|
||
|
||
/* Process the protocol parameter command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tiproto_param (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
if (fIclear_proto_param)
|
||
{
|
||
sIhold.cproto_params = 0;
|
||
sIhold.qproto_params = NULL;
|
||
fIclear_proto_param = FALSE;
|
||
}
|
||
|
||
return tadd_proto_param (&sIhold.cproto_params, &sIhold.qproto_params,
|
||
zerr, argc - 1, argv + 1);
|
||
}
|
||
|
||
/* Process the request command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tirequest (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
char b;
|
||
boolean fset;
|
||
|
||
b = argv[1][0];
|
||
if (b == 'y' || b == 'Y' || b == 't' || b == 'T')
|
||
fset = TRUE;
|
||
else if (b == 'n' || b == 'N' || b == 'f' || b == 'F')
|
||
fset = FALSE;
|
||
else
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: %s: Bad boolean", zerr, argv[0], argv[1]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
sIhold.fcall_request = fset;
|
||
sIhold.fcalled_request = fset;
|
||
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* Process the transfer command. */
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
titransfer (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
char b;
|
||
boolean fset;
|
||
|
||
b = argv[1][0];
|
||
if (b == 'y' || b == 'Y' || b == 't' || b == 'T')
|
||
fset = TRUE;
|
||
else if (b == 'n' || b == 'N' || b == 'f' || b == 'F')
|
||
fset = FALSE;
|
||
else
|
||
{
|
||
ulog (LOG_ERROR, "%s: %s: %s: Bad boolean", zerr, argv[0], argv[1]);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
sIhold.fcall_transfer = fset;
|
||
sIhold.fcalled_transfer = fset;
|
||
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
/* Mark all the contents of sIhold to be cleared before they are set.
|
||
If the falternate argument is TRUE, then only prepare to clear
|
||
those contents that should be cleared for an alternate. */
|
||
|
||
static void
|
||
uiset_clear (falternate)
|
||
boolean falternate;
|
||
{
|
||
if (! falternate)
|
||
{
|
||
fIclear_alias = TRUE;
|
||
fIclear_alternate = TRUE;
|
||
}
|
||
fIclear_time = TRUE;
|
||
fIclear_calltimegrade = TRUE;
|
||
fIclear_call_local_size = TRUE;
|
||
fIclear_call_remote_size = TRUE;
|
||
fIclear_called_local_size = TRUE;
|
||
fIclear_called_remote_size = TRUE;
|
||
fIclear_port = TRUE;
|
||
fIclear_chat_fail = TRUE;
|
||
fIclear_proto_param = TRUE;
|
||
fIclear_called_chat_fail = TRUE;
|
||
}
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
/* Set up the default values advertised in the documentation. */
|
||
|
||
void
|
||
uset_system_defaults (qsys)
|
||
struct ssysteminfo *qsys;
|
||
{
|
||
qsys->zname = NULL;
|
||
qsys->zalias = NULL;
|
||
qsys->qalternate = NULL;
|
||
qsys->zalternate = NULL;
|
||
qsys->ztime = xmalloc (1 + sizeof "Never");
|
||
sprintf (qsys->ztime, "%cNever", BGRADE_LOW);
|
||
qsys->zcalltimegrade = NULL;
|
||
qsys->zcall_local_size = NULL;
|
||
qsys->zcall_remote_size = NULL;
|
||
qsys->zcalled_local_size = NULL;
|
||
qsys->zcalled_remote_size = NULL;
|
||
qsys->ibaud = 0L;
|
||
qsys->ihighbaud = 0L;
|
||
qsys->zport = NULL;
|
||
qsys->zphone = NULL;
|
||
qsys->qport = NULL;
|
||
INIT_CHAT (&qsys->schat);
|
||
qsys->schat.zchat =
|
||
(char *) "\"\" \\r\\c ogin:-BREAK-ogin:-BREAK-ogin: \\L word: \\P";
|
||
qsys->schat.ctimeout = 10;
|
||
qsys->zcall_login = NULL;
|
||
qsys->zcall_password = NULL;
|
||
qsys->zcalled_login = NULL;
|
||
qsys->fcallback = FALSE;
|
||
qsys->fsequence = FALSE;
|
||
qsys->zprotocols = NULL;
|
||
qsys->cproto_params = 0;
|
||
qsys->qproto_params = NULL;
|
||
INIT_CHAT (&qsys->scalled_chat);
|
||
#if DEBUG > 1
|
||
qsys->idebug = 0;
|
||
qsys->imax_remote_debug = DEBUG_ABNORMAL | DEBUG_CHAT | DEBUG_HANDSHAKE;
|
||
#endif
|
||
qsys->fcall_request = TRUE;
|
||
qsys->fcalled_request = TRUE;
|
||
qsys->fcall_transfer = TRUE;
|
||
qsys->fcalled_transfer = TRUE;
|
||
qsys->zlocal_send = ZROOTDIR;
|
||
qsys->zcalled_local_send = NULL;
|
||
qsys->zremote_send = "~";
|
||
qsys->zcalled_remote_send = NULL;
|
||
qsys->zlocal_receive = "~";
|
||
qsys->zcalled_local_receive = NULL;
|
||
qsys->zremote_receive = "~";
|
||
qsys->zcalled_remote_receive = NULL;
|
||
qsys->zpath = CMDPATH;
|
||
qsys->zcmds = "rnews rmail";
|
||
qsys->cfree_space = DEFAULT_FREE_SPACE;
|
||
qsys->zforwardto = NULL;
|
||
qsys->zpubdir = NULL;
|
||
qsys->zlocalname = NULL;
|
||
}
|
||
|
||
/* Variables to store the loaded system information. */
|
||
|
||
static boolean fIhave_systems;
|
||
static int cIsystems;
|
||
static struct ssysteminfo *pasIsystems;
|
||
|
||
/* Read information about all systems. */
|
||
|
||
static void uiread_systems P((void));
|
||
|
||
static void
|
||
uiread_systems ()
|
||
{
|
||
if (fIhave_systems)
|
||
return;
|
||
|
||
fIhave_systems = TRUE;
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
if (zSysfile == NULL)
|
||
{
|
||
boolean fmore;
|
||
|
||
/* Only warn about a missing file if we aren't going to read the
|
||
V2 or BNU files. */
|
||
fmore = FALSE;
|
||
#if HAVE_V2_CONFIG
|
||
if (fV2)
|
||
fmore = TRUE;
|
||
#endif
|
||
#if HAVE_BNU_CONFIG
|
||
if (fBnu)
|
||
fmore = TRUE;
|
||
#endif
|
||
if (! fmore)
|
||
{
|
||
ulog (LOG_ERROR, "%s%s: file not found", NEWCONFIGLIB,
|
||
SYSFILE);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
struct smulti_file *qmulti;
|
||
int calc;
|
||
boolean fdefaults, fsystem;
|
||
struct ssysteminfo *qalternates;
|
||
|
||
qmulti = qmulti_open (zSysfile);
|
||
if (qmulti != NULL)
|
||
{
|
||
calc = 0;
|
||
fdefaults = FALSE;
|
||
fsystem = FALSE;
|
||
qalternates = NULL;
|
||
|
||
fIfirst = FALSE;
|
||
zInext_system = NULL;
|
||
|
||
while (TRUE)
|
||
{
|
||
qIalternates = qalternates;
|
||
fIdefault_alternates = TRUE;
|
||
|
||
/* Read commands. This will exit when it encounters the
|
||
start of a file (which it will when we first start
|
||
reading) and when it reads a ``system'' command. */
|
||
uprocesscmds ((FILE *) NULL, qmulti, asIcmds,
|
||
(const char *) NULL,
|
||
CMDFLAG_WARNUNRECOG | CMDFLAG_BACKSLASH);
|
||
|
||
/* The handling of alternates can get complex. Before
|
||
we start reading a system, fIclear_alternate is set
|
||
to TRUE (this is done in uiset_clear). After we have
|
||
finished reading a system, then if fIclear_alternate
|
||
is still TRUE then no ``alternate'' command was used
|
||
and the system information is in sIhold. Otherwise,
|
||
if fIclear_alternate is FALSE, an ``alternate''
|
||
command was used and we must call tialternate one
|
||
more time; after this final call to tialternate, the
|
||
system information will be in sIalternate.
|
||
|
||
The final call to tialternate is needed because each
|
||
occurrence of the ``alternate'' command links the
|
||
previous alternate into sIalternate and sets up
|
||
sIhold with the defaults for the next alternate. The
|
||
final call will link the last alternate into
|
||
sIalternate. */
|
||
|
||
if (fdefaults)
|
||
{
|
||
/* We were reading default information. Save it. */
|
||
if (fIclear_alternate)
|
||
sIdefault = sIhold;
|
||
else
|
||
{
|
||
(void) tialternate (0, (char **) NULL,
|
||
(pointer) NULL, "alternate");
|
||
sIdefault = sIalternate;
|
||
}
|
||
qalternates = sIdefault.qalternate;
|
||
sIdefault.qalternate = NULL;
|
||
fdefaults = FALSE;
|
||
}
|
||
else if (fsystem)
|
||
{
|
||
/* We just either finished a file or encountered a
|
||
``system'' command after we had started reading a
|
||
system. Finish up the information for the system
|
||
we were reading. */
|
||
if (cIsystems >= calc)
|
||
{
|
||
calc += 10;
|
||
pasIsystems =
|
||
((struct ssysteminfo *)
|
||
xrealloc ((pointer) pasIsystems,
|
||
calc * sizeof (struct ssysteminfo)));
|
||
}
|
||
|
||
/* We must now attach any remaining default
|
||
alternates. */
|
||
if (fIdefault_alternates)
|
||
{
|
||
while (qIalternates != NULL)
|
||
(void) tialternate (0, (char **) NULL,
|
||
(pointer) NULL, "alternate");
|
||
}
|
||
|
||
if (fIclear_alternate)
|
||
pasIsystems[cIsystems] = sIhold;
|
||
else
|
||
{
|
||
(void) tialternate (0, (char **) NULL,
|
||
(pointer) NULL, "alternate");
|
||
pasIsystems[cIsystems] = sIalternate;
|
||
}
|
||
|
||
++cIsystems;
|
||
|
||
fsystem = FALSE;
|
||
}
|
||
|
||
if (fIfirst)
|
||
{
|
||
/* We just started reading a new file. Reset the
|
||
default information. The next time around the
|
||
loop we will read the default information. */
|
||
uset_system_defaults (&sIhold);
|
||
uiset_clear (FALSE);
|
||
qalternates = NULL;
|
||
fdefaults = TRUE;
|
||
fIfirst = FALSE;
|
||
}
|
||
else if (zInext_system != NULL)
|
||
{
|
||
/* We just encountered a ``system'' command. Save
|
||
the name, reset the system information to the
|
||
defaults, and go on to read the system
|
||
information. */
|
||
sIhold = sIdefault;
|
||
sIhold.zname = zInext_system;
|
||
uiset_clear (FALSE);
|
||
fsystem = TRUE;
|
||
zInext_system = NULL;
|
||
}
|
||
else
|
||
{
|
||
/* We have reached the end of the files to read. */
|
||
break;
|
||
}
|
||
}
|
||
|
||
(void) fmulti_close (qmulti);
|
||
}
|
||
}
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
#if HAVE_V2_CONFIG
|
||
if (fV2)
|
||
{
|
||
int cv2;
|
||
struct ssysteminfo *pasv2;
|
||
|
||
uv2_read_systems (&cv2, &pasv2);
|
||
if (cv2 > 0)
|
||
{
|
||
pasIsystems =
|
||
((struct ssysteminfo *)
|
||
xrealloc ((pointer) pasIsystems,
|
||
(cIsystems + cv2) * sizeof (struct ssysteminfo)));
|
||
memcpy (pasIsystems + cIsystems, pasv2,
|
||
cv2 * sizeof (struct ssysteminfo));
|
||
cIsystems += cv2;
|
||
}
|
||
}
|
||
#endif /* HAVE_V2_CONFIG */
|
||
|
||
#if HAVE_BNU_CONFIG
|
||
if (fBnu)
|
||
{
|
||
int cbnu;
|
||
struct ssysteminfo *pasbnu;
|
||
|
||
ubnu_read_systems (&cbnu, &pasbnu);
|
||
if (cbnu > 0)
|
||
{
|
||
pasIsystems =
|
||
((struct ssysteminfo *)
|
||
xrealloc ((pointer) pasIsystems,
|
||
(cIsystems + cbnu) * sizeof (struct ssysteminfo)));
|
||
memcpy (pasIsystems + cIsystems, pasbnu,
|
||
cbnu * sizeof (struct ssysteminfo));
|
||
cIsystems += cbnu;
|
||
}
|
||
}
|
||
#endif /* HAVE_BNU_CONFIG */
|
||
}
|
||
|
||
/* Get information about all systems. */
|
||
|
||
void
|
||
uread_all_system_info (pc, ppas)
|
||
int *pc;
|
||
struct ssysteminfo **ppas;
|
||
{
|
||
if (! fIhave_systems)
|
||
uiread_systems ();
|
||
|
||
*pc = cIsystems;
|
||
*ppas = pasIsystems;
|
||
}
|
||
|
||
/* Get information about a specific system. */
|
||
|
||
boolean
|
||
fread_system_info (zsystem, qsys)
|
||
const char *zsystem;
|
||
struct ssysteminfo *qsys;
|
||
{
|
||
int i;
|
||
|
||
DEBUG_MESSAGE1 (DEBUG_CONFIG,
|
||
"fread_system_info: Reading information for system %s",
|
||
zsystem);
|
||
|
||
if (! fIhave_systems)
|
||
uiread_systems ();
|
||
|
||
for (i = 0; i < cIsystems; i++)
|
||
{
|
||
char *z;
|
||
|
||
if (strcmp (zsystem, pasIsystems[i].zname) == 0)
|
||
{
|
||
*qsys = pasIsystems[i];
|
||
|
||
DEBUG_MESSAGE1 (DEBUG_CONFIG,
|
||
"fread_system_info: Got information for system %s",
|
||
qsys->zname);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
z = pasIsystems[i].zalias;
|
||
if (z == NULL)
|
||
continue;
|
||
while (TRUE)
|
||
{
|
||
char *znext;
|
||
|
||
znext = z + strcspn (z, " ");
|
||
if (strncmp (zsystem, z, znext - z) == 0)
|
||
{
|
||
*qsys = pasIsystems[i];
|
||
|
||
DEBUG_MESSAGE1 (DEBUG_CONFIG,
|
||
"fread_system_info: Got system %s",
|
||
qsys->zname);
|
||
|
||
return TRUE;
|
||
}
|
||
z = znext;
|
||
if (*z == ' ')
|
||
++z;
|
||
else
|
||
break;
|
||
}
|
||
}
|
||
|
||
DEBUG_MESSAGE1 (DEBUG_CONFIG,
|
||
"fread_system_info: Could not find system %s",
|
||
zsystem);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/* Prepare to read commands defining unknown systems. */
|
||
|
||
void
|
||
uiunknown_start ()
|
||
{
|
||
#if HAVE_TAYLOR_CONFIG
|
||
uset_system_defaults (&sIhold);
|
||
uiset_clear (FALSE);
|
||
#else /* ! HAVE_TAYLOR_CONFIG */
|
||
uset_system_defaults (&sUnknown);
|
||
#endif /* ! HAVE_TAYLOR_CONFIG */
|
||
}
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
|
||
/* Process a command defining unknown systems. This is actually
|
||
called from the main configuration file, not the system file. */
|
||
|
||
enum tcmdtabret
|
||
tiunknown (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
fUnknown_ok = TRUE;
|
||
return tprocess_one_cmd (argc - 1, argv + 1, asIcmds, zerr,
|
||
CMDFLAG_WARNUNRECOG);
|
||
}
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
/* Finish up after all commands defining unknwon systems. */
|
||
|
||
void
|
||
uiunknown_end ()
|
||
{
|
||
#if HAVE_TAYLOR_CONFIG
|
||
if (fUnknown_ok)
|
||
{
|
||
/* Add the final alternate. */
|
||
if (fIclear_alternate)
|
||
sUnknown = sIhold;
|
||
else
|
||
{
|
||
(void) tialternate (0, (char **) NULL, (pointer) NULL, "alternate");
|
||
sUnknown = sIalternate;
|
||
}
|
||
}
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
}
|
||
|
||
/* Initialize the local system information. Perhaps it would be
|
||
desirable to allow the user to customize this as well. This is
|
||
called after the configuration file has been read in and the system
|
||
name has been determined. Only a few elements of this structure
|
||
are ever actually used, probably just zname and zremote_receive. */
|
||
|
||
void
|
||
uisetup_localsys ()
|
||
{
|
||
uset_system_defaults (&sLocalsys);
|
||
sLocalsys.zname = zLocalname;
|
||
}
|
||
|
||
/* Translate a system name into something we can use locally. This should
|
||
be more intelligent than it is. Right now we just truncate the name;
|
||
if this matches the name of another system, we reject the call. */
|
||
|
||
const char *
|
||
ztranslate_system (zsystem)
|
||
const char *zsystem;
|
||
{
|
||
char *z;
|
||
struct ssysteminfo s;
|
||
|
||
if (strlen (zsystem) <= cSysdep_max_name_len)
|
||
return zsystem;
|
||
z = (char *) xmalloc (cSysdep_max_name_len + 1);
|
||
strncpy (z, zsystem, cSysdep_max_name_len);
|
||
z[cSysdep_max_name_len] = '\0';
|
||
if (fread_system_info (z, &s))
|
||
{
|
||
xfree ((pointer) z);
|
||
return NULL;
|
||
}
|
||
return z;
|
||
}
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
|
||
/* Get the login name and password for a system out of the call file.
|
||
The call file is simple a sequence of lines. The first word on
|
||
each line is the system name, the second word is the login name,
|
||
and the third word is the password. We read it using uprocesscmds,
|
||
since it's easy. */
|
||
|
||
struct silogpass
|
||
{
|
||
char **pzlog;
|
||
char **pzpass;
|
||
};
|
||
|
||
static enum tcmdtabret tilog_pass P((int argc, char **argv, pointer pvar,
|
||
const char *zerr));
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
tilog_pass (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
struct silogpass *q = (struct silogpass *) pvar;
|
||
|
||
*q->pzlog = xstrdup (argv[1]);
|
||
*q->pzpass = xstrdup (argv[2]);
|
||
return CMDTABRET_FREE_AND_EXIT;
|
||
}
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
/* Get the login name and password to use for a system. */
|
||
|
||
boolean
|
||
fcallout_login (qsys, pzlog, pzpass)
|
||
const struct ssysteminfo *qsys;
|
||
char **pzlog;
|
||
char **pzpass;
|
||
{
|
||
*pzlog = NULL;
|
||
*pzpass = NULL;
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
{
|
||
struct smulti_file *qmulti;
|
||
struct scmdtab as[2];
|
||
struct silogpass s;
|
||
|
||
qmulti = qmulti_open (zCallfile);
|
||
if (qmulti == NULL)
|
||
return FALSE;
|
||
|
||
s.pzlog = pzlog;
|
||
s.pzpass = pzpass;
|
||
|
||
as[0].zcmd = qsys->zname;
|
||
as[0].itype = CMDTABTYPE_FN | 3;
|
||
as[0].pvar = (pointer)&s;
|
||
as[0].ptfn = tilog_pass;
|
||
|
||
as[1].zcmd = NULL;
|
||
|
||
uprocesscmds ((FILE *) NULL, qmulti, as, (const char *) NULL,
|
||
CMDFLAG_BACKSLASH);
|
||
|
||
(void) fmulti_close (qmulti);
|
||
}
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
if (*pzlog == NULL)
|
||
{
|
||
ulog (LOG_ERROR, "No call out login for system %s", qsys->zname);
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
|
||
/* Check whether a login name and password gathered by the UUCP program
|
||
itself are correct. */
|
||
|
||
static enum tcmdtabret ticheck_login P((int argc, char **argv,
|
||
pointer pvar, const char *zerr));
|
||
|
||
/*ARGSUSED*/
|
||
static enum tcmdtabret
|
||
ticheck_login (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
char **pz = (char **) pvar;
|
||
|
||
*pz = xstrdup (argv[1]);
|
||
return CMDTABRET_FREE_AND_EXIT;
|
||
}
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
boolean
|
||
fcheck_login (zuser, zpass)
|
||
const char *zuser;
|
||
const char *zpass;
|
||
{
|
||
#if HAVE_TAYLOR_CONFIG
|
||
struct smulti_file *qmulti;
|
||
struct scmdtab as[2];
|
||
char *zfilepass;
|
||
boolean fok;
|
||
|
||
if (zPwdfile == NULL)
|
||
{
|
||
ulog (LOG_ERROR, "%s%s: file not found", NEWCONFIGLIB,
|
||
PASSWDFILE);
|
||
return FALSE;
|
||
}
|
||
|
||
qmulti = qmulti_open (zPwdfile);
|
||
if (qmulti == NULL)
|
||
return FALSE;
|
||
|
||
zfilepass = NULL;
|
||
|
||
as[0].zcmd = zuser;
|
||
as[0].itype = CMDTABTYPE_FN | 2;
|
||
as[0].pvar = (pointer)&zfilepass;
|
||
as[0].ptfn = ticheck_login;
|
||
|
||
as[1].zcmd = NULL;
|
||
|
||
uprocesscmds ((FILE *) NULL, qmulti, as, (const char *) NULL,
|
||
CMDFLAG_CASESIGNIFICANT | CMDFLAG_BACKSLASH);
|
||
|
||
(void) fmulti_close (qmulti);
|
||
|
||
fok = zfilepass != NULL && strcmp (zfilepass, zpass) == 0;
|
||
|
||
if (zfilepass != NULL)
|
||
{
|
||
bzero (zfilepass, strlen (zfilepass));
|
||
xfree ((pointer) zfilepass);
|
||
}
|
||
|
||
if (! fok)
|
||
ulog (LOG_ERROR, "Bad login");
|
||
|
||
return fok;
|
||
|
||
#else /* HAVE_TAYLOR_CONFIG */
|
||
|
||
ulog (LOG_ERROR, "Not compiled to accept logins");
|
||
return FALSE;
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
}
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
|
||
/* Process a chat command. These are done as prefix commands. We set
|
||
it up such that argv[0] will contain the string "chat" and we must
|
||
look after that point to see what command to execute. */
|
||
|
||
static struct schat_info sChat;
|
||
|
||
static enum tcmdtabret tcchat_fail P((int argc, char **argv,
|
||
pointer pvar,
|
||
const char *zerr));
|
||
|
||
static const struct scmdtab asChatcmds[] =
|
||
{
|
||
{ "chat", CMDTABTYPE_FULLSTRING, (pointer) &sChat.zchat, NULL },
|
||
{ "chat-program", CMDTABTYPE_FULLSTRING, (pointer) &sChat.zprogram,
|
||
NULL },
|
||
{ "chat-timeout", CMDTABTYPE_INT, (pointer) &sChat.ctimeout, NULL },
|
||
{ "chat-fail", CMDTABTYPE_FN | 2, NULL, tcchat_fail },
|
||
{ "chat-seven-bit", CMDTABTYPE_BOOLEAN, (pointer) &sChat.fstrip, NULL },
|
||
{ NULL, 0, NULL, NULL }
|
||
};
|
||
|
||
enum tcmdtabret
|
||
tprocess_chat_cmd (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
struct schat_info *qchat = (struct schat_info *) pvar;
|
||
char *zchat;
|
||
enum tcmdtabret t;
|
||
|
||
zchat = strstr (argv[0], "chat");
|
||
|
||
#if DEBUG > 0
|
||
if (zchat == NULL)
|
||
ulog (LOG_FATAL, "tprocess_chat_cmd: Can't happen");
|
||
#endif
|
||
|
||
argv[0] = zchat;
|
||
|
||
sChat = *qchat;
|
||
t = tprocess_one_cmd (argc, argv, asChatcmds, zerr,
|
||
CMDFLAG_WARNUNRECOG);
|
||
*qchat = sChat;
|
||
|
||
return t;
|
||
}
|
||
|
||
/* Add a new chat failure string. */
|
||
|
||
static enum tcmdtabret
|
||
tcchat_fail (argc, argv, pvar, zerr)
|
||
int argc;
|
||
char **argv;
|
||
pointer pvar;
|
||
const char *zerr;
|
||
{
|
||
uadd_string (&sChat.zfail, argv[1], ' ');
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
#if HAVE_TAYLOR_CONFIG
|
||
|
||
/* Add a protocol parameter entry. The pc parameter points to the
|
||
number of protocol parameter entries, and the pq parameter points
|
||
to the array of protocol parameters. */
|
||
|
||
enum tcmdtabret
|
||
tadd_proto_param (pc, pq, zerr, cargs, azargs)
|
||
int *pc;
|
||
struct sproto_param **pq;
|
||
const char *zerr;
|
||
int cargs;
|
||
char **azargs;
|
||
{
|
||
int i;
|
||
struct sproto_param *q;
|
||
int ientry;
|
||
int icopy;
|
||
|
||
if (cargs < 1)
|
||
{
|
||
ulog (LOG_ERROR, "%s: protocol-parameter: Not enough arguments", zerr);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
if (azargs[0][1] != '\0')
|
||
{
|
||
ulog (LOG_ERROR,
|
||
"%s: protocol-parameter: Protocol names are single characters",
|
||
zerr);
|
||
return CMDTABRET_FREE;
|
||
}
|
||
|
||
q = NULL;
|
||
ientry = 0;
|
||
|
||
for (i = 0; i < *pc; i++)
|
||
{
|
||
if ((*pq)[i].bproto == azargs[0][0])
|
||
{
|
||
q = &(*pq)[i];
|
||
ientry = q->centries;
|
||
++q->centries;
|
||
q->qentries =
|
||
((struct sproto_param_entry *)
|
||
xrealloc ((pointer) q->qentries,
|
||
(q->centries * sizeof (struct sproto_param_entry))));
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i >= *pc)
|
||
{
|
||
++(*pc);
|
||
*pq = ((struct sproto_param *)
|
||
xrealloc ((pointer) *pq,
|
||
(*pc * sizeof (struct sproto_param))));
|
||
q = &(*pq)[*pc - 1];
|
||
q->bproto = azargs[0][0];
|
||
q->centries = 1;
|
||
q->qentries = ((struct sproto_param_entry *)
|
||
xmalloc (sizeof (struct sproto_param_entry)));
|
||
ientry = 0;
|
||
}
|
||
|
||
q->qentries[ientry].cargs = cargs - 1;
|
||
q->qentries[ientry].azargs =
|
||
(char **) xmalloc ((cargs - 1) * sizeof (char *));
|
||
for (icopy = 0; icopy < cargs - 1; icopy++)
|
||
q->qentries[ientry].azargs[icopy] = azargs[icopy + 1];
|
||
|
||
return CMDTABRET_CONTINUE;
|
||
}
|
||
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
|
||
/* Apply some protocol parameters, given the current protocol. */
|
||
|
||
void
|
||
uapply_proto_params (bproto, qcmds, c, pas)
|
||
int bproto;
|
||
struct scmdtab *qcmds;
|
||
int c;
|
||
struct sproto_param *pas;
|
||
{
|
||
int i;
|
||
struct sproto_param *q;
|
||
|
||
for (i = 0, q = pas;
|
||
i < c;
|
||
i++, q++)
|
||
{
|
||
if (q->bproto == (char) bproto)
|
||
{
|
||
char ab[sizeof "g protocol parameters"];
|
||
struct sproto_param_entry *qentry;
|
||
int ientry;
|
||
|
||
sprintf (ab, "%c protocol parameters", bproto);
|
||
q = &pas[i];
|
||
for (ientry = 0, qentry = &q->qentries[0];
|
||
ientry < q->centries;
|
||
ientry++, qentry++)
|
||
(void) tprocess_one_cmd (qentry->cargs, qentry->azargs,
|
||
qcmds, ab, CMDFLAG_WARNUNRECOG);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Maintain a list of systems which are permitted to log in using a
|
||
particular login name. This is the VALIDATE entry from the BNU
|
||
Permissions file. */
|
||
|
||
static struct svalidate
|
||
{
|
||
struct svalidate *qnext;
|
||
const char *zlogname;
|
||
int cmachines;
|
||
const char *azmachines[1];
|
||
} *qIvalidate;
|
||
|
||
/* Add an entry to the validation list. This assumes that it does not
|
||
have to copy the login name or the machine names. It does copy the
|
||
array of machines names. */
|
||
|
||
void
|
||
uadd_validate (zlogname, cmachines, pazmachines)
|
||
const char *zlogname;
|
||
int cmachines;
|
||
const char **pazmachines;
|
||
{
|
||
struct svalidate **pq, *q;
|
||
|
||
for (pq = &qIvalidate; *pq != NULL; pq = &(*pq)->qnext)
|
||
{
|
||
if (strcmp ((*pq)->zlogname, zlogname) == 0)
|
||
{
|
||
*pq = ((struct svalidate *)
|
||
xrealloc ((pointer) *pq,
|
||
sizeof (struct svalidate)
|
||
+ (((*pq)->cmachines + cmachines - 1)
|
||
* sizeof (const char *))));
|
||
memcpy ((*pq)->azmachines + (*pq)->cmachines, pazmachines,
|
||
cmachines * sizeof (const char *));
|
||
(*pq)->cmachines += cmachines;
|
||
return;
|
||
}
|
||
}
|
||
|
||
q = (struct svalidate *) xmalloc (sizeof (struct svalidate)
|
||
+ ((cmachines - 1)
|
||
* sizeof (const char *)));
|
||
q->qnext = qIvalidate;
|
||
q->zlogname = zlogname;
|
||
memcpy (q->azmachines, pazmachines,
|
||
cmachines * sizeof (const char *));
|
||
q->cmachines = cmachines;
|
||
qIvalidate = q;
|
||
}
|
||
|
||
/* Check whether a particular login name/machine name is valid. */
|
||
|
||
boolean
|
||
fcheck_validate (zlogname, zmachine)
|
||
const char *zlogname;
|
||
const char *zmachine;
|
||
{
|
||
struct svalidate *q;
|
||
|
||
for (q = qIvalidate; q != NULL; q = q->qnext)
|
||
{
|
||
if (strcmp (q->zlogname, zlogname) == 0)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < q->cmachines; i++)
|
||
if (strcmp (q->azmachines[i], zmachine) == 0)
|
||
return TRUE;
|
||
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/* The variables which hold the array of timetables. */
|
||
|
||
int cTtable;
|
||
struct stimetable *pasTtable;
|
||
|
||
/* Initialize the table of timetables as advertised in the
|
||
documentation. */
|
||
|
||
void
|
||
uinittimetables ()
|
||
{
|
||
pasTtable = (struct stimetable *) xmalloc (3 * sizeof (struct stimetable));
|
||
pasTtable[0].zname = "Evening";
|
||
pasTtable[0].ztime = "Wk1705-0755,Sa,Su";
|
||
pasTtable[1].zname = "Night";
|
||
pasTtable[1].ztime = "Wk2305-0755,Sa,Su2305-1655";
|
||
pasTtable[2].zname = "NonPeak";
|
||
pasTtable[2].ztime = "Wk1805-0655,Sa,Su";
|
||
cTtable = 3;
|
||
}
|
||
|
||
/* Add a new timetable entry. This assumes it can take control of the
|
||
strings it is passed, so they must not be on the stack and if they
|
||
have been allocated they must not be freed. */
|
||
|
||
void
|
||
uaddtimetable (zname, ztime)
|
||
const char *zname;
|
||
const char *ztime;
|
||
{
|
||
if (pasTtable == NULL)
|
||
uinittimetables ();
|
||
|
||
pasTtable = ((struct stimetable *)
|
||
xrealloc ((pointer) pasTtable,
|
||
(cTtable + 1) * sizeof (struct stimetable)));
|
||
pasTtable[cTtable].zname = zname;
|
||
pasTtable[cTtable].ztime = ztime;
|
||
++cTtable;
|
||
}
|