230 |
230 |
231 "Modified: / 5.5.1999 / 17:25:59 / cg" |
231 "Modified: / 5.5.1999 / 17:25:59 / cg" |
232 ! |
232 ! |
233 |
233 |
234 openOnInput:inStream output:outStream in:aView |
234 openOnInput:inStream output:outStream in:aView |
235 "open a terminalView on the given streams (which are typically some |
235 "open a terminalView on the given streams |
236 kind of socket or pty). |
236 (which are typically some kind of socket or pty). |
237 Keys pressed are sent to inStream, text appearing |
237 Keys pressed are sent to inStream, text appearing |
238 from outStream is displayed in the terminal view. |
238 from outStream is displayed in the terminal view. |
239 This can be used to implement things like rlogin |
239 This can be used to implement things like rlogin |
240 or telnet views (if connected to a modem, a com-program can also be |
240 or telnet views (if connected to a modem, a com-program can also be |
241 implemented this way)." |
241 implemented this way)." |
246 scr origin:0.0@0.0 corner:1.0@1.0. |
246 scr origin:0.0@0.0 corner:1.0@1.0. |
247 vt := scr scrolledView. |
247 vt := scr scrolledView. |
248 |
248 |
249 vt inStream:inStream. |
249 vt inStream:inStream. |
250 vt outStream:outStream. |
250 vt outStream:outStream. |
251 vt startReaderProcess. |
251 vt startReaderProcessWhenVisible. |
252 |
252 |
253 ^ scr |
253 ^ scr |
254 |
254 |
255 "Modified: / 5.5.1999 / 17:25:59 / cg" |
255 "Modified: / 5.5.1999 / 17:25:59 / cg" |
256 ! |
256 ! |
1104 ^ kbdMap |
1104 ^ kbdMap |
1105 |
1105 |
1106 "Modified: / 10.6.1998 / 17:46:59 / cg" |
1106 "Modified: / 10.6.1998 / 17:46:59 / cg" |
1107 ! |
1107 ! |
1108 |
1108 |
|
1109 readerProcessLoop |
|
1110 "look for the commands output, |
|
1111 and send me #processInput:n: events whenever something arrives." |
|
1112 |
|
1113 StreamError handle:[:ex | |
|
1114 Transcript show:'Terminal(PTY-reader) [error]: '; showCR:ex description. |
|
1115 ] do:[ |
|
1116 [true] whileTrue:[ |
|
1117 Object abortSignal handle:[:ex | |
|
1118 self showCursor. |
|
1119 ] do:[ |
|
1120 |n sensor| |
|
1121 |
|
1122 outStream readWait. |
|
1123 sensor := self sensor. |
|
1124 (sensor notNil and:[sensor hasKeyPressEventFor:self]) ifTrue:[ |
|
1125 true "(sensor userEventCount > 10)" ifTrue:[ |
|
1126 "/ give terminalView a chance to |
|
1127 "/ send out the character. |
|
1128 Delay waitForSeconds:0.01. |
|
1129 ] |
|
1130 ] ifFalse:[ |
|
1131 n := self readAnyAvailableData. |
|
1132 n > 0 ifTrue:[ |
|
1133 shellPid notNil ifTrue:[ |
|
1134 self waitForOutputToDrain. |
|
1135 ] |
|
1136 ] ifFalse:[ |
|
1137 n == 0 ifTrue:[ |
|
1138 "/ Windows IPC has a bug - it always |
|
1139 "/ returns 0 (when the command is idle) |
|
1140 "/ and says its at the end (sigh) |
|
1141 |
|
1142 OperatingSystem isMSWINDOWSlike ifTrue:[ |
|
1143 Delay waitForSeconds:0.01 |
|
1144 ] ifFalse:[ |
|
1145 outStream atEnd ifTrue:[ |
|
1146 outStream close. outStream := nil. |
|
1147 inStream close. inStream := nil. |
|
1148 Processor activeProcess terminate. |
|
1149 ] ifFalse:[ |
|
1150 "/ this should not happen. |
|
1151 |
|
1152 Delay waitForSeconds:0.05 |
|
1153 ] |
|
1154 ]. |
|
1155 ] |
|
1156 ] |
|
1157 ] |
|
1158 ] |
|
1159 ] |
|
1160 ] |
|
1161 ! |
|
1162 |
1109 reinitialize |
1163 reinitialize |
1110 "reinit after a snapIn. |
1164 "reinit after a snapIn. |
1111 this is invoked (by the system thread) after a snapShot image restart" |
1165 this is invoked (by the system thread) after a snapShot image restart" |
1112 |
1166 |
1113 super reinitialize. |
1167 super reinitialize. |
1150 |
1204 |
1151 startReaderProcess |
1205 startReaderProcess |
1152 "Start a reader process, which looks for the commands output, |
1206 "Start a reader process, which looks for the commands output, |
1153 and sends me #processInput:n: events whenever something arrives." |
1207 and sends me #processInput:n: events whenever something arrives." |
1154 |
1208 |
|
1209 self obsoleteMethodWarning. |
|
1210 self startReaderProcessWhenVisible. |
|
1211 |
|
1212 " |
|
1213 VT100TerminalView openShell |
|
1214 " |
|
1215 |
|
1216 "Modified: / 5.5.1999 / 17:58:02 / cg" |
|
1217 "Modified: / 28.1.2002 / 21:10:13 / micha" |
|
1218 ! |
|
1219 |
|
1220 startReaderProcessNow |
|
1221 "Start a reader process, which looks for the commands output, |
|
1222 and sends me #processInput:n: events whenever something arrives." |
|
1223 |
1155 readerProcess isNil ifTrue:[ |
1224 readerProcess isNil ifTrue:[ |
1156 readerProcess := [ |
1225 readerProcess := [ |
1157 [ |
1226 [ |
1158 self waitUntilVisible. |
1227 self readerProcessLoop. |
1159 |
|
1160 StreamError handle:[:ex | |
|
1161 Transcript show:'Terminal(PTY-reader) [error]: '; showCR:ex description. |
|
1162 ] do:[ |
|
1163 [true] whileTrue:[ |
|
1164 Object abortSignal handle:[:ex | |
|
1165 self showCursor. |
|
1166 ] do:[ |
|
1167 |n sensor| |
|
1168 |
|
1169 outStream readWait. |
|
1170 sensor := self sensor. |
|
1171 (sensor notNil and:[sensor hasKeyPressEventFor:self]) ifTrue:[ |
|
1172 true "(sensor userEventCount > 10)" ifTrue:[ |
|
1173 "/ give terminalView a chance to |
|
1174 "/ send out the character. |
|
1175 Delay waitForSeconds:0.01. |
|
1176 ] |
|
1177 ] ifFalse:[ |
|
1178 n := self readAnyAvailableData. |
|
1179 n > 0 ifTrue:[ |
|
1180 shellPid notNil ifTrue:[ |
|
1181 self waitForOutputToDrain. |
|
1182 ] |
|
1183 ] ifFalse:[ |
|
1184 n == 0 ifTrue:[ |
|
1185 "/ Windows IPC has a bug - it always |
|
1186 "/ returns 0 (when the command is idle) |
|
1187 "/ and says its at the end (sigh) |
|
1188 |
|
1189 OperatingSystem isMSWINDOWSlike ifTrue:[ |
|
1190 Delay waitForSeconds:0.01 |
|
1191 ] ifFalse:[ |
|
1192 outStream atEnd ifTrue:[ |
|
1193 outStream close. outStream := nil. |
|
1194 inStream close. inStream := nil. |
|
1195 Processor activeProcess terminate. |
|
1196 ] ifFalse:[ |
|
1197 "/ this should not happen. |
|
1198 |
|
1199 Delay waitForSeconds:0.05 |
|
1200 ] |
|
1201 ]. |
|
1202 ] |
|
1203 ] |
|
1204 ] |
|
1205 ] |
|
1206 ] |
|
1207 ] |
|
1208 ] ifCurtailed:[ |
1228 ] ifCurtailed:[ |
1209 readerProcess := nil |
1229 readerProcess := nil |
1210 ] |
1230 ] |
1211 ] fork. "/ forkAt:9. |
1231 ] fork. "/ forkAt:9. |
1212 readerProcess name:'pty reader'. |
1232 readerProcess name:'pty reader'. |
1218 |
1238 |
1219 "Modified: / 5.5.1999 / 17:58:02 / cg" |
1239 "Modified: / 5.5.1999 / 17:58:02 / cg" |
1220 "Modified: / 28.1.2002 / 21:10:13 / micha" |
1240 "Modified: / 28.1.2002 / 21:10:13 / micha" |
1221 ! |
1241 ! |
1222 |
1242 |
|
1243 startReaderProcessWhenVisible |
|
1244 "Start a reader process, which looks for the commands output, |
|
1245 and sends me #processInput:n: events whenever something arrives." |
|
1246 |
|
1247 readerProcess isNil ifTrue:[ |
|
1248 readerProcess := [ |
|
1249 [ |
|
1250 self waitUntilVisible. |
|
1251 self readerProcessLoop. |
|
1252 ] ifCurtailed:[ |
|
1253 readerProcess := nil |
|
1254 ] |
|
1255 ] fork. "/ forkAt:9. |
|
1256 readerProcess name:'pty reader'. |
|
1257 ] |
|
1258 |
|
1259 " |
|
1260 VT100TerminalView openShell |
|
1261 " |
|
1262 |
|
1263 "Modified: / 5.5.1999 / 17:58:02 / cg" |
|
1264 "Modified: / 28.1.2002 / 21:10:13 / micha" |
|
1265 ! |
|
1266 |
1223 stopReaderProcess |
1267 stopReaderProcess |
1224 "stop the background reader thread" |
1268 "stop the background reader thread" |
1225 |
1269 |
1226 |sensor| |
1270 |sensor| |
1227 |
1271 |
1239 "Modified: / 21.7.1998 / 19:00:13 / cg" |
1283 "Modified: / 21.7.1998 / 19:00:13 / cg" |
1240 ! ! |
1284 ! ! |
1241 |
1285 |
1242 !TerminalView methodsFor:'initialization-shell'! |
1286 !TerminalView methodsFor:'initialization-shell'! |
1243 |
1287 |
1244 startCommand:aCommand |
1288 basicStartCommand:aCommand in:aDirectory |
1245 "start a command on a pseudo terminal. If the command arg is nil, |
|
1246 a shell is started. The command is started in the current directory. |
|
1247 Also fork a reader process, to read the shells output and |
|
1248 tell me, whenever something arrives" |
|
1249 |
|
1250 ^ self startCommand:aCommand in:nil |
|
1251 |
|
1252 "Modified: / 20.7.1998 / 18:30:24 / cg" |
|
1253 ! |
|
1254 |
|
1255 startCommand:aCommand in:aDirectory |
|
1256 "start a command on a pseudo terminal. If the command arg is nil, |
1289 "start a command on a pseudo terminal. If the command arg is nil, |
1257 a shell is started. If aDirectory is not nil, the command is |
1290 a shell is started. If aDirectory is not nil, the command is |
1258 executed in that directory. |
1291 executed in that directory. |
1259 Also fork a reader process, to read the shells output and |
1292 Also fork a reader process, to read the shells output and |
1260 tell me, whenever something arrives" |
1293 tell me, whenever something arrives" |
1269 |
1302 |
1270 OperatingSystem isMSWINDOWSlike ifTrue:[ |
1303 OperatingSystem isMSWINDOWSlike ifTrue:[ |
1271 "use two pipes to COMMAND.COM" |
1304 "use two pipes to COMMAND.COM" |
1272 stxToCommandPipe := NonPositionableExternalStream makePipe. |
1305 stxToCommandPipe := NonPositionableExternalStream makePipe. |
1273 stxToCommandPipe isNil ifTrue:[ |
1306 stxToCommandPipe isNil ifTrue:[ |
1274 ^ self warn:'Could not create pipe to COMMAND.COM.'. |
1307 self warn:'Could not create pipe to COMMAND.COM.'. ^ self. |
1275 ]. |
1308 ]. |
1276 |
1309 |
1277 commandToStxPipe := NonPositionableExternalStream makePipe. |
1310 commandToStxPipe := NonPositionableExternalStream makePipe. |
1278 commandToStxPipe isNil ifTrue:[ |
1311 commandToStxPipe isNil ifTrue:[ |
1279 ^ self warn:'Could not create pipe from COMMAND.COM.'. |
1312 self warn:'Could not create pipe from COMMAND.COM.'. ^ self. |
1280 ]. |
1313 ]. |
1281 |
1314 |
1282 "/ pipe readSide is p at:1; |
1315 "/ pipe readSide is p at:1; |
1283 "/ writeSide is p at:2 |
1316 "/ writeSide is p at:2 |
1284 |
1317 |
1380 inStream close. |
1413 inStream close. |
1381 inStream := outStream := nil. |
1414 inStream := outStream := nil. |
1382 ^ self. |
1415 ^ self. |
1383 ]. |
1416 ]. |
1384 |
1417 |
1385 self startReaderProcess. |
1418 "Created: / 20.7.1998 / 18:19:32 / cg" |
|
1419 "Modified: / 5.5.1999 / 17:28:37 / cg" |
|
1420 ! |
|
1421 |
|
1422 startCommand:aCommand |
|
1423 "start a command on a pseudo terminal. If the command arg is nil, |
|
1424 a shell is started. The command is started in the current directory. |
|
1425 Also fork a reader process, to read the shells output and |
|
1426 tell me, whenever something arrives" |
|
1427 |
|
1428 self startCommand:aCommand in:nil |
|
1429 |
|
1430 "Modified: / 20.7.1998 / 18:30:24 / cg" |
|
1431 ! |
|
1432 |
|
1433 startCommand:aCommand in:aDirectory |
|
1434 "start a command on a pseudo terminal. If the command arg is nil, |
|
1435 a shell is started. If aDirectory is not nil, the command is |
|
1436 executed in that directory. |
|
1437 Also fork a reader process, to read the shells output and |
|
1438 tell me, whenever something arrives" |
|
1439 |
|
1440 self basicStartCommand:aCommand in:aDirectory. |
|
1441 self startReaderProcessWhenVisible. |
1386 |
1442 |
1387 "Created: / 20.7.1998 / 18:19:32 / cg" |
1443 "Created: / 20.7.1998 / 18:19:32 / cg" |
1388 "Modified: / 5.5.1999 / 17:28:37 / cg" |
1444 "Modified: / 5.5.1999 / 17:28:37 / cg" |
1389 ! |
1445 ! |
1390 |
1446 |
1405 startShellIn:aDirectory |
1461 startShellIn:aDirectory |
1406 "start a shell on a pseudo terminal in some directory. |
1462 "start a shell on a pseudo terminal in some directory. |
1407 Also fork a reader process, to read the shells output and |
1463 Also fork a reader process, to read the shells output and |
1408 tell me, whenever something arrives" |
1464 tell me, whenever something arrives" |
1409 |
1465 |
1410 ^ self startCommand:nil in:aDirectory |
1466 self startCommand:nil in:aDirectory |
1411 |
1467 |
1412 " |
1468 " |
1413 VT100TerminalView openShellIn:'/etc' |
1469 VT100TerminalView openShellIn:'/etc' |
1414 " |
1470 " |
1415 |
1471 |