第120行: 第120行:
  
 
; detach_utmp
 
; detach_utmp
仅在WWW中使用。
+
: 仅在WWW中使用。
  
 
; resolve_utmp
 
; resolve_utmp
第128行: 第128行:
 
* Utmp.Hash()
 
* Utmp.Hash()
  
    logloop
+
; logloop
 +
* verify.verifyUtmpHead()
 +
: 检测列表是否循环。
  
 
; getnewutmpent [(struct user_info *up)]
 
; getnewutmpent [(struct user_info *up)]
 
* Utmp.GetNewUtmpEntry()
 
* Utmp.GetNewUtmpEntry()
 +
: 将新建的UserInfo填入空闲的UserInfo中,插入列表和哈希表,增加用户技术等。登录的一部分。
  
 
; getnewutmpent2 [(struct user_info *up)]
 
; getnewutmpent2 [(struct user_info *up)]
仅在WWW中使用。
+
: 仅在WWW中使用。
 +
 
 +
; rebuild_list [(struct user_info *up, char *arg, int p)]
 +
* Utmp.RebuildList() '''TODO'''
 +
: 重建UtmpHead里的列表。方法是从空的开始一个一个插。
  
    rebuild_list [(struct user_info *up, char *arg, int p)]
 
 
     apply_ulist [(APPLY_UTMP_FUNC fptr, void *arg)]
 
     apply_ulist [(APPLY_UTMP_FUNC fptr, void *arg)]
 
     apply_ulist_addr [(APPLY_UTMP_FUNC fptr, void *arg)]
 
     apply_ulist_addr [(APPLY_UTMP_FUNC fptr, void *arg)]
第144行: 第150行:
  
 
; clear_utmp2 [(int uent)]
 
; clear_utmp2 [(int uent)]
* Utmp.Clear2() '''TODO'''
+
* Utmp.Clear2()
 +
: 清理会话,包括从列表和哈希表删掉,减上站数,清空记录,以及调DoAfterLogout()做收尾工作。
  
 
; clear_utmp [(int uent, int useridx, int pid)]
 
; clear_utmp [(int uent, int useridx, int pid)]
 
* Utmp.Clear()
 
* Utmp.Clear()
 +
: 稍作检查,将SHM弄成可写,拿锁,随后调Clear2(),之后防锁,恢复只读。
  
 
; get_utmp_number
 
; get_utmp_number
 
* UtmpHead.GetNumber()
 
* UtmpHead.GetNumber()
 +
: 拿上站人数
  
 
; get_utmpent [(int utmpnum)]
 
; get_utmpent [(int utmpnum)]

2012年2月5日 (日) 04:13的版本


BBS的用户相关的东西。这块非常复杂,分成好几个部分。

UTMP

UTMPHEAD

struct UTMPHEAD {
    int next[USHM_SIZE];
    int hashhead[UTMP_HASHSIZE + 1];    /* use UCACHE_HASHSIZE/32 */
    int number;
    int listhead;
    int list_prev[USHM_SIZE];   /* sorted list prev ptr */
    int list_next[USHM_SIZE];   /* sorted list next ptr */
    time_t uptime;
};

static struct UTMPHEAD *utmphead;

utmphead其实指向一块shared memory,key = UTMPHEAD_SHMKEY

UTMPHEAD结构/数据由UtmpHead类处理,全都为GetXXX/SetXXX形式。

listhead, list_prev和list_next构成一个单向循环链表,listhead是表头,里面按照不分大小写的userid排列。

hashhead和next构成一个拉链式散列表,hashhead是表头,next是链上下一个。

number是登录用户数。uptime是上次刷新用户列表的时间。

UTMPFILE

  • 摘自KBS网站

utmpshm 的类型是 UTMPFILE 结构,用来存储登录的状态信息。注意 wwwguest 和这个结构完全没有关系。 这其实也是一块shared memory, key = UTMP_SHMKEY

#define USHM_SIZE       (MAXACTIVE + 10)
struct UTMPFILE {
    struct user_info uinfo[USHM_SIZE];
//        登录状态信息。每个登录都有一个登录号(utmpnum),他就是该登录在
//        uinfo 数组中的位置,注意 utmpnum 是 1-based。
};

uinfo 数组的每一个元素都可以用来存储一个登录的状态信息,其结构 user_info 定义:

