/* A collection of stuff heavily dependent on the configuration info
 * in config.h. The idea is that configuration-dependent tables should
 * be located here to avoid having to pepper lots of .c files with #ifdefs,
 * requiring them to include config.h and be recompiled each time config.h
 * is modified.
 *
 * Copyright 1991 Phil Karn, KA9Q
 */
/* Mods by PA0GRI */

#include "global.h"
#include "commands.h"
#ifdef MSDOS
#include <conio.h>
#endif
#include "usock.h"
#ifdef	ARCNET
#include "arcnet.h"
#endif
#ifdef ETHER
#include "enet.h"
#endif
#include "kiss.h"
#include "pktdrvr.h"
#include "ppp.h"
#include "slip.h"
#include "arp.h"
#include "icmp.h"
#ifndef MSDOS
#define _TIPMAIL_H
#endif
#include "mailbox.h"
#include "mailcli.h"
#include "ax25mail.h"
#include "nr4mail.h"
#include "bootp.h"
#include "rspf.h"
#ifdef FORTH
#include "forth.h"
#endif
#include "main.h"
#include "gps.h"
#include "x.h"
#ifdef SQL
#include "sql.h"
#endif
#ifdef	TRACE
#include "trace.h"
#endif
#ifdef AXUDP
#include "axudp.h"
#endif

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: config.c,v 1.48 2001/05/06 16:32:55 brian Exp $";
#endif

#ifndef TRACE
void dump (struct iface * iface, int direction, unsigned type, struct mbuf * bp);
void raw_dump (struct iface * iface, int direction, struct mbuf * bp);
#endif

static int dostart (int argc, char *argv[], void *p);
static int dostop (int argc, char *argv[], void *p);
static void network (int, void *, void *);

#ifdef  AX25
static void axip (struct iface * iface, struct ax25_cb * axp, char *src,
			  char *dest, struct mbuf * bp, int mcast);
static void axarp (struct iface * iface, struct ax25_cb * axp, char *src,
			   char *dest, struct mbuf * bp, int mcast);
#ifdef RARP
static void axrarp (struct iface * iface, struct ax25_cb * axp, char *src,
			    char *dest, struct mbuf * bp, int mcast);
#endif
#ifdef NETROM
static void axnr (struct iface * iface, struct ax25_cb * axp, char *src,
			  char *dest, struct mbuf * bp, int mcast);
#endif
#endif


struct mbuf *Hopper;
unsigned Nsessions = NSESSIONS;
extern int cmdparse_newproc_type;

#ifndef UNIX
/* Free memory threshold, below which things start to happen to conserve
 * memory, like garbage collection, and refusing connects
 */
int32 Memthresh = MTHRESH;

#endif

/* these next few of lines are to keep from missing resources if
   MBFWD is not defined. It brings certain items in from the fwding.a
   library that would otherwise not be required in linking until after
   the fwding.a library was parsed.
 */
#ifndef MBFWD
extern int BIDuknos;
int fake_BIDuknos = BIDuknos;

#include "fwdparse.h"
typedef (void (*NULLFUNC)(void *));
NULLFUNC fake_fwdfree = (NULLFUNC) fwdfree;

void fwdunlockit (char *name);
NULLFUNC fake_fwdunlockit = (NULLFUNC) fwdunlockit;
#endif
 
 
/* Transport protocols atop IP */
struct iplink Iplink[] =
{
	{ TCP_PTCL,	tcp_input },
	{ UDP_PTCL,	udp_input },
	{ ICMP_PTCL,	icmp_input },
#ifdef ENCAP
	{ ENCAP_PTCL,	ipip_recv },
	{ IP_PTCL,	ipip_recv },
#endif
#ifdef  AXIP
	{ AX25_PTCL,	axip_input },
#endif
#ifdef	RSPF
	{ RSPF_PTCL,	rspf_input },
#endif /* RSPF */
	{ 0,		0 }
};


/* Transport protocols atop ICMP */
struct icmplink Icmplink[] =
{
	{ TCP_PTCL,	tcp_icmp },
	{ 0,		0 }
};


/* ARP protocol linkages */
struct arp_type Arp_type[NHWTYPES] =
{
#ifdef	NETROM					/* ARP_NETROM */
	{ AXALEN, 0, 0, 0, 0, NULLCHAR, pax25, setcall },
#else
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },
#endif

#ifdef	ETHER					/* ARP_ETHER */
	{ EADDR_LEN, IP_TYPE, ARP_TYPE, REVARP_TYPE, 1, (char *) Ether_bdcst, pether, gether },
#else
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },
#endif

	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },/* ARP_EETHER */

#ifdef	AX25					/* ARP_AX25 */
	{ AXALEN, PID_IP, PID_ARP, PID_RARP, 10, Ax25multi[0], pax25, setcall },
#else
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },
#endif
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },/* ARP_PRONET */
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },/* ARP_CHAOS */
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },/* ARP_IEEE802 */

#ifdef	ARCNET					/* ARP_ARCNET */
	{ AADDR_LEN, ARC_IP, ARC_ARP, 0, 1, ARC_bdcst, parc, garc },
#else
	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },
#endif

	{ 0, 0, 0, 0, 0, NULLCHAR, NULL, NULL },/* ARP_APPLETALK */
};


#ifdef	AX25
/* Linkage to network protocols atop ax25 */
struct axlink Axlink[] =
{
	{ PID_IP,	axip },
	{ PID_ARP,	axarp },
#ifdef RARP
	{ PID_RARP,	axrarp },
#endif
#ifdef  NETROM
	{ PID_NETROM,	axnr },
#endif
	{ PID_NO_L3,	axnl3 },
	{ 0,		NULL }
};
#endif



#ifdef  MAILCLIENT
struct daemon Mailreaders[] =
{
#ifdef	POP2CLIENT
	{ "POP2",	2048,	pop2_job },
#endif
#ifdef  POP3CLIENT
	{ "POP3",	2048,	pop3_job },
#endif
	{ NULLCHAR,	0,	NULL }
};
#endif


#ifndef BOOTP
int WantBootp = 0;

int
bootp_validPacket (struct ip *ip OPTIONAL, struct mbuf **bpp OPTIONAL)
{
	return 0;
}
#endif



#ifdef	MAILBOX
void (*Listusers) (int s) = listusers;
#else
void (*Listusers) (int s) = NULL;
#endif


/* daemons to be run at startup time */
struct daemon Daemons[] =
{
	{ "killer",		1024,	killer },
	{ "timer",		1024,	timerproc },
	{ "network",		3072,	network },
	{ "keyboard",		1024,	keyboard },
	{ "screendaemon",	512,	screendaemon },
#ifdef STATS
	{ "statsdaemon",	768,	statsdaemon },
#endif
#if !defined(TNOS_68K) && !defined(UNIX)
	{ "gcollect",		512,	gcollect },
#endif
	{ NULLCHAR, 		0,	NULLVFP ((int, void *, void *)) }
};



