void clear_utmp2(int uent) { int hashkey, find; struct user_info zeroinfo; struct userec* user; if (!uent) { bbslog("3system", "UTMP:clear uent == 0 entry"); #if 0 if (!CHECK_UENT(uinfo.uid)) return; uent = getSession()->utmpent; #endif return; } if (!utmpshm->uinfo[uent - 1].active) { //atppp 20051217 bbslog("3system", "UTMP:clear inactive entry [%d]", uent); // return; } user=getuserbynum(utmpshm->uinfo[uent-1].uid); do_after_logout(user,get_utmpent(uent),uent,0,true); do_after_logout(user,get_utmpent(uent),uent,0,false); hashkey = utmp_hash(utmpshm->uinfo[uent - 1].userid); find = utmphead->hashhead[hashkey]; if (find == uent) utmphead->hashhead[hashkey] = utmphead->next[uent - 1]; else { while (utmphead->next[find - 1] && utmphead->next[find - 1] != uent) find = utmphead->next[find - 1]; if (!utmphead->next[find - 1]) bbslog("3system", "UTMP:Can't find %s [%d]", utmpshm->uinfo[uent - 1].userid, uent); else utmphead->next[find - 1] = utmphead->next[uent - 1]; } /* remove from sorted list */ if (utmphead->listhead == uent) { utmphead->listhead = utmphead->list_next[uent - 1]; if (utmphead->listhead == uent) utmphead->listhead = 0; } utmphead->list_next[utmphead->list_prev[uent - 1] - 1] = utmphead->list_next[uent - 1]; utmphead->list_prev[utmphead->list_next[uent - 1] - 1] = utmphead->list_prev[uent - 1]; /* */ newbbslog(BBSLOG_USIES,"UTMP:clean %s(%d)", utmpshm->uinfo[uent - 1].userid, uent); utmphead->next[uent - 1] = utmphead->hashhead[0]; utmphead->hashhead[0] = uent; /* Delete the user's msglist entry from webmsgd, * if the user is login from web. */ /* if (utmpshm->uinfo[uent - 1].pid == 1) delfrom_msglist(uent, utmpshm->uinfo[uent - 1].userid); */ zeroinfo.active = false; zeroinfo.pid = 0; zeroinfo.invisible = true; zeroinfo.sockactive = false; zeroinfo.sockaddr = 0; zeroinfo.destuid = 0; if (utmpshm->uinfo[uent - 1].active != false) { utmphead->number--; setpublicshmreadonly(0); if (utmpshm->uinfo[uent-1].pid != 1) { get_publicshm()->logoutcount ++; get_publicshm()->staytime += time(NULL) - utmpshm->uinfo[uent-1].logintime; } else { get_publicshm()->wwwlogoutcount ++; get_publicshm()->wwwstaytime += time(NULL) - utmpshm->uinfo[uent-1].logintime; } setpublicshmreadonly(1); } utmpshm->uinfo[uent - 1] = zeroinfo; }
int getnewutmpent(struct user_info *up, int is_www) { struct user_info *uentp; time_t now; int pos, n, i,ret; int utmpfd, hashkey; utmpfd = utmp_lock(); utmp_setreadonly(0); up->utmpkey=rand() % 100000000; pos = utmphead->hashhead[0] - 1; if (pos == -1) { ret=-1; } else { /* add to sorted list */ if (!utmphead->listhead) { /* init the list head */ utmphead->list_prev[pos] = pos + 1; utmphead->list_next[pos] = pos + 1; utmphead->listhead = pos + 1; } else { int i; i = utmphead->listhead; if (strcasecmp(utmpshm->uinfo[i - 1].userid, up->userid) >= 0) { /* add to head */ utmphead->list_prev[pos] = utmphead->list_prev[i - 1]; utmphead->list_next[pos] = i; utmphead->list_prev[i - 1] = pos + 1; utmphead->list_next[utmphead->list_prev[pos] - 1] = pos + 1; utmphead->listhead = pos + 1; } else { int count; count = 0; i = utmphead->list_next[i - 1]; while ((strcasecmp(utmpshm->uinfo[i - 1].userid, up->userid) < 0) && (i != utmphead->listhead)) { i = utmphead->list_next[i - 1]; count++; if (count > USHM_SIZE) { utmphead->listhead = 0; bbslog("3system", "UTMP:maybe loop rebuild!"); apply_ulist((APPLY_UTMP_FUNC) rebuild_list, NULL); utmp_setreadonly(1); utmp_unlock(utmpfd); exit(-1); } } utmphead->list_prev[pos] = utmphead->list_prev[i - 1]; utmphead->list_next[pos] = i; utmphead->list_prev[i - 1] = pos + 1; utmphead->list_next[utmphead->list_prev[pos] - 1] = pos + 1; } } /* */ utmphead->hashhead[0] = utmphead->next[pos]; if (utmpshm->uinfo[pos].active) if (utmpshm->uinfo[pos].pid) { bbslog("3system", "utmp: alloc a active utmp! old:%s new:%s", utmpshm->uinfo[pos].userid, up->userid); kill(utmpshm->uinfo[pos].pid, SIGHUP); } utmpshm->uinfo[pos] = *up; hashkey = utmp_hash(up->userid); i = utmphead->hashhead[hashkey]; /* not need sort */ utmphead->next[pos] = i; utmphead->hashhead[hashkey] = pos + 1; utmphead->number++; setpublicshmreadonly(0); if (!is_www) { get_publicshm()->logincount ++; } else { get_publicshm()->wwwlogincount ++; } setpublicshmreadonly(1); if (get_utmp_number() + getwwwguestcount()>get_publicshm()->max_user) { setpublicshmreadonly(0); save_maxuser(); setpublicshmreadonly(1); } now = time(NULL); if ((now > utmphead->uptime + 120) || (now < utmphead->uptime - 120)) { utmphead->uptime = now; newbbslog(BBSLOG_USIES, "UTMP:Clean user utmp cache"); for (n = 0; n < USHM_SIZE; n++) { utmphead->uptime = now; uentp = &(utmpshm->uinfo[n]); if ((uentp->pid == 1) && ((now - uentp->freshtime) < IDLE_TIMEOUT)) { continue; } if (uentp->active && uentp->pid && kill(uentp->pid, 0) == -1) { /*uentp检查 */ char buf[STRLEN]; strncpy(buf, uentp->userid, IDLEN + 2); clear_utmp2(n + 1); /* 不需要再lock了 */ RemoveMsgCountFile(buf); } } } ret=pos+1; } utmp_setreadonly(1); utmp_unlock(utmpfd); return ret; }
/* same as getnewutmpent() except no updating of utmpshm * only called in www */ int getnewutmpent2(struct user_info *up, int is_www) { int pos, i,ret; int utmpfd, hashkey; utmpfd = utmp_lock(); utmp_setreadonly(0); up->utmpkey = rand() % 100000000; pos = utmphead->hashhead[0] - 1; if (pos == -1) { ret=-1; } else { /* add to sorted list */ if (!utmphead->listhead) { /* init the list head */ utmphead->list_prev[pos] = pos + 1; utmphead->list_next[pos] = pos + 1; utmphead->listhead = pos + 1; } else { int i; i = utmphead->listhead; if (strcasecmp(utmpshm->uinfo[i - 1].userid, up->userid) >= 0) { /* add to head */ utmphead->list_prev[pos] = utmphead->list_prev[i - 1]; utmphead->list_next[pos] = i; utmphead->list_prev[i - 1] = pos + 1; utmphead->list_next[utmphead->list_prev[pos] - 1] = pos + 1; utmphead->listhead = pos + 1; } else { int count; count = 0; i = utmphead->list_next[i - 1]; while ((strcasecmp(utmpshm->uinfo[i - 1].userid, up->userid) < 0) && (i != utmphead->listhead)) { i = utmphead->list_next[i - 1]; count++; if (count > USHM_SIZE) { utmphead->listhead = 0; bbslog("3system", "UTMP:maybe loop rebuild..!"); apply_ulist((APPLY_UTMP_FUNC) rebuild_list, NULL); utmp_setreadonly(1); utmp_unlock(utmpfd); exit(-1); } } utmphead->list_prev[pos] = utmphead->list_prev[i - 1]; utmphead->list_next[pos] = i; utmphead->list_prev[i - 1] = pos + 1; utmphead->list_next[utmphead->list_prev[pos] - 1] = pos + 1; } } utmphead->hashhead[0] = utmphead->next[pos]; if (utmpshm->uinfo[pos].active) if (utmpshm->uinfo[pos].pid) { bbslog("3system", "utmp: alloc a active utmp! old:%s new:%s", utmpshm->uinfo[pos].userid, up->userid); kill(utmpshm->uinfo[pos].pid, SIGHUP); } utmpshm->uinfo[pos] = *up; hashkey = utmp_hash(up->userid); i = utmphead->hashhead[hashkey]; /* not need sort */ utmphead->next[pos] = i; utmphead->hashhead[hashkey] = pos + 1; utmphead->number++; setpublicshmreadonly(0); if (!is_www) { get_publicshm()->logincount ++; } else { get_publicshm()->wwwlogincount ++; } setpublicshmreadonly(1); ret=pos+1; } utmp_setreadonly(1); utmp_unlock(utmpfd); return ret; }
int main(void) { int n,prev,pos,next,nn,ppd; int pig=0; int i,j;//,k; //int inlist=0; int utmpfd;//, hashkey; init_all(); pos=-1; #if 1 utmpfd = utmp_lock(); utmphead->hashhead[0]=0; for (i = 0; i <= USHM_SIZE - 1; i++) { if (!utmpshm->uinfo[i].active) { add_empty(i+1); } } utmp_unlock(utmpfd); printf("end\n"); // return; #endif j=0; for(i = utmphead->hashhead[0]; i; i = utmphead->next[i - 1]) j++; printf("items on hashhead[0] chain:%d\n",j); j=0; pig=0; for(i=0;i<USHM_SIZE;i++){ if (!utmpshm->uinfo[i].active) j++; else pig++; } printf("direct iteration: inactive:%d, active:%d\n",j,pig); pig=0; for(n=1;n<=UTMP_HASHSIZE;n++) { ppd=false; next = utmphead->hashhead[n]; prev = -1; while(next) { nn = utmphead->next[next - 1]; if (!utmpshm->uinfo[next - 1].active) { if (pos==-1) pos=prev; //printf("%d, %d, %s\n", next, nn, utmpshm->uinfo[next - 1].userid); ppd=true; } else { int hash = utmp_hash(getuserid2(utmpshm->uinfo[next - 1].uid)); if (hash!=n) { printf("utmp_hash err: %d %d %d %d %s\n", n, next, utmphead->hashhead[n], nn, getuserid2(utmpshm->uinfo[next - 1].uid)); if (0) { if (utmphead->hashhead[n] == next) { utmphead->hashhead[n] = nn; } else { utmphead->next[prev - 1] = nn; } } } } prev = next; next = nn; pig++; } if(ppd) printf("ERROR:%d,%d,%d\n", n, utmphead->hashhead[n], pos); } printf("active: %d, total: %d\n", pig, pig+j); n=utmphead->listhead; pig=0; prev=-1; while(n) { pig++; if (prev>0) { if (strcasecmp(utmpshm->uinfo[prev-1].userid, utmpshm->uinfo[n-1].userid) > 0) { printf("list chain error: %d %d\n", prev, n); } } prev=n; n=utmphead->list_next[n-1]; if (utmphead->list_prev[n-1]!=prev) { printf("list chain list_prev error: %d %d\n", prev, n); } if (n==utmphead->listhead) { break; } } printf("active on list chain: %d\n", pig); // return 0; #if 0 for (i = 0; i <= USHM_SIZE - 1; i++) { if (!utmpshm->uinfo[i].active) { if(!in_hash(i+1)){ //printf("%d empty but not in hash\n", i); pig ++; if(in_list(i)) inlist++; //if(pig >=40) break; } } } printf("%d total,%d inlist\n", pig, inlist); if(i==USHM_SIZE) return; return; k=utmphead->listhead; for(j=utmphead->list_next[k-1]; j!=k && j; j=utmphead->list_next[j-1]){ if(j==i+1) printf("in listhead\n"); } return; #endif pig=0; next = utmphead->hashhead[0]; while(next) { if (pos!=-1 &&pos==next) { printf("%d: on empty list\n", pos); return 0; } nn = utmphead->next[next - 1]; next = nn; pig++; } printf("%d %ld %ld\n", pig, utmphead->uptime, time(NULL)); time_t now = time(NULL); int web=0;int kick=0; pig=0; for (n = 0; n < USHM_SIZE; n++) { struct user_info *uentp = &(utmpshm->uinfo[n]); //printf("%d, %d\n", n, uentp->pid); if ((uentp->pid == 1) && ((now - uentp->freshtime) < IDLE_TIMEOUT)) { continue; } if (uentp->pid==0 && uentp->active) kick++; if (/*uentp->active &&*/ uentp->pid && kill(uentp->pid, 0) == -1) { /*uentp¼ì²é */ pig++; if(uentp->pid==1) web++; } } printf("killable: %d, web: %d, pid0: %d\n", pig, web, kick); return 0; }