/* 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 <stdio.h>
#ifdef MSDOS
#include <dos.h>
#include <conio.h>
#endif
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "timer.h"
#include "proc.h"
#include "iface.h"
#include "ip.h"
#include "tcp.h"
#include "udp.h"
#ifdef	ARCNET
#include "arcnet.h"
#endif
#include "lapb.h"
#include "ax25.h"
#ifdef ETHER
#include "enet.h"
#endif
#include "kiss.h"
#include "netrom.h"
#include "nr4.h"
#include "pktdrvr.h"
#include "ppp.h"
#include "slip.h"
#include "arp.h"
#include "icmp.h"
#include "hardware.h"	/***/
#include "usock.h"
#include "commands.h"
#include "mailbox.h"
#include "mailcli.h"
#include "ax25mail.h"
#include "nr4mail.h"
#include "tipmail.h"
#include "bootp.h"
#include "daemon.h"
#include "slhc.h"
#include "rspf.h"
#include "main.h"
#include "gps.h"
#include "rip.h"

static int dostart __ARGS((int argc,char *argv[],void *p));
static int dostop __ARGS((int argc,char *argv[],void *p));
#ifdef WPAGES
extern int dooldwpages __ARGS((int argc,char *argv[],void *p));
#endif
extern int doftpmaxclients __ARGS((int argc,char *argv[],void *p));
extern int dossaver __ARGS((int argc,char *argv[],void *p));
extern int dodrive __ARGS((int argc,char *argv[],void *p));
#ifdef XSPAWN
extern int doxspawn __ARGS((int argc,char *argv[],void *p));
#endif
extern int doquote __ARGS((int argc,char *argv[],void *p));
#ifdef MBFWD
extern int doforward __ARGS((int argc,char *argv[],void *p));
#endif
#ifdef RDATE
extern int dordate __ARGS((int argc,char *argv[],void *p));
#endif
#ifdef RLOGINSERV
int rlogin0 __ARGS((int argc,char *argv[],void *p));
int rlogin1 __ARGS((int argc,char *argv[],void *p));
#endif
extern int doerror __ARGS((int argc,char *argv[],void *p));
#ifdef TUTOR
extern int doscript __ARGS((int argc,char *argv[],void *p));
extern int dotutor __ARGS((int argc,char *argv[],void *p));
int tutor0 __ARGS((int argc,char *argv[],void *p));
int tutor1 __ARGS((int argc,char *argv[],void *p));
extern int doinfo __ARGS((int argc,char *argv[],void *p));
int info0 __ARGS((int argc,char *argv[],void *p));
int info1 __ARGS((int argc,char *argv[],void *p));
extern int donews __ARGS((int argc,char *argv[],void *p));
int news0 __ARGS((int argc,char *argv[],void *p));
int news1 __ARGS((int argc,char *argv[],void *p));
#endif
#if defined(TNOS_68K) || defined(UNIX)
extern void screendaemon __ARGS((int i, char *v1, void *v2));
#endif

extern int docolor __ARGS((int argc,char *argv[],void *p));
extern int dostatline __ARGS((int argc,char *argv[],void *p));
extern int doprompt __ARGS((int argc,char *argv[],void *p));
extern int doview __ARGS((int argc,char *argv[],void *p));
extern int dosystime __ARGS((int argc,char *argv[],void *p));
extern int dorepeat __ARGS((int argc,char *argv[],void *p));
static void network __ARGS((int,void *,void *));

#ifdef	NNTPS
extern int donntpcli __ARGS((int argc,char *argv[],void *p));
extern int nntp0 __ARGS((int argc,char *argv[],void *p));
extern int nntp1 __ARGS((int argc,char *argv[],void *p));
#endif

#ifdef	CONVERS
int conv0 __ARGS((int argc,char *argv[],void *p));
int conv1 __ARGS((int argc,char *argv[],void *p));
int doconvers __ARGS((int argc,char *argv[],void *p));
int doconf __ARGS((int argc,char *argv[],void *p));