struct iftype Iftypes[] =
{
/* This entry must be first, since Loopback refers to it */
	{ "None", NULL, NULL, NULL, NULL, CL_NONE, 0 },

#ifdef	AX25
	{ "AX25", ax_send, ax_output, pax25, setcall, CL_AX25, AXALEN },
#endif

#ifdef	SLIP
	{ "SLIP", slip_send, NULL, NULL, NULL, CL_NONE, 0 },
#endif

#ifdef	ETHER
/* Note: NULL is specified for the scan function even though
	 * gether() exists because the packet drivers don't support
	 * address setting.
	 */
	{ "Ethernet", enet_send, enet_output, pether, NULL, CL_ETHERNET, EADDR_LEN },
#endif

#ifdef	NETROM
	{ "NETROM", nr_send, NULL, pax25, setcall, CL_NETROM, AXALEN },
#endif

#ifdef	SLFP
	{ "SLFP", pk_send, NULL, NULL, NULL, CL_NONE, 0 },
#endif

#ifdef	PPP
	{ "PPP", ppp_send, ppp_output, NULL, NULL, CL_PPP, 0 },
#endif

	{ NULLCHAR, NULL, NULL, NULL, NULL, CL_NONE, 0 }
};




/* Command lookup and branch tables */
struct cmds Cmds[] =
{
/* The "go" command must be first */
	{ "",		go,		0,	0,	NULLCHAR },
	{ "?",		dohelp,		0,	0,	NULLCHAR },
#ifdef SHELL
	{ "!",		doshell,	0,	0,	NULLCHAR },
#endif
#ifdef ALLSESSIONS
	{ "abort",	doabort,	0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "alias",	doalias,	0,	0,	NULLCHAR },
#endif
#ifdef	APRSD
	{ "aprs",	doaprs,		0,	0,	NULLCHAR },
#endif
#if defined(AX25) || defined(ETHER)
	{ "arp",	doarp,		0,	0,	NULLCHAR },
#endif
#ifdef ASY
#ifdef UNIX
	{ "asyconfig",	doasyconfig,	0,	2,	"asyconfig <iface> <parameter>" },
#endif
	{ "asystat",	doasystat,	0,	0,	NULLCHAR },
#endif
#ifdef ATCMD
	{ "at",		doat,		0,	0,	NULLCHAR },
#endif
	{ "attach",	doattach,	0,	2,	"attach <hardware> <hw specific options>" },
#ifdef AX25
#ifdef AUTOROUTE
	{ "autoroute",	doax25autoroute,0,	0,	NULLCHAR },
#endif
	{ "ax25",	doax25,		0,	0,	NULLCHAR },
#ifdef AXUI
	{ "axui",	doaxui,		1024,	2,	"axui <interface> [callsign]" },
#endif
#endif /* AX25 */
#ifdef	MAILBOX
	{ "bbs",	dobbs,		2048,	0,	NULLCHAR },
#endif
#ifdef EXPIRY
	{ "bid",	dooldbids,	0,	0,	NULLCHAR },
#endif
#ifdef	BOOTPCLIENT
	{ "bootp",	dobootp,	0,	0,	NULLCHAR },
#endif
#ifdef BOOTPSERVER
	{ "bootpd",	bootpdcmd,	0,	0,	NULLCHAR },
#endif
#ifdef BROWSER
	{ "browser",	dobrowser,	1024,	2,	"browser <url>" },
	{ "browsercheck", dobrowsercheck, 0,	3,	"browsercheck <timeout> <complete url>" },
	{ "browseremail", dobrowseremail, 0,	0,	NULLCHAR },
#endif
#ifdef RLINE
	{ "bulletin",	dombrline,	0,	0,	NULLCHAR },
#endif
/* This one is out of alpabetical order to allow abbreviation to "c" */
#if defined(AX25) && defined(ALLSESSIONS)
	{ "connect",	doconnect,	1024,	3,	"connect <interface> <callsign>" },
#endif
#ifdef CALLBOOK
	{ "callserver",	doinetcallserver,0,	0,	NULLCHAR },
#endif
#if defined(CALLCLI) || defined(SAMCALLB) || defined(QRZCALLB)
	{ "callbook",	docallbook,	1024,	2,	"callbook CALLSIGN" },
	{ "callserver2",docallserver,	0,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "cd",		docd,		0,	0,	NULLCHAR },
#endif
#ifdef CALLSERVER
	{ "cdrom",	docdrom,	0,	0,	NULLCHAR },
#endif
#ifdef ALLSERV
	{ "chat",	chatcmd,	0,	0,	NULLCHAR },
#endif
#if defined(ALLCMD) && defined(TNOS_68K)
	{ "chd",	docd,		0,	0,	NULLCHAR },
#endif
	{ "close",	doclose,	0,	0,	NULLCHAR },
	{ "cls",	(int (*)(int, char **, void *)) clrscr,
					0,	0,	NULLCHAR },
	{ "color",	docolor,	0,	3,	"color <background> <foreground>" },
#ifdef ASY
	{ "comm",	doasycomm,	0,	3,	"comm <interface> <text-string>" },
#endif
#if defined(ALLSESSIONS) && defined(CONVERS)
	{ "conference",	doconf,		1024,	0,	NULLCHAR },
	{ "convers",	doconvers,	0,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "copy",	docopy,		0,	3,	"copy <file> <newfile>" },
#endif
#if defined(BETA) && defined(ALPHATEST)	/* not for production usage - diagnostic only */
	{ "crashprotect", docrashprot,	0, 	0, 	NULLCHAR },
#endif
#ifdef CRONTAB
	{ "crontab",	docrontab,	0,	0,	NULLCHAR },
#endif
/* This one is out of alpabetical order to allow abbreviation to "d" */
#ifdef ALLSESSIONS
	{ "disconnect",	doclose,	0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "decr",	dodecr,		0,	2,	"decr <variable> [offset]" },
#endif
#if defined(ALLCMD) && defined(TNOS_68K)
	{ "deldir",	dormd,		0,	2,	"deldir <directory>" },
#endif
#ifdef ALLCMD
	{ "delete",	dodelete,	0,	2,	"delete <file>" },
#endif
	{ "detach",	dodetach,	0,	2,	"detach <interface>" },
#ifdef	DIALER
	{ "dialer",	dodialer,	512,	2,	"dialer <iface> [<file> [<seconds> [<pings> [<hostid>]]]]" },
#endif
#ifdef ALLCMD
	{ "dir",	dodir,		0,	0,	NULLCHAR },
#endif
	{ "domain",	dodomain,	0,	0,	NULLCHAR },
#ifdef	DRSI
	{ "drsistat",	dodrstat,	0,	0,	NULLCHAR },
#endif
#if defined(ALLCMD) && !defined(UNIX)
	{ "dump",	domdump,	0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "echo",	doecho,		0,	0,	NULLCHAR },
#endif
#ifdef	EAGLE
	{ "eaglestat",	doegstat,	0,	0,	NULLCHAR },
#endif
	{ "echomode",	doechomode,	0,	0,	NULLCHAR },
#ifdef SCRIPTING
	{ "else",	doelse,		0,	2,	"else \"cmd\"" },
#endif
	{ "eol",	doeol,		0,	0,	NULLCHAR },
	{ "errors",	doerror,	0,	0,	NULLCHAR },
#ifdef ESCAPE
	{ "escape",	doescape,	0,	0,	NULLCHAR },
#endif
#ifdef	PC_EC
	{ "etherstat",	doetherstat,	0,	0,	NULLCHAR },
#endif
	{ "exit",	doexit,		0,	0,	NULLCHAR },
#ifdef EXPIRY
	{ "expire",	doexpire,	0,	0,	NULLCHAR },
#endif
#ifdef BBSIMPORT
	{ "export",	doexport,	0,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "finger",	dofinger,	1024,	2,	"finger name@host" },
#ifdef MSDOS
	{ "fkey",	dofkey,		0,	0,	NULLCHAR },
#endif
#ifdef MBFWD
	{ "forward",	doforward,	0,	0,	NULLCHAR },
#endif
#endif
#ifdef SCRIPTING
	{ "foreach",	doforeach,	0,	4,	"foreach <variable> \"list\" \"cmd\"" },
#endif
#ifdef FORTH
	{ "forth",	doforth,	0,	0,	NULLCHAR },
#endif
	{ "fstat",	dofstat,	0,	0,	NULLCHAR },
#ifdef ALLSESSIONS
	{ "ftp",	doftp,		2048,	2,	"ftp <address> [[inputfile] [pause]]" },
	{ "ftype",	doftype,	0,	0,	NULLCHAR },
#endif
#ifdef FTPTDISC
	{ "ftptdisc",	doftptdisc,	0,	0,	NULLCHAR },
#endif
	{ "ftpmaxclients",doftpmaxclients,0,	0,	NULLCHAR },
#ifdef SCRIPTING
	{ "gone",	dogone,		0,	0,	NULLCHAR },
	{ "goto",	dogoto,		0,	0,	NULLCHAR },
#endif
#ifdef GPS
	{ "gps",	dogps,		0,	0,	NULLCHAR },
#endif
#ifdef HAPN
	{ "hapnstat",	dohapnstat,	0,	0,	NULLCHAR },
#endif
	{ "help",	dohelp,		0,	0,	NULLCHAR },
#ifdef SCRIPTING
	{ "here",	dohere,		0,	0,	NULLCHAR },
#endif
	{ "history",	dohistory,	0,	0,	NULLCHAR },
#ifdef	HOPCHECK
	{ "hop",	dohop,		0,	0,	NULLCHAR },
#endif
	{ "hostname",	dohostname,	0,	0,	NULLCHAR },
#ifdef	HS
	{ "hs",		dohs,		0,	0,	NULLCHAR },
#endif
#ifdef HTTP
	{ "http",	dohttp,		0,	0,	NULLCHAR },
#endif
	{ "icmp",	doicmp,		0,	0,	NULLCHAR },
#ifdef SCRIPTING
	{ "if",		doif,		0,	0,	NULLCHAR },
	{ "ifdef",	doifdef,	0,	3,	"ifdef variable cmd" },
	{ "ifndef",	doifndef,	0,	3,	"ifndef variable cmd" },
#endif
	{ "ifconfig",	doifconfig,	0,	0,	NULLCHAR },
#ifdef BBSIMPORT
	{ "import",	doimport,	0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "incr",	doincr,		0,	2,	"incr <variable> [offset]" },
#endif
#ifdef TUTOR
	{ "info",	doinfo,		512,	0,	NULLCHAR },
#endif
	{ "ip",		doip,		0,	0,	NULLCHAR },
	{ "kick",	dokick,		0,	0,	NULLCHAR },
	{ "kstat",	dokstat,	0,	0,	NULLCHAR },
/* next one deliberately out of order to make 'lock' shortcut to 'l' */
#ifdef LOCK
	{ "lock",	dolock,		0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "label",	dolabel,	0,	0,	NULLCHAR },
#endif
	{ "log",	dolog,		0,	0,	NULLCHAR },
#ifdef LOOKSESSION
	{ "look",	dolook,		1024,	2,	"look <user|sock#>" },
#endif
#ifdef ALLCMD
	{ "ls",		dodir,		0,	0,	NULLCHAR },
#endif
#ifdef LZW
	{ "lzw",	dolzw,		0,	2,	"lzw <mode|bits>" },
#endif
#if defined(ALLCMD) && !defined(UNIX)
	{ "mail",	dobmail,	0,	0,	NULLCHAR },
#endif
#if defined(ALLCMD) && defined(TNOS_68K)
	{ "makdir",	domkd,		0,	2,	"makdir <directory>" },
#endif
	{ "man",	doman,		0,	2,	"man [section] topic" },
#ifdef ALLCMD
	{ "md",		domkd,		0,	2,	"md <directory>" },
#endif
#ifdef MSDOS
	{ "memory",	domem,		0,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "mkdir",	domkd,		0,	2,	"mkdir <directory>" },
#endif
#ifdef  AX25
	{ "mode",	domode,		0,	2,	"mode <interface>" },
#endif
#ifdef ALLCMD
	{ "more",	domore,		0,	2,
	 "more <filename> [searchstring]" },
	{ "motd",	domotd,		0,	0,	NULLCHAR },
#endif
#ifdef	NETROM
	{ "netrom",	donetrom,	0,	0,	NULLCHAR },
#endif /* NETROM */
#ifdef TUTOR
	{ "news",	donews,		512,	0,	NULLCHAR },
#endif
#if defined(NNTP) || defined(NNTPS)
	{ "nntp",	donntp,		0,	0,	NULLCHAR },
#endif
#ifdef NODECALL
	{ "node",	donode,		0,	0,	NULLCHAR },
#endif
#ifdef NRS
	{ "nrstat",	donrstat,	0,	0,	NULLCHAR },
#endif
#ifdef  MAILBOX
	{ "pbbs",	dopbbs,		0,	0,	NULLCHAR },
#endif
	{ "param",	doparam,	0,	2,	"param <interface>" },
#ifdef SCRIPTING
	{ "pause",	dopause,	0,	0,	NULLCHAR },
#endif
	{ "ping",	doping,		0,	2,
	 "ping <hostid> [<length> [<interval> [incflag]]]" },
#ifdef PIPECMD
	{ "pipe",	dopipe,		0,	2,	"pipe cmdname" },
#endif
#ifdef	PI
	{ "pistatus",	dopistat,	0,	0,	NULLCHAR },
#endif
#ifdef	POP
	{ "pop",	dopop,		0,	0,	NULLCHAR },
#endif
#ifdef  MAILCLIENT
	{ "popmail",	domsread,	0,	0,	NULLCHAR },
#endif
#ifdef GPS
	{ "position",	doposition,	0,	0,	NULLCHAR },
#endif
#ifdef PPP
	{ "ppp",	doppp_commands,	0,	0,	NULLCHAR },
#endif
	{ "profile",	doprofile,	0,	0,	NULLCHAR },
	{ "prompt",	doprompt,	0,	0,	NULLCHAR },
	{ "ps",		ps,		0,	0,	NULLCHAR },
#ifndef UNIX
#ifdef ALLCMD
	{ "pwd",	docd,		0,	0,	NULLCHAR },
#endif
#endif
	{ "quit",	doexit,		0,	0,	NULLCHAR },
	{ "quote",	doquote,	1024,	0,	NULLCHAR },
#if defined(AX25) || defined(ETHER)
#ifdef RARP
	{ "rarp",	dorarp,		0,	0,	NULLCHAR },
#endif /* RARP */
#endif
#ifdef ALLCMD
	{ "rd",		dormd,		0,	2,	"rd <directory>" },
#endif
#ifdef  RDATE
	{ "rdate",	dordate,	0,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "record",	dorecord,	0,	0,	NULLCHAR },
#endif
	{ "register",	doregister,	0,	0,	NULLCHAR },
	{ "remote",	doremote,	0,	3,	/*lint -save -e786 */
	"remote [-p <port#>] [-a <kickaddress>] <hostname> kickme\n"
	"   or: remote [-p <port#>] -k <key> <hostname> reset|exit\n"
	"   or: remote [-p <port#>] -k <key> -r <destIPaddr>[/<bits>] <hostname> add|drop\n"
	"   or: remote -s <password>\n   or: remote -g <gatewaypassword>" },	/*lint -restore */
#ifdef ALLCMD
	{ "rename",	dorename,	0,	3,	"rename <oldfile> <newfile>" },
#endif
	{ "repeat",	dorepeat,	512,	3,	"repeat [<interval>] <command> [args...]" },
	{ "reset",	doreset,	0,	0,	NULLCHAR },
#ifdef	RIP
	{ "rip",	dorip,		0,	0,	NULLCHAR },
#endif
#if defined(RLOGINCLI) || defined(RLOGINSERV)
	{ "rlogin",	dorlogin,	2048,	2,	"rlogin <address>" },
#endif
#ifdef ALLCMD
	{ "rm",		dodelete,	0,	2,	"rm <file>" },
	{ "rmdir",	dormd,		0,	2,	"rmdir <directory>" },
#endif
	{ "route",	doroute,	0,	0,	NULLCHAR },
#ifdef	RSPF
	{ "rspf",	dorspf,		0,	0,	NULLCHAR },
#endif /* RSPF */
	{ "sendmail",	dosendmail,	0,	4,	"sendmail <toaddr> [<fromaddr>] subj data\n\twhere 'data' is a string or <filename" },
	{ "session",	dosession,	0,	0,	NULLCHAR },
	{ "security",	dosecurity,	0,	0,	NULLCHAR },
#ifdef UNIX
	{ "sessmgr",	dosessmgr,	0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "set",	doset,		0,	0,	NULLCHAR },
#endif
#ifdef	SCC
	{ "sccstat",	dosccstat,	0,	0,	NULLCHAR },
#endif
#ifdef TUTOR
	{ "script",	doscript,	0,	2,	"script <filename>" },
#endif
#ifdef SHELL
	{ "shell",	doshell,	0,	0,	NULLCHAR },
#endif
	{ "shutdown",	doshutdown,	256,	3,	"shutdown <delay | \"now\"> \"reason\"" },
	{ "skick",	dokicksocket,	0,	2,	"skick <socket#>" },
#ifdef SCRIPTING
	{ "sleep",	dosleep,	0,	0,	NULLCHAR },
#endif
	{ "smtp",	dosmtp,		0,	0,	NULLCHAR },
	{ "socket",	dosock,		0,	0,	NULLCHAR },
/* this next line deliberately out of order */
	{ "source",	dosource,	0,	2,	"source <filename>" },
#ifdef SOUNDS
	{ "sounds",	dosounds,	0,	0,	NULLCHAR },
#endif
#if defined(AX25) && defined(ALLSESSIONS) && defined(ALLSERV)
	{ "split",	doconnect,	1024,	3,	"split <interface> <callsign>" },
#endif
#ifdef SQL
	{ "sql",	dosql,		0,	0,	NULLCHAR },
#endif
	{ "sreset",	doresetsocket,	0,	2,	"sreset <socket#>" },
#ifdef SCREENSAVER
	{ "ssaver",	dossaver,	0,	0,	NULLCHAR },
#endif
#ifdef	SERVERS
	{ "start",	dostart,	0,	2,	"start <servername>" },
#endif
	{ "statline",	dostatline,	0,	0,	NULLCHAR },
	{ "statmode",	dostatmode,	0,	0,	NULLCHAR },
#ifdef STATS
	{ "stats",	dostats,	0,	0,	NULLCHAR },
#endif
	{ "status",	dostatus,	0,	0,	NULLCHAR },
#ifdef	SERVERS
	{ "stop",	dostop,		0,	2,	"stop <servername>" },
#endif
#ifdef  TRACE
	{ "strace",	dostrace,	0,	0,	NULLCHAR },
#endif
#ifdef ALLSESSIONS		/* deliberately out of order to be first */
	{ "telnet",	dotelnet,	1024,	2,	"telnet <address> [port]" },
#endif
#ifdef TERMSERVER
	{ "term",	doterm,		256,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "tail",	dotail,		0,	2,	"tail <filename> [lines]" },
#endif
	{ "tcp",	dotcp,		0,	0,	NULLCHAR },
#ifdef  MAILBOX
	{ "thirdparty",	dothirdparty,	0,	0,	NULLCHAR },
#endif
	{ "time",	dosystime,	0,	0,	NULLCHAR },
	{ "timers",	dotimers,	0,	0,	NULLCHAR },
	{ "tip",	dotip,		0,	2,	"tip <iface (asyc only!)>" },
#ifdef  TRACE
	{ "trace",	dotrace,	0,	0,	NULLCHAR },
#endif
#ifdef ALLSERV
	{ "ttylink",	dotelnet,	1024,	2,	"ttylink <address> [port]" },
#endif
#ifdef TUTOR
	{ "tutor",	dotutor,	512,	0,	NULLCHAR },
#endif
	{ "udp",	doudp,		0,	0,	NULLCHAR },
#ifdef SCRIPTING
	{ "unalias",	dounalias,	0,	0,	NULLCHAR },
#endif
#ifdef LOCK
	{ "unlock",	dounlock,	0,	0,	NULLCHAR },
#endif
#ifdef SCRIPTING
	{ "unset",	dounset,	0,	2,	"unset <variable>" },
	{ "until",	dountil,	0,	0,	NULLCHAR },
#endif
#ifdef ALLCMD
	{ "upload",	doupload,	0,	0,	NULLCHAR },
#endif
	{ "uptime",	douptime,	0,	0,	NULLCHAR },
/* This one is out of alpabetical order to allow abbreviation to "v" */
	{ "view",	doview,		0,	2,	"view <filename>" },
#if defined(ALLCMD) || defined(VERSION_ON_FILE)
	{ "version",	doversion,	0,	0,	NULLCHAR },
#endif
	{ "warnings",	dowarnings,	0,	0,	NULLCHAR },
#ifdef SCRIPTING
	{ "while",	dowhile,	0,	0,	NULLCHAR },
#endif
#if defined(EXPIRY) && defined(WPAGES)
	{ "wpages",	dooldwpages,	0,	0,	NULLCHAR },
#endif
	{ "write",	dowrite,	256,	3,	"write <user|sock#> <msg>" },
	{ "writeall",	dowriteall,	256,	2,	"writeall <msg>" },
#ifdef XSERVER
	{ "xwindows",	doxwindows,	0,	0,	NULLCHAR },
#endif
#ifdef MSDOS
/* All commands from here to the end aren't displayed in help screen */
	{ "a:",		dodrive,	0,	0,	NULLCHAR },
	{ "b:",		dodrive,	0,	0,	NULLCHAR },
	{ "c:",		dodrive,	0,	0,	NULLCHAR },
	{ "d:",		dodrive,	0,	0,	NULLCHAR },
	{ "e:",		dodrive,	0,	0,	NULLCHAR },
	{ "f:",		dodrive,	0,	0,	NULLCHAR },
	{ "g:",		dodrive,	0,	0,	NULLCHAR },
/* other drive can be added also.... */
#endif
	{ NULLCHAR,	NULLFP ((int, char **, void *)),
					0,	0,	"Unknown command; type \"?\" for list" }
};



