Linux 版 (精华区)
发信人: netiscpu (夜☆星光点点☆), 信区: Linux
标 题: ◇ 在 UNIX 系统发展应用程式入门 (二)
发信站: 紫 丁 香 (Sun Nov 8 18:47:58 1998), 转信
寄信人: guest.bbs@hgluo.hust.edu.cn
标 题: ◇ 在 UNIX 系统发展应用程式入门 (二)
发信站: 华南理工大学 BBS木棉站
日 期: Thu Feb 20 14:13:31 1997
在 UNIX 系统发展应用程式入门 (二) 王志祥
取得 User 资料的 pitch 函数:
上其的 FindMan 的 Initial 部份提到两个 User Define 的函数,
一个是 catch, 另一个即是 pitch. Initial 部份 fork 的二十个程序都呼叫
pitch 函数向二十台工作站收集 User login 的资料并筛选出使用者所需的
资料, 先整理出来的程序便先向主程序要求传送资料, 传送以 Socket 完成.
有关 Socket 的部份以後再谈. 以下是 pitch 函数的部份程式:
pitch(host)
char *host;
{
int bufsize;
int ps, j, k, l;
char buffer[BUFSIZE];
int count;
struct utmpidlearr up;
int tmp, gcount, gidx[25];
char gname[25][80];
char line[25][9];
char name[25][9];
char hhost[25][17];
long time[25];
unsigned idle[25];
char temp[80];
up.uia_arr=(struct utmpidle **) malloc(25*sizeof(struct utmpidle *));
: : :
: : :
/* 此处省略要求 Connect 的 Socket 之 Initial 部份. */
: : :
: : :
strcpy(buffer,host);
k=strlen(host);
strcpy(&buffer[k],":\n");
k+=2;
if ( rusers(host, &up) == 0 ) {
count = up.uia_cnt;
buffer[k++] = (char) count;
for ( j=0; j<count; j++) {
strncpy(line[j],up.uia_arr[j]->ui_utmp.ut_line,8);
line[j][8]='\0';
strncpy(name[j],up.uia_arr[j]->ui_utmp.ut_name,8);
name[j][8]='\0';
strncpy(hhost[j],up.uia_arr[j]->ui_utmp.ut_host,16);
hhost[j][16]='\0';
time[j]=up.uia_arr[j]->ui_utmp.ut_time;
idle[j]=up.uia_arr[j]->ui_idle;
}
if (count != 0) {
gcount=check(count,name,gname,gidx);
buffer[k++] = (char) gcount;
if (gcount !=0)
for (j=0; j<gcount;) {
strcpy(&buffer[k],gname[j]);
k+=strlen(gname[j]);
do {
tmp=gidx[j++];
if ( j > gcount )
break;
buffer[k++]='\t';
strcpy(&buffer[k],line[tmp]);
k+=strlen(line[tmp]);
buffer[k++]='\t';
if ((l=idle[tmp]/60) != 0)
sprintf(temp,"%d:%d\t",l,(idle[tmp]%60));
else
sprintf(temp,"%d\t",(idle[tmp]%60));
strcpy(&buffer[k],temp);
k+=strlen(temp);
strcpy(temp,asctime(localtime(&time[tmp])));
strcpy(&buffer[k],temp);
k+=(strlen(temp) - 6);
buffer[k++]='\t';
strcpy(&buffer[k],hhost[tmp]);
k+=strlen(hhost[tmp]);
buffer[k++]='\n';
} while (strcmp(name[tmp],"repeat") == 0);
}
}
buffer[k++]='\0';
}
else {
count = -1;
buffer[k++] = (char) count;
}
: : :
: : :
/* 此处省略要求 Connect 的 Socket 之传送资料部份. */
: : :
: : :
}
其中 rusers 的部份可在 CCSUN 用 " man 3 rusers " 查, 兹摘录
如下:
==================> man 3 rusers 的摘录 <==============
NAME
rnusers, rusers - return information about users on remote
machines
DESCRIPTION
rnusers() returns the number of users logged on to host (-1
if it cannot determine that number). rusers() fills the
utmpidlearr structure with data about host, and returns 0 if
successful.
PROGRAMMING
#include <rpcsvc/rusers.h> <=== 查 struct 的地方
rnusers(host)
char *host
rusers(host, up)
char *host
struct utmpidlearr *up;
==========================================================
由於以上的 manual 中并没有指出 utmpidlearr 的结构型态如何,
因此我们必须列出我们所需要的 head file 资料以取得我们要的
utmpidlearr 结构. 以下是我的搜寻所得:
==================> utmpidlearr 重要资料 <=================
struct utmpidle {
struct utmp ui_utmp;
unsigned ui_idle;
};
struct utmpidlearr {
struct utmpidle **uia_arr;
int uia_cnt;
};
struct utmp {
char ut_line[8]; /* tty name */
char ut_name[8]; /* user id */
char ut_host[16]; /* host name, if remote */
long ut_time; /* time on */
};
============================================================
有了这些资料以後, 再看前面的程式就比较易懂了. ( 若因程式的
变数命名太差, 或流程太混乱, 请见谅. 因这一部份在完成之初又不断加新
的功能, 而不是一次完成的. )
程式中的 buffer 这个变数储存欲送出的资料, 其格式为:
==================================================================
工作站名 login 人数 符合资料的人数 帐号及其上机状态
any bytes 1 bytes 1 bytes any bytes
==================================================================
以下面 FindMan 的输出为例说明:
=====================> FindMan 部份输出 <=====================
ccsun7:
u813xx07 -----> xxxxxxxxxxx
ttyq0 0 Tue Apr 27 23:56:53 xxxuling.Dorm10.
ttyp1 0 Wed Apr 28 01:46:29 xxxuling.Dorm10.
u802xx23 Chen2 xxxxxxxx
ttyr6 31:47 Mon Apr 26 18:47:17 140.113.1xx.177:
ccsun16:
u813xx16 -----> xxxxxxxxxxx
ttyp1 0 Wed Apr 28 01:46:29 xxxmy.DormChu.NC
==============================================================
其中工作站名不限 byte 数, 接收端以 ":\n" 判断此部份的资料
结束与否. 当第二部份为 0 时即填入 -1 表示无人, 与资料比对後找不到
人亦如此. check 函数即是处理与资料比对的工作, FindMan 是与 .look
比对, ScanGirl 与 girl 的资料档比对. check 的函数传回 gcount、
gname、gidx 三个变数. gcount 即是 match 的人数, gname 是从 rusers
传回的资料档稍作修改 ( 重复的帐号改成 "repeat" ) 而成. 而 gidx 是
rusers 传回资料的排序後的 index.
从 check 函数传回的 gname、gidx 构成 buffer 阵列最後的资料.
即 "帐号及其上机状态" 部份. 全部完成後即将资料送出. 由於 check 函数
并不难写, 故不列出.
由於篇幅及时间所限, 这次只讲 pitch 函数, 其它以後再继续,
下期见!! 8-)
—————————————————————————————————
FindMan 关闭启示:
近来 CCSUN 的使用率大幅增加 , 使得 CCSUN
的 Load 高居不下, 我的 FindMan 公用程式只有在 Load 很轻的
SUN 上测试过 ( 0 到 2 ), 没想到最近 Load 重的 SUN ( 7 以上 )
上执行时, 我程式中加快搜寻速度的部份竟成为致命伤. 由於一
次开二十个程序, 若不幸因电脑异常, 则大部分程序会停住而无法离开,
使电脑 Load 更形加重, 也令系统管理者困扰. 在我花了十数小时不断
改程式後( 包括加上 Alarm Signal 控制执行时间 ), 终於还是不能克服
Load 重时的异常状况. 看来, 我的程式理念 ( 以多个程序平行处理来增
快速度 ) 只能在人数少的工作站或特殊的电脑才能用. 有志於发展应用程
式的同学, 切记这个教训.
由於旧的 FindMan 程式有时会出状况, 我已经将它去掉,
以後有空时再写新的单一程序之 FindMan. 虽然程式已撤掉, 但本文可当
成纯为讨论程式设计, 故仍继续下去.
—————————————————————————————————
--
m;32m※ 转寄:.华南网木棉站 bbs.gznet.edu.cn.[FROM: mtlab.hit.edu.cn]
--
Enjoy Linux!
-----It's FREE!-----
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: Baggio.hit.edu.c]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:204.879毫秒