您的位置:首页 > 其它

ac指令的简单实现

2015-09-14 22:19 330 查看
2015-09-14

ac指令通过分析/var/log/wtmp日志文件,统计登陆和退出记录,得出用户的连接时间。



1.第一步是读取wtmp文件
wtmp文件和utmp文件的记录格式是一样的,可以使用struct utmp结构体,将wtmp的记录逐条的都出来。
int
travel_wtmp( st_link_node **stppLink )
{
int fd = 0;
int iRdNum = 0;
int iEntSize = sizeof( struct utmp );
struct utmp stEntry;
struct utmp stFix;
st_link_node *stpCur = *stppLink;

if( ( fd = open( WTMP_FILE, O_RDONLY ) ) < 0 )
{
fprintf( stderr, "open error: %s\n", strerror( errno ) );
return -1;
}

while( ( iRdNum = read( fd, &stEntry, iEntSize ) ) == iEntSize )
{
st_link_node *stpNode = NULL;

if( stEntry.ut_type == DEAD_PROCESS || stEntry.ut_type == RUN_LVL )
{
find_matched_process( *stppLink, &stEntry );
continue;
}

if( strcmp( stEntry.ut_user, BOOT_USER ) == 0 )
find_matched_process( *stppLink, &stEntry );

if( ( stpNode = malloc( sizeof( st_link_node ) ) ) == NULL )
{
fprintf( stderr, "malloc error: %s\n", strerror( errno ) );
return -1;
}

init_node( stpNode );

memcpy( &( stpNode->data ), &stEntry, iEntSize );
if( stpCur == NULL )
*stppLink = stpNode;
else
stpCur->next = stpNode;

stpCur = stpNode;
}

memset( &stFix, 0x00, sizeof( struct utmp ) );
stFix.ut_type = RUN_LVL;
strcpy( stFix.ut_user, SHUT_USER );
stFix.ut_tv.tv_sec = time( NULL );

find_matched_process( *stppLink, &stFix );

if( iRdNum < 0 )
{
fprintf( stderr, "read error: %s\n", strerror( errno ) );
return -1;
}

return 0;
}

为了便于分析简单的将记录内容组织并输出如下:



2.通过分析wtmp的帮助文档(man 5 wtmp),简单得出如下论断:

1) 当ut_line为伪终端时,即上图所示device为pts/0的类似记录,其退出记录是ut_type为DEAD_PROCESS且ut_line相同的记录。如果没有该条记录,则应该将其退出记录记为之后最近的那次ut_user为shutdown的记录。

2) 当ut_line不是伪终端,即上图device为:0的记录,其退出记录是ut_type为DEAT_PROCESS且ut_line和ut_host相同的记录。如果没有该条记录,则应该将其退出记录记为之后最近的那次ut_user为shutdown的记录。

3) 对于ut_user为reboot的特殊记录,其退出记录是ut_user为shutdown的记录。
static int
find_matched_process( st_link_node *stpLink, struct utmp *stpData )
{
while( stpLink != NULL )
{
if( stpLink->data.ut_type == USER_PROCESS && stpLink->iFlag != MATCHED )
{
if( strcmp( stpLink->data.ut_line, NOUT_LINE ) == 0 )
{
if( ( stpData->ut_type == DEAD_PROCESS && strcmp( stpData->ut_line, stpLink->data.ut_line ) == 0 && strcmp( stpData->ut_host, stpLink->data.ut_host ) == 0 ) ||
( stpData->ut_type == RUN_LVL && strcmp( stpData->ut_user, SHUT_USER ) == 0 ) )
{
memcpy( &( stpLink->endata ), stpData, sizeof( struct utmp ) );
stpLink->iFlag = MATCHED;
}
}
else
{   /* pesu terminal */
if( ( stpData->ut_type == DEAD_PROCESS && strcmp( stpLink->data.ut_line, stpData->ut_line ) == 0 ) ||
( stpData->ut_type == RUN_LVL && strcmp( stpData->ut_user, SHUT_USER ) == 0 ) )
{
memcpy( &( stpLink->endata ), stpData, sizeof( struct utmp ) );
stpLink->iFlag = MATCHED;
}
}
}
else if( strcmp( stpLink->data.ut_user, BOOT_USER ) == 0 && stpLink->iFlag != MATCHED )
{
if( stpData->ut_type == RUN_LVL && strcmp( stpData->ut_user, SHUT_USER ) == 0 )
{
memcpy( &( stpLink->endata ), stpData, sizeof( struct utmp ) );
stpLink->iFlag = MATCHED;
}
}

stpLink = stpLink->next;
}

return 0;
}

3.将开始记录和退出记录合并成计算连接时间的记录,然后将连接时间累加起来就能得出总的连接时间。
typedef struct _link_node
{
struct utmp data;
struct utmp endata;
int         iFlag;
struct _link_node *next;
} st_link_node;




4.输出结果和系统的ac指令对比输出如下:



5.源代码

http://download.csdn.net/detail/qq123386926/9106479
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: