2

I have a MS-DOS 3.22 laptop that will receive simple text data over serial COM1.

I can make it save to file by doing TYPE COM1 >> data.log and I can make it show the data on the console with TYPE COM1 >> CON but I can't do this simultaneously as the TYPE COM1 is a never ending command.

Is there a way for me to both display the COM data on my console and to save it to file simultaneously?

thx!

  • I recommend reading this xkcd comic and narrowing your question down to one question (see How to Ask for some help). This is more a programming question, but since Batch doesn't provide a native tee I think this is better suited to here than Stack Overflow. – wizzwizz4 Oct 27 '18 at 20:08
  • oke, its now just the main question, I did post it on normal stack overflow but they where scared when they saw MS-DOS 3.22 and told me to ask here :) – looney Oct 27 '18 at 20:24
  • He wasn't rude or anything, he just thought it was better fitting for retrocomputing (of which I didn't know that it existed) – looney Oct 27 '18 at 20:30
  • It's just that generally you're not meant to cross-post across SE sites. It's not something that you'd have known, and people regularly tell each other to, but it makes it confusing for everyone when it happens. I'll link the Stack Overflow post to here. – wizzwizz4 Oct 27 '18 at 20:31
  • Do any of the many terminal programs that can log what comes across the line not do it for you? – Blrfl Oct 28 '18 at 12:25
4

The ideal tool for this is some DOS version of the Unix tee command; once you have that,

TEE data.log < COM1

will read data from the first serial port and write it to both data.log and the screen.

DOS versions of tee are available from a variety of sources:

  • 4DOS (a replacement shell) includes a built-in TEE command;
  • Ian Stewartson’s Unix utilities include TEE in part D;
  • I see Garbo has a few other implementations, which I haven’t tried (or don’t remember using).

(Other, Unix-style uses of TEE won’t have the same immediate effect under DOS since programs can’t run simultaneously: TYPE COM1 | TEE data.log would fail because under DOS, pipes work by redirecting the output to a temporary file, waiting for the command feeding the pipe to finish, then running the next command with its input redirected from the temporary file.)

  • looks promising but I can't get it to work it seems. I have tried the Stewartson and Garbo TEE.EXE but when I run TEE data.log < COM1 it does display the data on the console but it does not write anything to data.log. – looney Oct 27 '18 at 21:02
0

I do not know of any command or app to do as you ask. Instead I would use Borland Turbo C++ and code it myself... Its been ages I code something for MS-DOS so I am not confident to do it for you. But you're in luck I found something in my C++ archives I coded back in the days and will help I think:

//---------------------------------------------------------------------------
//--- Includes: -------------------------------------------------------------
//---------------------------------------------------------------------------
#include <iostream.h>
//----------------------------------------------------------------------------
//--- Global data: -----------------------------------------------------------
//----------------------------------------------------------------------------
typedef unsigned char byte;
typedef unsigned int word;
word far *memw=0x00000000;
byte far *mem=0x00000000;
char    key;
word    keyhi;

word    com;
//----------------------------------------------------------------------------
//--- I/O: -------------------------------------------------------------------
//----------------------------------------------------------------------------
void inkey()
    {
    key=0;
    keyhi=0;
    asm {
        mov ax,256
        int 0x16
        jz  esc
        mov ax,0
        int 0x16
        mov key,al
        mov keyhi,ax
        }
esc:
    }
//---------------------------------------------------------------------------
void inkeyw()
    {
    asm {
        mov ax,0
        int 0x16
        mov key,al
        mov keyhi,ax
        }
    }
//---------------------------------------------------------------------------
byte in(word adr)
    {
    byte    x;
    asm {
        mov dx,adr
        in  al,dx
        mov x,al
        }
        return x;
    }
//---------------------------------------------------------------------------
void out(word adr,byte x)
    {
    asm {
        mov dx,adr
        mov al,x
        out dx,al
        }
    }
//---------------------------------------------------------------------------
//--- com: ------------------------------------------------------------------
//---------------------------------------------------------------------------
void com_init(word x)
    {
    com=memw[(0x400>>1)+x-1];   // COM IO address from DOS TAB 0000:0400h
    out(com+1,0);           // no interrupts
    out(com+3,3);           // 1 start, 8 data, 1 stop, 0 parity
    }
//---------------------------------------------------------------------------
void com_speed(word f)
    {
    word x,h,l;
    x=115200/f;
    h=(x >> 8) & 255;
    l=x & 255;
    x=in(com+3) & 127;
    out(com+3,x+128);
    out(com+0,l);
    out(com+3,x+128);
    out(com+1,h);
    out(com+3,x);
    }
//---------------------------------------------------------------------------
byte com_in()
    {
    byte s;
//  do s=in(com+5); while ((s&1)!=1);
    s=in(com+0);
    return s;
    }
//---------------------------------------------------------------------------
void com_out(byte d)
    {
    byte s;
    do s=in(com+5); while ((s&32)!=32);
    out(com+0,d);
    }
//---------------------------------------------------------------------------
//--- Subroutines: ----------------------------------------------------------
//---------------------------------------------------------------------------
void couthex(word x)
    {
    word    a,i;
    char    c;

    for (i=0;i<4;i++)
        {
        a=(x >> 12) & 15;
        x=x << 4;
        if (a<10) c=a+'0';
        if (a>=10) c=a-10+'A';
        cout << c;
        }
    cout << 'h';
    }
//---------------------------------------------------------------------------
//--- Main: -----------------------------------------------------------------
//---------------------------------------------------------------------------
void main()
    {
    asm {
        mov ax,3
        int 0x10
        }

    char    x=0;

    com_init(1);
    com_speed(9600);        // set to speed used by source device
    cout << "COM adress = "; couthex(com);  cout << endl;

    do      {
        inkey();
        x=com_in(); // this reads 1 BYTE from COM
        couthex(x); // this write it as hex on screen
        cout << endl;
        } while (keyhi==0);


    cout << "COM adress = "; couthex(com);  cout << endl;
    inkeyw();

    }
//---------------------------------------------------------------------------
//--- End. ------------------------------------------------------------------
//---------------------------------------------------------------------------

So you just modify the main loop to write the BYTE x as a character and also store to some file.

I am not sure if on such old MS-DOS version is the configuration table in the same place so you might set the COM IO address manually.

if you do not have turbo C++ just google it its still being used in some schools so it should not be any problem finding it. Here first link I found by google just now:

IIRC I used 3.2.2.0 version on MS-DOS 6.22. As you want older MS-DOS then older version of C may be required too...

File access is also a common practice assignment so there should be no problem finding any examples of it but just in case:

//============================================================================
//=== includes: ==============================================================
//============================================================================
#include <iostream.h>
#include <fstream.h>
#include <ctype.h>
//============================================================================
//=== main: ==================================================================
//============================================================================
void main()
    {
    // IIRC this just clears screen into 80x25 text mode
    asm {
        mov ax,3
        int 16
        }

    ofstream out;
    out.open("some_file_name.txt",ios::out);
    out << "some text" << endl; // endl adds CR,LF
    out.close();

    // IIRC this just clears screen into 80x25 text mode and clears keyboard buffer
    asm {
        mov ax,0
        int 0x16
        mov ax,3
        int 16
        }
    }
//============================================================================
//=== end. ===================================================================
//============================================================================

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.