static void clear_zombies(int flags) { pid_t pid = waitpid(-1, NULL, flags); /* Interrupted ? */ if (pid < 0) return; /* See if we care what died. If we do then also check that * do not need to respawn it */ if (clear_utmp(initpid, initcount, pid) == 0) return; if (oldpid) clear_utmp(oldpid, oldcount, pid); }
/* uentp == NULL means to kick all logins */ int kick_user_utmp(int uid, struct user_info *uentp, int signal) { int i, currsave; struct kickuser_save s; s.count = 0; signal = signal ? signal: SIGHUP; if (!uentp) { struct userec *u = getuserbynum(uid); apply_utmp((APPLY_UTMP_FUNC) kickuser_count, 0, u->userid, &s); } else { s.entp[0] = uentp; s.pid[0] = uentp->pid; s.count = 1; } currsave = -1; for (i=0;i<s.count;i++) { struct user_info *enp = s.entp[i]; if (enp->active) { if (enp -> pid == getpid() && s.count > 1) { currsave = i; continue; } else if (enp->pid != 1) kill(enp->pid, signal); clear_utmp(get_utmpent_num(enp), uid , s.pid[i]); } } if (currsave != -1) { struct user_info *enp = s.entp[currsave]; if (enp -> active) { if (enp -> pid != 1) kill(enp -> pid, signal); clear_utmp(get_utmpent_num(enp), uid, s.pid[currsave]); } } return s.count; }
void utmpd() { int m_socket; struct sockaddr_in sin; int sinlen = sizeof(sin); int opt = 1; bzero(&sin, sizeof(sin)); if ((m_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { bbslog("3system", "utmpd:socket %s", strerror(errno)); exit(-1); } setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &opt, 4); memset(&sin, 0, sinlen); sin.sin_family = AF_INET; #ifdef CELESTIS sin.sin_port = htons(61002); #else sin.sin_port = htons(60002); #endif #ifdef HAVE_INET_ATON inet_aton("127.0.0.1", &sin.sin_addr); #elif defined HAVE_INET_PTON inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr); #else /* Is it OK? */ my_inet_aton("127.0.0.1", &sin.sin_addr); #endif if (0 != bind(m_socket, (struct sockaddr *) &sin, sizeof(sin))) { bbslog("3system", "utmpd:bind %s", strerror(errno)); exit(-1); } if (0 != listen(m_socket, 5)) { bbslog("3system", "utmpd:listen %s", strerror(errno)); exit(-1); } while (1) { int sock, id; sock = getutmprequest(m_socket); #if 0 { /*kill user */ time_t now; struct user_info *uentp; now = time(NULL); if ((now > utmpshm->uptime + 120) || (now < utmpshm->uptime - 120)) { int n; utmpshm->uptime = now; bbslog("1system", "UTMP:Clean user utmp cache"); for (n = 0; n < USHM_SIZE; n++) { utmpshm->uptime = now; uentp = &(utmpshm->uinfo[n]); if (uentp->active && uentp->pid && kill(uentp->pid, 0) == -1) { /*uentp检查 */ char buf[STRLEN]; strncpy(buf, uentp->userid, IDLEN + 2); clear_utmp(n + 1); RemoveMsgCountFile(buf); } } } } #endif /* utmp */ switch (utmpreq.command) { case 1: // getnewutmp id = getnewutmpent2(&utmpreq.u_info.utmp, 0 /* TODO ! */); break; case 2: id = -1; break; // clear, by uentp case 3: // clear, by id /*这个代码有错误的,因为pid不能不判断 */ clear_utmp(utmpreq.u_info.uent, 0, 0); id = 0; break; default: id = -1; break; } putrequest(sock, id); } return; }