巧妙增强UNIX操作系统的rlogin仿真功能
人民银行桂林市中心支行 丁昌荣
一、问题的提出
----随着计算机技术的飞速发展,UNIX操作系统已成为各类计算机使用的主流操作系统。目前银行的核心主机大都采用UNIX操作系统,并通过TCP/IP网络协议与其它的使用UNIX操作系统的主机联接成网络。用户可使用UNIX系统的rlogin仿真程序登录到联网的UNIX主机系统中,运行该主机的程序,就象在本机上操作一样,简单方便。 但是有时我们在执行仿真程序时又希望利用本机资源进行一些本地处理工作。例如:将远程主机上的终端“透明”打印改向由本地机并口的打印机打印, 触发调用本地的命令来完成一些特殊应用。而rlogin程序没有提供此种功能,只能进行仿真处理,因此有必要对rlogin进行功能扩充, 笔者总结了一种方法,在不修改rlogin程序的情况下,通过编写rlogin的“过滤”程序,结合使用UNIX管道技术,实现了自己的一些特殊仿真应用,巧妙地增强了rlogin仿真功能。
二、设计rlogin的“过滤”程序
---1.设计思想
----利用UNIX系统的管道技术将rlogin网络仿真命令的所有输出都交给另外一程序处理,此程序名称为fzcl,我们称之为“过滤”程序。Fzcl程序对rlogin输出的每个字符进行“过滤”性处理,正常处理是仍进行仿真处理,直接将字符输出到屏幕, 但是如果遇到特殊控制串,则由相应的特殊程序处理。因此只要将在需要本地执行的函数或程序定义好,并设计一个的特殊字符串来触发它的执行就可实现我们的特殊应用。例如在ANSI方式下我们定义特殊字符串ESC[5i(进入打印状态控制串)及dycl函数(此函数的功能是将rlogin 程序输出的每个字符保留在zckk_1中);特殊字符串ESC[4i(取消打印状态控制串)及fhpmcl 函数(将文件zckk_1输出内容输出到本地机上的打印机上)。FZCL程序在执行中遇到ESC[5i 则执行dycl函数,将rlogin 程序输出的每个字符保留在zckk_1中,直到遇ESC[4i,执行fhpmcl函数,将文件zckk_1输出内容输出到本地机上的打印机上,然后再继续仿真处理。这样在我们就可在fzcl程序中任意定义特殊字符串, 设计其处理函数或程序来完成我们需要的功能,使仿真功能更强大。
----2.建立“过滤”程序的串码表
----由于“过滤”程序要处理的特殊控制字符串的总数量有限,故可采取枚举法,建立特殊控制字符串码表(文本文件,以下称串码表),列举各种的特殊控制串的串码定义,以便“过滤”程序能通过查找本表,知道读入的字符串是特殊字符串还是普通的字符串,是进行特殊处理,还是进行仿真处理。每个特殊控制串的串码定义如下:助记字符串=输入字符串=串码值,串码间用冒号分隔。其中输入字符串一般为ESC打头的控制序列。例如:PRIN=\E[5i=100 的含义是转向本地打印,串码值为100,输入字符串ESC[4i的含义是取消本地打印,串码值为101。以下是ansi方式下的部分特殊控制串的串码表文件内容:
|ansi|ansi80x25|Ansi standard crt:\
PRIN=\E[5i=100:SCREEN=\E[4i=101:EXECUT=
\E[9S=102:ENDEXE=\E[8P=103:EXIT=~~=200 |
--- 3.“过滤”程序的关键函数myget_str的设计
----“过滤”程序的设计关键是fzcx程序如何区分正常显示字符与特殊控制串,由于C语言的字符输入,不能区分特殊控制串,故需编写一个能处理特殊控制串的通用字符函数myget_str来读入RLOGIN的输出。由于定义了特殊控制串的串码表,实现myget_str函数就显得容易了,首先设置时钟,以便read字符输入函数每读入一个字,在时钟到后,也能返回该字符。myget_str函数对于读入的每个字符,先查串码表,如果该字符与串码表的某个串码的输入字符串“部分”匹配,继续读入字符,直到完全匹配,返回在该串码中的串值乘256,否则将字符值放入myget_str函数的参数中,并返回该字符值,这样FZCL程序调用myget_str 函数得到返回值,如果返回值除以256等于0,就知道是正常的输入字符,其值为myget_str 函数的参数值;否则表示是特殊控制字符串,由返回值除以256的值可知道是哪个特殊控制串,再作相应的处理,从而达到了设计目的。
三、构筑新的仿真程序myrlogin
----为使用方便,笔者通过使用rlogin与fzcl并结合UNIX的管道技术,编写了一个sh程序myrlogin,来作为我们使用的仿真程序,并将myrlogin与fzcl移到适当的目录(如/usr/bin,/bin等)作为系统命令调用。myrlogin的具体内容如下:
#myrlogin sh程序
rlogin $* | fzcl
四、myrlogin程序的使用方法
----在编写好功能增强的仿真程序myrlogin后,我们在仿真时,就可以使用myrlogin,而不直接使用rlogin,myrlogin命令的使用方法、参数调用形式与rlogin完全一致,以下是用khxk用户凳录到名为IP99的主机的例子:
myrlogin ip99 -l khxk -8
五、“过滤”程序的源程序清单
[code:1:2d84b9e752]/* 过滤处理程序 fzcl.c */
#include < stdio.h >
#include < termio.h >
#include < signal.h >
#include < ctype.h >
#define MAX 100
int dybz,keysum,timeout,gnm[MAX];
char charkz[MAX][12],charstr[MAX][12],
*zcbuf,charbuf[80],cxbuf[80];
main()
{ FILE *fp,*fopen();
int fd,kzm,intc;
char c,inputstr[80];
init_scr(); /*初始化*/
while (1) {
kzm=myget_str(inputstr);
/*通用字符串输入函数*/
intc=kzm/256;
if (intc==0)
{ write(dybz,inputstr,strlen(inputstr));
/*正常字符串处理*/}
else /*特殊处理举例*/ {
if (intc==mykeyval("PRIN")) dycl(&dybz);
/*打印处理*/
if (intc== mykeyval("SCREEN"))
fhpmcl(dybz);/*输出内容转向屏幕,继续仿真处理*/
if (intc== mykeyval("EXCUTE"))
clcx(cxbuf);/*接收程序串*/
if (intc== mykeyval("END"))
system(cxbuf);/*执行程序*/
if (intc== mykeyval("EXIT"))
return(0); /*退出本程序*/
}
}
}
dycl(int *dybz)/*开始保存打印内容,输出内容转向打印机*/
{ FILE *fp,*fopen();
fp=fopen("zckk_1","wb");fclose(fp);
dybz=open("zckk_1",2); return(dybz);
}
fhpmcl(int dybz)/*结束保存打印内容,
并打印保存内容,输出内容转向屏幕*/
{ close(dykz);system("cat zckk_1 >/dev/lp0");
dybz=1; return(dybz);}
setexit()
{ timeout=1;}
myget_str(char *inputstr)/*通用字符串输入函数*/
{ int kzm,j,len,(*sigfn)();
char ch[8],*ss,ss1[60],
kz[20],c,zc_str[88];
zcbuf=charbuf;
sigfn=signal(SIGALRM,setexit);
/*设超时控制*/
while (1) {
timeout=0;
if (kzm==-2)/*已有部分匹配*/ alarm(1);
else {alarm(0);}
j=read(0,zcbuf,1);
*(zcbuf+1)=0;
alarm(0);
if (timeout==1) { zcbuf=charbuf;
return(charbuf[0]); }
kzm=check(charbuf);
if (kzm==-3) {/*不能匹配,返回该字符*/
strcpy(inputstr,charbuf);
zcbuf=charbuf; return
(charbuf[0]);
}
else {
if (kzm==-2) { zcbuf++; continue;
}/*部分匹配,继续输入*/
zcbuf=charbuf;
return(kzm); }
}
}
init_scr()/*初始化*/
{FILE *fp1,*fp,*fopen();
int j,i,sum,len;
char str[20],sx[20],zcstr[140],*ss,name[1024];
if ((fp=fopen("tskz.scr","rb"))==
NULL)/*打开特殊码文件*/ return(-1);
fgets(name,80,fp);
/*篇幅问题,取第1种ANSI终端方式*/
dybz=1;keysum=0;
while (!feof(fp)) {
fgets(name,1024,fp);/*行*/
if ((i=substr(name,"|")) >=0) break;
ss=name;
while (*ss!=0) {
if (qcstr(ss,sx,':')< 0) break;
/*取:结尾的串*/
if ((i=substr(sx,"=")) >=0) {
memcpy(zcstr,sx,i);
*(zcstr+i)=0;
strcpy(charkz[keysum],zcstr);
if ((j=substr(sx+i+1,"=")) >=0) {
memcpy(zcstr,sx+i+1,j);
*(zcstr+j)=0;
changestr(zcstr,"\\E","\033");
/*将\E转换为ESC*/
strcpy(charstr[keysum],zcstr);
gnm[keysum]=atoi(sx+i+j+2);
}
keysum++;
}
if (strlen(ss)==strlen(sx)) break;
ss+=strlen(sx)+1;}
}
}
check(char *str)
/*检查字符串str是否匹配“特殊”字符串*/
{int i,j;
for (i=0;i< keysum;i++) {
if ((j=substr(charstr[i],str))==0) {
if (strcmp(charstr[i],str)!=0) return(-2);
else { return(gnm[i]*256);}
}
}
return(-3);
}
substr(char string[],
char substring[]) /*子串匹配*/
{ int i,j,k;
for ( i=0;string[i] != '\0' ;i++)
for (j=i,k=0;substring[k]
== string[j];k++,j++)
if (substring[k+1] == '\0') return(i);
return(-1);
}
mykeyval(char *cm)/*取助记串的串值*/
{ int i;
for (i=0;i< keysum;i++)
if (strcmp(cm,charkz[i])==0) return(gnm[i]);
return(-1);
}
qcstr(char *name,char *zcstr,char ch)
/*取出name中以ch结尾的串,存放在zcstr中*/
{char *ss;
ss=zcstr;
while (*name!=0&&*name!=ch) *ss++=*name++;
*ss=0;
if (*(name-1)==0) return(-1);
return(0);
}
changestr(char *zcstr,char *src,char *dts)
/*将zcstr中src字符串用dst字符串代替*/
{ char zcstr1[256],*ss2,*ss1,*ss;
ss=zcstr;
ss1=zcstr1;
*ss1=0;
while (*ss!=0) {
if (substr(ss,src)==0) {
strcat(ss1,dts);
ss1+=strlen(dts);
ss+=strlen(src);
}
else *ss1++=*ss++;
}
*ss1=0;
strcpy(zcstr,zcstr1);
}[/code:1:2d84b9e752]
qiuming 回复于:2004-04-19 20:32:59 | |
我试过,好象不行 |
文章来源于领测软件测试网 https://www.ltesting.net/
领测软件测试网最新更新
关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:info@testage.com.cn 电话:010-51297073
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:info@testage.com.cn 电话:010-51297073