home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff225.lzh / AmigaTCP / src / telnetp.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  16KB  |  794 lines

  1. #include <stdio.h>
  2. #include <exec/types.h>
  3. #include <exec/nodes.h>
  4. #include <exec/lists.h>
  5. #include <exec/tasks.h>
  6. #include <exec/ports.h>
  7. #include <exec/libraries.h>
  8. #include <exec/io.h>
  9. #include <exec/devices.h>
  10. #include <exec/errors.h>
  11. #include <proto/exec.h>
  12. #include <devices/console.h>
  13. #include <libraries/dos.h>
  14. #include <libraries/dosextens.h>
  15. #include <intuition/intuition.h>
  16. #include <dos.h>
  17. #include "machdep.h"
  18. #include "mbuf.h"
  19. #include "timer.h"
  20. #include "internet.h"
  21. #include "icmp.h"
  22. #include "netuser.h"
  23. #include "tcp.h"
  24. #include "telnet.h"
  25. #include "session.h"
  26. #include "inetdev.h"
  27. #include "inetlib.h"
  28. #define DEBUG
  29. struct Process *mytask;
  30. APTR    oldwindowptr;
  31. struct IntuitionBase *IntuitionBase;
  32. char banner[80] = "telnet window";
  33. static struct NewWindow nw = {
  34.     0, 0, 640, 200,        /* left, top, (max) width, (max) height */
  35.     0, 1,            /* detail pen, block pen */
  36.     0,            /* IDCMP flags */
  37.     SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING |
  38.         SIZEBBOTTOM | ACTIVATE | NOCAREREFRESH,    /* window flags */
  39.     NULL, NULL,        /* gadget, checkmark */
  40.     (UBYTE *)&banner[0],    /* title of window */
  41.     NULL, NULL,        /* screen, bitmap */
  42.     200, 50, -1, -1,    /* sizing limits */
  43.     WBENCHSCREEN,        /* on the workbench */
  44. };
  45. struct Window *win;
  46. struct MsgPort *keyboard, *consinp, *consoutp, *tcpinp, *tcpoutp;
  47. struct IOStdReq consin, consout;
  48. char InputCharacter;
  49. int deviceopened = 0;
  50. struct IOINETReq tnreq, tninreq, tnoutreq;
  51. char recv[512], snd[512];
  52. struct telnet *tn;
  53. #ifdef LATTICE
  54. extern struct { short error; char *msg; } os_errlist[];
  55. extern int _OSERR, os_nerr;
  56. #endif
  57. static
  58. clean(why)
  59.     char *why;
  60. {
  61.     int i;
  62.     InputCharacter = ' ';
  63.         while (InputCharacter != '<')
  64.       if (kbread() > 0)
  65.         amigaputchar(InputCharacter);
  66.  
  67.     if (win)
  68.         CloseWindow(win);
  69.     if (consinp)
  70.         DeletePort(consinp);
  71.     if (consoutp)
  72.         DeletePort(consoutp);
  73.     if (tcpinp)
  74.         DeletePort(tcpinp);
  75.     if (tcpoutp)
  76.         DeletePort(tcpoutp);
  77.     if (deviceopened)
  78.         CloseDevice(&tnreq);
  79.     mytask->pr_WindowPtr = oldwindowptr;
  80.     if (why) {
  81.            myoserr(why);
  82.     }
  83.     exit(0);
  84. }
  85. printlist(l)
  86. struct List *l;
  87. {
  88.   printf("head %x tail %x tailpred %x\n", l->lh_Head, l->lh_Tail, 
  89.         l->lh_TailPred);
  90. }
  91. myoserr(why)
  92. char *why;
  93. {
  94.   int i;
  95.         fprintf(stderr, "%s: ", why); 
  96. #ifdef LATTICE
  97.         fprintf(stderr, "%d: ", _OSERR);
  98.  
  99.         for(i = 0; os_errlist[i].error < os_nerr; i++)
  100.           if (os_errlist[i].error == _OSERR)
  101.             fprintf(stderr, os_errlist[i].msg);
  102. #endif
  103.         fprintf(stderr, "\r\n");
  104. }
  105. /* Called at startup time to set up console I/O, memory heap */
  106. ioinit()
  107. {
  108.     struct Screen *scr;
  109.  
  110.     mytask = (struct Process *) FindTask((char *) NULL);
  111.     oldwindowptr = mytask->pr_WindowPtr;
  112.     mytask->pr_WindowPtr = (APTR) -1;    /* disable DOS requestors */
  113.  
  114.     if ((IntuitionBase = (struct IntuitionBase *)
  115.        OpenLibrary("intuition.library", 33L)) == NULL)
  116.         clean("No intuition: Version 1.2 of Amiga Systems Software required");
  117.     /*
  118.      *  Try to determine the size of the workbench screen
  119.      */
  120.     scr = malloc(sizeof(struct Screen));
  121.     if (scr==NULL)
  122.         clean("Can't alloc screen");
  123.  
  124.     if (GetScreenData(scr, (ULONG) sizeof(struct Screen),
  125.               WBENCHSCREEN, NULL) == TRUE) {
  126.         nw.Width = scr->Width;
  127.         nw.Height = scr->Height-20;
  128.         nw.TopEdge = 19;
  129.     } else
  130.         fprintf(stderr, "Can't GetScreenData()\n");
  131.  
  132.     free((char *)scr);
  133.     if ((win = OpenWindow(&nw)) == NULL)
  134.         clean("Can't open window");
  135.     if ((consinp = CreatePort("telnet:console in", 0L)) == NULL)
  136.         clean("Can't create console port");
  137.     if ((tcpinp = CreatePort("telnet:tcp in", 0L)) == NULL)
  138.         clean("Can't create telnet tcp input port");
  139.     if ((tcpoutp = CreatePort("telnet:tcp out", 0L)) == NULL)
  140.         clean("Can't create telnet tcp output port");
  141.  
  142.     consin.io_Data = (APTR) win;
  143.     consin.io_Length = sizeof(struct Window);
  144.  
  145.     _OSERR = OpenDevice("console.device", 0L, &consin, 0L);
  146.     if (_OSERR != 0L){
  147.         printf("opendevice returned %d\n", _OSERR);
  148.         myoserr("could not get console");
  149.         clean("Can't open console device");
  150.     }
  151.     consout = consin;
  152.  
  153.     consin.io_Message.mn_ReplyPort = consinp;
  154.     consin.io_Length = 1;
  155.     consin.io_Data = (APTR) &InputCharacter;
  156.     consin.io_Command = CMD_READ;
  157.     SendIO(&consin);
  158.     consout.io_Message.mn_ReplyPort = consoutp;
  159.     consout.io_Command = CMD_WRITE;
  160.  
  161.  
  162. }
  163. /* Read characters from the keyboard, translating them to "real" ASCII
  164.  * If none are ready, return the -1 from kbraw()
  165.  */
  166. kbread()
  167. {
  168.     char c;
  169.  
  170.     if (CheckIO(&consin)) {
  171.         WaitIO(&consin);
  172.         c = InputCharacter;
  173.         consin.io_Length = 1;
  174.         consin.io_Data = (APTR) &InputCharacter;
  175.         consin.io_Command = CMD_READ;
  176.         SendIO(&consin);        /* start next read up */
  177.         return (c & 0xff);
  178.     }
  179.  
  180.     return -1;        /* nuthin here */
  181. }
  182. extern char nospace[];
  183. int refuse_echo = 0;
  184. int unix_line_mode = 0;    /* if true turn <cr> to <nl> when in line mode */
  185.  
  186. #ifdef    DEBUG
  187. char *t_options[] = {
  188.     "Transmit Binary",
  189.     "Echo",
  190.     "",
  191.     "Suppress Go Ahead",
  192.     "",
  193.     "Status",
  194.     "Timing Mark"
  195. };
  196. #endif
  197. /* Telnet receiver upcall routine */
  198. void
  199. rcv_char()
  200. {
  201. /*printf("rcv_char: %d\n", tninreq.io_Actual);*/
  202.     tel_input(tn,tninreq.io_Data, tninreq.io_Actual);
  203.  
  204.     fflush(stdout);
  205. }
  206. brk()
  207. {
  208.   clean("ok i iwll quit\n");
  209. }
  210. /* TCP connection states */
  211. char *tcpstates[] = {
  212.     "Closed",
  213.     "Listen",
  214.     "SYN sent",
  215.     "SYN received",
  216.     "Established",
  217.     "FIN wait 1",
  218.     "FIN wait 2",
  219.     "Close wait",
  220.     "Closing",
  221.     "Last ACK",
  222.     "Time wait"
  223. };
  224. /* TCP segment header flags */
  225. char *tcpflags[] = {
  226.     "FIN",    /* 0x01 */
  227.     "SYN",    /* 0x02 */
  228.     "RST",    /* 0x04 */
  229.     "PSH",    /* 0x08 */
  230.     "ACK",    /* 0x10 */
  231.     "URG"    /* 0x20 */
  232. };
  233.  
  234. /* TCP closing reasons */
  235. char *reasons[] = {
  236.     "Normal",
  237.     "Reset",
  238.     "Timeout",
  239.     "ICMP"
  240. };
  241. char old = LISTEN;
  242. int done = 0;
  243. char *hostname="";
  244. int hostport=0;
  245. char *bannerfmt = "telnet %10s %4d %10s";
  246. void
  247. showstate(old, new)
  248.     char old, new;
  249. {
  250.  
  251.  
  252. /*    extern char *tcpstates[];
  253.     extern char *reasons[];
  254.     extern char *unreach[];
  255.     extern char *exceed[];
  256. */
  257.     /* Can't add a check for unknown connection here, it would loop
  258.      * on a close upcall! We're just careful later on.
  259.      */
  260.  
  261.     sprintf(banner, bannerfmt, hostname, hostport, tcpstates[new]);
  262.     SetWindowTitles(win, banner, -1);
  263.     switch(new){
  264.     case CLOSE_WAIT:
  265.         done = 1;
  266.         break;
  267.     case CLOSED:    /* court adjourned */
  268. /*            printf("%s (%s",tcpstates[new],reasons[tcb->reason]);
  269.             if(tcb->reason == NETWORK){
  270.                 switch(tcb->type){
  271.                 case DEST_UNREACH:
  272.                     printf(": %s unreachable",unreach[tcb->code]);
  273.                     break;
  274.                 case TIME_EXCEED:
  275.                     printf(": %s time exceeded",exceed[tcb->code]);
  276.                     break;
  277.                 }
  278.             }
  279.             printf(")\r\n");
  280. */
  281.         done = 1;
  282.         break;
  283.     default:
  284.         break;
  285.     }
  286.     fflush(stdout);
  287.  
  288. }
  289.  
  290. /* Execute user telnet command */
  291. main(argc,argv)
  292. int argc;
  293. char *argv[];
  294. {
  295.     extern int _OSERR;
  296.     struct InternetBase *InternetBase;
  297.     int send_tel();
  298.         int unix_send_tel();
  299.     struct session *s;
  300.  
  301. /*    struct tcb *tcb = NULL;*/
  302.     struct socket lsocket,fsocket;
  303.     ioinit();
  304.     hostname = argv[1];
  305.     old = LISTEN;
  306.     showstate(old, LISTEN);
  307.     tnreq.io_fsocket.address = aton(argv[1]);
  308.     if(argc < 3)
  309.         tnreq.io_fsocket.port = TELNET_PORT;
  310.     else
  311.         tnreq.io_fsocket.port = atoi(argv[2]);
  312.     tnreq.io_Device = NULL;
  313.     tnreq.io_Unit = NULL;
  314.     tnreq.io_Flags = 0;
  315.     tnreq.io_Error = 0;
  316.     InternetBase = (struct InternetBase *) OpenDevice("internet.device",
  317.                 (long) INET_UNIT_TCP, &tnreq, 0L);
  318.     if (InternetBase != 0L){
  319.       printf("it did not open %d\n",InternetBase);
  320.       clean("i quit");
  321.     }
  322. /*    tcb = (struct tcb *) tnreq.io_Unit->iu_ccb;*/
  323.  
  324.     hostport = tnreq.io_lsocket.port;
  325.     deviceopened = 1;
  326.     tninreq = tnreq; /* possible lettuce bug  ?*/
  327.     tnoutreq = tnreq;
  328.     tninreq.io_Length = 512;
  329.     tnoutreq.io_Length = 1;
  330.     tninreq.io_Data = recv;
  331.     tnoutreq.io_Data = &InputCharacter;
  332.     tninreq.io_Command = CMD_READ;
  333.     tnoutreq.io_Command = CMD_WRITE;
  334.     tninreq.io_Message.mn_ReplyPort = tcpinp;
  335.     tnoutreq.io_Message.mn_ReplyPort = tcpoutp;
  336.     /* Create and initialize a Telnet protocol descriptor */
  337.     if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN){
  338.         myoserr("calloc faiuled\n");
  339.         goto done;
  340.     }
  341.     tn->session = s;    /* Upward pointer */
  342.     tn->state = TS_DATA;
  343.         SendIO(&tninreq);
  344.     onbreak(&brk);
  345.     InputCharacter = ' ';
  346.     while (! done)
  347.       {
  348.         if ((snd[0] = kbread()) >= 0){
  349.           
  350.           unix_send_tel(snd, (short) 1);}
  351.  
  352.         if (CheckIO(&tninreq))
  353.           {
  354.         chkabort();
  355.         WaitIO(&tninreq);
  356.             rcv_char();
  357.             if (tninreq.io_State != old)
  358.               {
  359.             showstate(old, tninreq.io_State);
  360.             old = tninreq.io_State;
  361.               }
  362.                 SendIO(&tninreq);
  363.           }
  364.       }
  365. done:
  366.     clean("All done");          
  367.  
  368. #ifdef NOTDEF
  369.     /* Allocate a session descriptor */
  370.     if((s = newsession()) == NULLSESSION){
  371.         printf("Too many sessions\r\n");
  372.         return 1;
  373.     }
  374.     s->type = TELNET;
  375.     if ((refuse_echo == 0) && (unix_line_mode != 0)) {
  376.         s->parse = unix_send_tel;
  377.     } else {
  378.         s->parse = send_tel;
  379.     }
  380.     current = s;
  381.  
  382.     /* Create and initialize a Telnet protocol descriptor */
  383.     if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN){
  384.         printf(nospace);
  385.         s->type = FREE;
  386.         return 1;
  387.     }
  388.     tn->session = s;    /* Upward pointer */
  389.     tn->state = TS_DATA;
  390.     s->cb.telnet = tn;    /* Downward pointer */
  391.  
  392.     tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,0,
  393.      rcv_char,NULLVFP,t_state,0,(int *)tn);
  394.     if(tcb == NULLTCB || tcb->state == CLOSED){
  395.         /* This is actually a bit dirty here. About the only time the
  396.          * state will be closed here is if we tried to connect to
  397.          * ourselves and got RST'ed.  If this is true then the close
  398.          * upcall will already have freed the TCB and telnet block,
  399.          * so we're looking at the TCB after it's back on the heap.
  400.          */
  401.         return 0;
  402.     }
  403.     tn->tcb = tcb;    /* Downward pointer */
  404.     go();
  405.     return 0;
  406. #endif
  407. }
  408.  
  409. /* Process typed characters */
  410. int
  411. unix_send_tel(buf,n)
  412. char *buf;
  413. int16 n;
  414. {
  415.     int i;
  416. /*printf("unix_send_tel: buf[0] %d\n", buf[0]);*/
  417.     for (i=0; (i<n) && (buf[i] != '\r'); i++)
  418.         ;
  419.     if (buf[i] == '\r') {
  420.         buf[i] = '\n';
  421.         n = i+1;
  422.     }
  423.     send_tel(buf,n);
  424. }
  425. int
  426. send_tel(buf,n)
  427. char *buf;
  428. int16 n;
  429. {
  430.     int i;
  431.  
  432.     tnoutreq.io_Data = buf;
  433.     tnoutreq.io_Length = n;
  434.  
  435.     SendIO(&tnoutreq);
  436. /*    printf("now waitio insend_tel: ");*/
  437.     i = WaitIO(&tnoutreq); 
  438. /*printf("send_tel: WaitIo is %d\n", i);*/
  439.     if (tnoutreq.io_State != old)
  440.       {
  441.         showstate(old, tnoutreq.io_State);
  442.         old = tnoutreq.io_State;
  443.       }
  444.  
  445. }
  446.  
  447. /* Process incoming TELNET characters */
  448. int
  449. tel_input(tn,bp, len)
  450. register struct telnet *tn;
  451. char *bp;
  452. int len;
  453. {
  454.     char c;
  455.     int ci;
  456.     void doopt(),dontopt(),willopt(),wontopt(),answer();
  457. #ifdef    FAST    /* DON'T USE -- Aztec memchr() routine is broken */
  458.     char *memchr();
  459.  
  460.     /* Optimization for very common special case -- no command chars */
  461.     if(tn->state == TS_DATA){
  462.         while(bp != NULLBUF && memchr(bp->data,IAC,bp->cnt) 
  463.             == NULLCHAR){
  464.             fflush(stdout);
  465.             write(1,bp->data,bp->cnt);
  466.             bp = free_mbuf(bp);
  467.         }
  468.     }
  469. #endif
  470.     while(len--){
  471.         c = *bp++;
  472.         ci = c & 0xff;
  473.         switch(tn->state){
  474.         case TS_DATA:
  475.             if(ci == IAC){
  476.                 tn->state = TS_IAC;
  477.             } else {
  478.                 if(!tn->remote[TN_TRANSMIT_BINARY])
  479.                     c &= 0x7f;
  480.                 putchar(c);
  481.             }
  482.             break;
  483.         case TS_IAC:
  484.             switch(ci){
  485.             case WILL:
  486.                 tn->state = TS_WILL;
  487.                 break;
  488.             case WONT:
  489.                 tn->state = TS_WONT;
  490.                 break;
  491.             case DO:
  492.                 tn->state = TS_DO;
  493.                 break;
  494.             case DONT:
  495.                 tn->state = TS_DONT;
  496.                 break;
  497.             case IAC:
  498.                 putchar(c);
  499.                 tn->state = TS_DATA;
  500.                 break;
  501.             default:
  502.                 tn->state = TS_DATA;
  503.                 break;
  504.             }
  505.             break;
  506.         case TS_WILL:
  507.             willopt(tn,ci);
  508.             tn->state = TS_DATA;
  509.             break;
  510.         case TS_WONT:
  511.             wontopt(tn,ci);
  512.             tn->state = TS_DATA;
  513.             break;
  514.         case TS_DO:
  515.             doopt(tn,ci);
  516.             tn->state = TS_DATA;
  517.             break;
  518.         case TS_DONT:
  519.             dontopt(tn,ci);
  520.             tn->state = TS_DATA;
  521.             break;
  522.         }
  523.     }
  524. }
  525.  
  526. #ifdef NOTDEF
  527. /* State change upcall routine */
  528. void
  529. t_state(tcb,old,new)
  530. register struct tcb *tcb;
  531. char old,new;
  532. {
  533.     struct telnet *tn;
  534.     char notify = 0;
  535.     extern char *tcpstates[];
  536.     extern char *reasons[];
  537.     extern char *unreach[];
  538.     extern char *exceed[];
  539.  
  540.     /* Can't add a check for unknown connection here, it would loop
  541.      * on a close upcall! We're just careful later on.
  542.      */
  543.     tn = (struct telnet *)tcb->user;
  544.  
  545.     if(current != NULLSESSION && current->type == TELNET && current->cb.telnet == tn)
  546.         notify = 1;
  547.  
  548.     switch(new){
  549.     case CLOSE_WAIT:
  550.         if(notify)
  551.             printf("%s\r\n",tcpstates[new]);
  552.         close_tcp(tcb);
  553.         break;
  554.     case CLOSED:    /* court adjourned */
  555.         if(notify){
  556.             printf("%s (%s",tcpstates[new],reasons[tcb->reason]);
  557.             if(tcb->reason == NETWORK){
  558.                 switch(tcb->type){
  559.                 case DEST_UNREACH:
  560.                     printf(": %s unreachable",unreach[tcb->code]);
  561.                     break;
  562.                 case TIME_EXCEED:
  563.                     printf(": %s time exceeded",exceed[tcb->code]);
  564.                     break;
  565.                 }
  566.             }
  567.             printf(")\r\n");
  568.             cmdmode();
  569.         }
  570.         del_tcp(tcb);
  571.         if(tn != NULLTN)
  572.             free_telnet(tn);
  573.         break;
  574.     default:
  575.         if(notify)
  576.             printf("%s\r\n",tcpstates[new]);
  577.         break;
  578.     }
  579.     fflush(stdout);
  580. }
  581. #endif
  582. /* Delete telnet structure */
  583. static
  584. free_telnet(tn)
  585. struct telnet *tn;
  586. {
  587.  
  588.     if(tn != NULLTN)
  589.         free((char *)tn);
  590. }
  591.  
  592. /* The guts of the actual Telnet protocol: negotiating options */
  593. static
  594. void
  595. willopt(tn,opt)
  596. struct telnet *tn;
  597. int opt;
  598. {
  599.     int ack;
  600.     void answer();
  601.  
  602. #ifdef    DEBUG
  603.     printf("recv: will ");
  604.     if(opt <= NOPTIONS)
  605.         printf("%s\r\n",t_options[opt]);
  606.     else
  607.         printf("%u\r\n",opt);
  608. #endif
  609.     
  610.     switch(opt){
  611.     case TN_TRANSMIT_BINARY:
  612.     case TN_ECHO:
  613.     case TN_SUPPRESS_GA:
  614.         if(tn->remote[opt] == 1)
  615.             return;        /* Already set, ignore to prevent loop */
  616.         if(opt == TN_ECHO){
  617.             if(refuse_echo){
  618.                 /* User doesn't want to accept */
  619.                 ack = DONT;
  620.                 break;
  621.             } else
  622.                 raw();        /* Put tty into raw mode */
  623.         }
  624.         tn->remote[opt] = 1;
  625.         ack = DO;            
  626.         break;
  627.     default:
  628.         ack = DONT;    /* We don't know what he's offering; refuse */
  629.     }
  630.     answer(tn,ack,opt);
  631. }
  632. static
  633. void
  634. wontopt(tn,opt)
  635. struct telnet *tn;
  636. int opt;
  637. {
  638.     void answer();
  639.  
  640. #ifdef    DEBUG
  641.     printf("recv: wont ");
  642.     if(opt <= NOPTIONS)
  643.         printf("%s\r\n",t_options[opt]);
  644.     else
  645.         printf("%u\r\n",opt);
  646. #endif
  647.     if(opt <= NOPTIONS){
  648.         if(tn->remote[opt] == 0)
  649.             return;        /* Already clear, ignore to prevent loop */
  650.         tn->remote[opt] = 0;
  651.         if(opt == TN_ECHO)
  652.             cooked();    /* Put tty into cooked mode */
  653.     }
  654.     answer(tn,DONT,opt);    /* Must always accept */
  655. }
  656. static
  657. void
  658. doopt(tn,opt)
  659. struct telnet *tn;
  660. int opt;
  661. {
  662.     void answer();
  663.     int ack;
  664.  
  665. #ifdef    DEBUG
  666.     printf("recv: do ");
  667.     if(opt <= NOPTIONS)
  668.         printf("%s\r\n",t_options[opt]);
  669.     else
  670.         printf("%u\r\n",opt);
  671. #endif
  672.     switch(opt){
  673. #ifdef    FUTURE    /* Use when local options are implemented */
  674.         if(tn->local[opt] == 1)
  675.             return;        /* Already set, ignore to prevent loop */
  676.         tn->local[opt] = 1;
  677.         ack = WILL;
  678.         break;
  679. #endif
  680.     default:
  681.         ack = WONT;    /* Don't know what it is */
  682.     }
  683.     answer(tn,ack,opt);
  684. }
  685. static
  686. void
  687. dontopt(tn,opt)
  688. struct telnet *tn;
  689. int opt;
  690. {
  691.     void answer();
  692.  
  693. #ifdef    DEBUG
  694.     printf("recv: dont ");
  695.     if(opt <= NOPTIONS)
  696.         printf("%s\r\n",t_options[opt]);
  697.     else
  698.         printf("%u\r\n",opt);
  699. #endif
  700.     if(opt <= NOPTIONS){
  701.         if(tn->local[opt] == 0){
  702.             /* Already clear, ignore to prevent loop */
  703.             return;
  704.         }
  705.         tn->local[opt] = 0;
  706.     }
  707.     answer(tn,WONT,opt);
  708. }
  709. static
  710. void
  711. answer(tn,r1,r2)
  712. struct telnet *tn;
  713. int r1,r2;
  714. {
  715.     struct mbuf *bp,*qdata();
  716.     char s[3];
  717.  
  718. #ifdef    DEBUG
  719.     switch(r1){
  720.     case WILL:
  721.         printf("sent: will ");
  722.         break;
  723.     case WONT:
  724.         printf("sent: wont ");
  725.         break;
  726.     case DO:
  727.         printf("sent: do ");
  728.         break;
  729.     case DONT:
  730.         printf("sent: dont ");
  731.         break;
  732.     }
  733.     if(r2 <= 6)
  734.         printf("%s\r\n",t_options[r2]);
  735.     else
  736.         printf("%u\r\n",r2);
  737. #endif
  738.  
  739.     s[0] = IAC;
  740.     s[1] = r1;
  741.     s[2] = r2;
  742.     tnoutreq.io_Data = s;
  743.     tnoutreq.io_Length = 3;
  744.     DoIO(&tnoutreq);
  745. /*
  746.     bp = qdata(s,(int16)3);
  747.     send_tcp(tn->tcb,bp);
  748. */
  749. }
  750.  
  751. #define    BUFMAXCNT    150
  752. static char conbuf[BUFMAXCNT];
  753. static int concnt = 0;
  754.  
  755. int
  756. amigaputchar(c)
  757.     char c;
  758. {
  759.     conbuf[concnt++] = c;
  760.     if ((c == '\n') || (concnt == BUFMAXCNT))
  761.         amigaflush();
  762.     return c;
  763. }
  764.  
  765. amigaflush()
  766. {
  767.     if (concnt == 0)
  768.         return;
  769.     consout.io_Data = (APTR) conbuf;
  770.     consout.io_Length = concnt;
  771.     consout.io_Command = CMD_WRITE;
  772.     DoIO(&consout);
  773.     concnt = 0;
  774. }
  775.     
  776. /*
  777.  *  Begin terrible, horrible hack.  All output should be printed upon (into?)
  778.  *  the window we opened before.  Here goes nothing...
  779.  */
  780.  
  781. printf(a, b, c, d, e, f, g, h, i, j, k)
  782.     char *a;
  783.     int b, c, d, e, f, g, h, i, j, k;
  784. {
  785.     if (concnt)
  786.         amigaflush();
  787.  
  788.     sprintf(conbuf, a, b, c, d, e, f, g, h, i, j, k);
  789.     consout.io_Data = (APTR) conbuf;
  790.     consout.io_Length = strlen(conbuf);
  791.     consout.io_Command = CMD_WRITE;
  792.     DoIO(&consout);        /* no use in doing this async */
  793. }
  794.