lamb@lids.mit.edu.UUCP (04/16/87)
----------------PART 2 of 2 ---------------------
Some time ago I wrote a "from-scratch" uucp clone for use on our DG AOS machine
(with its brain-damaged uucp, useless to us and DG being no help).
Later I ported it to MS-DOS and VAX/VMS and its been working fine for a year
(Ive also hacked up a "rmail" for use between machines.)
Recently, with the help of John Gilmore, I was able to get the "g" protocol
realy workin (window size > 1). Previously all I could figure out was a
degenerate "g" proto using 1-window.
Im not crazy enough to say its perfect, but it does work.
Although this is a two-way (master+slave) uucico clone, compared to John's
uuslave, the coding and portibility has much to be desired. (This
project started as just an internal attempt to connect our DG to the world).
In any case for what its worth, Here it is...........
Hope everyone finds it useful.
As were not a real unix site, Id appreciate all correspondence thru
mail and not NEWS. (It took me most of last week to drum up a way to
post stuf to USENET writting a NNTP program).
Rick Lamb
Lamb@lids.mit.edu
or ...ihnp4!mit-eddie!lids!lamb
-------------CUT here ----------------------------------------
echo readme
cat >readme <<'@@@ Finished readme'
-------Notes on dcp.-------------------
---R.H.Lamb 6/86----------------------
Fix dcps.h for right system
Fix rmail.c for local mailer or no (#define LCLMAIL)
For PC compile comm.asm & dcpasm.asm files
Compile the rest of the .c files
Link dcp+ .c except rmail.c files + (comm+dcpasm for PC)
Link rmail
**************Finished creation**************
Modify "systems" for your site
Modify "userfile" for your site
**************Ready to run ******************
To que up mail in current directory type
rmail mit-eddie!lids!lamb <CR> or <NL>
Enter your message here ending with a line with only a "."
(Note: rmail does not presently put things in RFC820 format. A "filter"
program piped into rmail could do this easily. With out this
format things work ok, but youll see "Apparently to" s in your
mail.)
To read incomming mail type
rmail <CR> or <NL>
followed by <CR> or <NL> for each message
To send/receive files type
dcp master 3 <CR>
Where the last number is debug level
(0 is least)
**** Prog descriptions *****
dcp.c "uucico"
dcpsys.c Top level state machine
dcpstart.c uucp startup protocol+ dialing algorithm
dcpscan.c directory scan for work
dcpsend.c send file proto
dcprec.c rec file proto
dcpio.c general purpose serial I/O interface
dcppkt.c,dcpggpkt.c "g" proto Windowsize=1 (Previously tested))
dcpgpkt.c "g" proto Var windowsize (In use)
dcptpkt.c "t" proto no-error chk: for virt links
dcprpkt.c "r" proto My sliding window proto
dcpvms.c VMS support routines
dcxqt.c "uuxqt"
rmail.c "rmail"
comm.asm PC serial drivers (Saltzers pkg)
dcpasm.asm PC directory and other asm routines
systems "L.sys"
userfile site info
readme this file
format.doc info on msg formats (RFC8??) to be passed to rmail
makeobj.* make object files for PC(.bat) DG(.cli)
makeexe.* make dcp.exe or dcp.pr for PC or DG
call.* execute dcp in master mode
spawn.c VMS spawn testing subroutine (Not needed for oper)
------notes-----
PC info: MSC 3.0, LINK 3.01, MASM 4.00
DG info: C 3.21, LINK 6.00
VMS info: C 2.0, LINK ?
--------VMS notes--------
To send mail in VMS note:
rmail "a!b!c"
message
(Those dammed "."'s screwed up my posting on the first run >.<)
To send a file in VMS using redirected I/O (example "ss")
ss "rmail ""a!b!c" file nl:
In VMS host names with "_,-,?,&" are no good.
Make sure who you talk to has a simple name like "dgvax"
"userfile" should have
TT: for local console
0 for speed (use default speed on logon)
BUGS!!!!
The spawn command in dcxqt (lib$spawn in dcpvms) seems to work
only for small files. Redirection of input file to "rmail" larger than
a certain size get lost.
Cause is differing record file formats. Presently its a kludge that
runs "CONVERT/FDL=VAR" on the input files. Please- an VMS C hacker FIX.
@@@ Finished readme
echo format.doc
cat >format.doc <<'@@@ Finished format.doc'
-------A sample message that was received-----
-------/** denotes stuff my pgm added, the rest (**/) is what a---
------d.file should look like before sending---------
---The message was sent using:
% mail ggt@rutgers.UUCP
Subject: jeez
Hello there
(dammed dots >.<)
EOF
------------------------------------------------------
---------after recipt---------------
From uucp Tue Mar 10 16:36:03 1987 EDT remote from rutgers
>From tae Sat Mar 14 12:53:36 1987 remote from dspvax
Received: by dspvax.MIT.EDU (5.51/MIT.1.01x)
on Sat, 14 Mar 87 12:53:36 EST; User rutgers!ggt; Host rutgers
Date: Sat, 14 Mar 87 12:53:36 EST
From: Tae Joo <dspvax!tae>
Message-Id: <8703141753.AA02983@dspvax.MIT.EDU>
To: rutgers!ggt
Subject: jeez
Hello there
---------before send---------------
*****The Drutg115 file
From tae Sat Mar 14 12:53:36 1987 remote from dspvax
Received: by dspvax.MIT.EDU (5.51/MIT.1.01x)
on Sat, 14 Mar 87 12:53:36 EST; User rutgers!ggt; Host rutgers
Date: Sat, 14 Mar 87 12:53:36 EST
From: Tae Joo <dspvax!tae>
Message-Id: <8703141753.AA02983@dspvax.MIT.EDU>
To: rutgers!ggt
Subject: jeez
Hello there
******The Brutg115 file
-----note: for forwarding the last line is C rmail ggt!seismo!lamb
-----U=user I=input C=command F=general file
U uucp rutgers
F D.rutgers115
I D.rutgers115
C rmail ggt
******The Crutg115 file
----S=send R=receive(not common)
S Drutg115 D.rutgers115 uucp - Drutg115 0666
S Brutg115 X.rutgers115 uucp - Brutg115 0666
----------------end of document----------------
@@@ Finished format.doc
echo mboxuucp
cat >mboxuucp <<'@@@ Finished mboxuucp'
From uucp Sun Mar 15 22:18:54 1987 EDT remote from lids
Received: by lids on Sun Mar 15 22:18:54 1987 EDT
>From uucp Tue Apr 7 20:28:41 1987 remote from mit-eddie
Received: by EDDIE.MIT.EDU with UUCP with smail2.3 with sendmail-5.31/4.7 id <AA05017@EDDIE.MIT.EDU>; Tue, 7 Apr 87 20:28:30 EDT
Received: by lids on Sun Mar 15 22:14:42 1987 EDT
Date: 7 Apr 87 19:28:17 EST (Tue)
From: uucp@EDDIE.MIT.EDU
Message-Id: <8704071928.AA05012@EDDIE.MIT.EDU>
To: lids!lamb
Hello there.
From uucp Sun Mar 15 22:51:39 1987 EDT remote from lids
Received: by lids on Sun Mar 15 22:51:39 1987 EDT
>From uucp Tue Apr 7 20:55:47 1987 remote from mit-eddie
Received: by EDDIE.MIT.EDU with UUCP with smail2.3 with sendmail-5.31/4.7 id <AA05699@EDDIE.MIT.EDU>; Tue, 7 Apr 87 20:55:33 EDT
Received: by lids on Sun Mar 15 22:36:58 1987 EDT
Date: 7 Apr 87 19:55:25 EST (Tue)
From: uucp@EDDIE.MIT.EDU
Message-Id: <8704071955.AA05697@EDDIE.MIT.EDU>
To: lids!uucp
>From uucp Tue Apr 7 20:45:40 1987 remote from mit-eddie
Received: by EDDIE.MIT.EDU with UUCP with smail2.3 with sendmail-5.31/4.7 id <AA05435@EDDIE.MIT.EDU>; Tue, 7 Apr 87 20:44:59 EDT
Received: by lids on Sun Mar 15 22:26:58 1987 EDT
Received: by rutgers.UUCP (5.51/UUCP.1.01x) on Sat, 14 Mar 87 12:53:36 EST;
Date: Sat, 14 Mar 87 12:53:36 EST
From: UUCP <rutgers!uucp@EDDIE.MIT.EDU>
Subject: jeez
Message-Id: <8704071944.AA05432@EDDIE.MIT.EDU>
To: lids!mit-eddie!lids!uucp
Hello there
#include "dcp.h"
#include "dcp0.h"
/*<FF>*/
/* usage dcp (master/slave(D)) (debug level 0=none(D)) (system name(MYNAME))*/
/* (console device) */
main(argc,argv)
int argc;
char *argv[];
{
int ftmp;
char line[132];
flog=creat(SYSLOG,0775);
close(flog); flog=open(SYSLOG,2);
remote=TRUE;
debug=3;
fp = -1;
fw = -1;
ftmp=open(USERFILE,0);
getline(ftmp,line);
sscanf(line,"%s %s %s",myname,username);
getline(ftmp,line);
sscanf(line,"%s %s",tty,speed);
strcpy(spooldir,"."); /* default spooldir is current dir */
close(ftmp);
if(argc > 1 && strcmp(argv[1],"master") == 0) remote=FALSE;
if(argc > 2) sscanf(argv[2],"%d",&debug);
if(argc > 3) strcpy(myname,argv[3]);
if(argc > 4) strcpy(tty,argv[4]);
if(! remote)
{
if((fsys=open(SYSTEMS,0)) ==-1) return(FALSE);
state='I';
while(TRUE)
{
if(debug>0) printmsg("Mstate = %c",state);
switch(state)
{
case 'I': state=getsystem(); break;
case 'S': state=callup(); break;
case 'P': state=startup(); break;
case 'D': state=master(); break;
case 'Y': state=sysend(); break;
case 'G': state='I'; break;
}
if(state=='A') break;
}
close(fsys);
}
else
{
if(openline(tty,speed)==-1) return(FALSE);
state='L';
while(TRUE)
{
if(debug>0) printmsg("Sstate = %c",state);
switch(state)
{
case 'L':state=login(); break;
case 'I':state=startup(); break;
case 'R':state=slave(); break;
case 'Y':state=sysend(); break;
}
if(state=='A') break;
}
closeline();
}
if(dcxqt()) if(debug) printmsg("ERROR in DCXQT");
/* scan and process any recieved files */
close(flog);
}
/*<FF>*/
/*
**
**
**master
**
**
*/
master()
{
state='I';
while(TRUE)
{
if(debug>1) printmsg("Top level state (master mode) %c",state);
switch(state)
{
case 'I':state=sinit(); break;
case 'B':state=scandir(); break;
case 'S':state=send(); break;
case 'Q':state=sbreak(); break;
case 'G':state=receive(); break;
case 'C':state='Y'; break;
case 'Y':state=endp(); break;
case 'P':return('Y');
case 'A':return('A');
default:return('A');
}
}
}
/*<FF>*/
/*
**
**
**slave
**
**
*/
slave()
{
state='I';
while(TRUE)
{
if(debug>1) printmsg("Top level state (slave mode) %c",state);
switch(state)
{
case 'I':state=rinit(); break;
case 'F':state=receive(); break;
case 'C':state=schkdir(); break;
case 'T':state='B'; break;
case 'B':state=scandir(); break;
case 'S':state=send(); break;
case 'Q':state=sbreak(); break;
case 'G':return('Y');
case 'Y':state=endp(); break;
case 'P':return('Y');
case 'A':return('A');
default:return('A');
}
}
}
/*<FF>*/
/*
* r e c e i v e
*
* This is the state table switcher for receiving files.
*/
receive()
{
state = 'F';/* Receive-Init is the start state */
while(TRUE)
{
if (debug > 2) printmsg(" receive state: %c",state);
switch(state)/* Do until done */
{
case 'F':state = rfile(); break; /* Receive-File */
case 'D':state = rdata(); break; /* Receive-Data */
case 'C':return('C');/* Complete state */
case 'A':return('Y');/* "Abort" state */
default:return('Y');
}
}
}
/*<FF>*/
/*
* s e n d
*
* Sendsw is the state table switcher for sending files. It loops until
* either it finishes, or an error is encountered. The routines called
* by sendsw are responsible for changing the state.
*
*/
send()
{
fp = -1; /* reset file getter/opener */
state = 'F';/* Send initiate is the start state */
while(TRUE)/* Do this as long as necessary */
{
if (debug > 2) printmsg("send state: %c",state);
switch(state)
{
case 'F':state = sfile(); break; /* Send-File */
case 'D':state = sdata(); break; /* Send-Data */
case 'Z':state = seof(); break; /* Send-End-of-File */
case 'B':return ('B'); /* Complete */
case 'A':return ('Y'); /* "Abort" */
default:return ('Y'); /* Unknown, fail */
}
}
}
/*<FF>*/
/*
*
* login (for slave in PC mode)
*
*/
login()
{
char logmsg[132];
#ifdef PC
msgtime= 2*MSGTIME;
lretry:
wmsg("Username:",0);
rmsg(logmsg,0);
if(debug > 0) printmsg("Username = %s",logmsg);
wmsg("Password:",0);
rmsg(logmsg,0);
if(debug > 0) printmsg("Password = %s",logmsg);
if(strcmp(logmsg,"uucp") != 0) goto lretry;
#endif
return('I');
}
From uucp Mon Mar 16 03:20:48 1987 EDT remote from lids
Received: by lids on Mon Mar 16 03:20:48 1987 EDT
>From uucp Tue Apr 7 21:03:05 1987 remote from mit-eddie
Received: by EDDIE.MIT.EDU with UUCP with smail2.3 with sendmail-5.31/4.7 id <AA05879@EDDIE.MIT.EDU>; Tue, 7 Apr 87 21:02:42 EDT
Received: by lids on Sun Mar 15 22:43:44 1987 EDT
Date: 7 Apr 87 20:02:39 EST (Tue)
From: uucp@EDDIE.MIT.EDU
Message-Id: <8704072002.AA05877@EDDIE.MIT.EDU>
To: lids!uucp
>From uucp Tue Apr 7 20:49:16 1987 remote from mit-eddie
Received: by EDDIE.MIT.EDU with UUCP with smail2.3 with sendmail-5.31/4.7 id <AA05507@EDDIE.MIT.EDU>; Tue, 7 Apr 87 20:48:44 EDT
Received: by lids on Sun Mar 15 22:34:18 1987 EDT
Received: by rutgers.UUCP (5.51/UUCP.1.01x) on Sat, 14 Mar 87 12:53:36 EST;
Date: Sat, 14 Mar 87 12:53:36 EST
From: UUCP <rutgers!uucp@EDDIE.MIT.EDU>
Subject: jeez
Message-Id: <8704071948.AA05505@EDDIE.MIT.EDU>
To: lids!mit-eddie!lids!uucp
Hello there
#include "dcp.h"
#include "dcp0.h"
/*<FF>*/
/* usage dcp (master/slave(D)) (debug level 0=none(D)) (system name(MYNAME))*/
/* (console device) */
main(argc,argv)
int argc;
char *argv[];
{
int ftmp;
char line[132];
flog=creat(SYSLOG,0775);
close(flog); flog=open(SYSLOG,2);
remote=TRUE;
debug=3;
fp = -1;
fw = -1;
ftmp=open(USERFILE,0);
getline(ftmp,line);
sscanf(line,"%s %s %s",myname,username);
getline(ftmp,line);
sscanf(line,"%s %s",tty,speed);
strcpy(spooldir,"."); /* default spooldir is current dir */
close(ftmp);
if(argc > 1 && strcmp(argv[1],"master") == 0) remote=FALSE;
if(argc > 2) sscanf(argv[2],"%d",&debug);
if(argc > 3) strcpy(myname,argv[3]);
if(argc > 4) strcpy(tty,argv[4]);
if(! remote)
{
if((fsys=open(SYSTEMS,0)) ==-1) return(FALSE);
state='I';
while(TRUE)
{
if(debug>0) printmsg("Mstate = %c",state);
switch(state)
{
case 'I': state=getsystem(); break;
case 'S': state=callup(); break;
case 'P': state=startup(); break;
case 'D': state=master(); break;
case 'Y': state=sysend(); break;
case 'G': state='I'; break;
}
if(state=='A') break;
}
close(fsys);
}
else
{
if(openline(tty,speed)==-1) return(FALSE);
state='L';
while(TRUE)
{
if(debug>0) printmsg("Sstate = %c",state);
switch(state)
{
case 'L':state=login(); break;
case 'I':state=startup(); break;
case 'R':state=slave(); break;
case 'Y':state=sysend(); break;
}
if(state=='A') break;
}
closeline();
}
if(dcxqt()) if(debug) printmsg("ERROR in DCXQT");
/* scan and process any recieved files */
close(flog);
}
/*<FF>*/
/*
**
**
**master
**
**
*/
master()
{
state='I';
while(TRUE)
{
if(debug>1) printmsg("Top level state (master mode) %c",state);
switch(state)
{
case 'I':state=sinit(); break;
case 'B':state=scandir(); break;
case 'S':state=send(); break;
case 'Q':state=sbreak(); break;
case 'G':state=receive(); break;
case 'C':state='Y'; break;
case 'Y':state=endp(); break;
case 'P':return('Y');
case 'A':return('A');
default:return('A');
}
}
}
/*<FF>*/
/*
**
**
**slave
**
**
*/
slave()
{
state='I';
while(TRUE)
{
if(debug>1) printmsg("Top level state (slave mode) %c",state);
switch(state)
{
case 'I':state=rinit(); break;
case 'F':state=receive(); break;
case 'C':state=schkdir(); break;
case 'T':state='B'; break;
case 'B':state=scandir(); break;
case 'S':state=send(); break;
case 'Q':state=sbreak(); break;
case 'G':return('Y');
case 'Y':state=endp(); break;
case 'P':return('Y');
case 'A':return('A');
default:return('A');
}
}
}
/*<FF>*/
/*
* r e c e i v e
*
* This is the state table switcher for receiving files.
*/
receive()
{
state = 'F';/* Receive-Init is the start state */
while(TRUE)
{
if (debug > 2) printmsg(" receive state: %c",state);
switch(state)/* Do until done */
{
case 'F':state = rfile(); break; /* Receive-File */
case 'D':state = rdata(); break; /* Receive-Data */
case 'C':return('C');/* Complete state */
case 'A':return('Y');/* "Abort" state */
default:return('Y');
}
}
}
/*<FF>*/
/*
* s e n d
*
* Sendsw is the state table switcher for sending files. It loops until
* either it finishes, or an error is encountered. The routines called
* by sendsw are responsible for changing the state.
*
*/
send()
{
fp = -1; /* reset file getter/opener */
state = 'F';/* Send initiate is the start state */
while(TRUE)/* Do this as long as necessary */
{
if (debug > 2) printmsg("send state: %c",state);
switch(state)
{
case 'F':state = sfile(); break; /* Send-File */
case 'D':state = sdata(); break; /* Send-Data */
case 'Z':state = seof(); break; /* Send-End-of-File */
case 'B':return ('B'); /* Complete */
case 'A':return ('Y'); /* "Abort" */
default:return ('Y'); /* Unknown, fail */
}
}
}
/*<FF>*/
/*
*
* login (for slave in PC mode)
*
*/
login()
{
char logmsg[132];
#ifdef PC
msgtime= 2*MSGTIME;
lretry:
wmsg("Username:",0);
rmsg(logmsg,0);
if(debug > 0) printmsg("Username = %s",logmsg);
wmsg("Password:",0);
rmsg(logmsg,0);
if(debug > 0) printmsg("Password = %s",logmsg);
if(strcmp(logmsg,"uucp") != 0) goto lretry;
#endif
return('I');
}
@@@ Finished mboxuucp
echo systems
cat >systems <<'@@@ Finished systems'
ihnp4 Slave
lids Slave COM1 DIR 9600 g \n-me:-op\n-word:-dogbridge\ntest\n
dlids Slave COM1 DIR 9600 g \n-me:-tuucp\n-word:-ggggg\n
mit-eddie Any COM2 ACU 1200 g ATZ\r-OK\r-ATDT88222\r-CONNECT\r-\r-ogin:-uucp\r-assword:-uucp\r
hurob1 Slave
lids Slave COM2 ACU 1200 g ATZ\r-K\r-ATDT87444\r-CT\r-\n-ame:-op\n-ord:-dogbridge\ntest\n
lids Slave COM2 ACU 1200 g ATZ\r-K\r-ATDT87444\r-CT\r-\n-ame:-uucp\n-ord:-uucp\n
seismo Slave
orly Slave
rutgers Slave
speedy Slave
dspvax Any COM2 ACU 1200 g ATZ\r-K\r-ATDT86666\r-CT\r-\r-ogin:-uucp\r-ord:-what\r
mit-atrp Slave COM2 ACU 1200 g ATZ\r-K\r-ATDT87922\r-CT\r-\r-ogin:-uucp\r-ord:-duck\r
allegra Slave COM2 ACU 1200 g ATZ\r-K\r-ATDT9,15551212392\r-CT\r-\r-ogin:-uucp\r-ord:-attttt\r
@@@ Finished systems
echo userfile
cat >userfile <<'@@@ Finished userfile'
lids uucp
COM1 9600
(arghhhhhh >.< want a dot here!!!)
/* prototype */
machine-name user-name
default-console-for-call-in's default-baud
default-spool-directory
/************/
@@@ Finished userfile
echo comm.h
cat >comm.h <<'@@@ Finished comm.h'
/* declarations for comm.asm
**
** compilation must use the Ze switch to enable the
** "far" keyword for the small memory model
**
** Robin Rohlicek 3/86
*/
void far select_port( int ); /* select active port (1 or 2) */
void far save_com(); /* save the interupt vectors */
void far restore_com(); /* restore those vectors */
int far install_com(); /* install our vectors */
void far open_com( /* open com port */
int, /* baud */
int, /* 'M'odem or 'D'irect */
int, /* Parity 'N'one, 'O'dd, 'E'ven, 'S'pace, 'M'ark */
int, /* stop bits (1 or 2) */
int); /* Xon/Xoff 'E'nable, 'D'isable */
void far close_com(); /* close com port */
void far dtr_off(); /* clear DTR */
void far dtr_on(); /* set DTR */
long far r_count(); /* receive counts */
/* high word = total size of receive buffer */
/* low word = number of pending chars */
#define r_count_size() ( (int) (r_count()>>16) )
#define r_count_pending() ( (int) r_count() )
int far receive_com(); /* get one character */
/* return -1 if none available */
long far s_count(); /* send counts */
/* high word = total size of transmit buffer */
/* low word = number of bytes free in transmit buffer */
#define s_count_size() ( (int) (s_count()>>16) )
#define s_count_free() ( (int) s_count() )
void far send_com(int); /* send a character */
void far send_local(int); /* simulate receive of char */
void far sendi_com(int); /* send immediately */
void far break_com(); /* send a BREAK */
int * far com_errors(); /* pointer to error counts
(in static area) */
#define COM_EOVFLOW 0 /* buffer overflows */
#define COM_EOVRUN 1 /* receive overruns */
#define COM_EBREAK 2 /* break chars */
#define COM_EFRAME 3 /* framing errors */
#define COM_EPARITY 4 /* parity errors */
#define COM_EXMIT 5 /* transmit erros */
#define COM_EDSR 6 /* data set ready errors */
#define COM_ECTS 7 /* clear to send errors */
#define COM_NERR 8 /* number of errors */
@@@ Finished comm.h
echo dcp.h
cat >dcp.h <<'@@@ Finished dcp.h'
/* DCP a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
#include <stdio.h> /* Standard UNIX definitions */
#include "dcps.h"
#define MSGTIME 20
#define MAXPACK 256
#define ACK 4 /* general definitions */
#define NAK 2
#define DATA 0
#define CLOSE 1
#define ERROR 10
#define EMPTY 11
#define TRUE -1
#define FALSE 0
/*<FF>*/
typedef int (*procref)();
typedef struct {
char type;
procref a;
procref b;
procref c;
procref d;
} Proto;
/* the various protocols available. Add here for others */
extern procref getpkt,sendpkt,openpk,closepk;
extern int ggetpkt(),gsendpkt(),gopenpk(),gclosepk();
extern int kgetpkt(),ksendpkt(),kopenpk(),kclosepk();
extern int rgetpkt(),rsendpkt(),ropenpk(),rclosepk();
extern int tgetpkt(),tsendpkt(),topenpk(),tclosepk();
/*<FF>*/
extern int pktsize; /* packet size for this pro*/
extern int flog; /* system log file */
extern int fw; /* cfile pointer */
extern int fpr,fpw; /* comm dev pointer */
extern char cfile[80]; /* work file pointer */
extern int remote; /* -1 means we're remote*/
extern int debug; /* debugging level */
extern int msgtime; /* timout setting */
extern char fromfile[132];
extern char tofile[132];
extern char state; /* present state */
extern int fp; /* current disk file ptr */
extern int size; /* nbytes in buff */
extern int fsys;
extern char tty[20];
extern char myname[20];
extern char username[20];
extern char spooldir[80];
extern char rmtname[20];
extern char cctime[20];
extern char device[20];
extern char type[10];
extern char speed[10];
extern char proto[5];
extern char loginseq[132];
extern unsigned int checksum();
@@@ Finished dcp.h
echo dcps.h
cat >dcps.h <<'@@@ Finished dcps.h'
/* DCP a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/** select system */
#define PC /* */
/*#define DG /* */
/*#define VMS /* */
#define USERFILE "userfile"
#define SYSTEMS "systems"
#define SYSLOG "dcp.log"
@@@ Finished dcps.h
echo comm.asm
cat >comm.asm <<'@@@ Finished comm.asm'
TITLE COM_PKG2 -- Last updated 10/6/85
PAGE 75,132
;
; modified to use MSC calling sequence.
; jrr 3/86
;
; Communications Package for the IBM PC, XT, AT and PCjr
; and strict compatibles.
; May be copied and used freely -- This is a public domain program
; Developed by Richard Gillmann, John Romkey, Jerry Saltzer,
; Craig Milo Rogers, Dave Mitton and Larry Afrin.
;
; We'd sure like to see any improvements you might make.
; Please send all comments and queries about this package
; to GILLMANN@USC-ISIB.ARPA
;
; o Supports both serial ports simultaneously
; o All speeds to 19200 baud
; o Compatible with PC, XT, AT and PCjr.
; o Built in XON/XOFF flow control option
; o Assembly language calling conventions
; o Logs all comm errors
; o Direct connect or modem protocol
;
; MAXIMUM BUFFER SIZES
R_SIZE EQU 500 ; SIZE OF RECEIVE BUFFERS
S_SIZE EQU 500 ; SIZE OF TRANSMIT BUFFERS rhl/4/86
; INTERRUPT NUMBERS
INT_COM1 EQU 0CH ; COM1: FROM 8259
INT_COM2 EQU 0BH ; COM2: FROM 8259
; 8259 PORTS
INTA00 EQU 20H ; 8259A PORT, A0 = 0
INTA01 EQU 21H ; 8259A PORT, A0 = 1
; COM1: LEVEL 4
IRQ4 EQU 2*2*2*2 ; 8259A OCW1 MASK, M4=1, A0=0
NIRQ4 EQU NOT IRQ4 AND 0FFH ; COMPLEMENT OF ABOVE
EOI4 EQU 4 OR 01100000B ; 8259A OCW2 SPECIFIC IRQ4 EOI, A0=0
; COM2: LEVEL 3
IRQ3 EQU 2*2*2 ; 8259A OCW1 MASK, M3=1, A0=0
NIRQ3 EQU NOT IRQ3 AND 0FFH ; COMPLEMENT OF ABOVE
EOI3 EQU 3 OR 01100000B ; 8259A OCW2 SPECIFIC IRQ3 EOI, A0=0
; FLOW CONTROL CHARACTERS
CONTROL_Q EQU 11H ; XON
CONTROL_S EQU 13H ; XOFF
; MISC.
DOS EQU 21H ; DOS FUNCTION CALLS
PAGE
;
; ROM BIOS Data Area
;
RBDA SEGMENT AT 40H
RS232_BASE DW 4 DUP(?) ; ADDRESSES OF RS232 ADAPTERS
RBDA ENDS
;
; ROM PC-Type IDENT
;
ROM SEGMENT AT 0F000H
ORG 0FFFEH
ROMID DB ? ; 0FFH=PC OR EARLY XT, 0FEH=XT, 0FDH=JR
ROM ENDS
PAGE
;
; TABLE FOR EACH SERIAL PORT
;
SP_TAB STRUC
PORT DB ? ; 1 OR 2
; PARAMETERS FOR THIS INTERRUPT LEVEL
INT_COM DB ? ; INTERRUPT NUMBER
IRQ DB ? ; 8259A OCW1 MASK
NIRQ DB ? ; COMPLEMENT OF ABOVE
EOI DB ? ; 8259A OCW2 SPECIFIC END OF INTERRUPT
; INTERRUPT HANDLERS FOR THIS LEVEL
INT_HNDLR DW ? ; OFFSET TO INTERRUPT HANDLER
OLD_COM_OFF DW ? ; OLD HANDLER'S OFFSET
OLD_COM_SEG DW ? ; OLD HANDLER'S SEGMENT
; ATTRIBUTES
INSTALLED DB ? ; IS PORT INSTALLED ON THIS PC? (1=YES,0=NO)
BAUD_RATE DW ? ; 19200 MAX
CONNECTION DB ? ; M(ODEM), D(IRECT)
PARITY DB ? ; N(ONE), O(DD), E(VEN), S(PACE), M(ARK)
STOP_BITS DB ? ; 1, 2
XON_XOFF DB ? ; E(NABLED), D(ISABLED)
; FLOW CONTROL STATE
HOST_OFF DB ? ; HOST XOFF'ED (1=YES,0=NO)
PC_OFF DB ? ; PC XOFF'ED (1=YES,0=NO)
; ERROR COUNTS
ERROR_BLOCK DW 8 DUP(?) ; EIGHT ERROR COUNTERS
; 8250 PORTS
DATREG DW ? ; DATA REGISTER
IER DW ? ; INTERRUPT ENABLE REGISTER
IIR DW ? ; INTERRUPT IDENTIFICATION REGISTER
LCR DW ? ; LINE CONTROL REGISTER
MCR DW ? ; MODEM CONTROL REGISTER
LSR DW ? ; LINE STATUS REGISTER
MSR DW ? ; MODEM STATUS REGISTER
; BUFFER POINTERS
START_TDATA DW ? ; INDEX TO FIRST CHARACTER IN X-MIT BUFFER
END_TDATA DW ? ; INDEX TO FIRST FREE SPACE IN X-MIT BUFFER
START_RDATA DW ? ; INDEX TO FIRST CHARACTER IN REC. BUFFER
END_RDATA DW ? ; INDEX TO FIRST FREE SPACE IN REC. BUFFER
; BUFFER COUNTS
SIZE_TDATA DW ? ; NUMBER OF CHARACTERS IN X-MIT BUFFER
SIZE_RDATA DW ? ; NUMBER OF CHARACTERS IN REC. BUFFER
; BUFFERS
TDATA DB S_SIZE DUP(?) ; SEND BUFFER
RDATA DB R_SIZE DUP(?) ; RECEIVE BUFFER
SP_TAB ENDS
; SP_TAB EQUATES
; WE HAVE TO USE THESE BECAUSE OF PROBLEMS WITH STRUC
EOVFLOW EQU ERROR_BLOCK ; BUFFER OVERFLOWS
EOVRUN EQU ERROR_BLOCK+2 ; RECEIVE OVERRUNS
EBREAK EQU ERROR_BLOCK+4 ; BREAK CHARS
EFRAME EQU ERROR_BLOCK+6 ; FRAMING ERRORS
EPARITY EQU ERROR_BLOCK+8 ; PARITY ERRORS
EXMIT EQU ERROR_BLOCK+10 ; TRANSMISSION ERRORS
EDSR EQU ERROR_BLOCK+12 ; DATA SET READY ERRORS
ECTS EQU ERROR_BLOCK+14 ; CLEAR TO SEND ERRORS
DLL EQU DATREG ; LOW DIVISOR LATCH
DLH EQU IER ; HIGH DIVISOR LATCH
PAGE
; put the data in the DGROUP segment
; far calls enter with DS pointing to DGROUP
;
DGROUP GROUP _DATA
_DATA SEGMENT PUBLIC 'DATA'
;
DIV50PC EQU 2304 ; DIVISOR FOR 50 BAUD (PC,XT)
DIV50JR EQU 2237 ; DIVISOR FOR 50 BAUD (JR)
DIV50 DW 2304 ; ACTUAL DIVISOR FOR 50 BAUD IN USE
CURRENT_AREA DW AREA1 ; CURRENTLY SELECTED AREA
; DATA AREAS FOR EACH PORT
AREA1 SP_TAB <1,INT_COM1,IRQ4,NIRQ4,EOI4> ; COM1 DATA AREA
AREA2 SP_TAB <2,INT_COM2,IRQ3,NIRQ3,EOI3> ; COM2 DATA AREA
_DATA ENDS
PAGE
COM_TEXT SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:COM_TEXT,DS:DGROUP,ES:NOTHING
PUBLIC _select_port
PUBLIC _save_com
PUBLIC _install_com
PUBLIC _restore_com
PUBLIC _open_com
PUBLIC _close_com
PUBLIC _dtr_on
PUBLIC _dtr_off
PUBLIC _r_count
PUBLIC _s_count
PUBLIC _receive_com
PUBLIC _send_com
PUBLIC _sendi_com
PUBLIC _send_local
PUBLIC _break_com
PUBLIC _com_errors
PAGE
;
; SELECT WHICH PORT IS TO BE "ACTIVE"
; [bp+6] = port number
_select_port PROC FAR
push bp
mov bp,sp
mov AX,[bp+6] ; get aguement
TEST AL,1 ; FIRST PORT?
JZ SP1 ; IF NOT, IT MUST BE SECOND PORT
MOV AX,OFFSET DGROUP:AREA1 ; SELECT COM1 DATA AREA
JMP SHORT SPX ; CONTINUE
SP1: MOV AX,OFFSET DGROUP:AREA2 ; SELECT COM2 DATA AREA
SPX: MOV CURRENT_AREA,AX ; SET SELECTION IN MEMORY
mov sp,bp
pop bp
RET ; DONE
_select_port ENDP
PAGE
;
; SAVE ORIGINAL COM VECTOR
;
_save_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
PUSH ES ; SAVE EXTRA SEGMENT
MOV AREA1.INT_HNDLR,OFFSET INT_HNDLR1
MOV AREA2.INT_HNDLR,OFFSET INT_HNDLR2
MOV AH,30H ; GET DOS VERSION NUMBER
INT DOS ; DOS FUNCTION
CMP AL,2 ; AT LEAST DOS 2?
JB SVC1 ; JUMP IF DOS 1
; SAVE OLD VECTOR WITH DOS 2 CALLS
MOV AH,35H ; FETCH INTERRUPT VECTOR CONTENTS
MOV AL,INT_COM[SI] ; INTERRUPT NUMBER
INT DOS ; DOS 2 FUNCTION
MOV OLD_COM_OFF[SI],BX ; SAVE
MOV BX,ES ; ES:BX
MOV OLD_COM_SEG[SI],BX ; FOR LATER RESTORATION
JMP SHORT SVCX ; DONE
; SAVE OLD VECTOR WITH DOS 1 CALLS
SVC1: MOV AX,0 ; ZERO SEGMENT
MOV ES,AX ; ES POINTS TO INTERRUPT VECTORS
MOV BL,INT_COM[SI] ; OUR INTERRUPT NUMBER
MOV BH,0 ; BL -> BX
SHL BX,1 ; TIMES FOUR
SHL BX,1 ; IS OFFSET OF VECTOR IN MEMORY
MOV AX,WORD PTR ES:[BX] ; SAVE
MOV OLD_COM_OFF[SI],AX ; THE
ADD BX,2 ; OLD
MOV AX,WORD PTR ES:[BX] ; INTERRUPT
MOV OLD_COM_SEG[SI],AX ; VECTOR
SVCX: POP ES ; RESTORE ES
pop si
mov sp,bp
pop bp
RET ; DONE
_save_com ENDP
PAGE
;
; INSTALL_COM: INSTALL THE ACTIVE PORT
;
; SET 8250 PORTS FROM RS-232 BASE IN ROM BIOS DATA AREA
; INITIALIZE PORT CONSTANTS AND ERROR COUNTS
; INSTALL INTERRUPT VECTOR
;
; return ax=1 on success ax=0 on failure
;
_install_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
PUSH ES ; SAVE EXTRA SEGMENT
CMP INSTALLED[SI],1 ; ALREADY INSTALLED?
JNE INSTOK ; NO, CONTINUE
JMP INSTX ; ELSE JUMP IF ALREADY INSTALLED
; CLEAR ERROR COUNTS
INSTOK: MOV WORD PTR EOVFLOW[SI],0 ; BUFFER OVERFLOWS
MOV WORD PTR EOVRUN[SI],0 ; RECEIVE OVERRUNS
MOV WORD PTR EBREAK[SI],0 ; BREAK CHARS
MOV WORD PTR EFRAME[SI],0 ; FRAMING ERRORS
MOV WORD PTR EPARITY[SI],0 ; PARITY ERRORS
MOV WORD PTR EXMIT[SI],0 ; TRANSMISSION ERRORS
MOV WORD PTR EDSR[SI],0 ; DATA SET READY ERRORS
MOV WORD PTR ECTS[SI],0 ; CLEAR TO SEND ERRORS
; SENSE PC TYPE AND SET DIVISOR ACCORDINGLY
MOV BX,ROM ; HIGH ROM SEGMENT
MOV ES,BX ; TO ES
ASSUME ES:ROM
MOV DIV50,DIV50PC ; ASSUME PC OR XT
CMP ROMID,0FDH ; IS IT A PCjr?
JNE INST0 ; JUMP IF NOT
MOV DIV50,DIV50JR ; ELSE SET JR DIVISOR
; SET 8250 PORT ADDRESSES
INST0: MOV BX,RBDA ; ROM BIOS DATA AREA
MOV ES,BX ; TO ES
ASSUME ES:RBDA
TEST PORT[SI],1 ; PORT 1?
JZ INST1 ; JUMP IF NOT
MOV AX,3F8H ; COM1 BASE PORT ADDRESS
JMP SHORT INST2 ; CONTINUE
INST1: MOV AX,2F8H ; COM2 BASE PORT ADDRESS
INST2: CMP AX,RS232_BASE ; INSTALLED?
JE INST2A ; JUMP IF SO
CMP AX,RS232_BASE+2 ; INSTALLED?
JNE INST666 ; JUMP IF NOT
INST2A: MOV BX,DATREG ; OFFSET OF TABLE OF PORTS
MOV CX,7 ; LOOP SIX TIMES
INST3: MOV WORD PTR [SI][BX],AX ; SET PORT ADDRESS
INC AX ; NEXT PORT
ADD BX,2 ; NEXT WORD ADDRESS
LOOP INST3 ; RS232 BASE LOOP
; RESET VECTOR TO POINT TO OUR HANDLER
MOV AREA1.INT_HNDLR,OFFSET INT_HNDLR1
MOV AREA2.INT_HNDLR,OFFSET INT_HNDLR2
MOV AH,25H ; SET INTERRUPT VECTOR CONTENTS
MOV AL,INT_COM[SI] ; INTERRUPT NUMBER
MOV DX,OFFSET DGROUP:INT_HNDLR[SI] ; OUR INTERRUPT HANDLER
PUSH DS ; SAVE DATA SEGMENT
PUSH CS ; COPY CS
POP DS ; TO DS
INT DOS ; DOS FUNCTION
POP DS ; RECOVER DATA SEGMENT
; PORT INSTALLED
INSTX: MOV INSTALLED[SI],1 ; PORT INSTALLED
POP ES ; RESTORE ES
mov ax,1
pop si
mov sp,bp
pop bp
RET ; DONE
; PORT NOT INSTALLED
INST666:MOV INSTALLED[SI],0 ; PORT NOT INSTALLED ON THIS PC
POP ES ; RESTORE ES
mov ax,0
pop si
mov sp,bp
pop bp
RET ; DONE
_install_com ENDP
PAGE
;
; RESTORE ORIGINAL INTERRUPT VECTOR
;
_restore_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
MOV INSTALLED[SI],0 ; PORT IS NO LONGER INSTALLED
MOV AH,25H ; SET INTERRUPT VECTOR FUNCTION
MOV AL,INT_COM[SI] ; INTERRUPT NUMBER
MOV DX,OLD_COM_OFF[SI] ; OLD OFFSET TO DX
MOV BX,OLD_COM_SEG[SI] ; OLD SEG
PUSH DS ; SAVE DS
MOV DS,BX ; TO DS
INT DOS ; DOS FUNCTION
POP DS ; RECOVER DS
pop si
mov sp,bp
pop bp
RET ; DONE
_restore_com ENDP
PAGE
;
; OPEN_COM ON CURRENT PORT
;
; CLEAR BUFFERS
; RE-INITIALIZE THE INTEL 8250 UART
; ENABLE INTERRUPTS ON THE INTEL 8259 INTERRUPT CONTROL CHIP
;
; [bp+6] = BAUD RATE
; [bp+8] = CONNECTION: M(ODEM), D(IRECT)
; [bp+10] = PARITY: N(ONE), O(DD), E(VEN), S(PACE), M(ARK)
; [bp+12] = STOP BITS: 1, 2
; [bp+14] = XON/XOFF: E(NABLED), D(ISABLED)
;
_open_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
CLI ; INTERRUPTS OFF
mov ax,[bp+6]
MOV BAUD_RATE[SI],AX ; SET
mov bh,[bp+8]
MOV CONNECTION[SI],BH ; ARGS
mov bl,[bp+10]
MOV PARITY[SI],BL ; IN
mov ch,[bp+12]
MOV STOP_BITS[SI],CH ; MEMORY
mov cl,[bp+14]
MOV XON_XOFF[SI],CL
; RESET FLOW CONTROL
MOV HOST_OFF[SI],0 ; HOST FLOWING
MOV PC_OFF[SI],0 ; PC FLOWING
; RESET BUFFER COUNTS AND POINTERS
MOV START_TDATA[SI],0
MOV END_TDATA[SI],0
MOV START_RDATA[SI],0
MOV END_RDATA[SI],0
MOV SIZE_TDATA[SI],0
MOV SIZE_RDATA[SI],0
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JNZ OC1 ; SKIP IF SO
JMP OCX ; ELSE ABORT
OC1:
; RESET THE 8250
MOV AL,0
MOV DX,MCR[SI]
OUT DX,AL
JMP $+2 ; I/O DELAY FOR JR
MOV DX,LSR[SI] ; RESET LINE STATUS CONDITION
IN AL,DX
JMP $+2 ; I/O DELAY FOR JR
MOV DX,DATREG[SI] ; RESET RECSIVE DATA CONDITION
IN AL,DX
JMP $+2 ; I/O DELAY FOR JR
MOV DX,MSR[SI] ; RESET MODEM DELTAS AND CONDITIONS
IN AL,DX
; CONVERT PASSED BAUD RATE TO 8250 DIVISOR
MOV AX,50 ; 50 BAUD
MUL DIV50 ; TIMES ITS DIVISOR
DIV BAUD_RATE[SI] ; OTHER SPEEDS ARE PROPORTIONAL
MOV BX,AX ; RESULT TO BX
; SET 8250 DIVISOR
MOV DX,LCR[SI] ; LINE CONTROL REGISTER
MOV AL,80H ; HI BIT ON
OUT DX,AL ; SET DLAB = 1
JMP $+2 ; I/O DELAY FOR JR
MOV DX,WORD PTR DLL[SI] ; LEAST SIGNIFICANT BYTE
MOV AL,BL ; LSB FROM TABLE
OUT DX,AL ; SET LSB ON 8250
JMP $+2 ; I/O DELAY FOR JR
MOV DX,WORD PTR DLH[SI] ; MOST SIGNIFICANT BYTE
MOV AL,BH ; MSB FROM TABLE
OUT DX,AL ; SET MSB ON 8250
JMP $+2 ; I/O DELAY FOR JR
; SET PARITY AND NUMBER OF STOP BITS
MOV AL,03H ; NONE OR SPACE PARITY IS THE DEFAULT
CMP PARITY[SI],'O' ; ODD PARITY REQUESTED?
JNE P1 ; JUMP IF NOT
MOV AL,0AH ; SELECT ODD PARITY
JMP SHORT P3 ; CONTINUE
P1: CMP PARITY[SI],'E' ; EVEN PARITY REQUESTED?
JNE P2 ; JUMP IF NOT
MOV AL,1AH ; SELECT EVEN PARITY
JMP SHORT P3 ; CONTINUE
P2: CMP PARITY[SI],'M' ; MARK PARITY REQUESTED?
JNE P3 ; JUMP IF NOT
MOV AL,2AH ; SELECT MARK PARITY
P3: TEST STOP_BITS[SI],2 ; 2 STOP BITS REQUESTED?
JZ STOP1 ; NO
OR AL,4 ; YES
STOP1: MOV DX,LCR[SI] ; LINE CONTROL REGISTER
OUT DX,AL ; SET 8250 PARITY MODE AND DLAB=0
; ENABLE INTERRUPTS ON 8259 AND 8250
IN AL,INTA01 ; SET ENABLE BIT ON 8259
AND AL,NIRQ[SI]
OUT INTA01,AL
MOV DX,IER[SI] ; ENABLE INTERRUPTS ON 8250
MOV AL,5 ; RECEIVE & LINE ERROR
OUT DX,AL
JMP $+2 ; I/O DELAY FOR JR
MOV DX,MCR[SI] ; SET DTR AND ENABLE INT DRIVER
MOV AL,0BH
OUT DX,AL
OCX: STI ; INTERRUPTS ON
pop si
mov sp,bp
pop bp
RET ; DONE
_open_com ENDP
PAGE
;
; CLOSE_COM - TURNS OFF INTERRUPTS FROM THE COMMUNICATIONS PORT
;
_close_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ CCX ; ABORT IF NOT
; TURN OFF 8250
MOV DX,IER[SI]
MOV AL,0
OUT DX,AL
; TURN OFF 8259
MOV DX,INTA01
IN AL,DX
OR AL,IRQ[SI]
JMP $+2 ; DELAY FOR AT
OUT DX,AL
CCX: pop si
mov sp,bp
pop bp
RET
_close_com ENDP
PAGE
;
; DTR_OFF - TURNS OFF DTR TO TELL MODEMS THAT THE TERMINAL HAS GONE AWAY
; AND TO HANG UP THE PHONE
;
_dtr_off PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ DFX ; ABORT IF NOT
MOV DX,MCR[SI]
MOV AL,08H ; DTR OFF, RTS OFF, OUT2 ON
OUT DX,AL
DFX: POP SI ; RECOVER REGS
POP DX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET
_dtr_off ENDP
;
; DTR_ON - TURNS DTR ON
;
_dtr_on PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ DNX ; ABORT IF NOT
MOV DX,MCR[SI]
MOV AL,0BH
OUT DX,AL
DNX: POP SI ; RECOVER REGS
POP DX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_dtr_on ENDP
PAGE
;
; R_COUNT - RETURNS NUMBER OF BYTES IN THE RECEIVE BUFFER IN AX
; total in DX
;
_r_count PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH SI ; SAVE SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
MOV AX,0 ; NOTHING RECEIVED IF NOT INSTALLED
mov dx,R_SIZE
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ RCX ; ABORT IF NOT
MOV AX,SIZE_RDATA[SI] ; GET NUMBER OF BYTES USED
RCX: POP SI ; RESTORE SI
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET
_r_count ENDP
PAGE
;
; RECEIVE - RETURNS THE NEXT CHARACTER FROM THE RECEIVE BUFFER IN AL
; AND REMOVES IT FROM THE BUFFER
; THE PARITY BIT IS STRIPPED OFF
;
_receive_com PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH BX ; SAVE REGS
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
mov ax,-1 ; -1 if bad call
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ RCVX ; ABORT IF NOT
CMP SIZE_RDATA[SI],0 ; ANY CHARACTERS?
JE RCVX ; ABORT IF NOT
; GOOD CALL
mov ah,0 ; good call
MOV BX,START_RDATA[SI] ; GET POINTER TO OLDEST CHAR
MOV AL,RDATA[SI][BX] ; GET CHAR FROM BUFFER
; MOD BY LBA, 10/6/85 FOR PROPER SUPPORT OF NO PARITY COMMUNICATIONS
CMP PARITY[SI],'N' ; ARE WE RUNNING WITH NO PARITY?
JE L11 ; IF SO, DON'T STRIP HIGH BIT
; END OF MOD
AND AL,7FH ; STRIP PARITY BIT
L11: INC BX ; BUMP START_RDATA
CMP BX,R_SIZE ; SEE IF PAST END
JB L12 ; IF NOT THEN SKIP
MOV BX,0 ; ADJUST TO BEGINNING
L12: MOV START_RDATA[SI],BX ; SAVE THE NEW START_RDATA VALUE
DEC SIZE_RDATA[SI] ; ONE LESS CHARACTER
CMP XON_XOFF[SI],'E' ; FLOW CONTROL ENABLED?
JNE RCVX ; DO NOTHING IF DISABLED
CMP HOST_OFF[SI],1 ; HOST TURNED OFF?
JNE RCVX ; JUMP IF NOT
CMP SIZE_RDATA[SI],R_SIZE/20 ; RECEIVE BUFFER NEARLY EMPTY?
JGE RCVX ; DONE IF NOT
MOV HOST_OFF[SI],0 ; TURN ON HOST IF SO
PUSH AX ; SAVE RECEIVED CHAR
MOV AL,CONTROL_Q ; TELL HIM TO TALK
CLI ; TURN OFF INTERRUPTS
CALL SENDII ; SEND IMMEDIATELY INTERNAL
STI ; INTERRUPTS BACK ON
POP AX ; RESTORE RECEIVED CHAR
RCVX: POP SI ; RECOVER REGS
POP BX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_receive_com ENDP
PAGE
;
; S_COUNT - RETURNS IN AX THE AMOUNT OF FREE SPACE
; REMAINING IN THE TRANSMIT BUFFER
; DX total size
;
_s_count PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH SI ; SAVE SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
MOV AX,0 ; NO SPACE LEFT IF NOT INSTALLED
mov dx,S_SIZE
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ SCX ; ABORT IF NOT
MOV AX,S_SIZE ; GET THE SIZE OF THE X-MIT BUFFER
SUB AX,SIZE_TDATA[SI] ; SUBTRACT THE NUMBER OF BYTES USED
SCX: POP SI ; RECOVER SI
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET
_s_count ENDP
PAGE
;
; SEND - SEND A CHARACTER
; [bp+6] = char
;
_send_com PROC FAR
push bp
mov bp,sp
push si
mov al,[bp+6]
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH BX
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ L44 ; ABORT IF NOT
CMP SIZE_TDATA[SI],S_SIZE ; BUFFER FULL?
JL L4A ; JUMP IF NOT
INC WORD PTR EOVFLOW[SI] ; BUMP ERROR COUNT
JMP SHORT L44 ; PUNT
L4A: MOV BX,END_TDATA[SI] ; BX POINTS TO FREE SPACE
MOV TDATA[SI][BX],AL ; MOVE CHAR TO BUFFER
INC BX ; INCREMENT END_TDATA
CMP BX,S_SIZE ; SEE IF PAST END
JL L4 ; IF NOT THEN SKIP
MOV BX,0 ; ADJUST TO BEGINNING
L4: MOV END_TDATA[SI],BX ; SAVE NEW END_TDATA
INC SIZE_TDATA[SI] ; ONE MORE CHARACTER IN X-MIT BUFFER
MOV DX,IER[SI] ; INTERRUPT ENABLE REGISTER
IN AL,DX ; GET IT
TEST AL,2 ; SEE IF TX INTERRUPTS ARE ENABLED
JNZ L44 ; JUMP IF SO
MOV AL,7 ; IF NOT THEN RCV, TX, LINE ERROR
OUT DX,AL ; ARE ENABLED
L44: POP SI ; RESTORE REGS
POP DX
POP BX
POP AX
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_send_com ENDP
PAGE
;
; SENDI - SEND A CHARACTER IMMEDIATELY
; [bp+6] = char to send
;
_sendi_com PROC FAR
push bp
mov bp,sp
push si
mov al,[bp+6]
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH BX
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ LQ44 ; ABORT IF NOT
CLI ; MASK INTERRUPTS
CALL SENDII ; CALL INTERNAL SEND IMMEDIATE
STI ; INTERRRUPTS BACK ON
LQ44: POP SI ; RESTORE REGS
POP DX
POP BX
POP AX
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_sendi_com ENDP
PAGE
;
; INTERNAL ROUTINE
; DEPENDS ON CALLER TO KEEP INTERRUPTS CLEARED AND SET SI
; SENDI - SEND A CHARACTER IMMEDIATELY (PUT AT BEGINNING OF QUEUE)
; AL = CHAR TO WRITE
;
SENDII PROC NEAR
PUSH DX ; SAVE DX
CMP SIZE_TDATA[SI],S_SIZE ; BUFFER FULL?
JB LI4A ; JUMP IF NOT
INC WORD PTR EOVFLOW[SI] ; BUMP ERROR COUNT
MOV BX,START_TDATA[SI] ; BX POINTS TO FIRST CHAR IN BUFFER
MOV TDATA[SI][BX],AL ; CLOBBER FIRST CHAR IN BUFFER
JMP SHORT LI4B ; CONTINUE
LI4A: MOV BX,START_TDATA[SI] ; BX POINTS TO FIRST CHAR IN BUFFER
DEC BX ; BACKUP THE PTR
CMP BX,-1 ; BEFORE BEGINNING?
JNE LI4 ; JUMP IF NOT
MOV BX,S_SIZE-1 ; POINT TO END IF SO
LI4: MOV TDATA[SI][BX],AL ; MOVE CHAR TO BUFFER
MOV START_TDATA[SI],BX ; SAVE NEW START_TDATA
INC SIZE_TDATA[SI] ; ONE MORE CHARACTER IN X-MIT BUFFER
LI4B: MOV DX,IER[SI] ; INTERRUPT ENABLE REGISTER
IN AL,DX ; GET IT
TEST AL,2 ; SEE IF TX INTERRUPTS ARE ENABLED
JNZ LI44 ; JUMP IF SO
MOV AL,7 ; IF NOT THEN RCV, TX, LINE ERROR
OUT DX,AL ; ARE ENABLED
LI44: POP DX ; RECOVER DX
RET ; DONE
SENDII ENDP
PAGE
;
; S_LOCAL
;
_send_local PROC FAR
push bp
mov bp,sp
push si
mov al,[bp+6]
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH BX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ SLX ; ABORT IF NOT
CLI ; INTERRUPTS OFF
CMP SIZE_RDATA[SI],R_SIZE ; SEE IF ANY ROOM
JB L13A ; SKIP IF ROOM
INC WORD PTR EOVFLOW[SI] ; BUMP OVERFLOW COUNT
JMP SHORT L14 ; PUNT
L13A: MOV BX,END_RDATA[SI] ; BX POINTS TO FREE SPACE
MOV RDATA[SI][BX],AL ; SEND DATA TO BUFFER
INC BX ; INCREMENT END_RDATA POINTER
CMP BX,R_SIZE ; SEE IF GONE PAST END
JL L13 ; IF NOT THEN SKIP
MOV BX,0 ; ELSE ADJUST TO BEGINNING
L13: MOV END_RDATA[SI],BX ; SAVE VALUE
INC SIZE_RDATA[SI] ; GOT ONE MORE CHARACTER
L14: STI ; INTERRUPTS BACK ON
SLX: POP SI ; RECOVER REGS
POP BX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_send_local ENDP
PAGE
;
; BREAK - CAUSES A BREAK TO BE SENT OUT ON THE LINE
;
_break_com PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH CX
PUSH DX
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ BRX ; ABORT IF NOT
MOV DX,LCR[SI] ; LINE CONTROL REGISTER
IN AL,DX ; GET CURRENT SETTING
JMP $+2 ; I/O DELAY FOR JR
OR AL,40H ; TURN ON BREAK BIT
OUT DX,AL ; SET IT ON THE 8250
MOV CX,0C000H ; WAIT APPROX. 1/4 SEC.
BREAK1: LOOP BREAK1 ; BUSY WAIT
AND AL,0BFH ; TURN OFF BREAK BIT
OUT DX,AL ; RESTORE LINE CONTROL REGISTER
BRX: POP DX ; RECOVER REGS
POP CX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_break_com ENDP
PAGE
;
; COM_ERRORS - RETURN POINTER IN dx:ax TO ERROR COUNTS
;
_com_errors PROC FAR
push bp
mov bp,sp
mov ax,OFFSET DGROUP:CURRENT_AREA
add ax,ERROR_BLOCK
mov dx,ds
mov sp,bp
pop bp
RET ; DONE
_com_errors ENDP
PAGE
;
; INTERNAL ROUTINE
; BUMP ERROR COUNTS FROM LINE STATUS IN AL
;
E_BUMP PROC NEAR
TEST AL,2 ; OVERRUN ERROR?
JZ LSI1 ; JUMP IF NOT
INC WORD PTR EOVRUN[SI] ; ELSE BUMP ERROR COUNT
LSI1: TEST AL,4 ; PARITY ERROR?
JZ LSI2 ; JUMP IF NOT
INC WORD PTR EPARITY[SI] ; ELSE BUMP ERROR COUNT
LSI2: TEST AL,8 ; FRAMING ERROR?
JZ LSI3 ; JUMP IF NOT
INC WORD PTR EFRAME[SI] ; ELSE BUMP ERROR COUNT
LSI3: TEST AL,16 ; BREAK RECEIVED?
JZ LSI4 ; JUMP IF NOT
INC WORD PTR EBREAK[SI] ; ELSE BUMP ERROR COUNT
LSI4: RET ; DONE
E_BUMP ENDP
PAGE
;
; INTERNAL ROUTINE
; MODEM SEND PROTOCOL
;
M_PROTOCOL PROC NEAR
CMP CONNECTION[SI],'M' ; MODEM CONNECTION?
JNE S3 ; IF NOT, SKIP DSR & CTS PROTOCOL
; TELL MODEM WE'RE READY TO SEND
MOV DX,MCR[SI] ; MODEM CONTROL REGISTER
MOV AL,00001011B ; OUT 2, RTS, DTR
OUT DX,AL ; TERMINAL READY, REQUEST TO SEND
JMP $+2 ; I/O DELAY FOR JR
; WAIT UNTIL MODEM SAYS DATA SET READY
MOV CX,1000 ; TIMEOUT COUNT
MOV DX,MSR[SI] ; MODEM STATUS REGISTER
S1: IN AL,DX ; GET MODEM STATUS
TEST AL,20H ; DATA SET READY?
JNZ S1X ; YES, TEST CLEAR TO SEND
LOOP S1 ; NO, BUSY WAIT
INC WORD PTR EDSR[SI] ; BUMP ERROR COUNT
JMP SHORT S3 ; WE TIMED OUT
S1X:
; WAIT UNTIL MODEM SAYS IT'S CLEAR TO SEND
MOV CX,1000 ; TIMEOUT COUNT
S2: IN AL,DX ; GET MODEM STATUS
TEST AL,10H ; CLEAR TO SEND?
JNZ S2X ; YES
LOOP S2 ; NO, KEEP TRYING
INC WORD PTR ECTS[SI] ; BUMP ERROR COUNT - WE TIMED OUT
S2X:
; TEST FOR TRANSMITTER READY
S3: MOV DX,LSR[SI] ; LINE STATUS REGISTER
IN AL,DX ; GET LINE STATUS
TEST AL,20H ; TRANSMITTER READY?
JNZ S4 ; SKIP IF SO
INC WORD PTR EXMIT[SI] ; ELSE BUMP ERROR COUNT
S4: RET ; DONE
M_PROTOCOL ENDP
PAGE
;
; INTERNAL ROUTINES FOR FLOW CONTROL
;
; FLOW_IN - RESPOND TO FLOW CONTROL COMMANDS FROM HOST
; FLOW_OUT - ISSUE FLOW CONTROL COMMANDS TO HOST
;
FLOW_IN PROC NEAR
PUSH AX ; SAVE CHAR
CMP XON_XOFF[SI],'E'; FLOW CONTROL ENABLED?
JNE FI_2 ; DO NOTHING IF DISABLED
AND AL,7FH ; STRIP PARITY
CMP AL,CONTROL_S ; STOP COMMAND RECEIVED?
JNE FI_1 ; JUMP IF NOT
MOV PC_OFF[SI],1 ; WE MUST SHUT UP
JMP SHORT FI_2 ; CONTINUE
FI_1: CMP AL,CONTROL_Q ; GO COMMAND RECEIVED?
JNE FI_2 ; NO, MUST BE NORMAL CHAR
MOV PC_OFF[SI],0 ; WE START TALKING AGAIN
FI_2: POP AX ; RESTORE CHAR
RET ; DONE
FLOW_IN ENDP
;
FLOW_OUT PROC NEAR
CMP XON_XOFF[SI],'E'; FLOW CONTROL ENABLED?
JNE FO_X ; DO NOTHING IF DISABLED
CMP HOST_OFF[SI],1 ; HOST TURNED OFF?
JE FO_X ; JUMP IF SO
CMP SIZE_RDATA[SI],R_SIZE/2 ; RECEIVE BUFFER NEARLY FULL?
JLE FO_X ; DONE IF NOT
MOV AL,CONTROL_S ; TURN OFF HOST IF SO
CALL SENDII ; SEND IMMEDIATELY INTERNAL
MOV HOST_OFF[SI],1 ; HOST IS NOW OFF
FO_X: RET ; DONE
FLOW_OUT ENDP
PAGE
;
; INT_HNDLR1 - HANDLES INTERRUPTS GENERATED BY COM1:
;
INT_HNDLR1 PROC FAR
PUSH SI ; SAVE SI
MOV SI,OFFSET AREA1 ; DATA AREA FOR COM1:
JMP SHORT INT_COMMON ; CONTINUE
;
; INT_HNDLR2 - HANDLES INTERRUPTS GENERATED BY COM2:
;
INT_HNDLR2 PROC FAR
PUSH SI ; SAVE SI
MOV SI,OFFSET AREA2 ; DATA AREA FOR COM2:
;
; BODY OF INTERRUPT HANDLER
;
INT_COMMON:
PUSH AX ; SAVE REGS
PUSH BX
PUSH CX
PUSH DX
PUSH BP
PUSH DI
PUSH DS
PUSH ES
MOV AX,SEG _DATA ; OUR DATA SEG
MOV DS,AX ; TO DS
; CLEAR THE INTERRUPT CONTROLLER FLAG
MOV DX,INTA00 ; 8259 CONTROL PORT
MOV AL,EOI[SI] ; SPECIFIC END OF INTERRUPT
OUT DX,AL ; CLEAR FLAG
; FIND OUT WHERE INTERRUPT CAME FROM AND JUMP TO ROUTINE TO HANDLE IT
REPOLL:
MOV DX,IIR[SI] ; READ INTERRUPT STATUS REGISTER
IN AL,DX
CMP AL,4
JE RX_INT ; IF FROM THE RECEIVER
CMP AL,2
JE TX_INT ; IF FROM THE TRANSMITTER
CMP AL,6
JE LSTAT_INT ; INTERRUPT BECAUSE OF LINE STATUS
CMP AL,0
JE MSTAT_INT ; INTERRUPT BECAUSE OF MODEM STATUS
JMP FAR PTR INT_END ; DONE, EXIT (DON'T FIX FAR PTR STUFF)
LSTAT_INT:
MOV DX,LSR[SI] ; READ AND IGNORE LINE STATUS
IN AL,DX ;
CALL E_BUMP ; JUST BUMP ERROR COUNTS
JMP REPOLL ; SEE IF ANY MORE INTERRUPTS
MSTAT_INT:
MOV DX,MSR[SI] ; READ AND IGNORE MODEM STATUS
IN AL,DX ;
JMP REPOLL ; SEE IF ANY MORE INTERRUPTS
TX_INT:
CMP PC_OFF[SI],1 ; HAVE WE BEEN TOLD TO SHUT UP?
JNE GOODTX1 ; JUMP IF NOT
CMP HOST_OFF[SI],1 ; HAS HOST ALSO SHUT UP?
JNE SEND_NO_MORE ; JUMP IF NOT
; CLEAR XON/XOFF DEADLOCK
MOV PC_OFF[SI],0 ; WE SPEAK
MOV HOST_OFF[SI],0 ; THEY REPLY
MOV AL,CONTROL_Q ; BUT ONLY WHEN
CALL SENDII ; WE LET THEM
GOODTX1:
CMP SIZE_TDATA[SI],0 ; SEE IF ANY MORE DATA TO SEND
JG HAVE_DATA ; IF POSITIVE THEN THERE IS DATA TO SEND
; IF NO DATA TO SEND THEN RESET TX INTERRUPT AND RETURN
SEND_NO_MORE:
MOV DX,IER[SI] ;
MOV AL,5 ; JUST RCV AND LINE ERROR
OUT DX,AL ; ARE SET
JMP REPOLL ;
HAVE_DATA:
CALL M_PROTOCOL ; DO MODEM PROTOCOL IF NECESSARY
MOV BX,START_TDATA[SI] ; BX POINTS TO NEXT CHAR. TO BE SENT
MOV AL,TDATA[SI][BX] ; GET DATA FROM BUFFER
MOV DX,DATREG[SI] ; DX EQUALS PORT TO SEND DATA TO
OUT DX,AL ; SEND DATA
INC BX ; INCREMENT START_TDATA
CMP BX,S_SIZE ; SEE IF GONE PAST END
JB NTADJ ; IF NOT THEN SKIP
MOV BX,0 ; RESET TO BEGINNING
NTADJ: MOV START_TDATA[SI],BX ; SAVE START_TDATA
DEC SIZE_TDATA[SI] ; ONE LESS CHARACTER IN X-MIT BUFFER
JMP REPOLL
RX_INT:
MOV DX,DATREG[SI] ; 8250 DATA REGISTER
IN AL,DX ; GET DATA
CALL FLOW_IN ; RESPOND TO F.C. COMMANDS FROM HOST
CMP SIZE_RDATA[SI],R_SIZE ; SEE IF ANY ROOM
JL GOOD_RX1 ; CONTINUE IF SO
INC WORD PTR EOVFLOW[SI] ; BUMP OVERFLOW ERROR COUNT
JMP REPOLL ; PUNT
GOOD_RX1:
MOV BX,END_RDATA[SI] ; BX POINTS TO FREE SPACE
MOV RDATA[SI][BX],AL ; MOVE DATA TO BUFFER
INC SIZE_RDATA[SI] ; GOT ONE MORE CHARACTER
INC BX ; INCREMENT END_RDATA POINTER
CMP BX,R_SIZE ; SEE IF GONE PAST END
JB NRADJ ; IF NOT THEN SKIP
MOV BX,0 ; ELSE ADJUST TO BEGINNING
NRADJ: MOV END_RDATA[SI],BX ; SAVE VALUE
CALL FLOW_OUT ; ISSUE FLOW CONTROL COMMANDS TO HOST
JMP REPOLL ;
INT_END:
POP ES ; RESTORE REGS
POP DS
POP DI
POP BP
POP DX
POP CX
POP BX
POP AX
POP SI ; RESTORE SI, TOO
IRET
INT_HNDLR2 ENDP
INT_HNDLR1 ENDP
COM_TEXT ENDS
END
@@@ Finished comm.asm
echo dcpasm.asm
cat >dcpasm.asm <<'@@@ Finished dcpasm.asm'
; Support rotuines for DCP a uucp clone.
; Copyright Richard H. Lamb, 1985,1986,1987
; dos dir scan for a file
;""""""""""""""""""""""""""""""
_text segment byte public 'code'
_text ends
_data segment byte public 'data'
_data ends
const segment byte public 'const'
const ends
_bbs segment byte public 'bbs'
_bbs ends
dgroup group const,_bbs,_data
assume cs:_text,ds:dgroup,ss:dgroup,es:dgroup
_text SEGMENT
public _dir_open
_dir_open proc near
;_dir_open:
push bp
mov bp,sp
push ds
push dx
push cx
; set DTA
mov dx,word ptr [bp+6]
mov ah,01ah
int 21h
; find first file
mov dx,word ptr [bp+4]
mov ah,04eh
mov cx,010h
int 21h
; return 0=found
sub ah,ah
pop cx
pop dx
pop ds
pop bp
ret
_dir_open endp
;*******************************
_text ends
end
@@@ Finished dcpasm.asm
echo call.bat
cat >call.bat <<'@@@ Finished call.bat'
dcp master 3
@@@ Finished call.bat
echo makeexe.bat
cat >makeexe.bat <<'@@@ Finished makeexe.bat'
link dcp+dcpstart+dcpscan+dcpsys+dcprec+dcpsend+dcpgpkt+dcprpkt+dcptpkt+dcpkpkt+dcpio+dcxqt+dcpvms+comm+dcpasm;
@@@ Finished makeexe.bat
echo makeobj.bat
cat >makeobj.bat <<'@@@ Finished makeobj.bat'
msc dcp;
msc dcpsys;
msc dcpstart;
msc -Ze dcpio;
msc -Ze dcpscan;
msc dcpsend;
msc dcprec;
msc dcpgpkt;
msc dcprpkt;
msc dcptpkt;
msc dcpkpkt;
msc -Ze dcxqt;
msc dcpvms;
masm comm;
masm dcpasm;
msc rmail;
link rmail;
@@@ Finished makeobj.bat
echo call.cli
cat >call.cli <<'@@@ Finished call.cli'
xe dcp master 3
@@@ Finished call.cli
echo makeexe.cli
cat >makeexe.cli <<'@@@ Finished makeexe.cli'
ccl dcp,dcpsys,dcpstart,dcpscan,dcprec,dcpsend,dcpgpkt,dcptpkt,dcpio,dcprpkt, &
dcpkpkt,dcxqt,dcpvms
@@@ Finished makeexe.cli
echo makeobj.cli
cat >makeobj.cli <<'@@@ Finished makeobj.cli'
cc dcp
cc dcpsys
cc dcpstart
cc dcpscan
cc dcprec
cc dcpsend
cc dcpgpkt
cc dcptpkt
cc dcpio
cc dcxqt
cc dcprpkt
cc dcpkpkt
cc dcpvms
cc rmail
ccl rmail
@@@ Finished makeobj.cli
echo clink.vms
cat >clink.vms <<'@@@ Finished clink.vms'
$ link 'p1,sys$library:crtlib/lib
@@@ Finished clink.vms
echo makeexe.vms
cat >makeexe.vms <<'@@@ Finished makeexe.vms'
$ clink dcp,dcpstart,dcpsys,dcpscan,dcpsend,dcprec,dcpgpkt,dcptpkt,dcprpkt,dcpkpkt,dcpio,dcxqt,dcpvms
@@@ Finished makeexe.vms
echo makeobj.vms
cat >makeobj.vms <<'@@@ Finished makeobj.vms'
$ cc dcp
$ cc dcpstart
$ cc dcpsys
$ cc dcpscan
$ cc dcpsend
$ cc dcprec
$ cc dcpgpkt
$ cc dcptpkt
$ cc dcprpkt
$ cc dcpkpkt
$ cc dcpio
$ cc dcxqt
$ cc dcpvms
$ cc rmail
$ clink rmail
@@@ Finished makeobj.vms
echo setup.vms
cat >setup.vms <<'@@@ Finished setup.vms'
$ rmail :== $sys$user:[lids.lamb.c.dcp2]rmail
$ dcp :== $sys$user:[lids.lamb.c.dcp2]dcp
$ ss :== $sys$user:[lids.lamb.c.dcp2]spawn
@@@ Finished setup.vms
exit 0
End of Listing