[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     ! 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) */