/*lint -save -e786 */
/* List of supported hardware devices */
struct cmds Attab[] =
{
#ifdef	PC_EC
/* 3-Com Ethernet interface */
	{ "3c500", ec_attach, 0, 7, "attach 3c500 <address> <vector> arpa <label> <buffers> <mtu> [ip_addr]" },
#endif
#ifdef	ASY
/* Ordinary PC asynchronous adaptor */
	{ "asy", asy_attach, 0, 8, "attach asy <address> <vector> "
#ifdef SLIP
		"slip"
#endif
#ifdef AX25
#ifdef SLIP
		"|"
#endif
		"ax25"
#endif
#ifdef NRS
#if ((defined SLIP) || (defined AX25))
		"|"
#endif
		"nrs"
#endif
#ifdef POLLEDKISS
#if ((defined SLIP) || (defined AX25) || (defined NRS))
		"|"
#endif
		"pkiss"
#endif
#ifdef PPP
#if ((defined SLIP) || (defined AX25) || (defined NRS) || (defined POLLEDKISS))
		"|"
#endif
		"ppp"
#endif

		" <label> <bufsize> <mtu> <speed> [options]" },
#endif /* ASY */

#ifdef KISS
	/* fake ax25 loopback interface */
	{ "axloop", axloop_attach, 0, 1, "attach axloop" },
#endif

#ifdef AXIP
	{ "axip", axip_attach, 0, 4, "attach axip <name> <mtu> <remote-hostid> [callsign] [rmtcall]" },
#endif

#ifdef AXUDP
	/* 12Mar2001, VE4KLM */
	{ "axudp", axudp_attach, 0, 4, "attach axudp <name> <mtu> <remote-hostid> [callsign] [rmtcall] [UDP src port] [UDP dest port]" },
#endif

#ifdef	DRSI
/* DRSI PCPA card in low speed mode */
	{ "drsi", dr_attach, 0, 8, "attach drsi <address> <vector> ax25 <label> <bufsize> <mtu> <chan a speed> <chan b speed> [ip addr a] [ip addr b]" },
#endif

/* dummy interfaces */
	{ "dummy", dummy_attach, 0, 3, "attach dummy <label> <ip_addr>" },

#ifdef	EAGLE
/* EAGLE RS-232C 8530 HDLC adaptor */
	{ "eagle", eg_attach, 0, 8, "attach eagle <address> <vector> ax25 <label> <buffers> <mtu> <speed> [ip_addra] [ip_addrb]" },
#endif
#ifdef	HAPN
/* Hamilton Area Packet Radio (HAPN) 8273 HDLC adaptor */
	{ "hapn", hapn_attach, 0, 8, "attach hapn <address> <vector> ax25 <label> <rx bufsize> <mtu> csma|full [ip_addr]" },
#endif

#ifdef	HS
/* Special high speed driver for DRSI PCPA or Eagle cards */
	{ "hs", hs_attach, 0, 7, "attach hs <address> <vector> ax25 <label> <buffers> <mtu> <txdelay> <persistence> [ip_addra] [ip_addrb]" },
#endif

#if defined(linux) && defined(KERNEL_IF)
	{ "kernel", krnlif_attach, 0, 2, "attach kernel <iface> [nopromisc]" },
#endif

#ifdef	KISS
/* Multi-port KISS interfaer piggy-backing on ASY interface. */
	{ "kiss", kiss_attach, 0, 4, "attach kiss <asy_interface_label> <port> <label> [mtu]" },
#endif /* KISS */

#ifdef NETROM
/* fake netrom interface */
	{ "netrom", nr_attach, 0, 1, "attach netrom [ip_addr]" },
#endif

#ifdef	PACKET
/* FTP Software's packet driver spec */
	{ "packet", pk_attach, 0, 4, "attach packet <int#> <label> <buffers_in_kb> <mtu> [ip_addr]" },
#endif

#ifdef	PC100
/* PACCOMM PC-100 8530 HDLC adaptor */
	{ "pc100", pc_attach, 0, 8, "attach pc100 <address> <vector> ax25 <label> <buffers> <mtu> <speed> [ip_addra] [ip_addrb]" },
#endif

#ifdef	PI
/* Special high speed driver for PI 8530 HDLC adapter */
	{ "pi", pi_attach, 0, 8, "attach pi <address> <vector> <dmachannel> ax25 <label> <buffers> <mtu> <speed a> <speed b> [ip_addra] [ip_addrb]" },
#endif

#ifdef SCC
	{ "scc", scc_attach, 0, 7, "attach scc <devices> init <addr> <spacing> <Aoff> <Boff> <Dataoff>\n   <intack> <vec> [p]<clock> [hdwe] [param]\n"
		"attach scc <chan> slip|kiss|nrs|ax25 <label> <mtu> <speed> <bufsize> [call]" },
#endif
	{ NULLCHAR, NULL, 0, 4, NULLCHAR }
};
/*lint -restore */