#endif

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

struct mbuf *Hopper;
unsigned Nsessions = NSESSIONS;

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

#ifndef TNOS_68K
int Nibufs = NIBUFS;		/* Number of interrupt buffers */
unsigned Ibufsize = IBUFSIZE;	/* Size of each interrupt buffer */
#endif
#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
	AXALEN, 0, 0, 0, 0, NULLCHAR, pax25, setcall,	/* ARP_NETROM */
#else
	0, 0, 0, 0, 0, NULLCHAR,NULL,NULL,
#endif

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

	0, 0, 0, 0, 0, NULLCHAR,NULL,NULL,		/* ARP_EETHER */

#ifdef	AX25
	AXALEN, PID_IP, PID_ARP, PID_RARP, 10, Ax25multi[0], pax25, setcall,
#else
	0, 0, 0, 0, 0, NULLCHAR,NULL,NULL,		/* ARP_AX25 */
#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
	AADDR_LEN, ARC_IP, ARC_ARP, 0, 1, ARC_bdcst, parc, garc, /* ARP_ARCNET */
#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
};
#endif

#ifndef BOOTP
int WantBootp = 0;

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

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

/* daemons to be run at startup time */
struct daemon Daemons[] = {
	"killer",	1024,	killer,
	"timer",	1024,	timerproc,
	"network",	3072,	network,
	"keyboard",	512,	keyboard,
#if !defined(TNOS_68K) && !defined(UNIX)
	"gcollect",	512,	gcollect,
#endif
#if defined(TNOS_68K) || defined(UNIX)
	"screendaemon", 512,	screendaemon,
#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
};


