[BACK]Return to tn3270.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / telnet

Annotation of src/usr.bin/telnet/tn3270.c, Revision 1.1.1.1

1.1       deraadt     1: /*
                      2:  * Copyright (c) 1988, 1993
                      3:  *     The Regents of the University of California.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
                     33:
                     34: #ifndef lint
                     35: /* from: static char sccsid[] = "@(#)tn3270.c  8.1 (Berkeley) 6/6/93"; */
                     36: static char *rcsid = "$Id: tn3270.c,v 1.3 1994/02/25 03:00:48 cgd Exp $";
                     37: #endif /* not lint */
                     38:
                     39: #include <sys/types.h>
                     40: #include <arpa/telnet.h>
                     41:
                     42: #include "general.h"
                     43:
                     44: #include "defines.h"
                     45: #include "ring.h"
                     46: #include "externs.h"
                     47: #include "fdset.h"
                     48:
                     49: #if    defined(TN3270)
                     50:
                     51: #include "../ctlr/screen.h"
                     52: #include "../general/globals.h"
                     53:
                     54: #include "../sys_curses/telextrn.h"
                     55: #include "../ctlr/externs.h"
                     56:
                     57: #if    defined(unix)
                     58: int
                     59:        HaveInput,              /* There is input available to scan */
                     60:        cursesdata,             /* Do we dump curses data? */
                     61:        sigiocount;             /* Number of times we got a SIGIO */
                     62:
                     63: char   tline[200];
                     64: char   *transcom = 0;  /* transparent mode command (default: none) */
                     65: #endif /* defined(unix) */
                     66:
                     67: char   Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
                     68:
                     69: static char    sb_terminal[] = { IAC, SB,
                     70:                        TELOPT_TTYPE, TELQUAL_IS,
                     71:                        'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
                     72:                        IAC, SE };
                     73: #define        SBTERMMODEL     13
                     74:
                     75: static int
                     76:        Sent3270TerminalType;   /* Have we said we are a 3270? */
                     77:
                     78: #endif /* defined(TN3270) */
                     79:
                     80:
                     81:     void
                     82: init_3270()
                     83: {
                     84: #if    defined(TN3270)
                     85: #if    defined(unix)
                     86:     HaveInput = 0;
                     87:     sigiocount = 0;
                     88: #endif /* defined(unix) */
                     89:     Sent3270TerminalType = 0;
                     90:     Ifrontp = Ibackp = Ibuf;
                     91:     init_ctlr();               /* Initialize some things */
                     92:     init_keyboard();
                     93:     init_screen();
                     94:     init_system();
                     95: #endif /* defined(TN3270) */
                     96: }
                     97:
                     98: 
                     99: #if    defined(TN3270)
                    100:
                    101: /*
                    102:  * DataToNetwork - queue up some data to go to network.  If "done" is set,
                    103:  * then when last byte is queued, we add on an IAC EOR sequence (so,
                    104:  * don't call us with "done" until you want that done...)
                    105:  *
                    106:  * We actually do send all the data to the network buffer, since our
                    107:  * only client needs for us to do that.
                    108:  */
                    109:
                    110:     int
                    111: DataToNetwork(buffer, count, done)
                    112:     register char *buffer;     /* where the data is */
                    113:     register int  count;       /* how much to send */
                    114:     int                  done;         /* is this the last of a logical block */
                    115: {
                    116:     register int loop, c;
                    117:     int origCount;
                    118:
                    119:     origCount = count;
                    120:
                    121:     while (count) {
                    122:        /* If not enough room for EORs, IACs, etc., wait */
                    123:        if (NETROOM() < 6) {
                    124:            fd_set o;
                    125:
                    126:            FD_ZERO(&o);
                    127:            netflush();
                    128:            while (NETROOM() < 6) {
                    129:                FD_SET(net, &o);
                    130:                (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
                    131:                                                (struct timeval *) 0);
                    132:                netflush();
                    133:            }
                    134:        }
                    135:        c = ring_empty_count(&netoring);
                    136:        if (c > count) {
                    137:            c = count;
                    138:        }
                    139:        loop = c;
                    140:        while (loop) {
                    141:            if (((unsigned char)*buffer) == IAC) {
                    142:                break;
                    143:            }
                    144:            buffer++;
                    145:            loop--;
                    146:        }
                    147:        if ((c = c-loop)) {
                    148:            ring_supply_data(&netoring, buffer-c, c);
                    149:            count -= c;
                    150:        }
                    151:        if (loop) {
                    152:            NET2ADD(IAC, IAC);
                    153:            count--;
                    154:            buffer++;
                    155:        }
                    156:     }
                    157:
                    158:     if (done) {
                    159:        NET2ADD(IAC, EOR);
                    160:        netflush();             /* try to move along as quickly as ... */
                    161:     }
                    162:     return(origCount - count);
                    163: }
                    164:
                    165:
                    166: #if    defined(unix)
                    167:     void
                    168: inputAvailable(signo)
                    169:        int signo;
                    170: {
                    171:     HaveInput = 1;
                    172:     sigiocount++;
                    173: }
                    174: #endif /* defined(unix) */
                    175:
                    176:     void
                    177: outputPurge()
                    178: {
                    179:     (void) ttyflush(1);
                    180: }
                    181:
                    182:
                    183: /*
                    184:  * The following routines are places where the various tn3270
                    185:  * routines make calls into telnet.c.
                    186:  */
                    187:
                    188: /*
                    189:  * DataToTerminal - queue up some data to go to terminal.
                    190:  *
                    191:  * Note: there are people who call us and depend on our processing
                    192:  * *all* the data at one time (thus the select).
                    193:  */
                    194:
                    195:     int
                    196: DataToTerminal(buffer, count)
                    197:     register char      *buffer;                /* where the data is */
                    198:     register int       count;                  /* how much to send */
                    199: {
                    200:     register int c;
                    201:     int origCount;
                    202:
                    203:     origCount = count;
                    204:
                    205:     while (count) {
                    206:        if (TTYROOM() == 0) {
                    207: #if    defined(unix)
                    208:            fd_set o;
                    209:
                    210:            FD_ZERO(&o);
                    211: #endif /* defined(unix) */
                    212:            (void) ttyflush(0);
                    213:            while (TTYROOM() == 0) {
                    214: #if    defined(unix)
                    215:                FD_SET(tout, &o);
                    216:                (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
                    217:                                                (struct timeval *) 0);
                    218: #endif /* defined(unix) */
                    219:                (void) ttyflush(0);
                    220:            }
                    221:        }
                    222:        c = TTYROOM();
                    223:        if (c > count) {
                    224:            c = count;
                    225:        }
                    226:        ring_supply_data(&ttyoring, buffer, c);
                    227:        count -= c;
                    228:        buffer += c;
                    229:     }
                    230:     return(origCount);
                    231: }
                    232: 
                    233:
                    234: /*
                    235:  * Push3270 - Try to send data along the 3270 output (to screen) direction.
                    236:  */
                    237:
                    238:     int
                    239: Push3270()
                    240: {
                    241:     int save = ring_full_count(&netiring);
                    242:
                    243:     if (save) {
                    244:        if (Ifrontp+save > Ibuf+sizeof Ibuf) {
                    245:            if (Ibackp != Ibuf) {
                    246:                memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
                    247:                Ifrontp -= (Ibackp-Ibuf);
                    248:                Ibackp = Ibuf;
                    249:            }
                    250:        }
                    251:        if (Ifrontp+save < Ibuf+sizeof Ibuf) {
                    252:            (void)telrcv();
                    253:        }
                    254:     }
                    255:     return save != ring_full_count(&netiring);
                    256: }
                    257:
                    258:
                    259: /*
                    260:  * Finish3270 - get the last dregs of 3270 data out to the terminal
                    261:  *             before quitting.
                    262:  */
                    263:
                    264:     void
                    265: Finish3270()
                    266: {
                    267:     while (Push3270() || !DoTerminalOutput()) {
                    268: #if    defined(unix)
                    269:        HaveInput = 0;
                    270: #endif /* defined(unix) */
                    271:        ;
                    272:     }
                    273: }
                    274:
                    275:
                    276: /* StringToTerminal - output a null terminated string to the terminal */
                    277:
                    278:     void
                    279: StringToTerminal(s)
                    280:     char *s;
                    281: {
                    282:     int count;
                    283:
                    284:     count = strlen(s);
                    285:     if (count) {
                    286:        (void) DataToTerminal(s, count);        /* we know it always goes... */
                    287:     }
                    288: }
                    289:
                    290:
                    291: #if    ((!defined(NOT43)) || defined(PUTCHAR))
                    292: /* _putchar - output a single character to the terminal.  This name is so that
                    293:  *     curses(3x) can call us to send out data.
                    294:  */
                    295:
                    296:     void
                    297: _putchar(c)
                    298:     char c;
                    299: {
                    300: #if    defined(sun)            /* SunOS 4.0 bug */
                    301:     c &= 0x7f;
                    302: #endif /* defined(sun) */
                    303:     if (cursesdata) {
                    304:        Dump('>', &c, 1);
                    305:     }
                    306:     if (!TTYROOM()) {
                    307:        (void) DataToTerminal(&c, 1);
                    308:     } else {
                    309:        TTYADD(c);
                    310:     }
                    311: }
                    312: #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
                    313:
                    314:     void
                    315: SetIn3270()
                    316: {
                    317:     if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
                    318:                && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
                    319:        if (!In3270) {
                    320:            In3270 = 1;
                    321:            Init3270();         /* Initialize 3270 functions */
                    322:            /* initialize terminal key mapping */
                    323:            InitTerminal();     /* Start terminal going */
                    324:            setconnmode(0);
                    325:        }
                    326:     } else {
                    327:        if (In3270) {
                    328:            StopScreen(1);
                    329:            In3270 = 0;
                    330:            Stop3270();         /* Tell 3270 we aren't here anymore */
                    331:            setconnmode(0);
                    332:        }
                    333:     }
                    334: }
                    335:
                    336: /*
                    337:  * tn3270_ttype()
                    338:  *
                    339:  *     Send a response to a terminal type negotiation.
                    340:  *
                    341:  *     Return '0' if no more responses to send; '1' if a response sent.
                    342:  */
                    343:
                    344:     int
                    345: tn3270_ttype()
                    346: {
                    347:     /*
                    348:      * Try to send a 3270 type terminal name.  Decide which one based
                    349:      * on the format of our screen, and (in the future) color
                    350:      * capaiblities.
                    351:      */
                    352:     InitTerminal();            /* Sets MaxNumberColumns, MaxNumberLines */
                    353:     if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
                    354:        Sent3270TerminalType = 1;
                    355:        if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
                    356:            MaxNumberLines = 27;
                    357:            MaxNumberColumns = 132;
                    358:            sb_terminal[SBTERMMODEL] = '5';
                    359:        } else if (MaxNumberLines >= 43) {
                    360:            MaxNumberLines = 43;
                    361:            MaxNumberColumns = 80;
                    362:            sb_terminal[SBTERMMODEL] = '4';
                    363:        } else if (MaxNumberLines >= 32) {
                    364:            MaxNumberLines = 32;
                    365:            MaxNumberColumns = 80;
                    366:            sb_terminal[SBTERMMODEL] = '3';
                    367:        } else {
                    368:            MaxNumberLines = 24;
                    369:            MaxNumberColumns = 80;
                    370:            sb_terminal[SBTERMMODEL] = '2';
                    371:        }
                    372:        NumberLines = 24;               /* before we start out... */
                    373:        NumberColumns = 80;
                    374:        ScreenSize = NumberLines*NumberColumns;
                    375:        if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
                    376:            ExitString("Programming error:  MAXSCREENSIZE too small.\n",
                    377:                                                                1);
                    378:            /*NOTREACHED*/
                    379:        }
                    380:        printsub('>', sb_terminal+2, sizeof sb_terminal-2);
                    381:        ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
                    382:        return 1;
                    383:     } else {
                    384:        return 0;
                    385:     }
                    386: }
                    387:
                    388: #if    defined(unix)
                    389:        int
                    390: settranscom(argc, argv)
                    391:        int argc;
                    392:        char *argv[];
                    393: {
                    394:        int i;
                    395:
                    396:        if (argc == 1 && transcom) {
                    397:           transcom = 0;
                    398:        }
                    399:        if (argc == 1) {
                    400:           return 1;
                    401:        }
                    402:        transcom = tline;
                    403:        (void) strcpy(transcom, argv[1]);
                    404:        for (i = 2; i < argc; ++i) {
                    405:            (void) strcat(transcom, " ");
                    406:            (void) strcat(transcom, argv[i]);
                    407:        }
                    408:        return 1;
                    409: }
                    410: #endif /* defined(unix) */
                    411:
                    412: #endif /* defined(TN3270) */