/* Functions to be called on each clock tick */
void (*Cfunc[]) (void) = {
#ifndef UNIX
	pctick,			/* Call PC-specific stuff to keep time */
	kbint,			/* Necessary because there's no hardware keyboard interrupt */
#ifdef ASY
	asytimer,
#endif
#ifdef	SCC
	scctimer,
#endif
#endif
	axsetupflush,
	sesflush,
	NULL,
};



#ifdef MSDOS
/* Entry points for garbage collection */
void (*Gcollect[]) (int) = {
	tcp_garbage,
	ip_garbage,
	udp_garbage,
	st_garbage,
#ifdef	AX25
	lapb_garbage,
#endif
#ifdef	NETROM
	nr_garbage,
#endif
	NULL
};
#endif


#ifndef UNIX
/* Functions to be called at shutdown */
void (*Shutdown[]) (void) = {
#ifdef SCC
	sccstop,
#endif
	NULLVFP ((void)),
};
#endif



/* Packet tracing stuff */
#ifdef	TRACE

/* #ifdef MONITOR
 * #define NULLMONFP NULLVFP((FILE *,struct mbuf **, int, int))
 * #else
 */
#define NULLMONFP NULLVFP((FILE *,struct mbuf **, int))
/* #endif */

/* Protocol tracing function pointers. Matches list of class definitions
 * in pktdrvr.h.
 */
