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毫秒