/* Command lookup and branch tables */
struct cmds DFAR Cmds[] = {
	/* The "go" command must be first */
	"",		go,		0, 0, NULLCHAR,
	"?",		dohelp,		0, 0, NULLCHAR,
#ifndef	AMIGA
#ifdef SHELL
	"!",		doshell,	0, 0, NULLCHAR,
#endif
#endif
#ifdef ALLSESSIONS
    "abort",    doabort,    0, 0, NULLCHAR,
#endif
#ifdef  AMIGA
	"amiga",	doamiga,	0, 0, NULLCHAR,
#endif
#if	(defined(MAC) && defined(APPLETALK))
	"applestat",	doatstat,	0,	0, NULLCHAR,
#endif
#if	(defined(AX25) || defined(ETHER) || defined(APPLETALK))
	"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>",
	"attended",	doattended,	0, 0, NULLCHAR,
#ifdef	AX25
#ifdef AUTOROUTE
    "autoroute",doax25autoroute, 0, 0, NULLCHAR,
#endif /* AUTOROUTE */
    "ax25",     doax25,     0, 0, NULLCHAR,
#endif /* AX25 */
#ifdef	MAILBOX
    "bbs",      dobbs,      2048, 0, NULLCHAR,
#endif
#ifdef EXPIRY
    "bid",   dooldbids,  0, 0, NULLCHAR,
#endif
#ifdef	BOOTP
    "bootp",    dobootp,    0, 0, NULLCHAR,
	"bootpd",	bootpdcmd, 	0, 0, NULLCHAR,
#endif
#ifdef RLINE
    "bulletin", dombrline,  0, 0, NULLCHAR,
#endif
/* This one is out of alpabetical order to allow abbreviation to "c" */
#ifdef	AX25
#ifdef ALLSESSIONS
    "connect",  doconnect,  1024, 3,
	"connect <interface> <callsign>",
#endif
#endif
#ifdef CALLBOOK
    "callserver", doinetcallserver, 0, 0, NULLCHAR,
#endif
#if defined(CALLCLI) || defined(SAMCALLB)
  "callbook", docallbook, 1024, 2, "callbook CALLSIGN",
#endif
#if defined(CALLCLI) || defined(SAMCALLB)
  "callserver", docallserver, 0, 0, NULLCHAR,
#endif
#if !defined(AMIGA)
#ifdef ALLCMD
    "cd",       docd,       0, 0, NULLCHAR,
#endif
#ifdef CALLSERVER
  "cdrom", docdrom, 0, 0, NULLCHAR,
#endif
#endif
#if defined(ALLCMD) && defined(TNOS_68K)
    "chd",       docd,       0, 0, NULLCHAR,
#endif
	"close",	doclose,	0, 0, NULLCHAR,
    "cls",      (int (*)__ARGS((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
/* This one is out of alpabetical order to allow abbreviation to "d" */
#ifdef ALLSESSIONS
    "disconnect",   doclose,    0, 0, NULLCHAR,
#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
#ifndef AMIGA
#ifdef ALLCMD
    "dir",      dodir,      0, 0, NULLCHAR,
#endif
#endif
	"domain",	dodomain,	0, 0, NULLCHAR,
#ifdef	DRSI
	"drsistat",	dodrstat,	0, 0, NULLCHAR,
#endif
#ifdef ALLCMD
    "dump",     domdump,    0, 0, NULLCHAR,
#endif
#ifdef	EAGLE
	"eaglestat",	doegstat,	0, 0, NULLCHAR,
#endif
	"echo",		doecho,		0, 0, NULLCHAR,
	"eol",		doeol,		0, 0, NULLCHAR,
    "errors",   doerror,    0, 0, NULLCHAR,
#if	(!defined(MSDOS) || defined(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 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 ALLSESSIONS
    "ftp",      doftp,      2048, 2, "ftp <address>",
    "ftype",    doftype,    0, 0, NULLCHAR,
#endif
#ifdef FTPTDISC
    "ftptdisc", doftptdisc, 0, 0, NULLCHAR,
#endif
    "ftpmaxclients", doftpmaxclients, 0, 0, NULLCHAR,
#ifdef GPS
	"gps",		dogps,		0, 0, NULLCHAR,
#endif
#ifdef HAPN
	"hapnstat",	dohapnstat,	0, 0, NULLCHAR,
#endif
	"help",		dohelp,		0, 0, NULLCHAR,
	"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
	"icmp",		doicmp,		0, 0, NULLCHAR,
	"ifconfig",	doifconfig,	0, 0, NULLCHAR,
#ifdef TUTOR
    "info",     doinfo,     512, 0, NULLCHAR,
#endif
    "ip",       doip,       0, 0, NULLCHAR,
#ifdef	MSDOS
	"isat",		doisat,		0, 0, NULLCHAR,
#endif	
	"kick",		dokick,		0, 0, NULLCHAR,
#ifdef LOCK
    "lock",     dolock,     0, 0, NULLCHAR,
#endif
    "log",      dolog,      0, 0, NULLCHAR,
#ifndef AMIGA
#ifdef ALLCMD
    "ls",      dodir,      0, 0, NULLCHAR,
#endif
#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
#ifdef  MAILBOX
	"mbox",		dombox,		0, 0, NULLCHAR,
#endif
#ifdef ALLCMD
    "md",    domkd,      0, 2, "md <directory>",
#endif
#if !defined(UNIX) && !defined(TNOS_68K)
	"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  MSDOS
#ifdef MULTITASK
    "multitask",    dobackg,    0, 0, NULLCHAR,
#endif
#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 NRS
	"nrstat",	donrstat,	0, 0, NULLCHAR,
#endif
	"param",	doparam,	0, 2, "param <interface>",
	"ping",		doping,		0, 2,
	"ping <hostid> [<length> [<interval> [incflag]]]",
#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
	"prompt",	doprompt,	0, 0, NULLCHAR,
	"ps",		ps,		0, 0, NULLCHAR,
#if	!defined(UNIX) && !defined(AMIGA)
#ifdef ALLCMD
    "pwd",      docd,       0, 0, NULLCHAR,
#endif
#endif
    "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
    "remote",   doremote,   0, 3, "remote [-p port] [-k key] [-a kickaddr] <address> exit|reset|kick",
#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>",
#endif
#ifdef ALLCMD
    "rmdir",    dormd,      0, 2, "rmdir <directory>",
#endif
    "route",    doroute,    0, 0, NULLCHAR,
#ifdef	RSPF
	"rspf",		dorspf,		0, 0, NULLCHAR,
#endif	/* RSPF */
	"session",	dosession,	0, 0, NULLCHAR,
#ifdef UNIX
	"sessmgr",	dosessmgr,	0, 0, NULLCHAR,
#endif
#ifdef	SCC
	"sccstat",	dosccstat,	0, 0, NULLCHAR,
#endif
#ifdef TUTOR
	"script",	doscript,	0, 2, "script <filename>",
#endif
#if	!defined(AMIGA)
#ifdef SHELL
    "shell",    doshell,    0, 0, NULLCHAR,
#endif
#endif
    "skick",    dokicksocket,0,2, "skick <socket#>",
    "smtp",     dosmtp,     0, 0, NULLCHAR,
	"socket",	dosock,		0, 0, NULLCHAR,
	"source",	dosource,	0, 2, "source <filename>",
#ifdef  AX25
#ifdef ALLSESSIONS
#ifdef ALLSERV
    "split",  doconnect,  1024, 3,    "split <interface> <callsign>",
#endif
#endif
#endif
#ifdef SCREENSAVER
	"ssaver",	dossaver,	0, 0, NULLCHAR,
#endif
#ifdef	SERVERS
	"start",	dostart,	0, 2, "start <servername>",
#endif
    "statline",	dostatline, 0, 0, NULLCHAR,
    "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 ALLCMD
    "tail",     dotail,     0, 2, "tail <filename> [lines]",
#endif
    "tcp",      dotcp,      0, 0, NULLCHAR,
#ifdef nope
    "test",     dotest,     0, 0, NULLCHAR,
#endif
#ifdef  MAILBOX
	"thirdparty",	dothirdparty,	0, 0, NULLCHAR,
#endif
    "time",     dosystime,  0, 0, NULLCHAR,
    "tip",      dotip,      256, 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 ALLCMD
    "upload",   doupload,   0, 0, NULLCHAR,
#endif
/* This one is out of alpabetical order to allow abbreviation to "v" */
    "view",		doview,		0, 2, "view <filename>",
#ifdef ALLCMD
    "version",     doversion,     0, 0, NULLCHAR,
#endif
#if defined(MSDOS) && defined(ALLCMD) && (SWATCH)
    "watch",    doswatch,   0, 0, NULLCHAR,
#endif
#ifndef UNIX
    "watchdog", dowatchdog, 0, 0, NULLCHAR,
#endif
#if defined(EXPIRY) && defined(WPAGES)
    "wpages",dooldwpages, 0, 0, NULLCHAR,
#endif
    "write",    dowrite,    0, 3, "write <user|sock#> <msg>",
    "writeall", dowriteall, 0, 2, "writeall <msg>",
#ifdef XSPAWN
    "xspawn",	doxspawn,   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",
};

/* 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, 
#ifndef	AMIGA
#ifdef	NRS
#ifdef	PPP
	"attach asy <address> <vector> slip|ax25|nrs|ppp <label> <buffers> <mtu> <speed> [options]",
#else	/* PPP */
	"attach asy <address> <vector> slip|ax25|nrs <label> <buffers> <mtu> <speed> [options]",
#endif	/* PPP */
#else	/* NRS */
#ifdef	PPP
	"attach asy <address> <vector> slip|ax25|ppp <label> <buffers> <mtu> <speed> [options]",
#else	/* PPP */
	"attach asy <address> <vector> slip|ax25 <label> <buffers> <mtu> <speed> [options]",
#endif	/* PPP */
#endif	/* NRS */
#else
#ifdef	NRS
#ifdef	PPP
 	"attach asy <driver> <unit> slip|ax25|nrs|ppp <label> <buffers> <mtu> <speed> [options]",
#else	/* PPP */
 	"attach asy <driver> <unit> slip|ax25|nrs <label> <buffers> <mtu> <speed> [options]",
#endif	/* PPP */
#else	/* NRS */
#ifdef	PPP
 	"attach asy <driver> <unit> slip|ax25|ppp <label> <buffers> <mtu> <speed> [options]",
#else	/* PPP */
 	"attach asy <driver> <unit> slip|ax25 <label> <buffers> <mtu> <speed> [options]",
#endif	/* PPP */
#endif	/* NRS */
#endif	/* AMIGA */
#endif	/* ASY */
#ifdef	KISS
	/* Multi-port KISS interface piggy-backing on ASY interface. */
	"kiss", kiss_attach, 0, 4, 
	"attach kiss <asy_interface_label> <port> <label> [mtu]",
#endif	/* KISS */
#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	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
#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	APPLETALK
	/* Macintosh AppleTalk */
	"0", at_attach, 0, 7,
	"attach 0 <protocol type> <device> arpa <label> <rx bufsize> <mtu> [ip_addr]",
#endif
#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> <mtu> [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
#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
#ifdef AXIP
	"axip",axip_attach, 0, 4,
	"attach axip <name> <mtu> <remote-hostid> [callsign]",
#endif
	NULLCHAR,
};

#ifndef UNIX

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

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

/* Functions to be called at shutdown */
void (*Shutdown[]) __ARGS((void)) = {
#ifdef SCC
	sccstop,
#endif
#ifndef TNOS_68K
	uchtimer,	/* Unlink timer handler from timer chain */
#endif
	NULLVFP((void)),
};

#endif

/* Packet tracing stuff */
#ifdef	TRACE
#include "trace.h"

/* #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 DFAR 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 */

#ifdef	APPLETALK
	at_forus,	at_dump,	/* CL_APPLETALK */
#else
	NULLFP((struct iface*,struct mbuf*)),		NULLMONFP,
#endif	/* 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
	ax_forus,	ax25_dump,	/* CL_AX25 */
#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
	NULLFP((struct iface*,struct mbuf*)),		ip_dump,	/* CL_SLFP */
#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
	NULLFP((struct iface*,struct mbuf*)),		ppp_dump,	/* CL_PPP */
#else
	NULLFP((struct iface*,struct mbuf*)),		NULLMONFP,
#endif /* PPP */
};

#else

/* Stub for packet dump function */
void
#ifdef PROTOTYPES
dump(struct iface *iface,int direction,unsigned type,struct mbuf *bp)
#else
dump(iface,direction,type,bp)
struct iface *iface;
int direction;
unsigned type;
struct mbuf *bp;
#endif
{
}
void
#ifdef PROTOTYPES
raw_dump(struct iface *iface,int direction,struct mbuf *bp)
#else
raw_dump(iface,direction,bp)
struct iface *iface;
int direction;
struct mbuf *bp;
#endif
{
}

#endif	/* TRACE */


#ifdef	AX25
#ifdef AUTOROUTE
/* G4JEC's automatic ARP & Route resolution code primitive. */
extern void ax25eavesdrop __ARGS((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 */
void
axip(iface,axp,src,dest,bp,mcast)
struct iface *iface;
struct ax25_cb *axp;
char *src;
char *dest;
struct mbuf *bp;
int mcast;
{
#ifdef AUTOROUTE
    struct mbuf *nbp;

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

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

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

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

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

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

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

#ifdef	SERVERS
/* "start" and "stop" subcommands */
static struct cmds DFAR Startcmds[] = {
#if	defined(AX25) && defined(MAILBOX)
	"ax25",		ax25start,	256, 0, NULLCHAR,
#endif
#if defined(CALLSERVER) || defined(SAMCALLB)
	"callbook",	cdbstart,	256, 0, NULLCHAR,
#endif
#ifdef  CONVERS
	"convers",	conv1,		384, 0, NULLCHAR,
#endif
#ifdef ALLSERV
	"daytime",	daytime1,	256, 0, NULLCHAR,
    "discard",  dis1,       256, 0, NULLCHAR,
	"echo",		echo1,		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 TUTOR
	"info",		info1,		256, 0, NULLCHAR,
#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  RIP
	"rip",		doripinit,	0,   0, NULLCHAR,
#endif
#if defined(ALLSERV) && defined(RLOGINSERV)
	"rlogin",	rlogin1,	256, 0, NULLCHAR,
#endif
	"smtp",		smtp1,		512, 0, NULLCHAR,
#ifdef MAILBOX
	"telnet",	telnet1,	256, 0, NULLCHAR,
#ifdef ALLSERV
	"time",		time1,		256, 0, NULLCHAR,
#ifdef TIPMAIL
    "tip",      tipstart,   256, 2, "start tip <interface> [<modem|terminal>] [timeout seconds]",
#endif /* TIPMAIL */
#endif /* ALLSERV */
#endif /* MAILBOX */
#ifdef ALLSERV
    "ttylink",  ttylstart,  256, 0, NULLCHAR,
#endif
#ifdef TUTOR
    "tutor",    tutor1,     256, 0, NULLCHAR,
#endif
	NULLCHAR,
};
static struct cmds DFAR Stopcmds[] = {
#if	defined(AX25) && defined(MAILBOX)
	"ax25",		ax250,		0, 0, NULLCHAR,
#endif
#if defined(CALLSERVER) || defined(SAMCALLB)
	"callbook",	cdb0,		0, 0, NULLCHAR,
#endif
#ifdef  CONVERS
	"convers",  conv0,      384, 0, NULLCHAR,
#endif
#ifdef ALLSERV
	"daytime",	daytime0,	0, 0, NULLCHAR,
    "discard",  dis0,       0, 0, NULLCHAR,
	"echo",		echo0,		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 TUTOR
	"info",		info0,		0, 0, NULLCHAR,
#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,      2048,0, NULLCHAR,
#endif
#ifdef	POP3SERVER
    "pop3",         pop3stop,      2048,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  RIP
	"rip",		doripstop,	0, 0, NULLCHAR,
#endif
#if defined(ALLSERV) && defined(RLOGINSERV)
	"rlogin",	rlogin0,	0, 0, NULLCHAR,
#endif
	"smtp",		smtp0,		0, 0, NULLCHAR,
#ifdef	MAILBOX
	"telnet",	telnet0,	0, 0, NULLCHAR,
#ifdef ALLSERV
	"time",		time0,		0, 0, NULLCHAR,
#ifdef TIPMAIL
    "tip",      tip0,       0, 2, "stop tip <interface>",
#endif
#endif
#endif
#ifdef ALLSERV
    "ttylink",  ttyl0,      0, 0, NULLCHAR,
#endif
#ifdef TUTOR
    "tutor",    tutor0,     0, 0, NULLCHAR,
#endif
	NULLCHAR,

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

    if(Curproc->input == Command->input)	{
	    insave = Curproc->input;
	    outsave = Curproc->output;
	    Curproc->input = Cmdpp->input;
	    Curproc->output = Cmdpp->output;
	    swapped = 1;
    }

    subcmd(Startcmds,argc,argv,p);

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

static int
dostop(argc,argv,p)
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(ifp, type, bp)
struct iface *ifp;
int type;
struct mbuf *bp;
{
	struct mbuf *nbp;
	struct phdr phdr;

	phdr.iface = ifp;
	phdr.type = 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]
	 */
	pwait(NULL);
	return 0;
}

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

loop:
#if !defined(TNOS_68K) && !defined(UNIX)
	refiq();	/* Replenish interrupt buffer pool */
#endif

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

	bp = Hopper;
	Hopper = Hopper->anext;
	bp->anext = NULLBUF;

	restore(i_state);

	pullup(&bp,(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
    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:
		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
	 */
	pwait(NULL);
	goto loop;
}