struct trace Tracef[] =
{
	{ NULLFP ((struct iface *, struct mbuf *)), ip_dump },	/* CL_NONE */

#ifdef	ETHER							/* CL_ETHERNET */
	{ ether_forus, ether_dump },
#else
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },
#endif /* ETHER */

	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_PRONET_10 */
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_IEEE8025 */
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_OMNINET */
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_APPLETALK */

#ifdef VJCOMPRESS
	{ NULLFP ((struct iface *, struct mbuf *)), sl_dump },	/* CL_SERIAL_LINE */
#else
	{ NULLFP ((struct iface *, struct mbuf *)), ip_dump },	/* CL_SERIAL_LINE */
#endif
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_STARLAN */

#ifdef	ARCNET
	{ arc_forus, arc_dump },				/* CL_ARCNET */
#else
	{NULLFP ((struct iface *, struct mbuf *)), NULLMONFP},
#endif /* ARCNET */

#ifdef	AX25							/* CL_AX25 */
	{ ax_forus, ax25_dump },
#else
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },
#endif /* AX25 */

#ifdef	KISS							/* CL_KISS */
	{ ki_forus, ki_dump },
#else
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },
#endif /* KISS */

	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_IEEE8023 */
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_FDDI */
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_INTERNET_X25 */
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },/* CL_LANSTAR */
#ifdef	SLFP							/* CL_SLFP */
	{ NULLFP ((struct iface *, struct mbuf *)), ip_dump },
