static void dolastlogx(int quiet) { struct lastlogx ll; if (!quiet && getlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != NULL) { time_t t = (time_t)ll.ll_tv.tv_sec; (void)printf("Last login: %.24s ", ctime(&t)); if (*ll.ll_host != '\0') (void)printf("from %.*s ", (int)sizeof(ll.ll_host), ll.ll_host); (void)printf("on %.*s\n", (int)sizeof(ll.ll_line), ll.ll_line); } ll.ll_tv = now; (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); if (hostname) (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); else (void)memset(ll.ll_host, '\0', sizeof(ll.ll_host)); if (have_ss) ll.ll_ss = ss; else (void)memset(&ll.ll_ss, 0, sizeof(ll.ll_ss)); if (updlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != 0) syslog(LOG_NOTICE, "Cannot update lastlogx: %m"); }
/* * Returns the time when the user last logged in. Returns 0 if the * information is not available. This must be called before record_login. * The host the user logged in from will be returned in buf. */ time_t get_last_login_time(uid_t uid, const char *logname, char *buf, size_t bufsize) { #ifdef SUPPORT_UTMPX struct lastlogx llx, *llxp; #endif #ifdef SUPPORT_UTMP struct lastlog ll; int fd; #endif off_t pos, r; buf[0] = '\0'; #ifdef SUPPORT_UTMPX if ((llxp = getlastlogx(_PATH_LASTLOGX, uid, &llx)) != NULL) { if (bufsize > sizeof(llxp->ll_host) + 1) bufsize = sizeof(llxp->ll_host) + 1; strncpy(buf, llxp->ll_host, bufsize - 1); buf[bufsize - 1] = 0; return llxp->ll_tv.tv_sec; } #endif #ifdef SUPPORT_UTMP fd = open(_PATH_LASTLOG, O_RDONLY); if (fd < 0) return 0; pos = (off_t)uid * sizeof(ll); r = lseek(fd, pos, SEEK_SET); if (r == -1) { error("%s: lseek: %s", __func__, strerror(errno)); close(fd); return (0); } if (r != pos) { debug("%s: truncated lastlog", __func__); close(fd); return (0); } if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) { close(fd); return 0; } close(fd); if (bufsize > sizeof(ll.ll_host) + 1) bufsize = sizeof(ll.ll_host) + 1; strncpy(buf, ll.ll_host, bufsize - 1); buf[bufsize - 1] = '\0'; return (time_t)ll.ll_time; #else return 0; #endif }