1 1.16 maya /* $NetBSD: terminal.c,v 1.16 2018/12/14 06:08:18 maya Exp $ */ 2 1.5 thorpej 3 1.1 cgd /* 4 1.3 cgd * Copyright (c) 1988, 1990, 1993 5 1.3 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.13 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.6 christos #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.5 thorpej #if 0 35 1.5 thorpej static char sccsid[] = "@(#)terminal.c 8.2 (Berkeley) 2/16/95"; 36 1.5 thorpej #else 37 1.16 maya __RCSID("$NetBSD: terminal.c,v 1.16 2018/12/14 06:08:18 maya Exp $"); 38 1.5 thorpej #endif 39 1.1 cgd #endif /* not lint */ 40 1.1 cgd 41 1.1 cgd #include <arpa/telnet.h> 42 1.1 cgd #include <sys/types.h> 43 1.1 cgd 44 1.1 cgd #include "ring.h" 45 1.1 cgd 46 1.1 cgd #include "externs.h" 47 1.1 cgd #include "types.h" 48 1.1 cgd 49 1.7 thorpej #ifdef ENCRYPTION 50 1.7 thorpej #include <libtelnet/encrypt.h> 51 1.7 thorpej #endif 52 1.7 thorpej 53 1.1 cgd Ring ttyoring, ttyiring; 54 1.1 cgd unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ]; 55 1.15 christos char line[] = { '\0' }; 56 1.1 cgd 57 1.1 cgd int termdata; /* Debugging flag */ 58 1.1 cgd 59 1.1 cgd /* 60 1.1 cgd * initialize the terminal data structures. 61 1.1 cgd */ 62 1.1 cgd 63 1.10 christos void 64 1.10 christos init_terminal(void) 65 1.1 cgd { 66 1.1 cgd if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) { 67 1.1 cgd exit(1); 68 1.1 cgd } 69 1.1 cgd if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) { 70 1.1 cgd exit(1); 71 1.1 cgd } 72 1.1 cgd autoflush = TerminalAutoFlush(); 73 1.1 cgd } 74 1.1 cgd 75 1.1 cgd 76 1.1 cgd /* 77 1.14 heas * Send as much data as possible to the terminal, else exits if 78 1.14 heas * it encounters a permanent failure when writing to the tty. 79 1.1 cgd * 80 1.1 cgd * Return value: 81 1.1 cgd * -1: No useful work done, data waiting to go out. 82 1.1 cgd * 0: No data was waiting, so nothing was done. 83 1.1 cgd * 1: All waiting data was written out. 84 1.1 cgd * n: All data - n was written out. 85 1.1 cgd */ 86 1.1 cgd 87 1.1 cgd 88 1.10 christos int 89 1.10 christos ttyflush(int drop) 90 1.1 cgd { 91 1.8 wiz int n, n0, n1; 92 1.1 cgd 93 1.1 cgd n0 = ring_full_count(&ttyoring); 94 1.1 cgd if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) { 95 1.1 cgd if (drop) { 96 1.1 cgd TerminalFlushOutput(); 97 1.1 cgd /* we leave 'n' alone! */ 98 1.1 cgd } else { 99 1.1 cgd n = TerminalWrite(ttyoring.consume, n); 100 1.1 cgd } 101 1.1 cgd } 102 1.1 cgd if (n > 0) { 103 1.1 cgd if (termdata && n) { 104 1.1 cgd Dump('>', ttyoring.consume, n); 105 1.1 cgd } 106 1.1 cgd /* 107 1.1 cgd * If we wrote everything, and the full count is 108 1.1 cgd * larger than what we wrote, then write the 109 1.1 cgd * rest of the buffer. 110 1.1 cgd */ 111 1.1 cgd if (n1 == n && n0 > n) { 112 1.1 cgd n1 = n0 - n; 113 1.1 cgd if (!drop) 114 1.1 cgd n1 = TerminalWrite(ttyoring.bottom, n1); 115 1.4 jtk if (n1 > 0) 116 1.4 jtk n += n1; 117 1.1 cgd } 118 1.1 cgd ring_consumed(&ttyoring, n); 119 1.1 cgd } 120 1.9 christos if (n < 0) { 121 1.14 heas if (errno == EAGAIN || errno == EINTR) { 122 1.9 christos return -1; 123 1.14 heas } else { 124 1.14 heas ring_consumed(&ttyoring, ring_full_count(&ttyoring)); 125 1.14 heas setconnmode(0); 126 1.14 heas setcommandmode(); 127 1.14 heas NetClose(net); 128 1.14 heas fprintf(stderr, "Connection closed by foreign host.\n"); 129 1.14 heas exit(1); 130 1.14 heas } 131 1.9 christos } 132 1.1 cgd if (n == n0) { 133 1.1 cgd if (n0) 134 1.1 cgd return -1; 135 1.1 cgd return 0; 136 1.1 cgd } 137 1.1 cgd return n0 - n + 1; 138 1.1 cgd } 139 1.1 cgd 140 1.1 cgd 141 1.1 cgd /* 143 1.1 cgd * These routines decides on what the mode should be (based on the values 144 1.1 cgd * of various global variables). 145 1.1 cgd */ 146 1.1 cgd 147 1.10 christos 148 1.10 christos int 149 1.1 cgd getconnmode(void) 150 1.1 cgd { 151 1.1 cgd extern int linemode; 152 1.1 cgd int mode = 0; 153 1.1 cgd #ifdef KLUDGELINEMODE 154 1.1 cgd extern int kludgelinemode; 155 1.1 cgd #endif 156 1.1 cgd 157 1.1 cgd if (my_want_state_is_dont(TELOPT_ECHO)) 158 1.1 cgd mode |= MODE_ECHO; 159 1.1 cgd 160 1.1 cgd if (localflow) 161 1.1 cgd mode |= MODE_FLOW; 162 1.1 cgd 163 1.1 cgd if (my_want_state_is_will(TELOPT_BINARY)) 164 1.1 cgd mode |= MODE_INBIN; 165 1.1 cgd 166 1.1 cgd if (his_want_state_is_will(TELOPT_BINARY)) 167 1.1 cgd mode |= MODE_OUTBIN; 168 1.1 cgd 169 1.1 cgd #ifdef KLUDGELINEMODE 170 1.1 cgd if (kludgelinemode) { 171 1.1 cgd if (my_want_state_is_dont(TELOPT_SGA)) { 172 1.1 cgd mode |= (MODE_TRAPSIG|MODE_EDIT); 173 1.1 cgd if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) { 174 1.1 cgd mode &= ~MODE_ECHO; 175 1.1 cgd } 176 1.1 cgd } 177 1.1 cgd return(mode); 178 1.1 cgd } 179 1.1 cgd #endif 180 1.1 cgd if (my_want_state_is_will(TELOPT_LINEMODE)) 181 1.1 cgd mode |= linemode; 182 1.1 cgd return(mode); 183 1.1 cgd } 184 1.10 christos 185 1.10 christos void 186 1.1 cgd setconnmode(int force) 187 1.7 thorpej { 188 1.7 thorpej #ifdef ENCRYPTION 189 1.7 thorpej static int enc_passwd = 0; 190 1.8 wiz #endif 191 1.1 cgd int newmode; 192 1.1 cgd 193 1.1 cgd newmode = getconnmode()|(force?MODE_FORCE:0); 194 1.1 cgd 195 1.1 cgd TerminalNewMode(newmode); 196 1.7 thorpej 197 1.7 thorpej #ifdef ENCRYPTION 198 1.7 thorpej if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) { 199 1.7 thorpej if (my_want_state_is_will(TELOPT_ENCRYPT) 200 1.7 thorpej && (enc_passwd == 0) && !encrypt_output) { 201 1.7 thorpej encrypt_request_start(0, 0); 202 1.7 thorpej enc_passwd = 1; 203 1.7 thorpej } 204 1.7 thorpej } else { 205 1.7 thorpej if (enc_passwd) { 206 1.7 thorpej encrypt_request_end(); 207 1.7 thorpej enc_passwd = 0; 208 1.7 thorpej } 209 1.7 thorpej } 210 1.1 cgd #endif /* ENCRYPTION */ 211 1.1 cgd } 212 1.1 cgd 213 1.10 christos 214 1.10 christos void 215 1.1 cgd setcommandmode(void) 216 1.1 cgd { 217 1.1 cgd TerminalNewMode(-1); 218 } 219