#else
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },
#endif /* SLFP */

#ifdef	NETROM							/* CL_NETROM */
	{ NULLFP ((struct iface *, struct mbuf *)), ip_dump },
#else
	{ NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },
#endif

#ifdef PPP							/* CL_PPP */
        { NULLFP ((struct iface *, struct mbuf *)), ppp_dump },
#else
        { NULLFP ((struct iface *, struct mbuf *)), NULLMONFP },
#endif /* PPP */
};

#else

/* Stub for packet dump function */
void
dump (struct iface *iface, int direction, unsigned type, struct mbuf *bp)
{
}

void
raw_dump (struct iface *iface, int direction, struct mbuf *bp)
{
}

#endif /* TRACE */



#ifdef  AX25
#ifdef AUTOROUTE
/* G4JEC's automatic ARP & Route resolution code primitive. */
extern void ax25eavesdrop (struct iface * iface, char *source, char *dest, struct mbuf * bp);
extern int Ax25_autoroute;
#endif /* AUTOROUTE */


/* Hooks for passing incoming AX.25 data frames to network protocols */
static void
axip (struct iface *iface, struct ax25_cb *axp OPTIONAL, char *src, char *dest, struct mbuf *bp, int mcast)
{
#ifdef AUTOROUTE
struct mbuf *nbp;

        if (Ax25_autoroute) {
                (void) dup_p (&nbp, bp, 0, len_p (bp));
                ax25eavesdrop (iface, src, dest, nbp);
                free_p (nbp);
        }
#endif
        (void) ip_route (iface, bp, mcast);
}


static void
axarp (struct iface *iface, struct ax25_cb *axp OPTIONAL, char *src OPTIONAL, char *dest OPTIONAL, struct mbuf *bp, int mcast OPTIONAL)
{
        arp_input (iface, bp);
}


#ifdef RARP
static void
axrarp (struct iface *iface, struct ax25_cb *axp OPTIONAL, char *src OPTIONAL, char *dest OPTIONAL, struct mbuf *bp, int mcast OPTIONAL)
{
        rarp_input (iface, bp);
}

#endif /* RARP */



#ifdef  NETROM
static void
axnr (struct iface *iface, struct ax25_cb *axp, char *src, char *dest OPTIONAL, struct mbuf *bp, int mcast)
{
        if (!mcast)
                nr_route (bp, axp);
        else
                nr_nodercv (iface, src, bp);
}

#endif /* NETROM */
#endif /* AX25 */



#ifndef RIP
void rt_timeout (void *s);


/* Stub for routing timeout when RIP is not configured -- just remove entry */
void
rt_timeout (void *s)
{
struct route *stale = (struct route *) s;

        rt_drop (stale->target, stale->bits);
}
#endif



