home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / NCSATELN / TEL23SRC.ZIP / NET / ENET / BICC.DRI < prev    next >
Encoding:
Text File  |  1990-12-11  |  40.6 KB  |  1,086 lines

  1. This is some code that interfaces NCSA Telnet 2.2 with Microsoft C
  2. extentions, as provided by Jyrki Kuoppala, with the BICC ISOLAN
  3. 411x cards.
  4.  
  5. Instead of taking over the whole card, the port is made to work through
  6. the BICC Multi Protocol Software, enabling NCSA Telnet TCP/IP to
  7. coexist with other network protocols, like Novells IPX.
  8.  
  9. This port was initially made for the Institute of Social Research and
  10. the Institute of Applied Social Research for use on their Novell net,
  11. but since others might have interrest in this, I decided to put it on
  12. the net. The port has been in heavy use since the late spring of 1989
  13. and should be fairly good. No known bugs at this point, but the code 
  14. still has a flavour of an easy hack (it has not been changed due to
  15. the good proverb : "If it ain't broke, don't fix it"). The code has
  16. been written in a way so as if to make as few and as small changes to
  17. NCSA TELNET as possible. The program has been run towards a HP9000/825
  18. and a Interactive 386/ix.
  19.  
  20. Regarding the ownership of this code, it's still the authors property
  21. and will remain so even after the code has been posted to the net.
  22. But, the code can be used freely, as long as it's not being used
  23. commersially and all changes to the code are reported to me, so I can
  24. update and maintain this program. If somebody wants to use this code
  25. in commersial programs or put them under another licence, I must be
  26. consulted first. I'm not really opposed to this, but I won't let
  27. anybody change the copyright as they please. Please note that this code
  28. IS NOT A PART OF NCSA TELNET. If some people at NCSA finds it 
  29. interresting, it might be at some point. This is written to indicate that
  30. neither NCSA nor I would commit ourselves to supporting this port in
  31. the future. But, when 2.3 appears, I will do my best to make this port
  32. work there as well.
  33.  
  34. The port consists of two new files, ISO.C and MULTI.ASM which together
  35. make up the BICC support. I have also included PCTOOLS.C to show how
  36. the BICC support is wedged into NCSA TELNET (I assume I've done it the
  37. normal way). This program must be compiled with the symbol ISOLAN 
  38. defined (all changes to the original code is #ifdef'ed). I've also
  39. included the updated MAKEFILE, adapted to MS C by Jyrki Kuoppala and
  40. changed by me to support the BICC port. I've used Microsoft C 5.1 for
  41. the port, but I believe I've kept ANSI-specific stuff out of it, so
  42. earlier versions should be able to compile it with few or no 
  43. alterations.
  44.  
  45. BTW: I've also rewritten the 3COM 501 driver for NCSA in C to make it
  46. easier to understand and maintain. With my crude tests, I cannot find
  47. any notable changes in speed, but the tests were done on an PC AT and
  48. maybe speed problems would be more appearant on a plain 4.77 MHz PC.
  49. I would suggest that drivers should, as long as speed allows it, be
  50. written in C, since this would also enhance portability of the drivers
  51. themselves and maybe the system as a whole.
  52.  
  53. Please mail all questions and comments to: ingea@ifi.uio.no
  54. or during holydays to:  inge%beatnix@ifi.uio.no
  55.  
  56. Happy hacking!
  57.  
  58.    Inge Arnesen, University of Oslo, Norway
  59.  
  60. #! /bin/sh
  61. # This is a shell archive, meaning:
  62. # 1. Remove everything above the #! /bin/sh line.
  63. # 2. Save the resulting text in a file.
  64. # 3. Execute the file with /bin/sh (not csh) to create the files:
  65. #    iso.c
  66. #    multi.asm
  67. #    pctools.c
  68. #    makefile
  69. # This archive created: Wed Jan 17 14:14:32 1990
  70. export PATH; PATH=/bin:$PATH
  71. echo shar: extracting "'iso.c'" '(15525 characters)'
  72. if test -f 'iso.c'
  73. then
  74.     echo shar: will not over-write existing file "'iso.c'"
  75. else
  76. sed 's/^    X//' << \SHAR_EOF > 'iso.c'
  77.     X/****************************************************************************
  78.     X *  BICC 411x Multi Protocol Software code                                  *
  79.     X *  Inge Arnesen 1989                                                       *
  80.     X *                                                                          *
  81.     X *  Module to interface NCSA Telnet to the BICC 411x cards through the      *
  82.     X *  ISOLAN Multi Protocol Software. This enables NCSA Telnet to coexist     *
  83.     X *  with Novell Netware.                                                    *
  84.     X *                                                                          *
  85.     X *  THIS IS NOT A PART OF NCSA TELNET                                       *
  86.     X *                                                                          *
  87.     X ****************************************************************************
  88.     X *                                                                          *
  89.     X *                                                                          *
  90.     X *      (C) Inge Arnesen                                                    *
  91.     X *      Institute of Social Research                                        *
  92.     X *      Munthesgt. 31                                                       *
  93.     X *      N-0260 Oslo, NORWAY                                                 *
  94.     X *                                                                          *
  95.     X *                                                                          *
  96.     X *    DISCLAIMER: This code is not property of the institute, but of        *
  97.     X *                the author himself. No responsibility is claimed          *
  98.     X *                for anything whatsoever due to the use of this code!      *
  99.     X *                                                                          *
  100.     X ****************************************************************************
  101.     X *                                                                          *
  102.     X *    Created      : 89.05.27  by Inge Arnesen                              *
  103.     X *    Last modified: 89.05.29  by Inge Arnesen                              *
  104.     X *                                                                          *
  105.     X *    History: 89.05.29 Initial alpha version                               *
  106.     X *             89.07.01 Beta started - no changes                           *
  107.     X *             89.10.06 Final release - no changes                          *
  108.     X *                                                                          *
  109.     X ****************************************************************************
  110.     X
  111.     X        ILrecv          - Polled receive (dummy)
  112.     X        ILetopen        - Initialize Ethernet SW
  113.     X        ILetclose       - Close down Ethernet SW
  114.     X        ILgetaddr       - Get Ethernet cards address (must be initialized first)
  115.     X        ILetaddr        - Set Ethernet cards address (dummy)
  116.     X        ILxmit          - Send data across the Ethernet
  117.     X        ILetupdate      - Update buffer pointers
  118.     X
  119.     X
  120.     X        COMPILE:
  121.     X                cl -Ze -Zp -Gs iso.c
  122.     X        Options are:    Enable language extentions, pack structure members,
  123.     X                        Remove calls to Stack probe routine
  124.     X
  125.     X */
  126.     X/* Standard include files */
  127.     X#include        <conio.h>       /* Microsoft 'C' Include file   */
  128.     X#include        <ctype.h>       /* Microsoft 'C' Include file   */
  129.     X#include        <dos.h>         /* Microsoft 'C' Include file   */
  130.     X#include        <stdio.h>       /* Microsoft 'C' Include file   */
  131.     X#include        <string.h>      /* Microsoft 'C' Include file   */
  132.     X
  133.     X/* NCSA include files */
  134.     X#include        "protocol.h"
  135.     X#include        "data.h"
  136.     X
  137.     X/*
  138.     X *      Command codes for ISOLAN MPS SW
  139.     X */
  140.     X
  141.     X#define STATUS                  0xB3    /* XPORT & SFB */
  142.     X
  143.     X#define FAST_TIMER              0xF0    /* XPORT & SFB */
  144.     X#define L_ACTIVATE              0xF2    /* XPORT & SFB */
  145.     X#define L_DEACTIVATE            0xF3    /* XPORT & SFB */
  146.     X#define L_DATA_SEND             0xF4    /* XPORT & SFB */
  147.     X#define M_ACTIVATE              0xFA    /* XPORT & SFB */
  148.     X#define M_DEACTIVATE            0xFB    /* XPORT & SFB */
  149.     X
  150.     X#define L_ACTIVATE_CONF         0x03    /* Returned Event Code */
  151.     X#define L_DEACTIVATE_CONF       0x05    /* Returned Event Code */
  152.     X#define L_DATA_IND              0x08    /* Returned Event Code, LLC Data */
  153.     X#define M_DATA_IND              0x0a    /* Returned Event Code, Blue Book MAC Data */
  154.     X#define M_ACTIVATE_CONF         0x12    /* Returned Event Code */
  155.     X#define M_DEACTIVATE_CONF       0x14    /* Returned Event Code */
  156.     X
  157.     X#define FALSE                   0
  158.     X#define TRUE                    1
  159.     X
  160.     X#define BUF_SIZE                1504
  161.     X#define MAX_VC                  32
  162.     X
  163.     X
  164.     X/*
  165.     X *      DATA STRUCTURES
  166.     X */
  167.     X
  168.     Xunion adr_ptr
  169.     X{
  170.     X        char    far *pt;
  171.     X        struct  
  172.     X        {
  173.     X                unsigned short  start_type;
  174.     X                unsigned short  end_type;
  175.     X        } type;
  176.     X        struct mps_status *status;
  177.     X};
  178.     X
  179.     Xstruct tcb         /* Transfer Control Block */
  180.     X{
  181.     X        unsigned char   tcbcommand;     /* command code                         */
  182.     X        unsigned char   tcbcid;         /* command identity                     */
  183.     X        unsigned char   tcbvcid;        /* virtual circuit id                   */
  184.     X        unsigned short  tcblength;      /* buffer length                        */
  185.     X        union adr_ptr   tcbbaddr;       /* address of data                      */
  186.     X        unsigned char   tcbexpedited;   /* expedited data flag                  */
  187.     X        unsigned char   tcbcancelable;  /* cancelable flag                      */
  188.     X        unsigned char   tcbladdr[16];   /* local network address                */
  189.     X        unsigned char   tcbraddr[16];   /* remote address                       */
  190.     X        unsigned short  (far *tcbasync)(); /* address of async notification routine*/
  191.     X        unsigned long   tcblnet;        /* local network number                 */
  192.     X        unsigned long   tcbrnet;        /* remote network number                */
  193.     X        unsigned char   tcbrto;         /* call timeout                         */
  194.     X        unsigned char   tcbsto;         /* not used                             */
  195.     X        unsigned char   tcbres2[8];     /* reserved                             */
  196.     X        unsigned char   tcbcmdex;       /* command code extension               */
  197.     X        unsigned short  tcbstatus;      /* Blue Book MAC type                   */
  198.     X};
  199.     X
  200.     X
  201.     Xstruct acb              /* Asynchronous Control Block */
  202.     X{
  203.     X        unsigned char   acbcid;         /* return cid from TCB          */
  204.     X        unsigned char   acbvcid;        /* return vcid from TCB         */
  205.     X        unsigned char   acberr;         /* error code                   */
  206.     X        unsigned char   acbcmd;         /* return command from TCB      */
  207.     X        unsigned short  acblen;         /* actual length of message     */
  208.     X        unsigned char   acbraddr[16];   /* remote network address       */
  209.     X        unsigned long   acbrnet;        /* remote network number        */
  210.     X        unsigned char   acbladdr[16];   /* local network address        */
  211.     X        unsigned long   acblnet;        /* local network number         */
  212.     X        unsigned short  acbstatus;      /* Blue Book MAC type           */
  213.     X        unsigned char   acbeventcode;   /* copy of board event code     */
  214.     X        union adr_ptr   acbbaddr;       /* address of data              */
  215.     X        unsigned char   acbexpedited;   /* expedited data flag          */
  216.     X};
  217.     X
  218.     Xstruct recany_rec               /* receive any record */
  219.     X{
  220.     X        unsigned char   recany_count;   
  221.     X        unsigned char   recany_list[MAX_VC];
  222.     X};
  223.     X
  224.     X
  225.     Xstruct mps_status       
  226.     X{
  227.     X        unsigned char address[16];
  228.     X        unsigned long network;
  229.     X        unsigned char status;
  230.     X        unsigned char version;
  231.     X        unsigned int  maxcon;
  232.     X        unsigned int  maxcom;
  233.     X        unsigned long pack_sent;
  234.     X        unsigned long pack_rec;
  235.     X        unsigned int  pack_lost;
  236.     X        unsigned int  pack_abort;
  237.     X        unsigned int  pack_frame;
  238.     X        unsigned int  pack_crc;
  239.     X        unsigned char address_mask[16];
  240.     X        unsigned int  board_segment;
  241.     X        unsigned int  board_offset;
  242.     X        unsigned int  gen_tsel;
  243.     X        unsigned int  broad_tsel;
  244.     X        unsigned char reserved[0x3e];
  245.     X};
  246.     X
  247.     Xextern void ANR_ENTRY();
  248.     Xunsigned int anr_c();
  249.     Xstruct mps_status stat_buf;
  250.     X
  251.     X
  252.     Xextern unsigned char rstat;             /*  last status from read               */
  253.     Xextern unsigned char *bufpt;            /*  current buffer pointer              */
  254.     Xextern unsigned char *buforg;           /*  pointer to beginning of buffer      */
  255.     Xextern unsigned char *bufend;           /*  pointer to end of buffer            */
  256.     Xextern unsigned char *bufread;          /*  pointer to where program is reading */
  257.     Xextern unsigned int bufbig;             /*  integer, how many bytes we have     */
  258.     Xextern unsigned int buflim;             /*  integer, max bytes we can have      */
  259.     X
  260.     X
  261.     XILgetaddr(ethaddr, memaddr, ioaddr)
  262.     Xunsigned char ethaddr[DADDLEN];
  263.     Xunsigned int memaddr, ioaddr;
  264.     X{
  265.     X        int i; 
  266.     X        struct tcb t, *h;
  267.     X        union REGS inregs, outregs;
  268.     X        struct SREGS segregs;
  269.     X
  270.     X        /* Then send status request */
  271.     X        t.tcbcommand = STATUS;
  272.     X        t.tcbcid = STATUS;
  273.     X        t.tcbbaddr.status= &stat_buf;
  274.     X        t.tcblength    = sizeof(struct mps_status);
  275.     X        t.tcblnet= 0xffffffff;
  276.     X
  277.     X        t.tcbasync= (void *)ANR_ENTRY;
  278.     X
  279.     X        /*
  280.     X         *      now issue the int5b, es:bx point at the tcb
  281.     X         *
  282.     X         */
  283.     X        h= &t; 
  284.     X        segregs.es= FP_SEG(h);
  285.     X        inregs.x.bx= FP_OFF(h);
  286.     X        int86x(0x5B, &inregs, &outregs, &segregs);
  287.     X
  288.     X        for (i= 9; i < 15; i++)
  289.     X                ethaddr[i - 9]= stat_buf.address[i];
  290.     X}
  291.     X
  292.     XILrecv()
  293.     X{
  294.     X}
  295.     X
  296.     XILetupdate()
  297.     X{
  298.     X        /* Update all the pointers etc. */
  299.     X        bufbig-= *((int *)bufread) + sizeof( int );
  300.     X        bufread+= *((int *)bufread) + sizeof(int);
  301.     X        if(bufread >= bufend)
  302.     X                bufread= buforg;
  303.     X}
  304.     X
  305.     X
  306.     X
  307.     Xint ILxmit(pack, size)
  308.     XDLAYER *pack;
  309.     Xint size;
  310.     X{
  311.     X        struct tcb t, *h;               
  312.     X        int i;
  313.     X        union REGS inregs, outregs;
  314.     X        struct SREGS segregs;
  315.     X
  316.     X        t.tcbraddr[2] = 0;
  317.     X        t.tcbraddr[3] = 0;
  318.     X        t.tcbraddr[7] = 0;
  319.     X        t.tcbraddr[8] = 0;   /* LSAP */
  320.     X        t.tcbraddr[9] = pack->dest[0];     /* ETHADDR */
  321.     X        t.tcbraddr[10] = pack->dest[1];
  322.     X        t.tcbraddr[11] = pack->dest[2];
  323.     X        t.tcbraddr[12] = pack->dest[3];
  324.     X        t.tcbraddr[13] = pack->dest[4];
  325.     X        t.tcbraddr[14] = pack->dest[5];      /*--to here--*/
  326.     X        t.tcbraddr[15] = 0;
  327.     X        t.tcbcommand = L_DATA_SEND;
  328.     X
  329.     X        t.tcbstatus = intswap(pack->type);
  330.     X        for (i = 0; i < 16; ++i)
  331.     X                t.tcbladdr[i] = 0;
  332.     X
  333.     X        t.tcbasync= 0;   /* No ANR */
  334.     X
  335.     X        /*      setup pointer to data buffer    */
  336.     X        t.tcbbaddr.pt  = (char far *)pack + sizeof(DLAYER);
  337.     X        t.tcblength    = size - sizeof(DLAYER);
  338.     X        /*
  339.     X         *      now issue the int5b, es:bx point at the tcb
  340.     X         *
  341.     X         */
  342.     X        h= &t;
  343.     X        segregs.es= FP_SEG(h);
  344.     X        inregs.x.bx= FP_OFF(h);
  345.     X        int86x(0x5B, &inregs, &outregs, &segregs);
  346.     X        return(outregs.h.al);
  347.     X}
  348.     X
  349.     XILetopen(ethaddr, ioirq, memaddr, ioaddr)
  350.     Xunsigned char ethaddr[DADDLEN];
  351.     Xunsigned int memaddr, ioaddr;
  352.     X{
  353.     X        struct tcb t, *h;
  354.     X        int i;
  355.     X        union REGS inregs, outregs;
  356.     X        struct SREGS segregs;
  357.     X
  358.     X
  359.     X        t.tcbcommand = L_ACTIVATE;
  360.     X        t.tcbcid = L_ACTIVATE;
  361.     X
  362.     X        for (i = 0; i < 16; ++i)
  363.     X                t.tcbladdr[i] = 0;
  364.     X
  365.     X        t.tcbasync= (void *)ANR_ENTRY;
  366.     X
  367.     X        /*
  368.     X         *      now issue the int5b, es:bx point at the tcb
  369.     X         *
  370.     X         */
  371.     X        h= &t; 
  372.     X        segregs.es= FP_SEG(h);
  373.     X        inregs.x.bx= FP_OFF(h);
  374.     X        int86x(0x5B, &inregs, &outregs, &segregs);
  375.     X
  376.     X        return(outregs.h.al);
  377.     X}
  378.     X
  379.     XILetclose()
  380.     X{
  381.     X        union REGS inregs, outregs;
  382.     X        struct SREGS segregs;
  383.     X        struct tcb t, *h;               
  384.     X        int i;
  385.     X
  386.     X        t.tcbcommand = L_DEACTIVATE;
  387.     X        t.tcbcid = 0; /* Not used */
  388.     X
  389.     X        for (i = 0; i < 16; ++i)
  390.     X                t.tcbladdr[i] = 0;
  391.     X
  392.     X        /*
  393.     X         *      now issue the int5b, es:bx point at the tcb
  394.     X         *
  395.     X         */
  396.     X        h= &t; 
  397.     X        segregs.es= FP_SEG(h);
  398.     X        inregs.x.bx= FP_OFF(h);
  399.     X        int86x(0x5B, &inregs, &outregs, &segregs);
  400.     X        return(outregs.h.al);
  401.     X}
  402.     X
  403.     X
  404.     X/*
  405.     X *      Note: anr_c returns zero to the Multi Protocol Handler
  406.     X *
  407.     X *      Inside the ANR, Operating System calls must not be made, nor must
  408.     X *      space be grabbed from the Heap.  The use of Automatic variables
  409.     X *      is allowed, but make sure the stack is large enough.
  410.     X */
  411.     X
  412.     Xunsigned int anr_c(acb_ptr)
  413.     Xstruct  acb     *acb_ptr;
  414.     X{
  415.     X        int i;
  416.     X        int mine= TRUE;  /* We suspect all packets of coming from this card */
  417.     X                        /* Loop back is supported on link level */      
  418.     X                        /* If its mine, drop it like a hot potato */
  419.     X
  420.     X        char    far     *buffer_pt;     /* buffer pointer       */
  421.     X
  422.     X        if(acb_ptr->acbcmd != STATUS)
  423.     X        {
  424.     X                switch(acb_ptr->acbeventcode)
  425.     X                {
  426.     X                case L_ACTIVATE_CONF:
  427.     X                        break;
  428.     X                case L_DATA_IND:
  429.     X                case M_DATA_IND:
  430.     X                        /* If it is not one of mine, mark it as such */  
  431.     X                        for(i= 0; i < 6 ; i++)
  432.     X                                if(acb_ptr->acbraddr[i+9] != nnmyaddr[i])
  433.     X                                {
  434.     X                                        mine= FALSE; 
  435.     X                                        break;
  436.     X                                }       
  437.     X                        if (!mine)
  438.     X                        {
  439.     X                        /* with llc and mac commands, it's neccessary to copy   */
  440.     X                        /* the received data.                                   */
  441.     X
  442.     X                        buffer_pt = acb_ptr->acbbaddr.pt;
  443.     X                        /* The above instruction in theory should not be needed */
  444.     X                        /* but is in practise                                   */ 
  445.     X
  446.     X                        if(bufbig <= buflim) /* Enough room in the buffer ? */
  447.     X                        {
  448.     X                                if(bufpt >= bufend) /* Wrap around ? */
  449.     X                                {
  450.     X                                        bufpt= buforg;
  451.     X                                }
  452.     X                                /* Size of packet inc. DLAYER first in buffer */
  453.     X                                *((int *)bufpt)= acb_ptr->acblen + sizeof(DLAYER);
  454.     X                                bufpt+= 2;
  455.     X                                ((DLAYER *)bufpt)->type= intswap(acb_ptr->acbstatus);
  456.     X                                for(i= 0; i < 6 ; i++)
  457.     X                                {
  458.     X                                        ((DLAYER *)bufpt)->dest[i]= 
  459.     X                                                acb_ptr->acbladdr[i+9];
  460.     X                                        ((DLAYER *)bufpt)->me[i]= 
  461.     X                                                acb_ptr->acbraddr[i+9];
  462.     X                                }
  463.     X                                bufpt+= sizeof(DLAYER);
  464.     X                                movedata(FP_SEG( buffer_pt ), FP_OFF( buffer_pt ), 
  465.     X                                        FP_SEG(bufpt), FP_OFF(bufpt), acb_ptr->acblen);
  466.     X                                bufpt+= acb_ptr->acblen;
  467.     X                                bufbig+= acb_ptr->acblen + sizeof(DLAYER) + sizeof(int);
  468.     X                        }
  469.     X                        /* else we are going to drop packets ! */
  470.     X                        }
  471.     X                        break;
  472.     X                }
  473.     X        }
  474.     X        return(0);
  475.     X}
  476.     X
  477. SHAR_EOF
  478. if test 15525 -ne "`wc -c < 'iso.c'`"
  479. then
  480.     echo shar: error transmitting "'iso.c'" '(should have been 15525 characters)'
  481. fi
  482. fi # end of overwriting check
  483. echo shar: extracting "'multi.asm'" '(1909 characters)'
  484. if test -f 'multi.asm'
  485. then
  486.     echo shar: will not over-write existing file "'multi.asm'"
  487. else
  488. sed 's/^    X//' << \SHAR_EOF > 'multi.asm'
  489.     XTITLE 'MULTI.ASM'
  490.     X;
  491.     X;       These assembler routine provide an interface between the code
  492.     X;       written in 'C' and the Multi Protocol Handler.
  493.     X;
  494.     X
  495.     X.model large
  496.     X
  497.     X;
  498.     X;       Data Structures
  499.     X;
  500.     X.data
  501.     X
  502.     X;
  503.     X;       The Asynchronous Notification Routine Stack
  504.     X;
  505.     X;       Size of stack is
  506.     XSTACK_SIZE      EQU     100h
  507.     X;
  508.     X                DW      STACK_SIZE      DUP     (?)
  509.     XSTACK_START     DW      ?
  510.     X
  511.     X;
  512.     X;       Area to save Multi Protocol Handler Stack Pointer
  513.     X;
  514.     XSS_SAVE         DW      ?
  515.     XSP_SAVE         DW      ?
  516.     X;
  517.     X
  518.     X;
  519.     X;       Start of Code
  520.     X;
  521.     X
  522.     X
  523.     X.code
  524.     X
  525.     XEXTRN   _anr_c : FAR
  526.     X
  527.     XPUBLIC  _ANR_ENTRY
  528.     X
  529.     X_ANR_ENTRY      PROC    
  530.     X
  531.     X;
  532.     X;       This routine is the ANR entry point.  It is called by the
  533.     X;       Multi Protocol Handler, via a far call.  Before calling the main
  534.     X;       ANR routine (written in 'C'), it sets up the Data Segment, saves
  535.     X;       the Multi Protocol Handler's stack, and allocates a new stack.
  536.     X;       Before returning to the Multi Protocol Handler, it restores its
  537.     X;       stack.
  538.     X;
  539.     X;       The ANR routine (written in 'C') must not make use of the heap, 
  540.     X;       nor should it try to access to access automatic variables declared
  541.     X;       in main(), because the stack it has been allocated is NOT the same
  542.     X;       as the standard 'C' stack.
  543.     X;
  544.     X
  545.     X        MOV     AX, DGROUP      ; Get Data Segement
  546.     X        MOV     DS, AX          ; Set up DS
  547.     X
  548.     X        MOV     SS_SAVE, SS     ; Save Stack Pointers
  549.     X        MOV     SP_SAVE, SP     ;
  550.     X
  551.     X        MOV     SS, AX          ; Set up Stack Segment
  552.     X        LEA     SP, STACK_START ; 
  553.     X
  554.     X        PUSH    ES              ; The address of the ACB is passed as
  555.     X        PUSH    BX              ; a far pointer.
  556.     X
  557.     X        CLD
  558.     X
  559.     X        CALL    _anr_c          ; Call 'C' ANR routine
  560.     X                                ; _ANR_C returns a parameter in AX
  561.     X
  562.     X        MOV     SS, SS_SAVE     ; Restore Stack Pointers
  563.     X        MOV     SP, SP_SAVE
  564.     X
  565.     X        RET
  566.     X_ANR_ENTRY      ENDP
  567.     X
  568.     X        END
  569.     X
  570. SHAR_EOF
  571. if test 1909 -ne "`wc -c < 'multi.asm'`"
  572. then
  573.     echo shar: error transmitting "'multi.asm'" '(should have been 1909 characters)'
  574. fi
  575. fi # end of overwriting check
  576. echo shar: extracting "'pctools.c'" '(11904 characters)'
  577. if test -f 'pctools.c'
  578. then
  579.     echo shar: will not over-write existing file "'pctools.c'"
  580. else
  581. sed 's/^    X//' << \SHAR_EOF > 'pctools.c'
  582.     X/*
  583.     X*  pctools.c
  584.     X****************************************************************************
  585.     X*                                                                          *
  586.     X*      part of:                                                            *
  587.     X*      TCP/UDP/ICMP/IP Network kernel for NCSA Telnet                      *
  588.     X*      by Tim Krauskopf                                                    *
  589.     X*                                                                          *
  590.     X*      National Center for Supercomputing Applications                     *
  591.     X*      152 Computing Applications Building                                 *
  592.     X*      605 E. Springfield Ave.                                             *
  593.     X*      Champaign, IL  61820                                                *
  594.     X*                                                                          *
  595.     X****************************************************************************
  596.     X*
  597.     X*  those generic tool-type things that only work on PCs.
  598.     X*  includes all hardware-level calls to Ethernet that are unique to the PC
  599.     X*
  600.     X*  Function pointers for Ether calls
  601.     X*/
  602.     X#include "stdio.h"
  603.     X#include "protocol.h"
  604.     X#include "data.h"
  605.     X
  606.     X/*
  607.     X*   defined in assembly language file for interrupt driven Ether buffering
  608.     X*
  609.     X*/
  610.     X#ifdef MSC
  611.     Xextern unsigned char rstat;                    /* status from last read */
  612.     Xextern char *bufpt,*bufend,*bufread,*buforg;
  613.     Xextern int bufbig,buflim;
  614.     X#else
  615.     Xunsigned char rstat;                    /* status from last read */
  616.     Xchar *bufpt,*bufend,*bufread,*buforg;
  617.     Xint bufbig,buflim;
  618.     X#endif /* MSC */
  619.     X
  620.     X/*
  621.     X*  Declare each and every Ethernet driver.
  622.     X*  To add a driver, pick a unique 2 char prefix and declare your own
  623.     X*  routines.  I want to keep the same parameters for EVERY driver.
  624.     X*  If your driver needs additional parameters, then see netconfig() below 
  625.     X*  for an indication of where to put custom board code.
  626.     X*/
  627.     Xextern int E1etopen(),E1getaddr(),E1setaddr(),E1recv(),E1xmit(),E1etupdate(),E1etclose();
  628.     Xextern int E3etopen(),E3getaddr(),E3setaddr(),E3recv(),E3xmit(),E3etupdate(),E3etclose();
  629.     Xextern int M5etopen(),M5getaddr(),M5recv(),M5xmit(),M5etupdate(),M5etclose();
  630.     Xextern int U1etopen(),U1getaddr(),U1recv(),U1xmit(),U1etupdate(),U1etclose();
  631.     Xextern int U2etopen(),U2getaddr(),U2recv(),U2xmit(),U2etupdate(),U2etclose();
  632.     Xextern int WDetopen(),WDgetaddr(),WDrecv(),WDxmit(),WDetupdate(),WDetclose();
  633.     Xextern int E2etopen(),E2getaddr(),E2recv(),E2xmit(),E2etupdate(),E2etclose();
  634.     X#ifdef ISOLAN
  635.     Xextern int ILetopen(),ILgetaddr(),ILrecv(),ILxmit(),ILetupdate(),ILetclose();
  636.     X#endif
  637.     X
  638.     Xstatic int (*etopen)()=NULL,    /* open the device */
  639.     X        (*getaddr)()=NULL,              /* get the Ether address */
  640.     X        (*setaddr)()=NULL,                      /* set the Ether address to use */
  641.     X        (*recv)()=NULL,                         /* load a packet from queue */
  642.     X        (*etupdate)()=NULL,                     /* update pointers in buffer */
  643.     X        (*etclose)()=NULL,                      /* shut down network */
  644.     X        (*xmit)()=NULL;                         /* transmit a packet */
  645.     X
  646.     X
  647.     X/**********************************************************************/
  648.     X/*  statcheck
  649.     X*   look at the connection status of the memory buffers to see if the
  650.     X*   allocation schemes are working.  Only used as a debug tool.
  651.     X*/
  652.     Xstatcheck()
  653.     X        {
  654.     X        int i;
  655.     X        struct port *p;
  656.     X
  657.     X        for (i=0; i<20; i++) {
  658.     X                printf("\n%d > ",i);
  659.     X                p = portlist[i];
  660.     X                if (p != NULL) 
  661.     X                        printf("state: %d  %5u  %5u  %10ld  %5d  %5d",
  662.     X                                        p->state,intswap(p->tcpout.t.source),
  663.     X                                        intswap(p->tcpout.t.dest),p->out.lasttime,p->rto,
  664.     X                                        p->out.contain);
  665.     X        }
  666.     X}
  667.     X
  668.     X/*************************************************************************/
  669.     X/*  config network parameters
  670.     X*   Set IRQ and DMA parameters for initialization of the 3com adaptor
  671.     X*/
  672.     Xstatic int nnirq=3,nnaddr=0xd000,nnioaddr=0x300;
  673.     X
  674.     Xnetparms(irq,address,ioaddr)
  675.     X        int irq,address,ioaddr;
  676.     X        {
  677.     X
  678.     X        nnirq = irq;
  679.     X        nnaddr = address;
  680.     X        nnioaddr = ioaddr;
  681.     X
  682.     X        return(0);
  683.     X}
  684.     X
  685.     X/**********************************************************************/
  686.     X/* netconfig
  687.     X*  load the function pointers for network access
  688.     X*  Currently setaddr() is not used, so it isn't loaded.
  689.     X*
  690.     X*  Note that netparms is called BEFORE netconfig.  So if you have any
  691.     X*  really special variables to set for your board that involve
  692.     X*  irq,address and ioaddr, you can add calls to your special routines
  693.     X*  in this section.
  694.     X*
  695.     X*  Some drivers will do the interrupt driver and board initialization
  696.     X*  in etopen() and some will do it in getaddr().
  697.     X*/
  698.     Xnetconfig(s)
  699.     X        char *s;
  700.     X        {
  701.     X
  702.     X        if (!strncmp(s,"ni5",3) || !strncmp(s,"mi",2)) {
  703.     X                etopen = M5etopen;
  704.     X                xmit = M5xmit;
  705.     X                recv = M5recv;
  706.     X                getaddr = M5getaddr;
  707.     X                etupdate = M5etupdate;
  708.     X                etclose = M5etclose;
  709.     X/*
  710.     X*   special initialization call would go here
  711.     X*/
  712.     X        }
  713.     X        else if (!strncmp(s,"nicps",5)) {
  714.     X                etopen = U2etopen;
  715.     X                xmit = U2xmit;
  716.     X                recv = U2recv;
  717.     X                getaddr = U2getaddr;
  718.     X                etupdate = U2etupdate;
  719.     X                etclose = U2etclose;
  720.     X        }
  721.     X        else if (!strncmp(s,"nicpc",5) || !strncmp(s,"pcnic",5)) {
  722.     X                etopen = U1etopen;
  723.     X                xmit = U1xmit;
  724.     X                recv = U1recv;
  725.     X                getaddr = U1getaddr;
  726.     X                etupdate = U1etupdate;
  727.     X                etclose = U1etclose;
  728.     X        }
  729.     X        else if (!strncmp(s,"wd",2) || !strncmp(s,"800",3)) {
  730.     X                etopen = WDetopen;
  731.     X                xmit = WDxmit;
  732.     X                recv = WDrecv;
  733.     X                getaddr = WDgetaddr;
  734.     X                etupdate = WDetupdate;
  735.     X                etclose = WDetclose;
  736.     X        }
  737.     X        else if (!strncmp(s,"3c523",5) || !strncmp(s,"523",3)) {
  738.     X                etopen = E2etopen;
  739.     X                xmit = E2xmit;
  740.     X                recv = E2recv;
  741.     X                getaddr = E2getaddr;
  742.     X                etupdate = E2etupdate;
  743.     X                etclose = E2etclose;
  744.     X        }
  745.     X        else if (!strncmp(s,"r501",4)) {                /* special reserve driver */
  746.     X                etopen = E3etopen;
  747.     X                xmit = E3xmit;
  748.     X                recv = E3recv;
  749.     X                getaddr = E3getaddr;
  750.     X                etupdate = E3etupdate;
  751.     X                etclose = E3etclose;
  752.     X        }
  753.     X#ifdef ISOLAN
  754.     X        else if (!strncmp(s,"iso",3)) {
  755.     X                etopen = ILetopen;
  756.     X                xmit = ILxmit;
  757.     X                recv = ILrecv;
  758.     X                getaddr = ILgetaddr;
  759.     X                etupdate = ILetupdate;
  760.     X                etclose = ILetclose;
  761.     X        }
  762.     X#endif
  763.     X        else if (!strncmp(s,"3c",2) || 1) {             /* default choice */
  764.     X                etopen = E1etopen;
  765.     X                xmit = E1xmit;
  766.     X                recv = E1recv;
  767.     X                getaddr = E1getaddr;
  768.     X                etupdate = E1etupdate;
  769.     X                etclose = E1etclose;
  770.     X        }
  771.     X
  772.     X}
  773.     X
  774.     X/**********************************************************************/
  775.     X/*  netarpme
  776.     X*   send an arp to my address.  arpinterpret will notice any response.
  777.     X*   Checks for adapters which receive their own broadcast packets.
  778.     X*/
  779.     Xnetarpme(s)
  780.     X        char *s;
  781.     X        {
  782.     X
  783.     X        if (etopen == U2etopen)
  784.     X                return(0);
  785.     X        if (etopen == U1etopen)
  786.     X                return(0);
  787.     X
  788.     X        reqarp(s);              /* send it */
  789.     X
  790.     X        return(0);
  791.     X}
  792.     X
  793.     X
  794.     X/**********************************************************************/
  795.     X
  796.     Xinitbuffer()
  797.     X        {
  798.     X
  799.     X        bufpt = bufread = buforg = raw; /*  start at the beginning */
  800.     X
  801.     X        bufend = &raw[14500];                   /* leave 2K breathing room, required */
  802.     X        buflim = 12000;                      /* another 2K breathing room */
  803.     X
  804.     X        (*getaddr)(nnmyaddr,nnaddr,nnioaddr);
  805.     X
  806.     X        return(0);
  807.     X}
  808.     X
  809.     X/**********************************************************************/
  810.     X/*   demux
  811.     X*      find the packets in the buffer, determine their lowest level
  812.     X*  packet type and call the correct interpretation routines
  813.     X*
  814.     X*  the 'all' parameter tells demux whether it should attempt to empty
  815.     X*  the input packet buffer or return after the first packet is dealt with.
  816.     X*
  817.     X*  returns the number of packets demuxed
  818.     X*/
  819.     Xdemux(all)
  820.     X        int all;
  821.     X        {
  822.     X        uint16 getcode;
  823.     X        int nmuxed;
  824.     X        DLAYER *firstlook;
  825.     X
  826.     X        nmuxed = 0;
  827.     X        if (!etupdate)                                  /* check that network is hooked up */
  828.     X                return(0);
  829.     X
  830.     X        do {                                                    /* while all flag is on */
  831.     X
  832.     X                (*recv)();                                      /* NULL operation for 3COM */
  833.     X
  834.     X                if (bufbig > 0) {
  835.     X
  836.     X                        nmuxed++;
  837.     X                        firstlook = (DLAYER *)(bufread+2);      /* where packet is */
  838.     X
  839.     X                        getcode = firstlook->type;                      /* where does it belong? */
  840.     X
  841.     X                        switch (getcode) {                                      /* what to do with it? */
  842.     X                                case EARP:
  843.     X                                case ERARP:
  844.     X                                        arpinterpret(firstlook);        /* handle ARP packet */
  845.     X                                        break;
  846.     X                                case EIP:
  847.     X                                        ipinterpret(firstlook);
  848.     X                                        break;
  849.     X                                default:
  850.     X                                        break;
  851.     X                        }
  852.     X
  853.     X                        (*etupdate)();                  /* update read pointers in buffer, free packet */
  854.     X
  855.     X                }
  856.     X                else 
  857.     X                        all = 0;
  858.     X
  859.     X
  860.     X        } while (all);                  /* should we look for more to deal with? */
  861.     X
  862.     X
  863.     X        return(nmuxed);          /* no packets anymore */
  864.     X
  865.     X}
  866.     X
  867.     X/************************************************************************/
  868.     X/*  dlayersend
  869.     X*
  870.     X*  usage:   err = dlayersend(ptr,size)
  871.     X*      err = 0 for successful, non-zero error code otherwise
  872.     X*      ptr is to a dlayer packet header
  873.     X*      size is the number of bytes total
  874.     X*
  875.     X*  This particular dlayer routine is for Ethernet.  It will have to be
  876.     X*  replaced for any other dlayer.
  877.     X*
  878.     X*  Ethernet addresses are resolved at higher levels because they will only
  879.     X*  need to be resolved once per logical connection, instead of once per
  880.     X*  packet.  Not too layer-like, but hopefully modular.
  881.     X*
  882.     X*/
  883.     X
  884.     Xdlayersend(ptr,size)
  885.     X        DLAYER *ptr;
  886.     X        unsigned size;
  887.     X        {
  888.     X        int ret;
  889.     X        
  890.     X        ret = (*xmit)(ptr,size);        /* send it out, pass back return code */
  891.     X                                                                /* xmit checks for size < 60 */
  892.     X
  893.     X/*
  894.     X*   automatic, immediate retry once
  895.     X*/
  896.     X        if (ret) {
  897.     X                if (ret == (*xmit)(ptr,size))
  898.     X                        nnerror(100);           /* post user error message */
  899.     X        }
  900.     X
  901.     X        return(ret);
  902.     X}
  903.     X
  904.     X/***************************************************************************/
  905.     X/* dlayerinit
  906.     X*  Do machine dependent initializations of whatever hardware we have
  907.     X*  (happens to be ethernet board here ) 
  908.     X*/
  909.     Xdlayerinit()
  910.     X        {
  911.     X
  912.     X        if (initbuffer() || !etopen)
  913.     X                return(-1);
  914.     X
  915.     X        return((*etopen)(nnmyaddr,nnirq,nnaddr,nnioaddr));
  916.     X}
  917.     X
  918.     Xdlayershut()
  919.     X        {
  920.     X        if (etclose)
  921.     X                (*etclose)();
  922.     X}
  923.     X
  924.     X/***************************************************************************/
  925.     X/*  pcgetaddr
  926.     X*   return results from indirect getaddr call.
  927.     X*   This is a pc-specific request for the 48-bit address which was added
  928.     X*   so that the user program could print the value.
  929.     X*/
  930.     Xpcgetaddr(s,x,y)
  931.     X        char *s;
  932.     X        int x,y;
  933.     X        {
  934.     X        if (getaddr)
  935.     X                (*getaddr)(s,x,y);
  936.     X}
  937. SHAR_EOF
  938. if test 11904 -ne "`wc -c < 'pctools.c'`"
  939. then
  940.     echo shar: error transmitting "'pctools.c'" '(should have been 11904 characters)'
  941. fi
  942. fi # end of overwriting check
  943. echo shar: extracting "'makefile'" '(4342 characters)'
  944. if test -f 'makefile'
  945. then
  946.     echo shar: will not over-write existing file "'makefile'"
  947. else
  948. sed 's/^    X//' << \SHAR_EOF > 'makefile'
  949.     X# Makefile for NCSA telnet version 2.2S with added features by jkp@hutcs.hut.fi
  950.     X# Author: Jyrki Kuoppala (jkp@hutcs.hut.fi)
  951.     X# Last modified: 89.05.25 by Inge Arnesen (ingea@ifi.uio.no)
  952.     X
  953.     X# Assumes that you have LIB and INCLUDE environment variables
  954.     X# set to proper values for your compiler
  955.     X
  956.     X# I haven't tested the lattice version of makefile.
  957.     X# All knowledge I have about lattice is from the 'compile.bat'
  958.     X# script, so you should probably study the flags and change them
  959.     X# if necessary
  960.     X
  961.     X# Change the value of CC to lc if you have lattice, cl if msc.
  962.     X# It should be enough, but probably you need to change lattice part
  963.     X# Or, just say 'gmake CC=lc' or 'gmake CC=cl'
  964.     X
  965.     XCC=cl
  966.     X#CC=lc
  967.     X
  968.     X# Use this if backspace mapping doesn't work with you.
  969.     X# If you use it, however, ^H isn't ^H if mapping is on.
  970.     X
  971.     X#BUGSPACE=-DBugspace
  972.     X
  973.     X#ifeq ($(CC),cl)
  974.     X#   Use this for MSC 5.0.  Stack-checking is suppressed ; the interrupt
  975.     X#   routine setup doesn't work with it and I don't like the compiler generating
  976.     X#   code I haven't asked for anyhow :-)
  977.     XCFLAGS= -c -Otl -AL -DMSC -Itek -Ivs -Ienet -Iftp -I. -Gs -Zpi -DISOLAN
  978.     XASFLAGS=-Itek -Ivs -Ienet -DMicrosoft $(BUGSPACE)
  979.     X#else
  980.     X#   For lattice, untested
  981.     X#   remove -qd: if you don't have a ram disk called d:
  982.     X#CFLAGS= -ml -qd:
  983.     X#ASFLAGS=-Itek -Ivs -Ienet -DLattice $(BUGSPACE)
  984.     X#endif
  985.     X
  986.     XVPATH=.\vs:.\tek:.\enet:.\ftp
  987.     X
  988.     XAS=masm
  989.     XLIB=lib
  990.     XLIBFLAGS=
  991.     XLINK=link
  992.     XSTACK=/stack:4096
  993.     XLINKFLAGS=/CO
  994.     XRM=command /c del
  995.     X
  996.     X#LDFLAGS=/Fencsa /AL
  997.     X
  998.     X#.SUFFIXES: .c .o .obj .exe .asm
  999.     X
  1000.     X.c.obj:
  1001.     X        $(CC) $(CFLAGS) /Fo$*.obj $<
  1002.     X
  1003.     X.asm.obj:
  1004.     X        $(AS) $(ASFLAGS) $<, $*.obj  ;
  1005.     X
  1006.     Xall: minitel.exe telpass.exe telbin.exe finger.exe ftpbin.exe
  1007.     X
  1008.     Xtcp1m.lib : tcp.obj ip.obj dlayer.obj tools.obj multi.obj iso.obj pctools.obj enet\net8003.obj \
  1009.     X                enet\net3com.obj enet\net501.obj enet\net5210.obj enet\net523.obj \
  1010.     X                enet\netzyp.obj enet\netub.obj \
  1011.     X                protinit.obj user.obj ipasm.obj
  1012.     X        $(RM) tcp1m.lib
  1013.     X        $(LIB) $(LIBFLAGS) tcp1m.lib +tcp +ip +dlayer +tools +iso+multi+pctools ;
  1014.     X        $(LIB) $(LIBFLAGS) tcp1m.lib+protinit+user+ipasm+\
  1015.     X        enet\net8003+enet\net3com+enet\netzyp+enet\net501+enet\net5210+enet\net523+enet\netub ;
  1016.     X
  1017.     Xsessm.lib : util.obj pcutil.obj bkgr.obj confile.obj
  1018.     X        $(RM) sessm.lib
  1019.     X        $(LIB) $(LIBFLAGS) sessm.lib +util +pcutil +bkgr +confile ;
  1020.     X
  1021.     Xvs.lib: vs\vsinterf.obj vs\vsem.obj vs\vsintern.obj
  1022.     X        $(RM) vs.lib
  1023.     X        $(LIB) $(LIBFLAGS) vs.lib +vs\vsinterf +vs\vsintern +vs\vsem ;
  1024.     X
  1025.     Xtek.lib: tek\vgtek.obj tek\tekstor.obj tek\egaset.obj tek\rg0.obj tek\rge.obj tek\rgc.obj \
  1026.     X          tek\rgh.obj tek\rgp.obj tek\rghp.obj tek\rg9.obj 
  1027.     X        $(RM) tek.lib
  1028.     X        $(LIB) $(LIBFLAGS) tek.lib +tek\vgtek +tek\tekstor +tek\rg0 +tek\rge +tek\rgc \
  1029.     X         +tek\rgh +tek\rgp +tek\rghp +tek\rg9 +tek\egaset ;
  1030.     X
  1031.     Xtelbin.exe : look.obj ncsaio.obj rspc.obj tek.lib sessm.lib tcp1m.lib vs.lib
  1032.     X        $(LINK) $(LINKFLAGS) $(STACK) look+ncsaio+rspc,telbin,nul,tek+tcp1m+sessm+vs ;
  1033.     X
  1034.     Xtelpass.exe : telpass.obj ncsaio.obj
  1035.     X        $(LINK) $(LINKFLAGS) telpass+ncsaio,telpass,nul ;
  1036.     X
  1037.     Xftpbin.exe : ftp\ftpbin.obj ncsaio.obj tcp1m.lib sessm.lib
  1038.     X        $(LINK) $(LINKFLAGS) ftp\ftpbin+ncsaio,ftpbin,nul,tcp1m+sessm ;
  1039.     X
  1040.     Xminitel.exe : minitel.obj ncsaio.obj tcp1m.lib sessm.lib
  1041.     X        $(LINK) $(LINKFLAGS) minitel+ncsaio,minitel,nul,tcp1m+sessm ;
  1042.     X
  1043.     Xfinger.exe : finger.obj ncsaio.obj tcp1m.lib sessm.lib
  1044.     X        $(LINK) $(LINKFLAGS) finger+ncsaio,finger,nul,tcp1m+sessm ;
  1045.     X
  1046.     Xtar:
  1047.     X        (cd .. ; tar cf hackedsrc.tar source )
  1048.     X
  1049.     Xclean:
  1050.     X        $(RM) *.obj
  1051.     X        $(RM) make.out
  1052.     X        $(RM) *.exe
  1053.     X        $(RM) *.lib
  1054.     X        $(RM) *.bak
  1055.     X
  1056.     Xftpbin.obj : ftp\ftpbin.c ftp\ftppi.h
  1057.     X
  1058.     Xbkgr.obj: bkgr.c whatami.h hostform.h
  1059.     Xconfile.obj: confile.c whatami.h hostform.h
  1060.     Xdlayer.obj: dlayer.c protocol.h data.h
  1061.     Xfinger.obj: finger.c whatami.h hostform.h
  1062.     Xip.obj: ip.c protocol.h data.h
  1063.     Xlook.obj: look.c whatami.h nkeys.h windat.h hostform.h
  1064.     Xminitel.obj: minitel.c whatami.h hostform.h
  1065.     Xiso.obj: iso.c protocol.h data.h
  1066.     X
  1067.     Xmulti.obj: multi.asm
  1068.     X        masm -Zi -Ml multi.asm;
  1069.     X
  1070.     Xpctools.obj: pctools.c protocol.h data.h
  1071.     Xpcutil.obj: pcutil.c whatami.h
  1072.     Xprotinit.obj: protinit.c protocol.h data.h whatami.h
  1073.     Xrspc.obj: rspc.c whatami.h windat.h vskeys.h nkeys.h
  1074.     Xtcp.obj: tcp.c protocol.h data.h
  1075.     Xtools.obj: tools.c protocol.h data.h
  1076.     Xuser.obj: user.c protocol.h data.h
  1077.     Xutil.obj: util.c whatami.h hostform.h
  1078. SHAR_EOF
  1079. if test 4342 -ne "`wc -c < 'makefile'`"
  1080. then
  1081.     echo shar: error transmitting "'makefile'" '(should have been 4342 characters)'
  1082. fi
  1083. fi # end of overwriting check
  1084. #    End of shell archive
  1085. exit 0
  1086.