Xref: utzoo comp.protocols.tcp-ip:4132 comp.protocols.tcp-ip.ibmpc:663
Path: utzoo!attcan!uunet!husc6!rutgers!njin!princeton!phoenix!asjoshi
From: asjoshi@phoenix.Princeton.EDU (Amit S. Joshi)
Newsgroups: comp.protocols.tcp-ip,comp.protocols.tcp-ip.ibmpc
Subject: Ethernet Printer driver using KA9Q code
Keywords: TCP/IP Printers ethernet
Message-ID: <3289@phoenix.Princeton.EDU>
Date: 17 Jul 88 18:32:56 GMT
Organization: Princeton University, NJ
Lines: 1613
Hi,
Some people had requested a small printer driver that I had written
using the KA9Q code as the interface to the ethernet. Here it is.
Unshar it and compile. I only know that it compiles using Turbo C v1.5
It also need the KA9Q TCP/IP code. ( I know that it works with my port
to Turbo C of Ver 870829.6).
Have fun
Amit Joshi BITNET | Q3696@PUCC.BITNET
USENET | {seismo, rutgers}\!princeton\!phoenix\!asjoshi
"There's a pleasure in being mad... which none but madmen know!" - St.Dryden
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh EPRINT.C <<'END_OF_EPRINT.C'
X/* eprint.c - a simple print utility Author: Amit Joshi */
X
X/**
X
X This is a sample demo program to show how the use of
X the generic connections simplifies connecting to the
X net. You need Phil Karn's KA9Q TCP/IP package, and the
X 4 files "generic.c", "generic.h", "tick.c" and "tick.h"
X which have the interface functions.
X
X January 1988
X Amit Joshi
X**/
X
X/**
X Revision History:
X v1.1 March 1988 - added query on printfile option.
X - no longer have to perform netservice
X - ^C works properly now.
X v2.0 July 1988 - added wildcards support.
X - added recursive directory printing support.
X**/
X
X#define VERSION "2.00"
X
X#include
X#include
X#include
X#include
X#include
X#include
X#include
X#include
X#include
X
X#define PAGEFEED '\f'
X
X#define NULLCHAR (char)NULL
X#define YES 1
X#define NO 0
X#define MAXNAME 80
X
Xextern int errno;
X
Xchar printfailed[] = "Couldn't connect to printer\r\n";
Xint done = 0,closed =1,opened = 0;
Xstatic char **files;
Xstatic int nfiles = 0;
Xstruct generic *gn, *open_generic();
Xchar next = '\0';
Xint opt[] = {0,0,0,0 };
Xint skip = 0;
Xchar *default_printer = "otto";
X
Xvoid prt_dir();
Xvoid prt_file();
Xvoid print_file();
X
Xvoid
Xpout(gn,bp,cnt)
Xstruct generic *gn;
Xstruct mbuf *bp;
Xint16 cnt;
X{
X int c;
X FILE *fd;
X char *cp;
X
X cp = bp->data;
X
X if ((fd = (FILE *)gn->user) == NULLFILE) {
X if (closed == YES) exit(1);
X else return;
X }
X
X while (cnt != 0) {
X /* while there is buffer space get characters */
X if ((c = getc(fd)) == EOF) {
X /* done current file - flush page */
X *cp++ = PAGEFEED;
X bp->cnt++;
X cnt--;
X /* check for more files */
X done = 1;
X gn->user = (int *)NULLFILE;
X return;
X } else {
X *cp++ = c;
X bp->cnt++;
X cnt--;
X }
X }
X}
X
Xpsend() {
X char *buf[BUFSIZ];
X struct mbuf *bp, *qdata();
X FILE *fd;
X int cnt;
X
X if ((fd = (FILE *)gn->user) == NULLFILE) {
X if (closed == YES) exit(1);
X else return;
X }
X
X if ((cnt = sizeof(char)*fread(buf,sizeof(char),BUFSIZ,fd)) != 0) {
X bp = qdata(buf,(int16)cnt);
X send_tcp((struct tcb *)gn->tcb,bp);
X }
X
X}
X
X/* State change upcall routine */
Xvoid
Xpstate(gn,new)
Xstruct generic *gn;
Xchar new;
X{
X /* Only interested if connection has been closed */
X switch (new) {
X#ifdef DEBUG
X case LISTEN: printf("\nlistening\n");break;
X case SYN_SENT: printf("\nsyn sent\n"); break;
X case SYN_RECEIVED: printf("\nsyn received\n"); break;
X#endif DEBUG
X case ESTABLISHED:
X printf("connected\n");
X opened = YES;
X break;
X case CLOSED:
X closed = 1;
X#ifdef DEBUG
X printf("Debug: closed\n");
X#endif DEBUG
X break;
X default:
X#ifdef DEBUG
X printf("pstate, default : new = %d\n",new);
X#endif DEBUG
X break;
X }
X}
X
Xpopen(char *prtname) {
X /* open a connection to the printer */
X gn = open_generic(NULLPORT,PRINTER_PORT,prtname,NULLVFP,pout,pstate);
X if (gn == NULLGN) {
X printf("Couldn't connect to printer %s\n", prtname);
X exit(1);
X }
X printf("Opening connection to printer %s ...",prtname);
X fflush(stdout);
X opened = NO;
X closed = NO;
X while(opened == NO && closed == NO) ;
X if (closed == YES) exit(1);
X
X}
X
Xpclose() {
X
X if (closed == YES) return;
X
X close_generic(gn);
X
X printf("Done: Waiting to close connection to printer\n");
X fflush(stdout);
X
X while(closed == NO) ;
X
X}
X
Xvoid
Xprint_file(char *f){
X
X char dr[MAXDRIVE],dir[MAXDIR],fn[MAXFILE],fe[MAXEXT],dum[MAXPATH+5];
X int done;
X struct ffblk ffblk;
X
X fnsplit(f,dr,dir,fn,fe);
X
X#define FERR "ERROR: Path or file name = %s not found\n"
X
X done = findfirst(f,&ffblk,FA_DIREC);
X if (done && (errno == ENOENT) && (!opt[1])) {
X printf(FERR,f);
X }
X
X while (!done) {
X fnsplit(ffblk.ff_name,dum,dum,fn,fe);
X fnmerge(dum,dr,dir,fn,fe);
X if (ffblk.ff_attrib & FA_DIREC) {
X prt_dir(dum,ffblk.ff_name);
X } else {
X prt_file(dum);
X }
X done = findnext(&ffblk);
X }
X}
X
Xvoid
Xprt_file(char *fn)
X{
X char c;
X FILE *file;
X
X /* Make sure we have the printer */
X if (closed == YES) popen(default_printer);
X
X if (fn == NULL) {
X file = stdin;
X } else {
X /* Do we want to print this file */
X if (opt[1]) {
X printf("print %s (y/n) ?",fn); fflush(stdout);
X while (((c=getch()) != 'y') && (c != 'n'));
X printf("%c\n",c); fflush(stdout);
X } else c = 'y';
X if (c != 'y') return; /* Don't print this file */
X if ((file = fopen(fn,"r")) == NULL) {
X if (!opt[3]) {
X printf("Couldn't open %s\n",fn);
X exit(1);
X }
X }
X }
X
X gn->user = (int *)file;
X if (fn != NULL) printf("Printing file: %s ...",fn);
X fflush(stdout);
X psend();
X while (!done) ;
X done = 0;
X if (fn != NULL) {
X printf(" \n");
X fclose(file);
X }
X}
X
Xvoid
Xprt_dir(char *f, char *fn){
X
X int c;
X char *temp;
X void print_file();
X
X if (!strcmp(fn,".")) return;
X if (!strcmp(fn,"..")) return;
X
X if (!opt[2]) {
X if (!opt[3]) {
X printf("%s is a directory, print anyway (y/n) ?",f);
X while (((c=getch()) != 'y') && (c != 'n'));
X printf("%c\n",c);
X } else c = 'y';
X } else c = 'y';
X if (c == 'y') {
X c = strlen(f);
X strcat(f,"\\*.*");
X print_file(f);
X f[c] = NULLCHAR;
X }
X
X}
X
Xparseopt(char *f) {
X
X if ((*f == '-') && (!skip)) {
X if (*(++f) == NULLCHAR) {
X skip = 1;
X } else while (*f != NULLCHAR) {
X switch(*f) {
X case '?': usage('?');
X case 'p':
X if (*++f == NULLCHAR) {
X next = 'p';
X } else {
X if (closed == NO) pclose();
X popen(f);
X }
X return;
X case 'i':opt[0] = 1;opt[1] = 1;break;
X case 'r':opt[0] = 2;opt[2] = 1;break;
X case 'f':opt[0] = 3;opt[3] = 1;break;
X case '-':opt[opt[0]] = 0;opt[0] = 0;break;
X default: if (!opt[1]) usage(*f);
X }
X f++;
X }
X } else {
X if (next) {
X switch(next) {
X case 'p':
X if (closed == NO) pclose();
X popen(f);
X default:
X }
X next = 0;
X } else {
X nfiles++;
X print_file(f);
X }
X }
X}
X
Xusage(char c) {
X if (c != '?') printf("Unknown option : \"%c\n\"",c);
X printf("Usage:eprint [-?] [-p] [-i[-]] [-] \n");
X printf("\t-?\tPrint this message\n");
X printf("\t-i[-]\tQuery every file\n");
X printf("\t-r[-]\tRecursively print contents of directories\n");
X/* printf("\t-f[-]\tPrint quietly\n");*/
X printf("\t-\tUse next argument as a file name\n");
X printf("\t-p \t Printer to use\n");
X printf("\t\t\t\t Default printer is %s\n",default_printer);
X printf("\t\t files to print. No files => use stdin\n");
X printf("\nv%s (c) Princeton LCA\n",VERSION);
X exit(0);
X}
X
Xmain (int argc, char *argv[]) {
X
X char *f,*prtopt;
X int i;
X
X (void)remove_cbrk(NULLVFP); /* NEVER use ^C with the net BAD */
X prtopt = getenv("PRTOPT");
X for (f = strtok(prtopt," ");f != NULL; f = strtok(NULL," ")) {
X parseopt(f);
X }
X
X for (i = 1; i < argc; i++) {
X f = argv[i];
X parseopt(f);
X }
X if (!nfiles) {
X parseopt("-i-"); /* turn off interactive mode */
X prt_file(NULL);
X }
X pclose();
X}
X
END_OF_EPRINT.C
echo shar: Missing newline added to \"EPRINT.C\"
if test 6794 -ne `wc -c EPRINT.DOC <<'END_OF_EPRINT.DOC'
XNAME
X eprint - print files over the ethernet.
X
XVERSION
X 2.0 July 1988
X
XSYNOPSIS
X eprint [-?] [-ri[-]] [-pprintername]
X
XDESCIRPTION
X Eprint prints named files or directories. Unless the '-r' option is
X specified it asks before printing directories. Options can be stacked
X and can turned off and on for selective portions of the command line
X using the turn on/off feature
X
X Eprint depends links in all the TCP/IP routines from the KA9Q package
X that it needs and is standalone. It however requires a file called
X "system.rc" to be located in the root directory in order to resolve
X host names and certain other TCP/IP setup information. The contents
X of the "system.rc" file are similar to the "autoexec.net" file
X in the KA9Q TCP/IP package.
X
X An evironment variable lookup is available. Set the environment
X variable "PRTOPT" from DOS to your favourite settings.The DOS command:
X set PRTOPT=arguments
X will set the environment string to the arguments, which are exactly
X like those by the command itself (including filenames). First the
X environment options are evaluated, filenames given there are printed
X and then the usual command string is parsed. A typical use would be
X to put the following command in the autoexec.bat file
X
X set PRTOPT=-i
X
X A generic option line would look like:
X
X eprint options files option- files option2- files option files
X
X The options apply to files following the options and can be turned
X off by using '-' after the option (see examples).
X
X
X -? Give a short usage note.
X
X -r[-] Print directories recursively. If a directory is encountered
X it is printed and all its contents (including subdirectories)
X are printed. '-r' turns the option on and '-r-' turns the
X option off.
X
X -i[-] Print interactively. Queries before printing every file.
X '-i' turns the option on and '-i-' turns the option off.
X
X -[-] Use the next argument as a filename. This is to allow use
X of file names which begin with a '-'. '-' turns the option
X on and '--' turns the option off (can't think of any use of
X '--' since it is a noop!).
X
X Names of files to be printed. Wild cards are allowed. For
X names begining with '-' see option '-'. Directories are
X not deleted unless '-r' option is specified. NOTE: If no
X file name is specified the standard input is used. However
X since it does not about EOF's from the keyboard (^D or ^Z)
X this is useful only for pipes and redirected output.
X
XEXAMPLES
X All examples assume that PRTOPT is not set to anything.
X
X eprint a *.opt
X will print the file "a" and all files "*.opt". Directories will not
X be printed.
X
X eprint -r dirname
X will print "dirname" even if it is a directory.
X
X eprint -r dirs1 -r- dirs2
X will print "dirs1" even if it is a directory but will not print
X "dirs2" if it is a directory. The option '-r-' is read as follows
X '-' + 'r-' => option symbol + don't print directories
X
X eprint - -r
X will print a file "-r". Note here because of the '-' option "-r"
X is used as a filename rather than as an option.
X
XNOTES
X The option on/off feature is not available in Unix(tm).
X The environment option is not available in Unix(tm).
X This version fixes a bug in v1.00 :
X When a nonexistent single file was asked to be deleted
X the program correctly found there was no file but then
X tried to delete the file as if it were read-only.
X This version fixes a bug in v1.10 :
X When a multiple directory deletion was attempted the
X entire disk was wiped out.
X
XBUGS
X 1. ^C does not work. It may abort the program but will not
X reset interrupt vectors and so should not be used. It is
X an inherent problem with the KA9Q TCP/IP package.
X 2. When the amount of data to be printed is a lot and the
X printer buffer is full then sometimes the program will
X hang. This is because typically when the printer is
X processing data it does not reply to queries and causes
X it's own TCP/IP to time out while the eprint program
X does not know this and so it keeps tyring (since it started
X the whole thing). One way around is not to use the collated
X mode. This bug has been seen on the Imagen 2308 printer using
X v3.2 TCP/IP software.
X Notify all bugs to Q3696@PUCC.BITNET or
X {seismo, rutgers}\!princeton\!phoenix\!asjoshi.
X
XACKNOWLEDGEMENTS
X The program was written using Turbo C v1.5. The command is based on
X the idea of "iprint", a very basic ethernet printer driver for
X imagen printers available in binary with the MIT TCP/IP package.
X This version has been written using the KA9Q TCP/IP package.
X The program and this manual page are completly written by me.
X Thanks go to Phil Karn for the great TCP/IP package and very
X readable code.
X Thanks also to Borland for the inexpensive, fast C compiler.
X Thanks to Dennis Linse for pointing some serious shortcomings
X in v1.1.
END_OF_EPRINT.DOC
if test 4833 -ne `wc -c EPRINT.SH <<'END_OF_EPRINT.SH'
END_OF_EPRINT.SH
if test 0 -ne `wc -c GENERIC.C <<'END_OF_GENERIC.C'
X/* Main network program - provides both client and server functions */
X#ifdef TURBOC /* The length of the command line causes problems */
X#include "tcdefs.h"
X#endif
X#ifndef CLEAN
X#define NSESSIONS 10 /* Maximum interactive client sessions */
X#endif
X#ifndef STARTUP
X#define STARTUP "/system.rc" /* File to read startup commands from */
X#endif
X
X#ifdef TURBOC
X#include
X#include
X#endif
X
X#include
X#include "generic.h"
X
Xextern struct interface *ifaces;
Xextern char major_rev[], minor_rev[];
Xextern struct mbuf *loopq;
X
Xint mode;
XFILE *logfp;
Xchar badhost[] = "Unknown host %s\r\n";
Xint32 gateway;
X
X#ifdef TRACE
X#include "trace.h"
Xint32 trace;
X#endif
X
X/* Command lookup and branch table */
Xint doipaddr(),doexit(),dohostname(),
X dowindow(),doroute(),
X domss(),doattach(),
X dottl(),go(),
X dogateway();
X
Xstatic struct cmds cmds[] = {
X /* The "go" command must be first */
X "", go, 0, NULLCHAR, NULLCHAR,
X "attach", doattach, 2,
X "attach ", NULLCHAR,
X "exit", doexit, 0, NULLCHAR, NULLCHAR,
X "gateway", dogateway, 0, NULLCHAR, NULLCHAR,
X "hostname", dohostname, 0, NULLCHAR, NULLCHAR,
X "ipaddr", doipaddr, 0, NULLCHAR, NULLCHAR,
X "mss", domss, 0, NULLCHAR, NULLCHAR,
X "route", doroute, 0, NULLCHAR, NULLCHAR,
X "ttl", dottl, 0, NULLCHAR, NULLCHAR,
X "window", dowindow, 0, NULLCHAR, NULLCHAR,
X NULLCHAR, NULLFP, 0,
X "Unknown command; type \"?\" for list", NULLCHAR,
X};
X
Xchar hostname[HOSTNAMELEN];
Xint32 resolve();
Xint16 lportavail = 1001;
Xchar net_inited = 0;
Xchar prompt[] = "net> ";
Xchar nospace[] = "No space!!\r\n"; /* Generic malloc fail message */
Xchar notval[] = "Not a valid TCB\r\n";
Xchar finished = 0,wait_to_close = 0;
Xstruct generic *session;
X
Xstruct generic *
Xopen_generic(lport,fport,fhost,in,out,state)
Xint16 lport,fport; /* local and foreign ports */
Xchar *fhost; /* foreign host name */
Xvoid (*in)(); /* called when ready to process data */
Xvoid (*out)(); /* called when ready to send data */
Xvoid (*state)(); /* called when state changes */
X{
X void g_state(),grcv_char(),gsend_char();
X char *inet_ntoa();
X#ifdef TURBOC
X void *calloc(),*malloc();
X#else
X char *calloc(),*malloc();
X#endif
X int32 resolve();
X struct generic *gn;
X struct tcb *tcb;
X struct socket lsocket,fsocket;
X
X if (!net_inited)
X if (net_init())
X return NULLGN;
X
X lsocket.address = ip_addr;
X if (lport == NULLPORT) lsocket.port = lportavail++;
X else lsocket.port = lport;
X if ((fsocket.address = resolve(fhost)) == 0) {
X printf(badhost,fhost);
X return NULLGN;
X }
X
X if (fport == NULLPORT) {
X printf("badport %d",fport);
X return NULLGN;
X } else fsocket.port = fport;
X
X /* Allocate a session descriptor */
X if((gn = (struct generic *)calloc(1,sizeof(struct generic))) == NULLGN){
X printf(nospace);
X return NULLGN;
X }
X gn->in = in;
X gn->out = out;
X gn->state = state;
X
X tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,0,
X grcv_char,gsend_char,g_state,0,(int *)gn);
X gn->tcb = tcb;
X session = gn;
X return gn;
X}
X
Xint
Xclose_generic(gn)
Xstruct generic *gn;
X{
X if (gn != NULLGN)
X close_tcp(gn->tcb);
X}
X
Xint
Xsend_generic(gn,bp)
Xstruct generic *gn;
Xstruct mbuf *bp;
X{
X if (gn != NULLGN)
X if (gn->tcb != NULLTCB)
X send_tcp(gn->tcb,bp);
X}
X
X/* Generic receiver upcall routine */
Xvoid
Xgrcv_char(tcb,cnt)
Xregister struct tcb *tcb;
Xint16 cnt;
X{
X struct mbuf *bp;
X struct generic *gn;
X
X if((gn = (struct generic *)tcb->user) == NULLGN){
X /* Unknown connection; ignore it */
X return;
X }
X
X if(recv_tcp(tcb,&bp,cnt) > 0)
X if (gn->in != NULLVFP) gn->in(gn,bp,cnt);
X}
X
X/* State change upcall routine */
Xvoid
Xg_state(tcb,old,new)
Xregister struct tcb *tcb;
Xchar old,new;
X{
X struct generic *gn;
X char notify = 0;
X extern char *tcpstates[];
X extern char *reasons[];
X extern char *unreach[];
X extern char *exceed[];
X void (*state)();
X
X /* Can't add a check for unknown connection here, it would loop
X * on a close upcall! We're just careful later on.
X */
X gn = (struct generic *)tcb->user;
X if ((state = gn->state) != NULLVFP) notify = 1;
X
X switch(new){
X case CLOSE_WAIT:
X close_tcp(tcb);
X break;
X case CLOSED: /* court adjourned */
X if(tcb->reason == NETWORK){
X printf("%s (%s",tcpstates[new],reasons[tcb->reason]);
X switch(tcb->type){
X case DEST_UNREACH:
X printf(": %s unreachable",unreach[tcb->code]);
X break;
X case TIME_EXCEED:
X printf(": %s time exceeded",exceed[tcb->code]);
X break;
X }
X printf(")\r\n");
X fflush(stdout);
X }
X del_tcp(tcb);
X if(gn != NULLGN)
X free_generic(gn);
X break;
X default:
X break;
X }
X if(notify) state(gn,new);
X}
X
X/* Delete generic structure */
Xstatic
Xfree_generic(gn)
Xstruct generic *gn;
X{
X if(gn != NULLGN) {
X free((char *)gn);
X }
X}
X
Xvoid
Xgsend_char(tcb,cnt)
Xstruct tcb *tcb;
Xint16 cnt;
X{
X struct generic *gn;
X struct mbuf *bp;
X char *cp;
X int c;
X
X if ((gn = (struct generic *)tcb->user) == NULLGN) {
X /* Unknown connection */
X return;
X }
X
X if ((bp = alloc_mbuf(cnt)) == NULLBUF) {
X /* just don't do a thing here */
X return;
X }
X
X if (gn->out != NULLVFP)
X gn->out(gn,bp,cnt);
X
X if(bp->cnt != 0)
X send_tcp(tcb,bp);
X else
X free_p(bp);
X}
X
Xint
Xnet_init()
X{
X static char inbuf[BUFSIZ]; /* keep it off the stack */
X int cmdparse();
X FILE *fp;
X struct mbuf *bp;
X
X#ifdef TURBOC
X#define INITERR "Can't initialize network: %s\n"
X void c_break(); /* clean up on system abort */
X void net_exit(); /* clean up on exit */
X void net_service(); /* net background service routine */
X
X#if (INSTALL_TIMER != 0)
X if (install_timer(net_service)) {
X printf(INITERR, "can't install timer");
X return 1;
X }
X#endif INSTALL_TIMER
X if (install_cbrk(c_break)) {
X printf(INITERR,"can't install ctrl brk function");
X return 1;
X }
X if (atexit(net_exit)) {
X printf(INITERR,"too many exit functions\n");
X return 1;
X }
X#endif TURBOC
X ioinit();
X if((fp = fopen(STARTUP,"r")) != NULLFILE){
X while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
X cmdparse(cmds,inbuf);
X }
X fclose(fp);
X }
X net_inited = 1;
X return 0;
X}
X
X/* Clean up everthing before exiting or else pay the price */
Xvoid
Xnet_exit() {
X net_inited = 0; /* I'm pessimistic */
X iostop(0);
X}
X
Xvoid
Xnet_service() {
X static int n_ticks = 0;
X struct mbuf *bp;
X struct interface *ifp;
X
X#if (INSTALL_TIMER != 0)
X /* Service net every INSTALL_TIMER ticks to avoid */
X /* DOS stack failiures */
X if (n_ticks++ <= INSTALL_TIMER) return; else n_ticks = 0;
X#endif INSTALL_TIMER
X
X /* Service the loopback queue */
X while((bp = dequeue(&loopq)) != NULLBUF)
X ip_recv(bp,0);
X
X /* Service the interfaces */
X for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){
X if(ifp->recv != NULLFP)
X (*ifp->recv)(ifp);
X }
X
X grcv_char(session->tcb,0); /* get any pending input */
X
X /* Service the clock if it has ticked */
X check_time();
X}
X
Xgo(){} /* This needed by the command parser routine! */
X
X#ifdef TURBOC
Xvoid
Xc_break(void)
X{
X fprintf(stderr,"Aborting : wait for cleanup ...\n");
X net_inited = 0;
X iostop(1); /* clean up dos only */
X}
X#endif
X
X
Xstatic
Xdogateway(argc,argv)
Xint argc;
Xchar *argv[];
X{
X char *inet_ntoa();
X int32 n;
X
X if(argc < 2){
X printf("%s\r\n",inet_ntoa(gateway));
X } else if((n = resolve(argv[1])) == 0){
X printf(badhost,argv[1]);
X return 1;
X } else
X gateway = n;
X return 0;
X}
Xstatic
Xdoexit(argc,argv)
Xint argc;
Xchar *argv[];
X{
X iostop();
X exit(0);
X}
Xstatic
Xdohostname(argc,argv)
Xint argc;
Xchar *argv[];
X{
X char *strncpy();
X
X if(argc < 2)
X printf("%s\r\n",hostname);
X else
X strncpy(hostname,argv[1],HOSTNAMELEN);
X return 0;
X}
X/* List of supported hardware devices */
Xint ec_attach();
X
Xstruct cmds attab[] = {
X#ifdef PC_EC
X /* 3-Com Ethernet interface */
X "3c500", ec_attach, 7,
X "attach 3c500 arpa