#ifdef  SERVERS
/* "start" and "stop" subcommands */
static struct cmds Startcmds[] =
{
#if     defined(AX25) && defined(MAILBOX)
        { "ax25",       ax25start,      256,    0, NULLCHAR },
#endif
#if defined(CALLSERVER) || defined(SAMCALLB) || defined(QRZCALLB)
        { "callbook",   cdbstart,       256,    0, NULLCHAR },
#endif
#ifdef  CONVERS
        { "convers",    conv1,          384,    0, NULLCHAR },
#endif
#ifdef CRONTAB
        { "cron",       cron1,          384,    0, NULLCHAR },
#endif
#ifdef ALLSERV
        { "daytime",    daytime1,       256,    0, NULLCHAR },
        { "discard",    dis1,           256,    0, NULLCHAR },
#ifdef ENCAP
	{ "dynamic",	routecli1,	256,	2, "start dynamic <hostname> [<port>]" },
#endif
        { "echo",       echo1,          256,    0, NULLCHAR },
#endif
#ifdef MAILBOX
	{ "fbbtelnet",	fbbtelnet1,	256,	0, NULLCHAR },
#endif /* MAILBOX */
#ifdef FIFOSERVER
        { "fifo",       fifo1,          256,    0, NULLCHAR },
#endif
        { "finger",     finstart,       256,    0, NULLCHAR },
        { "ftp",        ftpstart,       256,    0, NULLCHAR },
#ifdef GPS
        { "gps",        GPSstart,       256,    2, "start gps <interface>" },
#endif
#ifdef HTTP
        { "http",       httpstart,      256,    0, NULLCHAR },
#endif
#ifdef TUTOR
        { "info",       info1,          256,    0, NULLCHAR },
#endif
#ifdef  MESSAGESERVER
	{ "message",	message1,	256,	3, "start message <port> <messagestring> [<ipaddress>]" },
#endif
#if     defined(NETROM) && defined(MAILBOX)
        { "netrom",     nr4start,       256,    0, NULLCHAR },
#endif
#ifdef TUTOR
        { "news",       news1,          256,    0, NULLCHAR },
#endif
#ifdef  NNTPS
        { "nntp",       nntp1,          256,    0, NULLCHAR },
#endif
#ifdef  POP
        { "pop",        pop1,           256,    0, NULLCHAR },
#endif
#ifdef  POP2SERVER
        { "pop2",       pop2start,      2048,   0, NULLCHAR },
#endif
#ifdef  POP3SERVER
        { "pop3",       pop3start,      2048,   0, NULLCHAR },
#endif
#ifdef GPS
        { "position",   POSstart,       256,    0, NULLCHAR },
#endif
#ifdef ALLSERV
        { "quote",      quote1,         256,    0, NULLCHAR },
#endif
        { "remote",     rem1,           768,    0, NULLCHAR },
#ifdef ROUTESERVER
	{ "router",	route1,		256,	0, NULLCHAR },
#endif
#ifdef  RIP
        { "rip",        doripinit,      0,      0, NULLCHAR },
#endif
#ifdef RLOGINSERV
        { "rlogin",     rlogin1,        256,    0, NULLCHAR },
#endif
	{ "smtp",	smtp1,		512,	0, NULLCHAR },
#ifdef BROWSER
	{ "statnews",	statnews1,	256,	0, NULLCHAR },
#endif
#ifdef TCPGATE	
	{ "tcpgate",	tcpgate1,	256,	3, "start tcpgate <tcp port> <host:service>" },
#endif
#ifdef MAILBOX
	{ "telnet",	telnet1,	256,	0, NULLCHAR },
#endif /* MAILBOX */
#ifdef TERMSERVER
	{ "term",	term1,		256,	0, NULLCHAR },
#endif
#ifdef ALLSERV
	{ "time",	time1,		256,	0, NULLCHAR },
#endif /* ALLSERV */
#ifdef TIPMAIL
	{ "tip",	tipstart,	256,	2, "start tip <interface> [<modem|terminal>] [timeout seconds]" },
#endif /* TIPMAIL */
#ifdef  TRACESERVER
	{ "trace",	trace1,		256,	0, NULLCHAR },
#endif
#ifdef  TSCRIPTSERVER
	{ "tscript",	tscript1,	256,	3, "start tscript <port> <scriptname> [<ipaddress>]" },
#endif
#ifdef ALLSERV
	{ "ttylink",	ttylstart,	256,	0, NULLCHAR },
#endif
#ifdef TUTOR
	{ "tutor",	tutor1,		256,	0, NULLCHAR },
#endif
#ifdef XSERVER
	{ "xserver",	xserver1,	256,	0, NULLCHAR },
#endif
	{ NULLCHAR,	0,		0,	0, NULLCHAR },
};



static struct cmds Stopcmds[] =
{
#if	defined(AX25) && defined(MAILBOX)
	{ "ax25",	ax250,		0, 0, NULLCHAR },
#endif
#if defined(CALLSERVER) || defined(SAMCALLB) || defined(QRZCALLB)
	{ "callbook",	cdb0,		0, 0, NULLCHAR },
#endif
#ifdef  CONVERS
	{ "convers",	conv0,		0, 0, NULLCHAR },
#endif
#ifdef CRONTAB
	{ "cron",	cron0,		0, 0, NULLCHAR },
#endif
#ifdef ALLSERV
	{ "daytime",	daytime0,	0, 0, NULLCHAR },
	{ "discard",	dis0,		0, 0, NULLCHAR },
#ifdef ENCAP
	{ "dynamic",	routecli0,	0, 0, NULLCHAR },
#endif
	{ "echo",	echo0,		0, 0, NULLCHAR },
#endif
#ifdef	MAILBOX
	{ "fbbtelnet",	fbbtelnet0,	0, 0, NULLCHAR },
#endif
#ifdef FIFOSERVER
        { "fifo",       fifo0,          0, 0, NULLCHAR },
#endif
	{ "finger",	fin0,		0, 0, NULLCHAR },
	{ "ftp",	ftp0,		0, 0, NULLCHAR },
#ifdef GPS
	{ "gps",	GPSstop,	0, 2, "stop gps <interface>" },
#endif
#ifdef HTTP
	{ "http",	http0,		0, 0, NULLCHAR },
#endif
#ifdef TUTOR
	{ "info",	info0,		0, 0, NULLCHAR },
#endif
#ifdef  MESSAGESERVER
	{ "message",	message0,	0, 2, "stop message <port> [<ipaddress>]" },
#endif
#if defined(NETROM) && defined(MAILBOX)
	{ "netrom",	nr40,		0, 0, NULLCHAR },
#endif
#ifdef TUTOR
	{ "news",	news0,		0, 0, NULLCHAR },
#endif
#ifdef	NNTPS
	{ "nntp",	nntp0,		0, 0, NULLCHAR },
#endif
#ifdef  POP
	{ "pop",	pop0,		0, 0, NULLCHAR },
#endif
#ifdef  POP2SERVER
	{ "pop2",	pop2stop,	0, 0, NULLCHAR },
#endif
#ifdef	POP3SERVER
	{ "pop3",	pop3stop,	0, 0, NULLCHAR },
#endif
#ifdef GPS
	{ "position",	POSstop,	0, 0, NULLCHAR },
#endif
#ifdef ALLSERV
	{ "quote",	quote0,		0, 0, NULLCHAR },
#endif
	{ "remote",	rem0,		0, 0, NULLCHAR },
#ifdef ROUTESERVER
	{ "router",	route0,		0, 0, NULLCHAR },
#endif
#ifdef  RIP
	{ "rip",	doripstop,	0, 0, NULLCHAR },
#endif
#ifdef RLOGINSERV
	{ "rlogin",	rlogin0, 	0, 0, NULLCHAR },
#endif
	{ "smtp",	smtp0,		0, 0, NULLCHAR },
#ifdef BROWSER
	{ "statnews",	statnews0,	0, 0, NULLCHAR },
#endif
#ifdef TCPGATE
	{ "tcpgate",	tcpgate0,	0, 2, "stop tcpgate <tcp port>" },
#endif
#ifdef	MAILBOX
	{ "telnet",	telnet0,	0, 0, NULLCHAR },
#endif
#ifdef TERMSERVER
	{ "term",	term0,		0, 0, NULLCHAR },
#endif
#ifdef ALLSERV
	{ "time",	time0,		0, 0, NULLCHAR },
#endif
#ifdef TIPMAIL
	{ "tip",	(int(*)(int,char **,void *))tip0,
					0, 2, "stop tip <interface>" },
#endif
#ifdef  TRACESERVER
	{ "trace",	trace0,		0, 0, NULLCHAR },
#endif
#ifdef  TSCRIPTSERVER
	{ "tscript",	tscript0,	0, 2, "stop tscript <port> [<ipaddress>]" },
#endif
#ifdef ALLSERV
	{ "ttylink",	ttyl0,		0, 0, NULLCHAR },
#endif
#ifdef TUTOR
	{ "tutor",	tutor0,		0, 0, NULLCHAR },
#endif
#ifdef XSERVER
	{ "xserver",	xserver0,	0, 0, NULLCHAR },
#endif
	{ NULLCHAR,	0,		0, 0, NULLCHAR }
};



