Visit Jeremy's Blog.
Go Back > Forums > Linux Forums > Linux - Software
User Name
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.


  Search this Thread
Old 11-05-2009, 09:11 AM   #1
LQ Newbie
Registered: Nov 2009
Location: bahama, nc
Distribution: freebsd, ubuntu, gentoo
Posts: 3

Rep: Reputation: 0
Question how do i use s3270/x3270 for scripting

I'm trying to write a script which will (upon completion), navigate through records maintained on an IBM mainframe using a tn3270 terminal, and scrape said records into html files for later manipulation.

I've read


The latter states:
Commands are emulator actions; the syntax is the same as for the right-hand side of an Xt translation table entry (an x3270 or c3270 keymap). Unlike translation tables, action names are case-insensitive, can be uniquely abbreviated, and the parentheses may be omitted if there are no parameters. Any input line that begins with # or ! is treaded as a comment and will be ignored.

By that definition, the following should work:

connect( \
ascii() \
string(command1) \
enter() \
ascii() \
enter() \
string(command2) \
ascii() \
pf(3) \

However, when i call the above using the script() function in s3270, the script prints to stdout, but the actions are not executed as expected.

For example:

(NOTICE: I've shortened the script for example's sake)
$ s3270

L U U N N 4 24 80 0 0 0x0 -
Expected output would've been (for starters) the first character of the status string changing to U (as the keyboard should unlock when i am connected), and the initial screen printed in ascii, a command sent, and the resulting screen printed in ascii as well.

I'm not sure what i am doing wrong. Can someone give me an example script that works? Something simple that depicts how i can use something like bash, perl, or python to send commands to this application and navigate through screens.

Thanks in advance

Last edited by doomed9; 11-05-2009 at 09:14 AM. Reason: pointing out that the script i executed has been shortened from the example i gave earier in the post
Old 11-05-2009, 07:12 PM   #2
LQ Newbie
Registered: Nov 2009
Location: bahama, nc
Distribution: freebsd, ubuntu, gentoo
Posts: 3

Original Poster
Rep: Reputation: 0

So, i worked out how to do this in bash; though, i don't like the result.

date=$(date +"%Y%m%d%H%M%S")
x3270if "connect("
x3270if "printtext(html,file,$file_path/myhost-$date.html)"
x3270if "string(command1)"
x3270if "enter"
x3270if "printtext(html,file,$file_path/myhost-$date.html)"
x3270if "enter"
x3270if "string(command2)"
x3270if "enter"
This is a bash script that, if called from within s3270, will navigate to the application login page and create html files of each page along the way.

while x3270if is nice, i reckon i expected a simpler solution...something easier to use with a language's built-in functionality.

What would i do with perl? Hopefully not make a call to system() each time i want to input data. Is there a way to treat the terminal connection as a file handle and just send commands to it via print()?
Old 11-06-2009, 01:18 AM   #3
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Centos 7.7 (?), Centos 8.1
Posts: 18,059

Rep: Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663Reputation: 2663
If you're keen on doing this in Perl, ask the gurus over at
Old 11-07-2009, 04:55 PM   #4
LQ Newbie
Registered: Nov 2009
Location: bahama, nc
Distribution: freebsd, ubuntu, gentoo
Posts: 3

Original Poster
Rep: Reputation: 0
Thumbs up Thanks


Thank you for the excellent referral. I was on the right track to my answer in a few minutes...

Using perl's IPC::Run module, i was able to pipe commands directly to the s3270 subprocess. Thus, the below is an example of x3270's peer script facility:


my @s3270 = s3270;

use IPC::Run qw( start pump finish timeout );
      # Incrementally read from / write to scalars.
      # $in is drained as it is fed to s3270's stdin,
      # $out accumulates s3270's stdout
      # $err accumulates s3270's stderr
      # $h is for "harness".
      my $h = start \@s3270, \$in, \$out, \$err, timeout( 10 );

      $in .= "connect(\n";
      $in .= "ascii\n";

      $in .= "quit";
      finish $h or die "s3270 returned $?";

      warn $err if $err;
      print $out;         ## All of cat's output
hope this helps any googlers interested in scripting with s3270.

Chris, Thanks again
Old 07-05-2010, 08:11 PM   #5
LQ Newbie
Registered: Jul 2010
Posts: 1

Rep: Reputation: 0
Wink X3270 Script Example

I had similar problem and, although it's an old topic, I'd like to share a bourne shell script that worked out for me (based on example script from the author of x3270 (look at sourceforge).
Amazingly, you will find NOTHING when goggling "x3270 script example". Documentation could be better and is not focused toward dummies like me. Looks like nobody does x3270 scripting, or don't care to share.
I did have a bad time trying to make this script work, hope you save your time.
Enough talking, here it goes:

#! /bin/bash
# TSO login script, which runs as a peer of x3270.
# bash version
# to disconnect user, go to
# www . efglobe . com / cgi-bin / mainframe / mainuser

set -x

# Set up login parameters

# Verbose flag for x3270if

# Define some handly local functions.

# x3270 interface function
function xi
	X3270OUTPUT=6 X3270INPUT=5 x3270if 5>$ip 6<$op $v "$@"
	echo `date +"%H:%M:%S:%N"` 1>&2

# Common x3270 Ascii function
function ascii
	xi 'Ascii('$1')'

# Common x3270 String function
function string
	xi 'String("'"$@"'")'

# x3270 cursor column
function cursor_col
	xi -s 10

# x3270 connection status
function cstatus
	xi -s 4

# Failure.
function die
	xi "Info(\"$me error: $@\")"
	xi "CloseScript(1)"
	exit 1
# loop until expected text appears on screen at given coords and
# send next command followed by enter
# Espera is Wait in portuguese, Envia is Send in portuguese
function Espera-Envia 
  texto=$1  #expected text
  coord=$2  #coords from begning of texto (screen initiates at 0,0)
  envia=$3  #command to send

  while [ "$(ascii $coord)" != "$texto" ] && [ $i -lt 20 ]
  do	#sleep 0.5
  	xi "Wait(8000,InputField)" #man says timeout is in secs, but I thing it is in millisecs
	xi "Wait(8000,Unlock)" 
        xi "Wait(8000,Output)"
        [ $i -gt 10 ] && xi "Wait(1000,NVTMode)" #if other waits dont work, try this...
        let "i +=1"
  [ "$i" = "20" ] && die "Timeout waiting for: " $texto

  [ "$envia" = "" ] && return

  string "$envia"
  xi Enter
  xi "Wait(8000,Unlock)"

# --- MAIN -----------------------------------------------------------
# Set up pipes for x3270 I/O
rm -f $ip $op
trap "rm -f $ip $op" EXIT
trap "exit" INT QUIT HUP TERM
mknod $ip p
mknod $op p

# Start x3270
x3270 -script -model 2 <$ip >$op &
exec 5>$ip	# hold the pipe open
xi -s 0 >/dev/null || exit 1

# Connect to host
xi "Connect($tcp_host)" || die "Connection failed."

# Make sure we're connected.
xi Wait
[ "$(cstatus)" = N ] && die "Not connected."

#---  SCREEN-SCRAPING -------------------------------------

# wait initial menu, choose option TSO
Espera-Envia "Enter"  "20,0,5"  "TSO"

# wait prompt userid, send it.
Espera-Envia "ENTER USERID"  "0,11,12"  "$userid" 

# wait prompt PASSWORD, send PASSWORD
Espera-Envia "Password"  "7,4,8"  "$password"

#add userid size to text
#typeset -i nl=18+${#userid} 
#Espera-Envia "$userid LOGON IN PROGRESS"  "1,1,$nl"  "" 

# Make sure TSO is waiting for a '***' enter
#[ "$(cursor_col)" -eq 5 ] || die "Don't understand logon screen"

# wait ***, send next command
Espera-Envia "***"  "22,1,3"  "IPLINFO"

Espera-Envia "Option ===>"  "3,1,11"   "6"

Espera-Envia "===> "  "5,1,5"   "TSO LISTC"

#enough navegating, you can catch screen with snap action

sleep 800 #so you can watch the screen a little bit.
# Off to ISPF
xi Enter
xi 'CloseScript(0)'

Last edited by ffabreti; 07-05-2010 at 08:14 PM.
Old 03-04-2011, 09:53 AM   #6
LQ Newbie
Registered: Mar 2011
Posts: 1

Rep: Reputation: Disabled
yes, I Know, the thread is old. However the thread is good and there isn't out so much about tn3270.
So here are my experiences:

I just compiled it on AIX using gcc-4.4.5-1 and used the following short ksh-script to test TSO availability using a ssl connection, without login:

s3270 -trace << EOF


Last edited by AIXroot; 03-09-2011 at 11:16 AM. Reason: correction
Old 09-26-2011, 08:34 PM   #7
LQ Newbie
Registered: Sep 2011
Posts: 2

Rep: Reputation: Disabled
I realize this is an old post but all the help I could google wasn't enough. I was stumped on this thing for a solid week so I am providing some sample code on how to better interact with s3270 using PHP.


//This is straight from the page. Just sets up an array for your pipes
PHP Code:
<?php $descriptorspec = array(
=> array("pipe","r"),
=> array("pipe","w"),
=> array("pipe","w")
//This opens the process s3270 and enables the pipes for you to read and write from. We will set both to nonblocking and continually page for results later.
PHP Code:
$process proc_open('/usr/local/bin/s3270'$descriptorspec$pipesnullnull);
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0); 
//This function will watch for text on the screen similar to Expect but without having to install an additional module and configure it. Basically until the text shows up on the screen it will continually re-run the ascii() command and wait indefinitely.
PHP Code:
function expecttxt ($thetxt) {
$x false;
$g false;
      while (
$x == false) {
         while (
$mydat fgets($pipes[1])) {
                        if (
preg_match("/$thetxt/i"$mydat)) {
$g true;
                  if (
$g == true) {
                        while (
$mydat fgets($pipes[1])) {
$x true;
fwrite($pipes[0], "ascii()\n");

//This function is the same as above except it will only wait about 10 seconds for a response and then continue running the script.
PHP Code:
function expectemp ($thetxt) {

$g false;
$i 1$i <= 10$i++)  {
           while (
$mydat fgets($pipes[1])) {
                        if (
preg_match("/$thetxt/i"$mydat)) {
$g true;
                        if (
$g == true) {
                                while (
$mydat fgets($pipes[1])) {
$i 11;
fwrite($pipes[0], "ascii()\n");

//You can then use the above functions and run commands real time. I initially did a lot of sleep(x) between commands and set it for a pretty high timeout. This resulted in an extremely inefficient script that STILL wouldn't work because occasionally network latency wouldn't get a response back before the sleep amount was up.
PHP Code:
if(is_resource($process)) {
fwrite($pipes[0], "connect(L:hostname:port)\n");
fwrite($pipes[0], "ascii()\n");
fwrite($pipes[0], "string(session-name)\n");
fwrite($pipes[0], "enter\n");
fwrite($pipes[0], "ascii()\n");
expecttxt("SESSION STATUS");
fwrite($pipes[0], "PF(2)\n");
fwrite($pipes[0], "ascii()\n");
expecttxt("NEXT INFO");


Old 03-01-2012, 04:20 AM   #8
LQ Newbie
Registered: Mar 2012
Posts: 1

Rep: Reputation: Disabled
doesn't work under WAMP

thank's to paleos for his exemple in PHP. It's work fine on a LAMP server but not under windows.

when i use ws3270.exe in command line ascii() return correct things, but in php all lines are umpty. I use the same php code on linux and on windows.

does some one try it under windows ?
Old 05-26-2017, 03:55 PM   #9
LQ Newbie
Registered: May 2017
Location: Poland
Posts: 1

Rep: Reputation: Disabled
I wrote a library for using x3270 in Python. Here is copy-paste from code with many useful examples how to handle x3270 scripting under Python:

def get_output(self):
        output = subprocess.Popen(["x3270if", "-p",, "ascii"], stdout=subprocess.PIPE).communicate()[0]
        return output
    def get_position(self):
        return subprocess.Popen(["x3270if", "-p",, 'query("cursor")'], stdout=subprocess.PIPE).communicate()[0].strip()
    def set_position(self, position):
        position = position.replace(' ', ',') # so you can type position with coma or with space["x3270if", "-p",, 'MoveCursor(' + position + ')'])
    def confirm(self):["x3270if", "-p",, "enter"])
    def PF(self, number):["x3270if", "-p",, "PF(" + str(number) + ")"])
    def type_in(self, string, position= 'None'):
        x3270_position = X3270.get_position(self)
        position = position.replace(',', ' ') # so you can type position with coma or with space
        def x3270_write(self, string):
  ["x3270if", "-p",, 'string(' + string + ')'])

        if position == 'None':
            x3270_write(self, string)
            print("position is empty")
        elif x3270_position == position:
            print("position is equal")
            x3270_write(self, string)
            return True
            if __name__ == "__main__":
                print("Position is different. I will exit so nothing gets broken.")
            return False

    def wait_for(self, string, timeout=50):
        output = X3270.get_output(self)
        counter = 0
        if timeout == 'unlimited':
            timeout = float("inf")
        while string not in output:
            sleep(0.5) #first sleep half a second for 10 seconds
            counter += 1
            output = X3270.get_output(self)
            if counter >= timeout:
      ['notify-send', '-u', 'normal', '-t', '30000', '-i', sys.path[0]+'/process-stop.png', self.win_title, 'The window does not work properly, script terminated.'])
            if counter >= 30 and counter < timeout:
                print("now sleeping 10 seconds")
            if counter >= 20 and counter < 30:
                print("now sleeping 5 seconds")
            if counter >= 10 and counter < 20: # then sleep a second for 10 seconds
                print("now sleeping half a second more")
else: return True
Instruction how to write scripts using this library can be found in readme.
Project's site:


bash, linux, script, sync

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
x3270/s3270 Scripting [IBM Mainframes] arkanunz Linux - Software 3 12-04-2008 08:18 PM
what is this x3270??? muzzamil.luqman Linux - Newbie 7 12-03-2008 06:52 PM
x3270 emulator bourne Linux - Software 9 11-03-2008 11:42 AM
x3270 Install issue jlueke Linux - Software 0 11-21-2005 03:33 PM
x3270 nex6 Linux - Software 1 03-03-2005 12:48 PM > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 10:33 AM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration