void vsf_insert_uwtmp(const struct mystr* p_user_str, const struct mystr* p_host_str) { if (sizeof(s_utent.ut_line) < 16) { return; } if (s_uwtmp_inserted) { bug("vsf_insert_uwtmp"); } { struct mystr line_str = INIT_MYSTR; str_alloc_text(&line_str, "vsftpd:"); str_append_ulong(&line_str, vsf_sysutil_getpid()); if (str_getlen(&line_str) >= sizeof(s_utent.ut_line)) { str_free(&line_str); return; } vsf_sysutil_strcpy(s_utent.ut_line, str_getbuf(&line_str), sizeof(s_utent.ut_line)); str_free(&line_str); } s_uwtmp_inserted = 1; s_utent.ut_type = USER_PROCESS; s_utent.ut_pid = vsf_sysutil_getpid(); vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str), sizeof(s_utent.ut_user)); vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str), sizeof(s_utent.ut_host)); s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); setutxent(); (void) pututxline(&s_utent); endutxent(); updwtmpx(WTMPX_FILE, &s_utent); }
static void add_utmp_entry(main_server_st *s, struct proc_st* proc) { #ifdef HAVE_LIBUTIL struct utmpx entry; struct timespec tv; if (s->config->use_utmp == 0) return; memset(&entry, 0, sizeof(entry)); entry.ut_type = USER_PROCESS; entry.ut_pid = proc->pid; snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", proc->tun_lease.name); snprintf(entry.ut_user, sizeof(entry.ut_user), "%s", proc->username); #ifdef __linux__ if (proc->remote_addr_len == sizeof(struct sockaddr_in)) memcpy(entry.ut_addr_v6, SA_IN_P(&proc->remote_addr), sizeof(struct in_addr)); else memcpy(entry.ut_addr_v6, SA_IN6_P(&proc->remote_addr), sizeof(struct in6_addr)); #endif gettime(&tv); entry.ut_tv.tv_sec = tv.tv_sec; entry.ut_tv.tv_usec = tv.tv_nsec / 1000; getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, entry.ut_host, sizeof(entry.ut_host), NULL, 0, NI_NUMERICHOST); setutxent(); pututxline(&entry); endutxent(); #if defined(WTMPX_FILE) updwtmpx(WTMPX_FILE, &entry); #endif return; #endif }
/* * Record login in wtmp file. */ void dologin(struct passwd *pw, struct sockaddr *sin) { #if __FreeBSD_version >= 900007 struct utmpx ut; memset(&ut, 0, sizeof ut); ut.ut_type = USER_PROCESS; gettimeofday(&ut.ut_tv, NULL); ut.ut_pid = getpid(); snprintf(ut.ut_id, sizeof ut.ut_id, "%xuucp", ut.ut_pid); SCPYN(ut.ut_user, pw->pw_name); realhostname_sa(ut.ut_host, sizeof ut.ut_host, sin, sin->sa_len); pututxline(&ut); #else char line[32]; char remotehost[UT_HOSTSIZE + 1]; int f; time_t cur_time; realhostname_sa(remotehost, sizeof(remotehost) - 1, sin, sin->sa_len); remotehost[sizeof remotehost - 1] = '\0'; /* hack, but must be unique and no tty line */ sprintf(line, "uucp%ld", (long)getpid()); time(&cur_time); if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) { struct lastlog ll; ll.ll_time = cur_time; lseek(f, (off_t)pw->pw_uid * sizeof(struct lastlog), L_SET); SCPYN(ll.ll_line, line); SCPYN(ll.ll_host, remotehost); (void) write(f, (char *) &ll, sizeof ll); (void) close(f); } logwtmp(line, pw->pw_name, remotehost); #endif }
static void utmpx_update(struct utmpx *ut, char *line, const char *user, const char *host) { struct timeval tmp; char *clean_tty = clean_ttyname(line); strncpy(ut->ut_line, clean_tty, sizeof(ut->ut_line)); #ifdef HAVE_STRUCT_UTMPX_UT_ID strncpy(ut->ut_id, make_id(clean_tty), sizeof(ut->ut_id)); #endif strncpy(ut->ut_user, user, sizeof(ut->ut_user)); shrink_hostname (host, ut->ut_host, sizeof(ut->ut_host)); #ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN ut->ut_syslen = strlen(host) + 1; if (ut->ut_syslen > sizeof(ut->ut_host)) ut->ut_syslen = sizeof(ut->ut_host); #endif ut->ut_type = USER_PROCESS; gettimeofday (&tmp, 0); ut->ut_tv.tv_sec = tmp.tv_sec; ut->ut_tv.tv_usec = tmp.tv_usec; pututxline(ut); #ifdef WTMPX_FILE updwtmpx(WTMPX_FILE, ut); #elif defined(WTMP_FILE) { /* XXX should be removed, just drop wtmp support */ struct utmp utmp; int fd; prepare_utmp (&utmp, line, user, host); if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { write(fd, &utmp, sizeof(struct utmp)); close(fd); } } #endif }
static void login_utmpx(struct utmpx *utmpx, const char *username, const char *hostname, const char *tty, const struct timeval *now) { const char *t; (void)memset(utmpx, 0, sizeof(*utmpx)); utmpx->ut_tv = *now; (void)strncpy(utmpx->ut_name, username, sizeof(utmpx->ut_name)); if (hostname) (void)strncpy(utmpx->ut_host, hostname, sizeof(utmpx->ut_host)); (void)strncpy(utmpx->ut_line, tty, sizeof(utmpx->ut_line)); utmpx->ut_type = USER_PROCESS; utmpx->ut_pid = getpid(); t = tty + strlen(tty); if ((size_t)(t - tty) >= sizeof(utmpx->ut_id)) { (void)strncpy(utmpx->ut_id, t - sizeof(utmpx->ut_id), sizeof(utmpx->ut_id)); } else { (void)strncpy(utmpx->ut_id, tty, sizeof(utmpx->ut_id)); } (void)pututxline(utmpx); endutxent(); }
void dologout(void) { int status; pid_t pid; #if __FreeBSD_version >= 900007 struct utmpx ut; #else char line[32]; #endif while ((pid=wait((int *)&status)) > 0) { #if __FreeBSD_version >= 900007 memset(&ut, 0, sizeof ut); ut.ut_type = DEAD_PROCESS; gettimeofday(&ut.ut_tv, NULL); ut.ut_pid = pid; snprintf(ut.ut_id, sizeof ut.ut_id, "%xuucp", pid); pututxline(&ut); #else sprintf(line, "uucp%ld", (long)pid); logwtmp(line, "", ""); #endif } }
void KPty::logout() { #ifdef HAVE_UTEMPTER Q_D(KPty); removeLineFromUtmp(d->ttyName, d->masterFd); #else Q_D(KPty); const char *str_ptr = d->ttyName.data(); if (!memcmp(str_ptr, "/dev/", 5)) { str_ptr += 5; } # ifdef __GLIBC__ else { const char * sl_ptr = strrchr(str_ptr, '/'); if (sl_ptr) { str_ptr = sl_ptr + 1; } } # endif # ifdef HAVE_LOGIN # ifdef HAVE_LOGINX ::logoutx(str_ptr, 0, DEAD_PROCESS); # else ::logout(str_ptr); # endif # else # ifdef HAVE_UTMPX struct utmpx l_struct, *ut; # else struct utmp l_struct, *ut; # endif memset(&l_struct, 0, sizeof(l_struct)); strncpy(l_struct.ut_line, str_ptr, sizeof(l_struct.ut_line)); # ifdef HAVE_UTMPX utmpxname(_PATH_UTMPX); setutxent(); if ((ut = getutxline(&l_struct))) { # else utmpname(_PATH_UTMP); setutent(); if ((ut = getutline(&l_struct))) { # endif memset(ut->ut_name, 0, sizeof(*ut->ut_name)); memset(ut->ut_host, 0, sizeof(*ut->ut_host)); # ifdef HAVE_STRUCT_UTMP_UT_SYSLEN ut->ut_syslen = 0; # endif # ifdef HAVE_STRUCT_UTMP_UT_TYPE ut->ut_type = DEAD_PROCESS; # endif # ifdef HAVE_UTMPX gettimeofday(&ut->ut_tv, 0); pututxline(ut); } endutxent(); # else ut->ut_time = time(0); pututline(ut); } endutent(); # endif # endif #endif }
void KPty::login(const char * user, const char * remotehost) { #ifdef HAVE_UTEMPTER Q_D(KPty); addToUtmp(d->ttyName, remotehost, d->masterFd); Q_UNUSED(user); #else # ifdef HAVE_UTMPX struct utmpx l_struct; # else struct utmp l_struct; # endif memset(&l_struct, 0, sizeof(l_struct)); // note: strncpy without terminators _is_ correct here. man 4 utmp if (user) { strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name)); } if (remotehost) { strncpy(l_struct.ut_host, remotehost, sizeof(l_struct.ut_host)); # ifdef HAVE_STRUCT_UTMP_UT_SYSLEN l_struct.ut_syslen = qMin(strlen(remotehost), sizeof(l_struct.ut_host)); # endif } # ifndef __GLIBC__ Q_D(KPty); const char * str_ptr = d->ttyName.data(); if (!memcmp(str_ptr, "/dev/", 5)) { str_ptr += 5; } strncpy(l_struct.ut_line, str_ptr, sizeof(l_struct.ut_line)); # ifdef HAVE_STRUCT_UTMP_UT_ID strncpy(l_struct.ut_id, str_ptr + strlen(str_ptr) - sizeof(l_struct.ut_id), sizeof(l_struct.ut_id)); # endif # endif # ifdef HAVE_UTMPX gettimeofday(&l_struct.ut_tv, 0); # else l_struct.ut_time = time(0); # endif # ifdef HAVE_LOGIN # ifdef HAVE_LOGINX ::loginx(&l_struct); # else ::login(&l_struct); # endif # else # ifdef HAVE_STRUCT_UTMP_UT_TYPE l_struct.ut_type = USER_PROCESS; # endif # ifdef HAVE_STRUCT_UTMP_UT_PID l_struct.ut_pid = getpid(); # ifdef HAVE_STRUCT_UTMP_UT_SESSION l_struct.ut_session = getsid(0); # endif # endif # ifdef HAVE_UTMPX utmpxname(_PATH_UTMPX); setutxent(); pututxline(&l_struct); endutxent(); # ifdef HAVE_UPDWTMPX updwtmpx(_PATH_WTMPX, &l_struct); # endif # else utmpname(_PATH_UTMP); setutent(); pututline(&l_struct); endutent(); updwtmp(_PATH_WTMP, &l_struct); # endif # endif #endif }
void utmp_logout (char *line) { #ifdef HAVE_UTMPX_H struct utmpx utx; struct utmpx *ut; strncpy (utx.ut_line, line, sizeof (utx.ut_line)); # ifdef HAVE_PUTUTXLINE setutxent(); ut = getutxline (&utx); if (ut) { struct timeval tv; ut->ut_type = DEAD_PROCESS; # ifdef HAVE_STRUCT_UTMPX_UT_EXIT memset (&ut->ut_exit, 0, sizeof (ut->ut_exit)); # endif gettimeofday (&tv, 0); ut->ut_tv.tv_sec = tv.tv_sec; ut->ut_tv.tv_usec = tv.tv_usec; # ifdef HAVE_STRUCT_UTMPX_UT_USER memset (&ut->ut_user, 0, sizeof (ut->ut_user)); # elif defined HAVE_STRUCT_UTMPX_UT_NAME memset (&ut->ut_name, 0, sizeof (ut->ut_name)); # endif # ifdef HAVE_STRUCT_UTMPX_UT_HOST memset (ut->ut_host, 0, sizeof (ut->ut_host)); # ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN ut->ut_syslen = 1; /* Counting NUL. */ # endif # endif /* UT_HOST */ pututxline (ut); /* Some systems perform wtmp updating * already in calling pututxline(). */ # ifdef HAVE_UPDWTMPX updwtmpx (PATH_WTMPX, ut); # elif defined HAVE_LOGWTMPX logwtmpx (ut->ut_line, "", "", 0, DEAD_PROCESS); # endif } endutxent (); # elif defined HAVE_LOGOUTX /* !HAVE_PUTUTXLINE */ if (logoutx (line, 0, DEAD_PROCESS)) logwtmpx (line, "", "", 0, DEAD_PROCESS); # endif /* HAVE_LOGOUTX */ #else /* !HAVE_UTMPX_H */ struct utmp utx; # ifdef HAVE_PUTUTLINE struct utmp *ut; # endif strncpy (utx.ut_line, line, sizeof (utx.ut_line)); # ifdef HAVE_PUTUTLINE setutent(); ut = getutline (&utx); if (ut) { # ifdef HAVE_STRUCT_UTMP_UT_TV struct timeval tv; # endif # ifdef HAVE_STRUCT_UTMP_UT_TYPE ut->ut_type = DEAD_PROCESS; # endif # ifdef HAVE_STRUCT_UTMP_UT_EXIT memset (&ut->ut_exit, 0, sizeof (ut->ut_exit)); # endif # ifdef HAVE_STRUCT_UTMP_UT_TV gettimeofday (&tv, 0); ut->ut_tv.tv_sec = tv.tv_sec; ut->ut_tv.tv_usec = tv.tv_usec; # else /* !HAVE_STRUCT_UTMP_UT_TV */ time (&(ut->ut_time)); # endif # ifdef HAVE_STRUCT_UTMP_UT_USER memset (&ut->ut_user, 0, sizeof (ut->ut_user)); # elif defined HAVE_STRUCT_UTMP_UT_NAME memset (&ut->ut_name, 0, sizeof (ut->ut_name)); # endif # ifdef HAVE_STRUCT_UTMP_UT_HOST memset (ut->ut_host, 0, sizeof (ut->ut_host)); # endif pututline (ut); # ifdef HAVE_UPDWTMP updwtmp (WTMP_FILE, ut); # elif defined HAVE_LOGWTMP /* !HAVE_UPDWTMP */ logwtmp (ut->ut_line, "", ""); # endif } endutent (); # elif defined HAVE_LOGOUT /* !HAVE_PUTUTLINE */ if (logout (line)) logwtmp (line, "", ""); # endif /* HAVE_LOGOUT */ #endif }
/* EXTPROTO */ void rxvt_cleanutent(rxvt_t *r) { #ifdef UTEMPTER_SUPPORT utempter_remove_record (PVTS(r)->cmd_fd); #else /* UTEMPTER_SUPPORT */ #ifdef HAVE_STRUCT_UTMP struct utmp *ut = &(PVTS(r)->ut); #endif #if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) struct utmpx *tmputx, *utx = &(PVTS(r)->utx); #endif #ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UTMP_PID MEMSET(ut, 0, sizeof(struct utmp)); setutent(); STRNCPY(ut->ut_id, PVTS(r)->ut_id, sizeof(ut->ut_id)); ut->ut_type = USER_PROCESS; { struct utmp *tmput = getutid(ut); if (tmput) /* position to entry in utmp file */ ut = tmput; } ut->ut_type = DEAD_PROCESS; # else MEMSET(ut->ut_name, 0, sizeof(ut->ut_name)); # ifdef HAVE_UTMP_HOST MEMSET(ut->ut_host, 0, sizeof(ut->ut_host)); # endif # endif ut->ut_time = time(NULL); #endif #if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) MEMSET(utx, 0, sizeof(struct utmpx)); setutxent(); STRNCPY(utx->ut_id, PVTS(r)->ut_id, sizeof(utx->ut_id)); utx->ut_type = USER_PROCESS; if ((tmputx = getutxid(utx))) /* position to entry in utmp file */ utx = tmputx; utx->ut_type = DEAD_PROCESS; # ifdef HAVE_UTMPX_SESSION utx->ut_session = getsid(0); # endif utx->ut_tv.tv_sec = time(NULL); utx->ut_tv.tv_usec = 0; #endif /* * Write ending wtmp entry */ #ifdef WTMP_SUPPORT # ifdef WTMP_ONLY_ON_LOGIN if (ISSET_OPTION(r, Opt_loginShell)) # endif { # ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UPDWTMP updwtmp(RXVT_WTMP_FILE, ut); # else rxvt_update_wtmp(RXVT_WTMP_FILE, ut); # endif # endif # if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) # ifdef HAVE_UPDWTMPX updwtmpx(RXVT_WTMPX_FILE, utx); # else pututxline (utx); # endif # endif } #endif /* * Write utmp entry */ #ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UTMP_PID if (ut->ut_pid == PVTS(r)->cmd_pid) pututline(ut); endutent(); # else MEMSET(ut, 0, sizeof(struct utmp)); rxvt_write_bsd_utmp(PVTS(r)->utmp_pos, ut); # endif #endif #if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) if (utx->ut_pid == PVTS(r)->cmd_pid) pututxline(utx); endutxent(); #endif #endif /* UTEMPTER_SUPPORT */ }
void exec_shell(struct conf *cfp, int fd, int parentfd) { int master, slave; pid_t pid; char line[MAXPATHLEN]; char *tty; #ifdef HAVE_UTMP_H struct utmp ut; #elif HAVE_UTMPX_H struct utmpx ut; struct timeval tv; #endif #if defined(HAVE_UTMP_H) || defined(HAVE_UTMPX_H) memset(&ut, 0, sizeof(ut)); #endif if (pipe(pipechld) < 0) { syslog(LOG_ERR, "exec_shell() pipe %m"); _exit(1); } (void)non_blocking(pipechld[0]); (void)non_blocking(pipechld[1]); if (openpty(&master, &slave, line, NULL, NULL) == -1) { syslog(LOG_ERR, "openpty %m"); _exit(1) ; } /* * pts/x compatible */ if ((tty = strstr(line, "/dev/"))) tty += 5; else tty = line; #if defined(HAVE_UTMP_H) || defined(HAVE_UTMPX_H) if (cfp->utmp) { if (cfp->utname) { #ifdef HAVE_UTMP_H (void)strncpy(ut.ut_name, cfp->utname, sizeof(ut.ut_name)-1); ut.ut_name[sizeof(ut.ut_name)-1] = '\0'; #elif HAVE_UTMPX_H (void)strncpy(ut.ut_user, cfp->utname, sizeof(ut.ut_user)-1); ut.ut_user[sizeof(ut.ut_user)-1] = '\0'; #endif } else { struct passwd *pw; pw = get_pwentry(cfp->havesetuser ? cfp->setuser : \ 0); #ifdef HAVE_UTMP_H (void)strncpy(ut.ut_name, pw->pw_name, sizeof(ut.ut_name)-1); ut.ut_name[sizeof(ut.ut_name)-1] = '\0'; #elif HAVE_UTMPX_H (void)strncpy(ut.ut_user, pw->pw_name, sizeof(ut.ut_user)-1); ut.ut_user[sizeof(ut.ut_user)-1] = '\0'; #endif } (void)strncpy(ut.ut_line, tty, sizeof(ut.ut_line)-1); ut.ut_line[sizeof(ut.ut_line)-1] = '\0'; if (cfp->uthost) { (void)strncpy(ut.ut_host, cfp->uthost, sizeof(ut.ut_host)-1); ut.ut_host[sizeof(ut.ut_host)-1] = '\0'; } #ifdef HAVE_UTMP_H (void)time(&ut.ut_time); #elif HAVE_UTMPX_H (void)gettimeofday(&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; (void)strncpy(ut.ut_id, ut.ut_line, sizeof(ut.ut_id)-1); ut.ut_line[sizeof(ut.ut_line)-1] = '\0'; ut.ut_pid = getpid(); ut.ut_type = USER_PROCESS; #endif } #endif /* * overwriting signal disposition */ (void)signal(SIGCHLD, sig_chld); switch (pid = fork()) { case -1: syslog(LOG_ERR, "forkpty: %m"); _exit(1); case 0: (void)close(parentfd); (void)close(pipechld[0]); (void)close(pipechld[1]); (void)close(master); (void)close(fd); (void)login_tty(slave); #ifdef HAVE_UTMP_H login(&ut); #elif HAVE_UTMPX_H setutxent(); (void)pututxline(&ut); #endif set_privileges(cfp); /* * SUIP PROGRAM HERE */ #ifdef __NetBSD__ (void)execl(_PATH_BSHELL,"sh", "-c",cfp->suipfile,(char *)NULL); #else (void)execl(_PATH_BSHELL, "sh", "-p", "-c", cfp->suipfile, (char *)NULL); #endif _exit(127); default: { int ctrls; int exit_status = 0; (void)close(slave); /* * trying to open a control channel * control_create() returns the number of bytes which were * written * select_fd() returns -1 if errors exist you can check errno */ if (control_create(&ctrls, fd) == 1) { if (select_fd(cfp, fd, master, ctrls, parentfd) < 0) exit_status = 1; } else { syslog(LOG_ERR, "can't open ctrl chan"); exit_status = 1; } #if defined(HAVE_UTMP_H) || defined(HAVE_UTMPX_H) if (cfp->utmp) { #ifdef HAVE_UTMP_H if (!logout(tty)) { syslog(LOG_ERR, "unable to logout on %s", tty); exit_status = 1; } else logwtmp(tty, "", ""); #elif HAVE_UTMPX_H ut.ut_type = DEAD_PROCESS; (void)gettimeofday(&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; (void)memset(&ut.ut_user, 0, sizeof(ut.ut_user)); setutxent(); if (pututxline(&ut) == NULL) { syslog(LOG_ERR, "unable to logout on %s (utmpx)", tty); exit_status = 1; } endutxent(); #endif } #endif cleanup(line); _exit(exit_status); }} /* * never reached */ _exit(1); }
static void setthetime(const char *fmt, const char *p, int jflag, int nflag) { struct utmpx utx; struct tm *lt; struct timeval tv; const char *dot, *t; int century; lt = localtime(&tval); lt->tm_isdst = -1; /* divine correct DST */ if (fmt != NULL) { t = strptime(p, fmt, lt); if (t == NULL) { fprintf(stderr, "Failed conversion of ``%s''" " using format ``%s''\n", p, fmt); badformat(); } else if (*t != '\0') fprintf(stderr, "Warning: Ignoring %ld extraneous" " characters in date string (%s)\n", (long) strlen(t), t); } else { for (t = p, dot = NULL; *t; ++t) { if (isdigit(*t)) continue; if (*t == '.' && dot == NULL) { dot = t; continue; } badformat(); } if (dot != NULL) { /* .ss */ dot++; /* *dot++ = '\0'; */ if (strlen(dot) != 2) badformat(); lt->tm_sec = ATOI2(dot); if (lt->tm_sec > 61) badformat(); } else lt->tm_sec = 0; century = 0; /* if p has a ".ss" field then let's pretend it's not there */ switch (strlen(p) - ((dot != NULL) ? 3 : 0)) { case 12: /* cc */ lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE; century = 1; /* FALLTHROUGH */ case 10: /* yy */ if (century) lt->tm_year += ATOI2(p); else { lt->tm_year = ATOI2(p); if (lt->tm_year < 69) /* hack for 2000 ;-} */ lt->tm_year += 2000 - TM_YEAR_BASE; else lt->tm_year += 1900 - TM_YEAR_BASE; } /* FALLTHROUGH */ case 8: /* mm */ lt->tm_mon = ATOI2(p); if (lt->tm_mon > 12) badformat(); --lt->tm_mon; /* time struct is 0 - 11 */ /* FALLTHROUGH */ case 6: /* dd */ lt->tm_mday = ATOI2(p); if (lt->tm_mday > 31) badformat(); /* FALLTHROUGH */ case 4: /* HH */ lt->tm_hour = ATOI2(p); if (lt->tm_hour > 23) badformat(); /* FALLTHROUGH */ case 2: /* MM */ lt->tm_min = ATOI2(p); if (lt->tm_min > 59) badformat(); break; default: badformat(); } } /* convert broken-down time to GMT clock time */ if ((tval = mktime(lt)) == -1) errx(1, "nonexistent time"); if (!jflag) { /* set the time */ if (nflag || netsettime(tval)) { utx.ut_type = OLD_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); tv.tv_sec = tval; tv.tv_usec = 0; if (settimeofday(&tv, (struct timezone *)NULL)) err(1, "settimeofday (timeval)"); utx.ut_type = NEW_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); } if ((p = getlogin()) == NULL) p = "???"; syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p); } }
int setdate(struct tm *current_date, char *date) { int i; int mm; int hh; int min; int sec = 0; char *secptr; int yy; int dd = 0; int minidx = 6; int len; int dd_check; /* Parse date string */ if ((secptr = strchr(date, '.')) != NULL && strlen(&secptr[1]) == 2 && isdigit(secptr[1]) && isdigit(secptr[2]) && (sec = atoi(&secptr[1])) >= 0 && sec < 60) secptr[0] = '\0'; /* eat decimal point only on success */ len = strlen(date); for (i = 0; i < len; i++) { if (!isdigit(date[i])) { (void) fprintf(stderr, gettext("date: bad conversion\n")); exit(1); } } switch (strlen(date)) { case 12: yy = atoi(&date[8]); date[8] = '\0'; break; case 10: /* * The YY format has the following representation: * 00-68 = 2000 thru 2068 * 69-99 = 1969 thru 1999 */ if (atoi(&date[8]) <= 68) { yy = 1900 + (atoi(&date[8]) + 100); } else { yy = 1900 + atoi(&date[8]); } date[8] = '\0'; break; case 8: yy = 1900 + current_date->tm_year; break; case 4: yy = 1900 + current_date->tm_year; mm = current_date->tm_mon + 1; /* tm_mon goes from 1 to 11 */ dd = current_date->tm_mday; minidx = 2; break; default: (void) fprintf(stderr, gettext("date: bad conversion\n")); return (1); } min = atoi(&date[minidx]); date[minidx] = '\0'; hh = atoi(&date[minidx-2]); date[minidx-2] = '\0'; if (!dd) { /* * if dd is 0 (not between 1 and 31), then * read the value supplied by the user. */ dd = atoi(&date[2]); date[2] = '\0'; mm = atoi(&date[0]); } if (hh == 24) hh = 0, dd++; /* Validate date elements */ dd_check = 0; if (mm >= 1 && mm <= 12) { dd_check = month_size[mm - 1]; /* get days in this month */ if (mm == 2 && isleap(yy)) /* adjust for leap year */ dd_check++; } if (!((mm >= 1 && mm <= 12) && (dd >= 1 && dd <= dd_check) && (hh >= 0 && hh <= 23) && (min >= 0 && min <= 59))) { (void) fprintf(stderr, gettext("date: bad conversion\n")); return (1); } /* Build date and time number */ for (clock_val = 0, i = 1970; i < yy; i++) clock_val += year_size(i); /* Adjust for leap year */ if (isleap(yy) && mm >= 3) clock_val += 1; /* Adjust for different month lengths */ while (--mm) clock_val += (time_t)month_size[mm - 1]; /* Load up the rest */ clock_val += (time_t)(dd - 1); clock_val *= 24; clock_val += (time_t)hh; clock_val *= 60; clock_val += (time_t)min; clock_val *= 60; clock_val += sec; if (!uflag) { /* convert to GMT assuming standard time */ /* correction is made in localtime(3C) */ /* * call localtime to set up "timezone" variable applicable * for clock_val time, to support Olson timezones which * can allow timezone rules to change. */ (void) localtime(&clock_val); clock_val += (time_t)timezone; /* correct if daylight savings time in effect */ if (localtime(&clock_val)->tm_isdst) clock_val = clock_val - (time_t)(timezone - altzone); } (void) time(&wtmpx[0].ut_xtime); if (stime(&clock_val) < 0) { perror("date"); return (1); } #if defined(i386) /* correct the kernel's "gmt_lag" and the PC's RTC */ (void) system("/usr/sbin/rtc -c > /dev/null 2>&1"); #endif (void) time(&wtmpx[1].ut_xtime); (void) pututxline(&wtmpx[0]); (void) pututxline(&wtmpx[1]); (void) updwtmpx(WTMPX_FILE, &wtmpx[0]); (void) updwtmpx(WTMPX_FILE, &wtmpx[1]); return (0); }
/* * Add or delete an entry in the system's utmp file. */ void doutmp(int action, struct layer *l) { /* * Note that pututxline() may need privileges to work; but at least * on Solaris, it does not as the libc arranges this for us. If shl * has suid or sgid privileges, these are reset on startup and * restored for utmp handling here. */ struct passwd *pwd = getpwuid(myuid); struct utmpx utx; char *id; memset(&utx, 0, sizeof utx); strncpy(utx.ut_line, l->l_line + 5, sizeof utx.ut_line); strncpy(utx.ut_user, pwd->pw_name, sizeof utx.ut_user); utx.ut_pid = l->l_pid; gettimeofday(&utx.ut_tv, NULL); if ((id = strrchr(l->l_line, '/')) != NULL) strncpy(utx.ut_id, id, sizeof utx.ut_id); switch (action) { case UTMP_ADD: utx.ut_type = USER_PROCESS; break; case UTMP_DEL: utx.ut_type = DEAD_PROCESS; break; } if (myuid != myeuid) setuid(myeuid); if (mygid != myegid) setgid(myegid); #ifndef __linux__ if (action == UTMP_DEL) { /* * On (at least) Solaris 8, /usr/lib/utmp_update will hang at * ioctl(tty, TCGETA, ...) respective isatty() when the pty is * in packet mode, but removing the pckt module we once pushed * fails with EPERM in some circumstances (exact conditions * unknown). If it does, close the pty master; pututxline() * refuses to work then, but utmpd(1M) will remove the stale * entry a few seconds later. This is not the ultimate * solution, but better than hanging, of course. If shl needs * privilegues to call pututxline(), these calls will not cause * any harm since there is no dependency on the actual terminal * device then. */ if (ioctl(l->l_pty, I_POP, 0) < 0) { close(l->l_pty); l->l_pty = -1; } } #endif /* !__linux__ */ setutxent(); getutxline(&utx); pututxline(&utx); endutxent(); if (myuid != myeuid) setuid(myuid); if (mygid != myegid) setgid(mygid); }
/* EXTPROTO */ void rxvt_cleanutent(rxvt_t *r) { #ifdef HAVE_STRUCT_UTMP struct utmp *tmput, *ut = &(r->h->ut); #endif #ifdef HAVE_STRUCT_UTMPX struct utmpx *tmputx, *utx = &(r->h->utx); #endif #ifdef HAVE_STRUCT_UTMP # ifdef RXVT_UTMP_PID MEMSET(ut, 0, sizeof(struct utmp)); setutent(); STRNCPY(ut->ut_id, r->h->ut_id, sizeof(ut->ut_id)); ut->ut_type = USER_PROCESS; if ((tmput = getutid(ut))) /* position to entry in utmp file */ ut = tmput; ut->ut_type = DEAD_PROCESS; # else MEMSET(ut->ut_name, 0, sizeof(ut->ut_name)); MEMSET(ut->ut_host, 0, sizeof(ut->ut_host)); # endif ut->ut_time = time(NULL); #endif #ifdef HAVE_STRUCT_UTMPX MEMSET(utx, 0, sizeof(struct utmpx)); setutxent(); STRNCPY(utx->ut_id, r->h->ut_id, sizeof(utx->ut_id)); utx->ut_type = USER_PROCESS; if ((tmputx = getutxid(utx))) /* position to entry in utmp file */ utx = tmputx; utx->ut_type = DEAD_PROCESS; utx->ut_session = getsid(0); utx->ut_tv.tv_sec = time(NULL); utx->ut_tv.tv_usec = 0; #endif /* * Write ending wtmp entry */ #ifdef WTMP_SUPPORT # ifdef WTMP_ONLY_ON_LOGIN if (r->Options & Opt_loginShell) # endif { # ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UPDWTMP updwtmp(RXVT_WTMP_FILE, ut); # else rxvt_update_wtmp(RXVT_WTMP_FILE, ut); # endif # endif # ifdef HAVE_STRUCT_UTMPX updwtmpx(RXVT_WTMPX_FILE, utx); # endif #endif } /* * Write utmp entry */ #ifdef HAVE_STRUCT_UTMP # ifdef RXVT_UTMP_PID if (ut->ut_pid == r->h->cmd_pid) pututline(ut); endutent(); # else if (r->h->utmp_pos > 0) { MEMSET(ut, 0, sizeof(struct utmp)); rxvt_write_bsd_utmp(r->h->utmp_pos, ut); } # endif #endif #ifdef HAVE_STRUCT_UTMPX if (utx->ut_pid == r->h->cmd_pid) pututxline(utx); endutxent(); #endif }
int main(int argc, char *argv[]) { struct utmpx utx; const struct passwd *pw; int ch, howto, i, fd, lflag, nflag, qflag, sverrno, Nflag; u_int pageins; const char *user, *kernel = NULL; if (strcmp(getprogname(), "halt") == 0) { dohalt = 1; howto = RB_HALT; } else howto = 0; lflag = nflag = qflag = 0; while ((ch = getopt(argc, argv, "dk:lNnpqr")) != -1) switch(ch) { case 'd': howto |= RB_DUMP; break; case 'k': kernel = optarg; break; case 'l': lflag = 1; break; case 'n': nflag = 1; howto |= RB_NOSYNC; break; case 'N': nflag = 1; Nflag = 1; break; case 'p': howto |= RB_POWEROFF; break; case 'q': qflag = 1; break; case 'r': howto |= RB_REROOT; break; case '?': default: usage(); } argc -= optind; argv += optind; if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT)) errx(1, "cannot dump (-d) when halting; must reboot instead"); if (Nflag && (howto & RB_NOSYNC) != 0) errx(1, "-N cannot be used with -n"); if ((howto & RB_REROOT) != 0 && howto != RB_REROOT) errx(1, "-r cannot be used with -d, -n, or -p"); if (geteuid()) { errno = EPERM; err(1, NULL); } if (qflag) { reboot(howto); err(1, NULL); } if (kernel != NULL) { fd = open("/boot/nextboot.conf", O_WRONLY | O_CREAT | O_TRUNC, 0444); if (fd > -1) { (void)write(fd, "nextboot_enable=\"YES\"\n", 22); (void)write(fd, "kernel=\"", 8L); (void)write(fd, kernel, strlen(kernel)); (void)write(fd, "\"\n", 2); close(fd); } } /* Log the reboot. */ if (!lflag) { if ((user = getlogin()) == NULL) user = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; if (dohalt) { openlog("halt", 0, LOG_AUTH | LOG_CONS); syslog(LOG_CRIT, "halted by %s", user); } else if (howto & RB_REROOT) { openlog("reroot", 0, LOG_AUTH | LOG_CONS); syslog(LOG_CRIT, "rerooted by %s", user); } else { openlog("reboot", 0, LOG_AUTH | LOG_CONS); syslog(LOG_CRIT, "rebooted by %s", user); } } utx.ut_type = SHUTDOWN_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); /* * Do a sync early on, so disks start transfers while we're off * killing processes. Don't worry about writes done before the * processes die, the reboot system call syncs the disks. */ if (!nflag) sync(); /* * Ignore signals that we can get as a result of killing * parents, group leaders, etc. */ (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTERM, SIG_IGN); (void)signal(SIGTSTP, SIG_IGN); /* * If we're running in a pipeline, we don't want to die * after killing whatever we're writing to. */ (void)signal(SIGPIPE, SIG_IGN); /* * Only init(8) can perform rerooting. */ if (howto & RB_REROOT) { if (kill(1, SIGEMT) == -1) err(1, "SIGEMT init"); return (0); } /* Just stop init -- if we fail, we'll restart it. */ if (kill(1, SIGTSTP) == -1) err(1, "SIGTSTP init"); /* Send a SIGTERM first, a chance to save the buffers. */ if (kill(-1, SIGTERM) == -1 && errno != ESRCH) err(1, "SIGTERM processes"); /* * After the processes receive the signal, start the rest of the * buffers on their way. Wait 5 seconds between the SIGTERM and * the SIGKILL to give everybody a chance. If there is a lot of * paging activity then wait longer, up to a maximum of approx * 60 seconds. */ sleep(2); for (i = 0; i < 20; i++) { pageins = get_pageins(); if (!nflag) sync(); sleep(3); if (get_pageins() == pageins) break; } for (i = 1;; ++i) { if (kill(-1, SIGKILL) == -1) { if (errno == ESRCH) break; goto restart; } if (i > 5) { (void)fprintf(stderr, "WARNING: some process(es) wouldn't die\n"); break; } (void)sleep(2 * i); } reboot(howto); /* FALLTHROUGH */ restart: sverrno = errno; errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "", strerror(sverrno)); /* NOTREACHED */ }
/*ARGSUSED*/ static void reset(const time_t newt, const int nflag) { register int fid; time_t oldt; static struct { struct utmp before; struct utmp after; } s; #if HAVE_UTMPX_H static struct { struct utmpx before; struct utmpx after; } sx; #endif /* ** Wouldn't it be great if stime returned the old time? */ (void) time(&oldt); if (stime(&newt) != 0) oops("stime"); s.before.ut_type = OLD_TIME; s.before.ut_time = oldt; (void) strcpy(s.before.ut_line, OTIME_MSG); s.after.ut_type = NEW_TIME; s.after.ut_time = newt; (void) strcpy(s.after.ut_line, NTIME_MSG); fid = open(WTMP_FILE, O_WRONLY | O_APPEND); if (fid < 0) oops(_("log file open")); if (write(fid, (char *) &s, sizeof s) != sizeof s) oops(_("log file write")); if (close(fid) != 0) oops(_("log file close")); #if !HAVE_UTMPX_H pututline(&s.before); pututline(&s.after); #endif /* !HAVE_UTMPX_H */ #if HAVE_UTMPX_H sx.before.ut_type = OLD_TIME; sx.before.ut_tv.tv_sec = oldt; (void) strcpy(sx.before.ut_line, OTIME_MSG); sx.after.ut_type = NEW_TIME; sx.after.ut_tv.tv_sec = newt; (void) strcpy(sx.after.ut_line, NTIME_MSG); #if !SUPPRESS_WTMPX_FILE_UPDATE /* In Solaris 2.5 (and presumably other systems), `date' does not update /var/adm/wtmpx. This must be a bug. If you'd like to reproduce the bug, define SUPPRESS_WTMPX_FILE_UPDATE to be nonzero. */ fid = open(WTMPX_FILE, O_WRONLY | O_APPEND); if (fid < 0) oops(_("log file open")); if (write(fid, (char *) &sx, sizeof sx) != sizeof sx) oops(_("log file write")); if (close(fid) != 0) oops(_("log file close")); #endif /* !SUPPRESS_WTMPX_FILE_UPDATE */ pututxline(&sx.before); pututxline(&sx.after); #endif /* HAVE_UTMPX_H */ }
/* * make and write utmp and wtmp entries */ void ptytty_unix::login (int cmd_pid, bool login_shell, const char *hostname) { const char *pty = name; if (!pty || !*pty) return; this->cmd_pid = cmd_pid; this->login_shell = login_shell; #ifdef HAVE_STRUCT_UTMP struct utmp *ut = &this->ut; #endif #ifdef HAVE_STRUCT_UTMPX struct utmpx *utx = &this->utx; #endif int i; struct passwd *pwent = getpwuid (getuid ()); const char *name = (pwent && pwent->pw_name) ? pwent->pw_name : "?"; if (!strncmp (pty, "/dev/", 5)) pty += 5; /* skip /dev/ prefix */ #if defined(HAVE_UTMP_PID) || defined(HAVE_STRUCT_UTMPX) if (!strncmp (pty, "pty", 3) || !strncmp (pty, "tty", 3)) strncpy (ut_id, pty + 3, sizeof (ut_id)); else if (sscanf (pty, "pts/%d", &i) == 1) sprintf (ut_id, "vt%02x", (i & 0xff)); /* sysv naming */ else { ptytty_warn ("can't parse tty name \"%s\", not adding utmp entry.\n", pty); return; } #endif #ifdef HAVE_STRUCT_UTMP memset (ut, 0, sizeof (struct utmp)); # ifdef HAVE_UTMP_PID setutent (); strncpy (ut->ut_id, ut_id, sizeof (ut->ut_id)); ut->ut_type = DEAD_PROCESS; getutid (ut); /* position to entry in utmp file */ # endif #endif #ifdef HAVE_STRUCT_UTMPX memset (utx, 0, sizeof (struct utmpx)); setutxent (); strncpy (utx->ut_id, ut_id, sizeof (utx->ut_id)); utx->ut_type = DEAD_PROCESS; getutxid (utx); /* position to entry in utmp file */ #endif #ifdef HAVE_STRUCT_UTMP strncpy (ut->ut_line, pty, sizeof (ut->ut_line)); # ifdef HAVE_UTMP_HOST strncpy (ut->ut_host, hostname, sizeof (ut->ut_host)); # endif ut->ut_time = time (NULL); # ifdef HAVE_UTMP_PID strncpy (ut->ut_user, name, sizeof (ut->ut_user)); strncpy (ut->ut_id, ut_id, sizeof (ut->ut_id)); ut->ut_pid = cmd_pid; ut->ut_type = USER_PROCESS; pututline (ut); endutent (); /* close the file */ utmp_pos = 0; # else strncpy (ut->ut_name, name, sizeof (ut->ut_name)); # endif #endif #ifdef HAVE_STRUCT_UTMPX strncpy (utx->ut_line, pty, sizeof (utx->ut_line)); strncpy (utx->ut_user, name, sizeof (utx->ut_user)); strncpy (utx->ut_id, ut_id, sizeof (utx->ut_id)); # if HAVE_UTMPX_SESSION utx->ut_session = getsid (0); # endif utx->ut_tv.tv_sec = time (NULL); utx->ut_tv.tv_usec = 0; utx->ut_pid = cmd_pid; # ifdef HAVE_UTMPX_HOST strncpy (utx->ut_host, hostname, sizeof (utx->ut_host)); # if 0 { char *colon; if ((colon = strrchr (ut->ut_host, ':')) != NULL) *colon = '\0'; } # endif # endif utx->ut_type = USER_PROCESS; pututxline (utx); endutxent (); /* close the file */ utmp_pos = 0; #endif #if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID) { # if 1 int fdstdin = dup (STDIN_FILENO); dup2 (tty, STDIN_FILENO); i = ttyslot (); if (write_bsd_utmp (i, ut)) utmp_pos = i; dup2 (fdstdin, STDIN_FILENO); close (fdstdin); # endif } #endif #ifdef WTMP_SUPPORT #ifdef LOG_ONLY_ON_LOGIN if (login_shell) #endif { # ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UPDWTMP updwtmp (WTMP_FILE, ut); # else update_wtmp (WTMP_FILE, ut); # endif # endif # if defined(HAVE_STRUCT_UTMPX) && defined(HAVE_UPDWTMPX) updwtmpx (WTMPX_FILE, utx); # endif } #endif #if defined(LASTLOG_SUPPORT) && defined(LASTLOG_FILE) #ifdef LOG_ONLY_ON_LOGIN if (login_shell) #endif update_lastlog (LASTLOG_FILE, pty, hostname); #endif }
static void rmut(void) { pam_handle_t *pamh; struct utmpx *up; char user[sizeof (up->ut_user) + 1]; char ttyn[sizeof (up->ut_line) + 1]; char rhost[sizeof (up->ut_host) + 1]; /* while cleaning up dont allow disruption */ (void) sigset(SIGCHLD, SIG_IGN); setutxent(); while (up = getutxent()) { if (up->ut_pid == pid) { if (up->ut_type == DEAD_PROCESS) break; /* Cleaned up elsewhere. */ /* * call pam_close_session if login changed * the utmpx user entry from type LOGIN_PROCESS * to type USER_PROCESS, which happens * after pam_open_session is called. */ if (up->ut_type == USER_PROCESS) { (void) strlcpy(user, up->ut_user, sizeof (user)); (void) strlcpy(ttyn, up->ut_line, sizeof (ttyn)); (void) strlcpy(rhost, up->ut_host, sizeof (rhost)); /* * Use the same pam_prog_name that * 'login' used. */ if ((pam_start(pam_prog_name, user, NULL, &pamh)) == PAM_SUCCESS) { (void) pam_set_item(pamh, PAM_TTY, ttyn); (void) pam_set_item(pamh, PAM_RHOST, rhost); (void) pam_close_session(pamh, 0); (void) pam_end(pamh, PAM_SUCCESS); } } up->ut_type = DEAD_PROCESS; up->ut_exit.e_termination = WTERMSIG(0); up->ut_exit.e_exit = WEXITSTATUS(0); (void) time(&up->ut_tv.tv_sec); if (modutx(up) == NULL) { /* * Since modutx failed we'll * write out the new entry * ourselves. */ (void) pututxline(up); updwtmpx("wtmpx", up); } break; } } endutxent(); (void) sigset(SIGCHLD, cleanup); }
void servo_perform_clock_step(RunTimeOpts * rtOpts, PtpClock * ptpClock) { if(rtOpts->noAdjust){ WARNING("Could not step clock - clock adjustment disabled\n"); return; } TimeInternal oldTime, newTime; /*No need to reset the frequency offset: if we're far off, it will quickly get back to a high value */ getTime(&oldTime); subTime(&newTime, &oldTime, &ptpClock->offsetFromMaster); setTime(&newTime); #ifdef HAVE_LINUX_RTC_H if(rtOpts->setRtc) { setRtc(&newTime); } #endif /* HAVE_LINUX_RTC_H */ initClock(rtOpts, ptpClock); #ifdef HAVE_SYS_TIMEX_H if(ptpClock->clockQuality.clockClass > 127) restoreDrift(ptpClock, rtOpts, TRUE); #endif /* HAVE_SYS_TIMEX_H */ ptpClock->servo.runningMaxOutput = FALSE; toState(PTP_FAULTY, rtOpts, ptpClock); /* make a full protocol reset */ /* Major time change - need to inform utmp / wtmp */ if(oldTime.seconds != newTime.seconds) { /* Add the old time entry to utmp/wtmp */ /* About as long as the ntpd implementation, but not any less ugly */ #ifdef HAVE_UTMPX_H struct utmpx utx; memset(&utx, 0, sizeof(utx)); strncpy(utx.ut_user, "date", sizeof(utx.ut_user)); #ifndef OTIME_MSG strncpy(utx.ut_line, "|", sizeof(utx.ut_line)); #else strncpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); #endif /* OTIME_MSG */ #ifdef OLD_TIME utx.ut_tv.tv_sec = oldTime.seconds; utx.ut_tv.tv_usec = oldTime.nanoseconds / 1000; utx.ut_type = OLD_TIME; #else /* no ut_type */ utx.ut_time = oldTime.seconds; #endif /* OLD_TIME */ /* ======== BEGIN OLD TIME EVENT - UTMPX / WTMPX =========== */ #ifdef HAVE_UTMPXNAME utmpxname("/var/log/utmp"); #endif /* HAVE_UTMPXNAME */ setutxent(); pututxline(&utx); endutxent(); #ifdef HAVE_UPDWTMPX updwtmpx("/var/log/wtmp", &utx); #endif /* HAVE_IPDWTMPX */ /* ======== END OLD TIME EVENT - UTMPX / WTMPX =========== */ #else /* NO UTMPX_H */ #ifdef HAVE_UTMP_H struct utmp ut; memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_name, "date", sizeof(ut.ut_name)); #ifndef OTIME_MSG strncpy(ut.ut_line, "|", sizeof(ut.ut_line)); #else strncpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); #endif /* OTIME_MSG */ #ifdef OLD_TIME ut.ut_tv.tv_sec = oldTime.seconds; ut.ut_tv.tv_usec = oldTime.nanoseconds / 1000; ut.ut_type = OLD_TIME; #else /* no ut_type */ ut.ut_time = oldTime.seconds; #endif /* OLD_TIME */ /* ======== BEGIN OLD TIME EVENT - UTMP / WTMP =========== */ #ifdef HAVE_UTMPNAME utmpname(UTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ #ifdef HAVE_UTMPNAME utmpname(WTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ /* ======== END OLD TIME EVENT - UTMP / WTMP =========== */ #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ /* Add the new time entry to utmp/wtmp */ #ifdef HAVE_UTMPX_H memset(&utx, 0, sizeof(utx)); strncpy(utx.ut_user, "date", sizeof(utx.ut_user)); #ifndef NTIME_MSG strncpy(utx.ut_line, "}", sizeof(utx.ut_line)); #else strncpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); #endif /* NTIME_MSG */ #ifdef NEW_TIME utx.ut_tv.tv_sec = newTime.seconds; utx.ut_tv.tv_usec = newTime.nanoseconds / 1000; utx.ut_type = NEW_TIME; #else /* no ut_type */ utx.ut_time = newTime.seconds; #endif /* NEW_TIME */ /* ======== BEGIN NEW TIME EVENT - UTMPX / WTMPX =========== */ #ifdef HAVE_UTMPXNAME utmpxname("/var/log/utmp"); #endif /* HAVE_UTMPXNAME */ setutxent(); pututxline(&utx); endutxent(); #ifdef HAVE_UPDWTMPX updwtmpx("/var/log/wtmp", &utx); #endif /* HAVE_UPDWTMPX */ /* ======== END NEW TIME EVENT - UTMPX / WTMPX =========== */ #else /* NO UTMPX_H */ #ifdef HAVE_UTMP_H memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_name, "date", sizeof(ut.ut_name)); #ifndef NTIME_MSG strncpy(ut.ut_line, "}", sizeof(ut.ut_line)); #else strncpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); #endif /* NTIME_MSG */ #ifdef NEW_TIME ut.ut_tv.tv_sec = newTime.seconds; ut.ut_tv.tv_usec = newTime.nanoseconds / 1000; ut.ut_type = NEW_TIME; #else /* no ut_type */ ut.ut_time = newTime.seconds; #endif /* NEW_TIME */ /* ======== BEGIN NEW TIME EVENT - UTMP / WTMP =========== */ #ifdef HAVE_UTMPNAME utmpname(UTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ #ifdef HAVE_UTMPNAME utmpname(WTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ /* ======== END NEW TIME EVENT - UTMP / WTMP =========== */ #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ } }
void ptytty_unix::log_session (bool login, const char *hostname) { struct passwd *pwent = getpwuid (getuid ()); const char *user = (pwent && pwent->pw_name) ? pwent->pw_name : "?"; const char *pty = name; if (!strncmp (pty, "/dev/", 5)) pty += 5; /* skip /dev/ prefix */ #ifdef HAVE_STRUCT_UTMP struct utmp *tmput; struct utmp ut; fill_utmp (&ut, login, cmd_pid, pty, user, hostname); #endif #ifdef HAVE_STRUCT_UTMPX struct utmpx *tmputx; struct utmpx utx; fill_utmpx (&utx, login, cmd_pid, pty, user, hostname); #endif #ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UTMP_PID setutent (); if (login || ((tmput = getutid (&ut)) && tmput->ut_pid == cmd_pid)) pututline (&ut); endutent (); # else write_bsd_utmp (utmp_pos, &ut); # endif #endif #ifdef HAVE_STRUCT_UTMPX setutxent (); if (login || ((tmputx = getutxid (&utx)) && tmputx->ut_pid == cmd_pid)) pututxline (&utx); endutxent (); #endif #ifdef WTMP_SUPPORT if (login_shell) { # ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UPDWTMP updwtmp (WTMP_FILE, &ut); # else update_wtmp (WTMP_FILE, &ut); # endif # endif # if defined(HAVE_STRUCT_UTMPX) && defined(HAVE_UPDWTMPX) updwtmpx (WTMPX_FILE, &utx); # endif } #endif #ifdef LASTLOG_SUPPORT if (login_shell) if (login) { if (pwent) update_lastlog (pty, hostname); else PTYTTY_WARN ("no entry in password file, not updating lastlog.\n"); } #endif }
void setutmp(const char *name, const char *line, const char *host) { struct utmp *utmp, utline; struct utmpx *utmpx, utxline; pid_t pid = getpid (); int found_utmpx = 0, found_utmp = 0; /* * The canonical device name doesn't include "/dev/"; skip it * if it is already there. */ if (strncmp (line, "/dev/", 5) == 0) line += 5; /* * Update utmpx. We create an empty entry in case there is * no matching entry in the utmpx file. */ setutxent (); setutent (); while (utmpx = getutxent ()) { if (utmpx->ut_pid == pid) { found_utmpx = 1; break; } } while (utmp = getutent ()) { if (utmp->ut_pid == pid) { found_utmp = 1; break; } } /* * If the entry matching `pid' cannot be found, create a new * entry with the device name in it. */ if (! found_utmpx) { memset ((void *) &utxline, 0, sizeof utxline); strncpy (utxline.ut_line, line, sizeof utxline.ut_line); utxline.ut_pid = getpid (); } else { utxline = *utmpx; if (strncmp (utxline.ut_line, "/dev/", 5) == 0) { memmove (utxline.ut_line, utxline.ut_line + 5, sizeof utxline.ut_line - 5); utxline.ut_line[sizeof utxline.ut_line - 5] = '\0'; } } if (! found_utmp) { memset ((void *) &utline, 0, sizeof utline); strncpy (utline.ut_line, utxline.ut_line, sizeof utline.ut_line); utline.ut_pid = utxline.ut_pid; } else { utline = *utmp; if (strncmp (utline.ut_line, "/dev/", 5) == 0) { memmove (utline.ut_line, utline.ut_line + 5, sizeof utline.ut_line - 5); utline.ut_line[sizeof utline.ut_line - 5] = '\0'; } } /* * Fill in the fields in the utmpx entry and write it out. Do * the utmp entry at the same time to make sure things don't * get messed up. */ strncpy (utxline.ut_user, name, sizeof utxline.ut_user); strncpy (utline.ut_user, name, sizeof utline.ut_user); utline.ut_type = utxline.ut_type = USER_PROCESS; gettimeofday(&utxline.ut_tv, NULL); utline.ut_time = utxline.ut_tv.tv_sec; strncpy(utxline.ut_host, host ? host : "", sizeof utxline.ut_host); pututxline (&utxline); pututline (&utline); updwtmpx(_WTMP_FILE "x", &utxline); updwtmp(_WTMP_FILE, &utline); utxent = utxline; utent = utline; }
/* * remove utmp and wtmp entries */ void ptytty_unix::logout () { if (!cmd_pid) return; #ifdef HAVE_STRUCT_UTMP struct utmp *tmput, *ut = &this->ut; #endif #ifdef HAVE_STRUCT_UTMPX struct utmpx *tmputx, *utx = &this->utx; #endif #ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UTMP_PID memset (ut, 0, sizeof (struct utmp)); setutent (); strncpy (ut->ut_id, this->ut_id, sizeof (ut->ut_id)); ut->ut_type = USER_PROCESS; if ((tmput = getutid (ut))) /* position to entry in utmp file */ ut = tmput; ut->ut_type = DEAD_PROCESS; # else memset (ut->ut_name, 0, sizeof (ut->ut_name)); # ifdef HAVE_UTMP_HOST memset (ut->ut_host, 0, sizeof (ut->ut_host)); # endif # endif ut->ut_time = time (NULL); #endif #ifdef HAVE_STRUCT_UTMPX memset (utx, 0, sizeof (struct utmpx)); setutxent (); strncpy (utx->ut_id, this->ut_id, sizeof (utx->ut_id)); utx->ut_type = USER_PROCESS; if ((tmputx = getutxid (utx))) /* position to entry in utmp file */ utx = tmputx; utx->ut_type = DEAD_PROCESS; # if HAVE_UTMPX_SESSION utx->ut_session = getsid (0); # endif utx->ut_tv.tv_sec = time (NULL); utx->ut_tv.tv_usec = 0; #endif /* * Write ending wtmp entry */ #ifdef WTMP_SUPPORT #ifdef LOG_ONLY_ON_LOGIN if (login_shell) #endif { # ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UPDWTMP updwtmp (WTMP_FILE, ut); # else update_wtmp (WTMP_FILE, ut); # endif # endif # if defined(HAVE_STRUCT_UTMPX) && defined(HAVE_UPDWTMPX) updwtmpx (WTMPX_FILE, utx); # endif } #endif /* * Write utmp entry */ #ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UTMP_PID if (ut->ut_pid == cmd_pid) pututline (ut); endutent (); # else memset (ut, 0, sizeof (struct utmp)); write_bsd_utmp (utmp_pos, ut); # endif #endif #ifdef HAVE_STRUCT_UTMPX if (utx->ut_pid == cmd_pid) pututxline (utx); endutxent (); #endif cmd_pid = 0; }
int step_systime( double step ) { time_t pivot; /* for ntp era unfolding */ struct timeval timetv, tvlast, tvdiff; struct timespec timets; struct calendar jd; l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ /* * Get pivot time for NTP era unfolding. Since we don't step * very often, we can afford to do the whole calculation from * scratch. And we're not in the time-critical path yet. */ #if SIZEOF_TIME_T > 4 /* * This code makes sure the resulting time stamp for the new * system time is in the 2^32 seconds starting at 1970-01-01, * 00:00:00 UTC. */ pivot = 0x80000000; #if USE_COMPILETIME_PIVOT /* * Add the compile time minus 10 years to get a possible target * area of (compile time - 10 years) to (compile time + 126 * years). This should be sufficient for a given binary of * NTPD. */ if (ntpcal_get_build_date(&jd)) { jd.year -= 10; pivot += ntpcal_date_to_time(&jd); } else { msyslog(LOG_ERR, "step-systime: assume 1970-01-01 as build date"); } #else UNUSED_LOCAL(jd); #endif /* USE_COMPILETIME_PIVOT */ #else UNUSED_LOCAL(jd); /* This makes sure the resulting time stamp is on or after * 1969-12-31/23:59:59 UTC and gives us additional two years, * from the change of NTP era in 2036 to the UNIX rollover in * 2038. (Minus one second, but that won't hurt.) We *really* * need a longer 'time_t' after that! Or a different baseline, * but that would cause other serious trouble, too. */ pivot = 0x7FFFFFFF; #endif /* get the complete jump distance as l_fp */ DTOLFP(sys_residual, &fp_sys); DTOLFP(step, &fp_ofs); L_ADD(&fp_ofs, &fp_sys); /* ---> time-critical path starts ---> */ /* get the current time as l_fp (without fuzz) and as struct timeval */ get_ostime(&timets); fp_sys = tspec_stamp_to_lfp(timets); tvlast.tv_sec = timets.tv_sec; tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; /* get the target time as l_fp */ L_ADD(&fp_sys, &fp_ofs); /* unfold the new system time */ timetv = lfp_stamp_to_tval(fp_sys, &pivot); /* now set new system time */ if (ntp_set_tod(&timetv, NULL) != 0) { msyslog(LOG_ERR, "step-systime: %m"); return FALSE; } /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ sys_residual = 0; lamport_violated = (step < 0); if (step_callback) (*step_callback)(); #ifdef NEED_HPUX_ADJTIME /* * CHECKME: is this correct when called by ntpdate????? */ _clear_adjtime(); #endif /* * FreeBSD, for example, has: * struct utmp { * char ut_line[UT_LINESIZE]; * char ut_name[UT_NAMESIZE]; * char ut_host[UT_HOSTSIZE]; * long ut_time; * }; * and appends line="|", name="date", host="", time for the OLD * and appends line="{", name="date", host="", time for the NEW * to _PATH_WTMP . * * Some OSes have utmp, some have utmpx. */ /* * Write old and new time entries in utmp and wtmp if step * adjustment is greater than one second. * * This might become even Uglier... */ tvdiff = abs_tval(sub_tval(timetv, tvlast)); if (tvdiff.tv_sec > 0) { #ifdef HAVE_UTMP_H struct utmp ut; #endif #ifdef HAVE_UTMPX_H struct utmpx utx; #endif #ifdef HAVE_UTMP_H ZERO(ut); #endif #ifdef HAVE_UTMPX_H ZERO(utx); #endif /* UTMP */ #ifdef UPDATE_UTMP # ifdef HAVE_PUTUTLINE # ifndef _PATH_UTMP # define _PATH_UTMP UTMP_FILE # endif utmpname(_PATH_UTMP); ut.ut_type = OLD_TIME; strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = tvlast.tv_sec; setutent(); pututline(&ut); ut.ut_type = NEW_TIME; strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = timetv.tv_sec; setutent(); pututline(&ut); endutent(); # else /* not HAVE_PUTUTLINE */ # endif /* not HAVE_PUTUTLINE */ #endif /* UPDATE_UTMP */ /* UTMPX */ #ifdef UPDATE_UTMPX # ifdef HAVE_PUTUTXLINE utx.ut_type = OLD_TIME; strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); utx.ut_tv = tvlast; setutxent(); pututxline(&utx); utx.ut_type = NEW_TIME; strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); utx.ut_tv = timetv; setutxent(); pututxline(&utx); endutxent(); # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ #endif /* UPDATE_UTMPX */ /* WTMP */ #ifdef UPDATE_WTMP # ifdef HAVE_PUTUTLINE # ifndef _PATH_WTMP # define _PATH_WTMP WTMP_FILE # endif utmpname(_PATH_WTMP); ut.ut_type = OLD_TIME; strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = tvlast.tv_sec; setutent(); pututline(&ut); ut.ut_type = NEW_TIME; strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = timetv.tv_sec; setutent(); pututline(&ut); endutent(); # else /* not HAVE_PUTUTLINE */ # endif /* not HAVE_PUTUTLINE */ #endif /* UPDATE_WTMP */ /* WTMPX */ #ifdef UPDATE_WTMPX # ifdef HAVE_PUTUTXLINE utx.ut_type = OLD_TIME; utx.ut_tv = tvlast; strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); # ifdef HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &utx); # else /* not HAVE_UPDWTMPX */ # endif /* not HAVE_UPDWTMPX */ # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ # ifdef HAVE_PUTUTXLINE utx.ut_type = NEW_TIME; utx.ut_tv = timetv; strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); # ifdef HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &utx); # else /* not HAVE_UPDWTMPX */ # endif /* not HAVE_UPDWTMPX */ # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ #endif /* UPDATE_WTMPX */ } return TRUE; }
static void updateXtmp_unix (TimeInternal oldTime, TimeInternal newTime) { /* Add the old time entry to utmp/wtmp */ /* About as long as the ntpd implementation, but not any less ugly */ #ifdef HAVE_UTMPX_H struct utmpx utx; memset(&utx, 0, sizeof(utx)); strncpy(utx.ut_user, "date", sizeof(utx.ut_user)); #ifndef OTIME_MSG strncpy(utx.ut_line, "|", sizeof(utx.ut_line)); #else strncpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); #endif /* OTIME_MSG */ #ifdef OLD_TIME utx.ut_tv.tv_sec = oldTime.seconds; utx.ut_tv.tv_usec = oldTime.nanoseconds / 1000; utx.ut_type = OLD_TIME; #else /* no ut_type */ utx.ut_time = oldTime.seconds; #endif /* OLD_TIME */ /* ======== BEGIN OLD TIME EVENT - UTMPX / WTMPX =========== */ #ifdef HAVE_UTMPXNAME utmpxname("/var/log/utmp"); #endif /* HAVE_UTMPXNAME */ setutxent(); pututxline(&utx); endutxent(); #ifdef HAVE_UPDWTMPX updwtmpx("/var/log/wtmp", &utx); #endif /* HAVE_IPDWTMPX */ /* ======== END OLD TIME EVENT - UTMPX / WTMPX =========== */ #else /* NO UTMPX_H */ #ifdef HAVE_UTMP_H struct utmp ut; memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_name, "date", sizeof(ut.ut_name)); #ifndef OTIME_MSG strncpy(ut.ut_line, "|", sizeof(ut.ut_line)); #else strncpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); #endif /* OTIME_MSG */ #ifdef OLD_TIME #ifdef HAVE_STRUCT_UTMP_UT_TIME ut.ut_time = oldTime.seconds; #else ut.ut_tv.tv_sec = oldTime.seconds; ut.ut_tv.tv_usec = oldTime.nanoseconds / 1000; #endif /* HAVE_STRUCT_UTMP_UT_TIME */ ut.ut_type = OLD_TIME; #else /* no ut_type */ ut.ut_time = oldTime.seconds; #endif /* OLD_TIME */ /* ======== BEGIN OLD TIME EVENT - UTMP / WTMP =========== */ #ifdef HAVE_UTMPNAME utmpname(UTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ #ifdef HAVE_UTMPNAME utmpname(WTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ /* ======== END OLD TIME EVENT - UTMP / WTMP =========== */ #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ /* Add the new time entry to utmp/wtmp */ #ifdef HAVE_UTMPX_H memset(&utx, 0, sizeof(utx)); strncpy(utx.ut_user, "date", sizeof(utx.ut_user)); #ifndef NTIME_MSG strncpy(utx.ut_line, "{", sizeof(utx.ut_line)); #else strncpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); #endif /* NTIME_MSG */ #ifdef NEW_TIME utx.ut_tv.tv_sec = newTime.seconds; utx.ut_tv.tv_usec = newTime.nanoseconds / 1000; utx.ut_type = NEW_TIME; #else /* no ut_type */ utx.ut_time = newTime.seconds; #endif /* NEW_TIME */ /* ======== BEGIN NEW TIME EVENT - UTMPX / WTMPX =========== */ #ifdef HAVE_UTMPXNAME utmpxname("/var/log/utmp"); #endif /* HAVE_UTMPXNAME */ setutxent(); pututxline(&utx); endutxent(); #ifdef HAVE_UPDWTMPX updwtmpx("/var/log/wtmp", &utx); #endif /* HAVE_UPDWTMPX */ /* ======== END NEW TIME EVENT - UTMPX / WTMPX =========== */ #else /* NO UTMPX_H */ #ifdef HAVE_UTMP_H memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_name, "date", sizeof(ut.ut_name)); #ifndef NTIME_MSG strncpy(ut.ut_line, "{", sizeof(ut.ut_line)); #else strncpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); #endif /* NTIME_MSG */ #ifdef NEW_TIME #ifdef HAVE_STRUCT_UTMP_UT_TIME ut.ut_time = newTime.seconds; #else ut.ut_tv.tv_sec = newTime.seconds; ut.ut_tv.tv_usec = newTime.nanoseconds / 1000; #endif /* HAVE_STRUCT_UTMP_UT_TIME */ ut.ut_type = NEW_TIME; #else /* no ut_type */ ut.ut_time = newTime.seconds; #endif /* NEW_TIME */ /* ======== BEGIN NEW TIME EVENT - UTMP / WTMP =========== */ #ifdef HAVE_UTMPNAME utmpname(UTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ #ifdef HAVE_UTMPNAME utmpname(WTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ /* ======== END NEW TIME EVENT - UTMP / WTMP =========== */ #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ }
int slave() { int tries; long electiontime, refusetime, looktime, looptime, adjtime; u_short seq; long fastelection; #define FASTTOUT 3 struct in_addr cadr; struct timeval otime; struct sockaddr_in taddr; char tname[MAXHOSTNAMELEN]; struct tsp *msg, to; struct timeval ntime, wait, tmptv; time_t tsp_time_sec; struct tsp *answer; int timeout(); char olddate[32]; char newdate[32]; struct netinfo *ntp; struct hosttbl *htp; struct utmpx utx; old_slavenet = 0; seq = 0; refusetime = 0; adjtime = 0; (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; if (justquit) looktime = electiontime; else looktime = fastelection; looptime = fastelection; if (slavenet) xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr); if (status & MASTER) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) masterup(ntp); } } loop: get_goodgroup(0); (void)gettimeofday(&ntime, NULL); if (ntime.tv_sec > electiontime) { if (trace) fprintf(fd, "election timer expired\n"); longjmp(jmpenv, 1); } if (ntime.tv_sec >= looktime) { if (trace) fprintf(fd, "Looking for nets to master\n"); if (Mflag && nignorednets > 0) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == IGNORE || ntp->status == NOMASTER) { lookformaster(ntp); if (ntp->status == MASTER) { masterup(ntp); } else if (ntp->status == MASTER) { ntp->status = NOMASTER; } } if (ntp->status == MASTER && --ntp->quit_count < 0) ntp->quit_count = 0; } makeslave(slavenet); /* prune extras */ setstatus(); } (void)gettimeofday(&ntime, NULL); looktime = ntime.tv_sec + delay2; } if (ntime.tv_sec >= looptime) { if (trace) fprintf(fd, "Looking for loops\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = MAX_HOPCNT; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr)) < 0) { trace_sendto_err(ntp->dest_addr.sin_addr); } } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + delay2; } wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec; if (wait.tv_sec < 0) wait.tv_sec = 0; wait.tv_sec += FASTTOUT; wait.tv_usec = 0; msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); if (msg != NULL) { /* * filter stuff not for us */ switch (msg->tsp_type) { case TSP_SETDATE: case TSP_TRACEOFF: case TSP_TRACEON: /* * XXX check to see they are from ourself */ break; case TSP_TEST: case TSP_MSITE: break; case TSP_MASTERUP: if (!fromnet) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; default: if (!fromnet || fromnet->status == IGNORE || fromnet->status == NOMASTER) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; } /* * now process the message */ switch (msg->tsp_type) { case TSP_ADJTIME: if (fromnet != slavenet) break; if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted time adjustment by %s", msg->tsp_name); suppress(&from, msg->tsp_name, fromnet); break; } /* * Speed up loop detection in case we have a loop. * Otherwise the clocks can race until the loop * is found. */ (void)gettimeofday(&otime, NULL); if (adjtime < otime.tv_sec) looptime -= (looptime-otime.tv_sec)/2 + 1; setmaster(msg); if (seq != msg->tsp_seq) { seq = msg->tsp_seq; synch(tvtomsround(msg->tsp_time)); } (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; adjtime = ntime.tv_sec + SAMPLEINTVL*2; break; case TSP_SETTIME: if (fromnet != slavenet) break; if (seq == msg->tsp_seq) break; seq = msg->tsp_seq; /* adjust time for residence on the queue */ (void)gettimeofday(&otime, NULL); adj_msg_time(msg,&otime); /* * the following line is necessary due to syslog * calling ctime() which clobbers the static buffer */ (void)strcpy(olddate, date()); tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted time setting by untrusted %s to %s", msg->tsp_name, newdate); suppress(&from, msg->tsp_name, fromnet); break; } setmaster(msg); tmptv.tv_sec = msg->tsp_time.tv_sec; tmptv.tv_usec = msg->tsp_time.tv_usec; timevalsub(&ntime, &tmptv, &otime); if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { /* * do not change the clock if we can adjust it */ synch(tvtomsround(ntime)); } else { utx.ut_type = OLD_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); (void)settimeofday(&tmptv, 0); utx.ut_type = NEW_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); syslog(LOG_NOTICE, "date changed by %s from %s", msg->tsp_name, olddate); if (status & MASTER) spreadtime(); } (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; /* This patches a bad protocol bug. Imagine a system with several networks, * where there are a pair of redundant gateways between a pair of networks, * each running timed. Assume that we start with a third machine mastering * one of the networks, and one of the gateways mastering the other. * Imagine that the third machine goes away and the non-master gateway * decides to replace it. If things are timed just 'right,' we will have * each gateway mastering one network for a little while. If a SETTIME * message gets into the network at that time, perhaps from the newly * masterful gateway as it was taking control, the SETTIME will loop * forever. Each time a gateway receives it on its slave side, it will * call spreadtime to forward it on its mastered network. We are now in * a permanent loop, since the SETTIME msgs will keep any clock * in the network from advancing. Normally, the 'LOOP' stuff will detect * and correct the situation. However, with the clocks stopped, the * 'looptime' timer cannot expire. While they are in this state, the * masters will try to saturate the network with SETTIME packets. */ looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1; break; case TSP_MASTERUP: if (slavenet && fromnet != slavenet) break; if (!good_host_name(msg->tsp_name)) { suppress(&from, msg->tsp_name, fromnet); if (electiontime > fastelection) electiontime = fastelection; break; } makeslave(fromnet); setmaster(msg); setstatus(); answerdelay(); xmit(TSP_SLAVEUP, 0, &from); (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; refusetime = 0; break; case TSP_MASTERREQ: if (fromnet->status != SLAVE) break; (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; break; case TSP_SETDATE: tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); schgdate(msg, newdate); break; case TSP_SETDATEREQ: if (fromnet->status != MASTER) break; tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); htp = findhost(msg->tsp_name); if (0 == htp) { syslog(LOG_WARNING, "DATEREQ from uncontrolled machine"); break; } if (!htp->good) { syslog(LOG_WARNING, "attempted date change by untrusted %s to %s", htp->name, newdate); spreadtime(); break; } schgdate(msg, newdate); break; case TSP_TRACEON: traceon(); break; case TSP_TRACEOFF: traceoff("Tracing ended at %s\n"); break; case TSP_SLAVEUP: newslave(msg); break; case TSP_ELECTION: if (fromnet->status == SLAVE) { (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; seq = 0; if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "suppress election of %s", msg->tsp_name); to.tsp_type = TSP_QUIT; electiontime = fastelection; } else if (cadr.s_addr != from.sin_addr.s_addr && ntime.tv_sec < refusetime) { /* if the candidate has to repeat itself, the old code would refuse it * the second time. That would prevent elections. */ to.tsp_type = TSP_REFUSE; } else { cadr.s_addr = from.sin_addr.s_addr; to.tsp_type = TSP_ACCEPT; refusetime = ntime.tv_sec + 30; } taddr = from; (void)strcpy(tname, msg->tsp_name); (void)strcpy(to.tsp_name, hostname); answerdelay(); if (!acksend(&to, &taddr, tname, TSP_ACK, 0, 0)) syslog(LOG_WARNING, "no answer from candidate %s\n", tname); } else { /* fromnet->status == MASTER */ htp = addmach(msg->tsp_name, &from,fromnet); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer)) { syslog(LOG_ERR, "no reply from %s to ELECTION-QUIT", htp->name); (void)remmach(htp); } } break; case TSP_CONFLICT: if (fromnet->status != MASTER) break; /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ (void)strcpy(to.tsp_name, hostname); /* The other master often gets into the same state, * with boring results. */ ntp = fromnet; /* (acksend() can leave fromnet=0 */ for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp, 0); if (answer == NULL) break; htp = addmach(answer->tsp_name,&from,ntp); to.tsp_type = TSP_QUIT; answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (!answer) { syslog(LOG_WARNING, "conflict error: no reply from %s to QUIT", htp->name); (void)remmach(htp); } } masterup(ntp); break; case TSP_MSITE: if (!slavenet) break; taddr = from; to.tsp_type = TSP_MSITEREQ; to.tsp_vers = TSPVERSION; to.tsp_seq = 0; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &slavenet->dest_addr, ANYADDR, TSP_ACK, slavenet, 0); if (answer != NULL && good_host_name(answer->tsp_name)) { setmaster(answer); to.tsp_type = TSP_ACK; (void)strcpy(to.tsp_name, answer->tsp_name); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&taddr, sizeof(taddr)) < 0) { trace_sendto_err(taddr.sin_addr); } } break; case TSP_MSITEREQ: break; case TSP_ACCEPT: case TSP_REFUSE: case TSP_RESOLVE: break; case TSP_QUIT: doquit(msg); /* become a slave */ break; case TSP_TEST: electiontime = 0; break; case TSP_LOOP: /* looking for loops of masters */ if (!(status & MASTER)) break; if (fromnet->status == SLAVE) { if (!strcmp(msg->tsp_name, hostname)) { /* * Someone forwarded our message back to * us. There must be a loop. Tell the * master of this network to quit. * * The other master often gets into * the same state, with boring results. */ ntp = fromnet; for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp,0); if (answer == NULL) break; taddr = from; (void)strcpy(tname, answer->tsp_name); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to, &taddr, tname, TSP_ACK, 0, 1)) { syslog(LOG_ERR, "no reply from %s to slave LOOP-QUIT", tname); } else { electiontime = 0; } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + FASTTOUT; } else { if (msg->tsp_hopcnt-- < 1) break; bytenetorder(msg); for (ntp = nettab; ntp != 0; ntp = ntp->next) { if (ntp->status == MASTER && 0 > sendto(sock, (char *)msg, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr))) trace_sendto_err(ntp->dest_addr.sin_addr); } } } else { /* fromnet->status == MASTER */ /* * We should not have received this from a net * we are master on. There must be two masters, * unless the packet was really from us. */ if (from.sin_addr.s_addr == fromnet->my_addr.s_addr) { if (trace) fprintf(fd,"discarding forwarded LOOP\n"); break; } /* * The other master often gets into the same * state, with boring results. */ ntp = fromnet; for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp,0); if (!answer) break; htp = addmach(answer->tsp_name, &from,ntp); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to,&htp->addr,htp->name, TSP_ACK, 0, htp->noanswer)) { syslog(LOG_ERR, "no reply from %s to master LOOP-QUIT", htp->name); (void)remmach(htp); } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + FASTTOUT; } break; default: if (trace) { fprintf(fd, "garbage message: "); print(msg, &from); } break; } } goto loop; }
/* * Records that the user has logged in. I wish these parts of operating * systems were more standardized. */ void record_login(pid_t pid, const char *tty, const char *user, uid_t uid, const char *host, struct sockaddr *addr, socklen_t addrlen) { #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX) int fd; #endif struct timeval tv; #ifdef SUPPORT_UTMP struct utmp u; struct lastlog ll; #endif #ifdef SUPPORT_UTMPX struct utmpx ux, *uxp = &ux; struct lastlogx llx; #endif (void)gettimeofday(&tv, NULL); /* * XXX: why do we need to handle logout cases here? * Isn't the function below taking care of this? */ /* save previous login details before writing new */ store_lastlog_message(user, uid); #ifdef SUPPORT_UTMP /* Construct an utmp/wtmp entry. */ memset(&u, 0, sizeof(u)); strncpy(u.ut_line, tty + 5, sizeof(u.ut_line)); u.ut_time = (time_t)tv.tv_sec; strncpy(u.ut_name, user, sizeof(u.ut_name)); strncpy(u.ut_host, host, sizeof(u.ut_host)); login(&u); /* Update lastlog unless actually recording a logout. */ if (*user != '\0') { /* * It is safer to memset the lastlog structure first because * some systems might have some extra fields in it (e.g. SGI) */ memset(&ll, 0, sizeof(ll)); /* Update lastlog. */ ll.ll_time = time(NULL); strncpy(ll.ll_line, tty + 5, sizeof(ll.ll_line)); strncpy(ll.ll_host, host, sizeof(ll.ll_host)); fd = open(_PATH_LASTLOG, O_RDWR); if (fd >= 0) { lseek(fd, (off_t)uid * sizeof(ll), SEEK_SET); if (write(fd, &ll, sizeof(ll)) != sizeof(ll)) logit("Could not write %.100s: %.100s", _PATH_LASTLOG, strerror(errno)); close(fd); } } #endif #ifdef SUPPORT_UTMPX /* Construct an utmpx/wtmpx entry. */ memset(&ux, 0, sizeof(ux)); strncpy(ux.ut_line, tty + 5, sizeof(ux.ut_line)); if (*user) { ux.ut_pid = pid; ux.ut_type = USER_PROCESS; ux.ut_tv = tv; strncpy(ux.ut_name, user, sizeof(ux.ut_name)); strncpy(ux.ut_host, host, sizeof(ux.ut_host)); /* XXX: need ut_id, use last 4 char of tty */ if (strlen(tty) > sizeof(ux.ut_id)) { strncpy(ux.ut_id, tty + strlen(tty) - sizeof(ux.ut_id), sizeof(ux.ut_id)); } else strncpy(ux.ut_id, tty, sizeof(ux.ut_id)); /* XXX: It would be better if we had sockaddr_storage here */ if (addrlen > sizeof(ux.ut_ss)) addrlen = sizeof(ux.ut_ss); (void)memcpy(&ux.ut_ss, addr, addrlen); if (pututxline(&ux) == NULL) logit("could not add utmpx line: %.100s", strerror(errno)); /* Update lastlog. */ (void)gettimeofday(&llx.ll_tv, NULL); strncpy(llx.ll_line, tty + 5, sizeof(llx.ll_line)); strncpy(llx.ll_host, host, sizeof(llx.ll_host)); (void)memcpy(&llx.ll_ss, addr, addrlen); if (updlastlogx(_PATH_LASTLOGX, uid, &llx) == -1) logit("Could not update %.100s: %.100s", _PATH_LASTLOGX, strerror(errno)); } else { if ((uxp = getutxline(&ux)) == NULL) logit("could not find utmpx line for %.100s", tty); else { uxp->ut_type = DEAD_PROCESS; uxp->ut_tv = tv; /* XXX: we don't record exit info yet */ if (pututxline(&ux) == NULL) logit("could not replace utmpx line: %.100s", strerror(errno)); } } endutxent(); updwtmpx(_PATH_WTMPX, uxp); #endif }
int main(int argc, char *argv[]) { struct utmpx ut; char *devName; if (argc < 2 || strcmp(argv[1], "--help") == 0) usageErr("%s username [sleep-time]\n", argv[0]); /* Initialize login record for utmp and wtmp files */ memset(&ut, 0, sizeof(struct utmpx)); ut.ut_type = USER_PROCESS; /* This is a user login */ strncpy(ut.ut_user, argv[1], sizeof(ut.ut_user)); if (time((time_t *) &ut.ut_tv.tv_sec) == -1) errExit("time"); /* Stamp with current time */ ut.ut_pid = getpid(); /* Set ut_line and ut_id based on the terminal associated with 'stdin'. This code assumes terminals named "/dev/[pt]t[sy]*". The "/dev/" dirname is 5 characters; the "[pt]t[sy]" filename prefix is 3 characters (making 8 characters in all). */ devName = ttyname(STDIN_FILENO); if (devName == NULL) errExit("ttyname"); if (strlen(devName) <= 8) /* Should never happen */ fatal("Terminal name is too short: %s", devName); strncpy(ut.ut_line, devName + 5, sizeof(ut.ut_line)); strncpy(ut.ut_id, devName + 8, sizeof(ut.ut_id)); printf("Creating login entries in utmp and wtmp\n"); printf(" using pid %ld, line %.*s, id %.*s\n", (long) ut.ut_pid, (int) sizeof(ut.ut_line), ut.ut_line, (int) sizeof(ut.ut_id), ut.ut_id); setutxent(); /* Rewind to start of utmp file */ if (pututxline(&ut) == NULL) /* Write login record to utmp */ errExit("pututxline"); updwtmpx(_PATH_WTMP, &ut); /* Append login record to wtmp */ /* Sleep a while, so we can examine utmp and wtmp files */ sleep((argc > 2) ? getInt(argv[2], GN_NONNEG, "sleep-time") : 15); /* Now do a "logout"; use values from previously initialized 'ut', except for changes below */ ut.ut_type = DEAD_PROCESS; /* Required for logout record */ time((time_t *) &ut.ut_tv.tv_sec); /* Stamp with logout time */ memset(&ut.ut_user, 0, sizeof(ut.ut_user)); /* Logout record has null username */ printf("Creating logout entries in utmp and wtmp\n"); setutxent(); /* Rewind to start of utmp file */ if (pututxline(&ut) == NULL) /* Overwrite previous utmp record */ errExit("pututxline"); updwtmpx(_PATH_WTMP, &ut); /* Append logout record to wtmp */ endutxent(); exit(EXIT_SUCCESS); }
/* EXTPROTO */ void rxvt_makeutent(rxvt_t *r, const char *pty, const char *hostname) { #ifdef UTEMPTER_SUPPORT utempter_add_record (PVTS(r)->cmd_fd, hostname); #else /* UTEMPTER_SUPPORT */ #ifdef HAVE_STRUCT_UTMP struct utmp *ut = &(PVTS(r)->ut); #endif #if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) struct utmpx *utx = &(PVTS(r)->utx); #endif #ifdef HAVE_UTMP_PID int i; #endif char ut_id[5]; struct passwd *pwent = getpwuid(getuid()); if (!STRNCMP(pty, "/dev/", 5)) pty += 5; /* skip /dev/ prefix */ if (!STRNCMP(pty, "pty", 3) || !STRNCMP(pty, "tty", 3)) { STRNCPY(ut_id, (pty + 3), sizeof(ut_id)); } #ifdef HAVE_UTMP_PID else if (sscanf(pty, "pts/%d", &i) == 1) sprintf(ut_id, "vt%02x", (i & 0xff)); /* sysv naming */ #endif else if (STRNCMP(pty, "pty", 3) && STRNCMP(pty, "tty", 3)) { rxvt_msg (DBG_ERROR, DBG_LOGGING, "can't parse tty name \"%s\"", pty); return; } #ifdef HAVE_STRUCT_UTMP MEMSET(ut, 0, sizeof(struct utmp)); # ifdef HAVE_UTMP_PID setutent(); STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id)); ut->ut_type = DEAD_PROCESS; getutid(ut); /* position to entry in utmp file */ STRNCPY(PVTS(r)->ut_id, ut_id, sizeof(PVTS(r)->ut_id)); # endif #endif #if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) MEMSET(utx, 0, sizeof(struct utmpx)); setutxent(); STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id)); utx->ut_type = DEAD_PROCESS; getutxid(utx); /* position to entry in utmp file */ STRNCPY(PVTS(r)->ut_id, ut_id, sizeof(PVTS(r)->ut_id)); #endif #ifdef HAVE_STRUCT_UTMP STRNCPY(ut->ut_line, pty, sizeof(ut->ut_line)); ut->ut_time = time(NULL); # ifdef HAVE_UTMP_PID STRNCPY(ut->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?", sizeof(ut->ut_user)); STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id)); ut->ut_time = time(NULL); ut->ut_pid = PVTS(r)->cmd_pid; # ifdef HAVE_UTMP_HOST STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host)); # endif ut->ut_type = USER_PROCESS; pututline(ut); endutent(); /* close the file */ PVTS(r)->utmp_pos = 0; # else STRNCPY(ut->ut_name, (pwent && pwent->pw_name) ? pwent->pw_name : "?", sizeof(ut->ut_name)); # ifdef HAVE_UTMP_HOST STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host)); # endif # endif #endif #if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) STRNCPY(utx->ut_line, pty, sizeof(utx->ut_line)); STRNCPY(utx->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?", sizeof(utx->ut_user)); STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id)); # ifdef HAVE_UTMPX_SESSION utx->ut_session = getsid(0); # endif utx->ut_tv.tv_sec = time(NULL); utx->ut_tv.tv_usec = 0; utx->ut_pid = PVTS(r)->cmd_pid; # ifdef HAVE_UTMPX_HOST STRNCPY(utx->ut_host, hostname, sizeof(utx->ut_host)); # endif utx->ut_type = USER_PROCESS; pututxline(utx); endutxent(); /* close the file */ PVTS(r)->utmp_pos = 0; #endif #if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID) { int i; # ifdef HAVE_TTYSLOT i = ttyslot(); if (rxvt_write_bsd_utmp(i, ut)) PVTS(r)->utmp_pos = i; # else FILE *fd0; if (NOT_NULL(fd0 = fopen(TTYTAB_FILENAME, "r"))) { char buf[256], name[256]; buf[sizeof(buf) - 1] = '\0'; for (i = 1; NOT_NULL(fgets(buf, sizeof(buf) - 1, fd0)); ) { if (*buf == '#' || sscanf(buf, "%s", name) != 1) continue; if (!STRCMP(ut->ut_line, name)) { if (!rxvt_write_bsd_utmp(i, ut)) i = 0; PVTS(r)->utmp_pos = i; fclose(fd0); break; } i++; } fclose(fd0); } # endif } #endif #ifdef WTMP_SUPPORT # ifdef WTMP_ONLY_ON_LOGIN if (ISSET_OPTION(r, Opt_loginShell)) # endif { # ifdef HAVE_STRUCT_UTMP # ifdef HAVE_UPDWTMP updwtmp(RXVT_WTMP_FILE, ut); # else rxvt_update_wtmp(RXVT_WTMP_FILE, ut); # endif # endif # if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP) # ifdef HAVE_UPDWTMPX updwtmpx(RXVT_WTMPX_FILE, utx); # else pututxline (utx); # endif # endif } #endif #endif /* UTEMPTER_SUPPORT */ #if defined(LASTLOG_SUPPORT) && defined(RXVT_LASTLOG_FILE) if (ISSET_OPTION(r, Opt_loginShell)) rxvt_update_lastlog(RXVT_LASTLOG_FILE, pty, hostname); #endif }
/* * Update wtmp and utmp logs. */ static void log_utmp(struct login_context *cxt) { struct utmpx ut; struct utmpx *utp; struct timeval tv; utmpxname(_PATH_UTMP); setutxent(); /* Find pid in utmp. * * login sometimes overwrites the runlevel entry in /var/run/utmp, * confusing sysvinit. I added a test for the entry type, and the * problem was gone. (In a runlevel entry, st_pid is not really a pid * but some number calculated from the previous and current runlevel.) * -- Michael Riepe <*****@*****.**> */ while ((utp = getutxent())) if (utp->ut_pid == cxt->pid && utp->ut_type >= INIT_PROCESS && utp->ut_type <= DEAD_PROCESS) break; /* If we can't find a pre-existing entry by pid, try by line. * BSD network daemons may rely on this. */ if (utp == NULL && cxt->tty_name) { setutxent(); ut.ut_type = LOGIN_PROCESS; str2memcpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); utp = getutxline(&ut); } /* If we can't find a pre-existing entry by pid and line, try it by id. * Very stupid telnetd daemons don't set up utmp at all. (kzak) */ if (utp == NULL && cxt->tty_number) { setutxent(); ut.ut_type = DEAD_PROCESS; str2memcpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id)); utp = getutxid(&ut); } if (utp) memcpy(&ut, utp, sizeof(ut)); else /* some gettys/telnetds don't initialize utmp... */ memset(&ut, 0, sizeof(ut)); if (cxt->tty_number && ut.ut_id[0] == 0) str2memcpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id)); if (cxt->username) str2memcpy(ut.ut_user, cxt->username, sizeof(ut.ut_user)); if (cxt->tty_name) str2memcpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); gettimeofday(&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; ut.ut_type = USER_PROCESS; ut.ut_pid = cxt->pid; if (cxt->hostname) { str2memcpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host)); if (*cxt->hostaddress) memcpy(&ut.ut_addr_v6, cxt->hostaddress, sizeof(ut.ut_addr_v6)); } pututxline(&ut); endutxent(); updwtmpx(_PATH_WTMP, &ut); }