static int
dostart (int argc, char *argv[], void *p)
{
int insave = 0, outsave = 0, swapped = 0;

	if (Curproc->input == Command->input) {
		insave = Curproc->input;
		outsave = Curproc->output;
		Curproc->input = Cmdpp->input;
		Curproc->output = Cmdpp->output;
		swapped = 1;
	}
	cmdparse_newproc_type = PTYPE_SERVER;
	(void) subcmd (Startcmds, argc, argv, p);
	cmdparse_newproc_type = PTYPE_NORMAL;

	if (swapped) {
		Curproc->input = insave;
		Curproc->output = outsave;
	}
	return 0;
}


static int
dostop (int argc, char *argv[], void *p)
{
	return subcmd (Stopcmds, argc, argv, p);
}

#endif /* SERVERS */



/* Various configuration-dependent functions */

/* put mbuf into Hopper for network task
 * returns 0 if OK
 */
int
net_route (struct iface *ifp, int type, struct mbuf *bp)
{
struct mbuf *nbp;
struct phdr phdr;

	if (ifp == NULLIF)	{
		kwait (NULL);
		return 0;
	}

	phdr.iface = ifp;
	phdr.type = (int16) type;

	if ((nbp = pushdown (bp, sizeof (phdr))) == NULLBUF)
		return -1;

	memcpy (&nbp->data[0], (char *) &phdr, sizeof (phdr));
	enqueue (&Hopper, nbp);
	/* Especially on slow machines, serial I/O can be quite
	 * compute intensive, so release the machine before we
	 * do the next packet.  This will allow this packet to
	 * go on toward its ultimate destination. [Karn]
	 */
	kwait (NULL);

	return 0;
}


/* Process packets in the Hopper */
static void
network (int i OPTIONAL, void *v1 OPTIONAL, void *v2 OPTIONAL)
{
struct mbuf *bp;
struct phdr phdr;
int i_state;
#ifdef RXECHO
struct mbuf *bbp;
#endif

	server_disconnect_io ();
loop:
	while (Hopper == NULLBUF)
		kwait (&Hopper);
	/* this is silly, first we turn ints on, then off again...? -WG7J */
	/* Process the input packet */
	/*    bp = dequeue(&Hopper);     */

	i_state = disable ();
	bp = Hopper;
	Hopper = Hopper->anext;
	bp->anext = NULLBUF;

	restore (i_state);

	(void) pullup (&bp, (unsigned char *) &phdr, sizeof (phdr));
	if (phdr.iface != NULLIF) {
		phdr.iface->rawrecvcnt++;
		phdr.iface->lastrecv = secclock ();
	}
#ifdef TRACE
	dump (phdr.iface, IF_TRACE_IN, (unsigned) phdr.type, bp);
#endif
#ifdef RXECHO
	/* If configured, echo this packet before handling - WG7J */
	/* But only if packet is not CL_KISS. Kiss packets must be */
	/* echoed after retrieving port info in kiss_recv() - OH2BNS */
#if defined (KISS) || defined(AX25)
	if (phdr.type != CL_KISS) {
#endif
		if (phdr.iface && phdr.iface->rxecho) {
			(void) dup_p (&bbp, bp, 0, len_p (bp));
			(void) (*phdr.iface->rxecho->raw) (phdr.iface->rxecho, bbp);
		}
#if defined (KISS) || defined(AX25)
	}
#endif
#endif /* RXECHO */
	switch (phdr.type) {
#ifdef	KISS
		case CL_KISS:
			kiss_recv (phdr.iface, bp);
			break;
#endif
#ifdef	AX25
		case CL_AX25:
			ax_recv (phdr.iface, bp);
			break;
#endif
#ifdef	ETHER
		case CL_ETHERNET:
			eproc (phdr.iface, bp);
			break;
#endif
#ifdef ARCNET
		case CL_ARCNET:
			aproc (phdr.iface, bp);
			break;
#endif
#ifdef PPP
		case CL_PPP:
			ppp_proc (phdr.iface, bp);
			break;
#endif
			/* These types have no link layer protocol at the point when they're
			 * put in the hopper, so they can be handed directly to IP. The
			 * separate types are just for user convenience when running the
			 * "iface" command.
			 */
		case CL_NONE:
		case CL_SERIAL_LINE:
		case CL_SLFP:
			(void) ip_route (phdr.iface, bp, 0);
			break;
		default:
			free_p (bp);
			break;
	}
	/* Let everything else run - this keeps the system from wedging
	 * when we're hit by a big burst of packets
	 */
	kwait (NULL);
	goto loop;
}