struct user_info {              /* Structure used in UTMP file */
    int active;                 /* When allocated this field is true */
//        本结构当前是否代表一个登录用户。
    int uid;                    /* Used to find user name in passwd file */
//        登录用户的 uid。
    int pid;                    /* kill() to notify user of talk request */
//        telnet 登录表示其进程号。www 登录设置为 1。
    int invisible;              /* Used by cloaking function in Xyz menu */
//        是否隐身。
    int sockactive;             /* Used to coordinate talk requests */
    int sockaddr;               /* ... */
    int destuid;                /* talk uses this to identify who called */
    int mode;                   /* UL/DL, Talk Mode, Chat Mode, ... */
//        状态,应该赋值为 modes.h 里面的常数。
    int pager;                  /* pager toggle, true, or false */
/*        呼叫器状态,bitwise-OR 以下属性
            ALL_PAGER       0x1
            FRIEND_PAGER    0x2
            ALLMSG_PAGER    0x4
            FRIENDMSG_PAGER 0x8 */
    int in_chat;                /* for in_chat commands   */
    char chatid[16];            /* chat id, if in chat mode */
    char from[IPLEN + 4];       /* machine name the user called in from */
//        登录 IP。
    time_t logintime;
//        登录时间戳。
    int lastpost;
//        上次发文的时间戳。
    char unused[32];
    time_t freshtime;
//        上次活动的时间戳,用来计算发呆时间。
    int utmpkey;
//        登录 key,用于 www cookie 验证保持用户身份。
    unsigned int mailbox_prop;  /* properties of getCurrentUser()'s mailbox */
//        用户信箱选项,登录时从用户 .mailbox.prop 文件读取,参考 3.3 节
    char userid[20];
//        用户名
    char realname[20];
//        真实姓名,登录时从用户 userdata 结构读取
    char username[40];
//        用户昵称,登录时从 uidshm 共享内存去读取,修改临时昵称就是修改这个字段
    int friendsnum;
//        好友数量
    int friends_uid[MAXFRIENDS];
//        每个好友的 uid,前 friendsnum 个有效。
#ifdef FRIEND_MULTI_GROUP
    unsigned int friends_p[MAXFRIENDS];
#endif
    int currentboard;
//        当前所在版面的 bid 号
    unsigned int mailcheck;     /* if have new mail or new msg, stiger */
//        当前登录是否有新信或新消息
};

utmp.c

get_utmpshm_addr()
  • Utmp.utmpshm
longlock [(int signo)]
  • inside Utmp.Lock()
utmp_lock
  • Utmp.Lock()
utmp_unlock [(int fd)]
  • Utmp.Unlock()
utmp_setreadonly [(int readonly)]
  • UtmpHead.SetReadOnly()
detach_utmp
仅在WWW中使用。
resolve_utmp
  • Utmp.Init()
utmp_hash [(const char *userid)]
  • Utmp.Hash()
logloop
  • verify.verifyUtmpHead()
检测列表是否循环。
getnewutmpent [(struct user_info *up)]
  • Utmp.GetNewUtmpEntry()
将新建的UserInfo填入空闲的UserInfo中,插入列表和哈希表,增加用户技术等。登录的一部分。
getnewutmpent2 [(struct user_info *up)]
仅在WWW中使用。
rebuild_list [(struct user_info *up, char *arg, int p)]
  • Utmp.RebuildList() TODO
重建UtmpHead里的列表。方法是从空的开始一个一个插。
   apply_ulist [(APPLY_UTMP_FUNC fptr, void *arg)]
   apply_ulist_addr [(APPLY_UTMP_FUNC fptr, void *arg)]
   apply_utmpuid [(APPLY_UTMP_FUNC fptr, int uid, void *arg)]
   apply_utmp [(APPLY_UTMP_FUNC fptr, int maxcount,const char *userid, void *arg)]
   search_ulist [(struct user_info *uentp, int (*fptr) (int, struct user_info *), int farg)]
clear_utmp2 [(int uent)]
  • Utmp.Clear2()
清理会话,包括从列表和哈希表删掉,减上站数,清空记录,以及调DoAfterLogout()做收尾工作。
clear_utmp [(int uent, int useridx, int pid)]
  • Utmp.Clear()
稍作检查,将SHM弄成可写,拿锁,随后调Clear2(),之后防锁,恢复只读。
get_utmp_number
  • UtmpHead.GetNumber()
拿上站人数
get_utmpent [(int utmpnum)]
  • UserInfo.__init__()
get_utmpent_num [(struct user_info *uent)]
  • UserInfo.GetIndex()

好友相关

BBS 好友列表

   cmpfuid [(const void*a,const void*b)]
   getfriendstr [(struct userec* user,struct user_info* puinfo)]
   myfriend [(int uid, char *fexp)]
   hisfriend [(int uid,struct user_info* him)]