static void whoami(void) { struct utmpx ut, *utx; struct passwd *pwd; const char *name, *tty; if ((tty = ttyname(STDIN_FILENO)) == NULL) tty = "tty??"; else if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0) tty += sizeof _PATH_DEV - 1; strlcpy(ut.ut_line, tty, sizeof ut.ut_line); /* Search utmp for our tty, dump first matching record. */ if ((utx = getutxline(&ut)) != NULL && utx->ut_type == USER_PROCESS) { row(utx); return; } /* Not found; fill the utmp structure with the information we have. */ memset(&ut, 0, sizeof(ut)); if ((pwd = getpwuid(getuid())) != NULL) name = pwd->pw_name; else name = "?"; strlcpy(ut.ut_user, name, sizeof ut.ut_user); gettimeofday(&ut.ut_tv, NULL); row(&ut); }
static char * _getlogin() { /* find name of the controlling terminal of the calling process */ char *tty; /* if the controlling terminal name cannot be determined, return a NULL pointer. * `errno` will have been appropriately set by `ttyname(3)`. */ if ((tty = ttyname(STDIN_FILENO)) == NULL) return NULL; /* the static data structure used for all calls to this function */ static char login[GETLOGIN_LOGIN_MAX]; utmpname(GETLOGIN_UTMP_FILE); /* search for an entry in the utmp file where the ut_line field matches * that of the controlling terminal name */ errno = 0; setutxent(); if (errno != 0) return NULL; struct utmpx *entry, criteria; char *line; /* drop the leading slash, if any */ if (tty[0] == '/') ++tty; /* remove the `dev/` prefix from the ttyname, if existent */ if ((line = strchr(tty, '/')) == NULL) line = tty; else /* dev/pts/0 becomes pts/0 */ ++line; strncpy(criteria.ut_line, line, __UT_LINESIZE); if ((entry = getutxline(&criteria)) == NULL) return NULL; strncpy(login, entry->ut_user, GETLOGIN_LOGIN_MAX); /* finish the reading of the utmp file */ errno = 0; endutxent(); if (errno != 0) return NULL; return login; }
static void logout(const char *line) { #ifdef HAVE_GETUTXENT struct utmpx utx, *putx; pid_t pid; strcpy(utx.ut_line, line); setutxent(); putx = getutxline(&utx); if (putx != NULL) { gettimeofday(&utx.ut_tv, NULL); strncpy(utx.ut_line, putx->ut_line, sizeof(utx.ut_line)); strncpy(utx.ut_user, putx->ut_name, sizeof(utx.ut_name)); pid = getpid(); utx.ut_pid = pid; strncpy(utx.ut_id, putx->ut_id, sizeof(utx.ut_id)); utx.ut_type = DEAD_PROCESS; pututxline(&utx); updwtmpx(WTFILE, &utx); } endutxent(); #else /* HAVE_GETUTXENT */ struct utmp utmp; struct utmp *putmp; pid_t pid; strcpy(utmp.ut_line, line); setutent(); putmp = getutline(&utmp); if (putmp != NULL) { time(&utmp.ut_time); strncpy(utmp.ut_line, putmp->ut_line, sizeof(utmp.ut_line)); strncpy(utmp.ut_user, putmp->ut_name, sizeof(utmp.ut_name)); pid = getpid(); utmp.ut_pid = pid; strncpy(utmp.ut_id, putmp->ut_id, sizeof(utmp.ut_id)); utmp.ut_type = DEAD_PROCESS; pututline(&utmp); updwtmp(WTFILE, &utmp); } endutent(); #endif /* HAVE_GETUTXENT */ }
int logoutx(const char *line, int status, int type) { struct utmpx *utp, ut; (void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line)); if ((utp = getutxline(&ut)) == NULL) { endutxent(); return 0; } utp->ut_type = type; if (WIFEXITED(status)) utp->ut_exit.e_exit = (uint16_t)WEXITSTATUS(status); if (WIFSIGNALED(status)) utp->ut_exit.e_termination = (uint16_t)WTERMSIG(status); (void)gettimeofday(&utp->ut_tv, NULL); (void)pututxline(utp); endutxent(); return 1; }
/* * 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 }
/* * NOT the same locate_host() in locate_host.c. This one just does a * 'who am i' to try to discover where the user is... */ void locate_host(CtdlIPC* ipc, char *hbuf) { #ifndef HAVE_UTMP_H char buf[SIZ]; FILE *who; int a,b; who = (FILE *)popen("who am i","r"); if (who==NULL) { strcpy(hbuf, ipc->ServInfo.fqdn); return; } fgets(buf,sizeof buf,who); pclose(who); b = 0; for (a=0; !IsEmptyStr(&buf[a]); ++a) { if ((buf[a]=='(')||(buf[a]==')')) ++b; } if (b<2) { strcpy(hbuf, ipc->ServInfo.fqdn); return; } for (a=0; a<strlen(buf); ++a) { if (buf[a]=='(') { strcpy(buf,&buf[a+1]); } } for (a=0; a<strlen(buf); ++a) { if (buf[a]==')') buf[a] = 0; } if (IsEmptyStr(buf)) strcpy(hbuf, ipc->ServInfo.fqdn); else strncpy(hbuf,buf,24); #else char *tty = ttyname(0); #ifdef HAVE_GETUTXLINE struct utmpx ut, *put; #else struct utmp ut, *put; #endif if (tty == NULL) { fail: safestrncpy(hbuf, ipc->ServInfo.fqdn, 24); return; } if (strncmp(tty, "/dev/", 5)) goto fail; safestrncpy(ut.ut_line, &tty[5], sizeof ut.ut_line); #ifdef HAVE_GETUTXLINE /* Solaris uses this */ if ((put = getutxline(&ut)) == NULL) #else if ((put = getutline(&ut)) == NULL) #endif goto fail; #if defined(HAVE_UT_TYPE) || defined(HAVE_GETUTXLINE) if (put->ut_type == USER_PROCESS) { #endif #if defined(HAVE_UT_HOST) || defined(HAVE_GETUTXLINE) if (*put->ut_host) safestrncpy(hbuf, put->ut_host, 24); else #endif safestrncpy(hbuf, put->ut_line, 24); #if defined(HAVE_UT_TYPE) || defined(HAVE_GETUTXLINE) } else goto fail; #endif #endif /* HAVE_UTMP_H */ }
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 checkutmp(int picky) { char *line; struct utmp *ut; #if HAVE_UTMPX_H struct utmpx *utx; #endif pid_t pid = getpid(); #if HAVE_UTMPX_H setutxent(); #endif setutent(); if (picky) { #if HAVE_UTMPX_H while ((utx = getutxent())) if (utx->ut_pid == pid) break; if (utx) utxent = *utx; #endif while ((ut = getutent())) if (ut->ut_pid == pid) break; if (ut) utent = *ut; #if HAVE_UTMPX_H endutxent(); #endif endutent(); if (!ut) { puts(NO_UTENT); exit(1); } #ifndef UNIXPC /* * If there is no ut_line value in this record, fill * it in by getting the TTY name and stuffing it in * the structure. The UNIX/PC is broken in this regard * and needs help ... */ if (utent.ut_line[0] == '\0') #endif /* !UNIXPC */ { if (!(line = ttyname(0))) { puts(NO_TTY); exit(1); } if (strncmp(line, "/dev/", 5) == 0) line += 5; strncpy(utent.ut_line, line, sizeof utent.ut_line); #if HAVE_UTMPX_H strncpy(utxent.ut_line, line, sizeof utxent.ut_line); #endif } } else { if (!(line = ttyname(0))) { puts(NO_TTY); exit(1); } if (strncmp(line, "/dev/", 5) == 0) line += 5; strncpy (utent.ut_line, line, sizeof utent.ut_line); if ((ut = getutline(&utent))) strncpy(utent.ut_id, ut->ut_id, sizeof ut->ut_id); strcpy(utent.ut_user, "LOGIN"); utent.ut_pid = getpid(); utent.ut_type = LOGIN_PROCESS; time(&utent.ut_time); #if HAVE_UTMPX_H strncpy(utxent.ut_line, line, sizeof utxent.ut_line); if ((utx = getutxline(&utxent))) strncpy(utxent.ut_id, utx->ut_id, sizeof utxent.ut_id); strcpy(utxent.ut_user, "LOGIN"); utxent.ut_pid = utent.ut_pid; utxent.ut_type = utent.ut_type; gettimeofday((struct timeval *) &utxent.ut_tv, NULL); utent.ut_time = utxent.ut_tv.tv_sec; #endif } }
/* * 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); }
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 }
/* * 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); }
static void rmut(void) { struct utmpx utmpx, *non_save_utxp; char *clean_tty = clean_ttyname(line); /* * This updates the utmpx and utmp entries and make a wtmp/x entry */ setutxent(); memset(&utmpx, 0, sizeof(utmpx)); strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); utmpx.ut_type = LOGIN_PROCESS; non_save_utxp = getutxline(&utmpx); if (non_save_utxp) { struct utmpx *utxp; struct timeval tv; char user0; utxp = malloc(sizeof(struct utmpx)); *utxp = *non_save_utxp; user0 = utxp->ut_user[0]; utxp->ut_user[0] = '\0'; utxp->ut_type = DEAD_PROCESS; #ifdef HAVE_STRUCT_UTMPX_UT_EXIT #ifdef _STRUCT___EXIT_STATUS utxp->ut_exit.__e_termination = 0; utxp->ut_exit.__e_exit = 0; #elif defined(__osf__) /* XXX */ utxp->ut_exit.ut_termination = 0; utxp->ut_exit.ut_exit = 0; #else utxp->ut_exit.e_termination = 0; utxp->ut_exit.e_exit = 0; #endif #endif gettimeofday (&tv, NULL); utxp->ut_tv.tv_sec = tv.tv_sec; utxp->ut_tv.tv_usec = tv.tv_usec; pututxline(utxp); #ifdef WTMPX_FILE utxp->ut_user[0] = user0; updwtmpx(WTMPX_FILE, utxp); #elif defined(WTMP_FILE) /* This is a strange system with a utmpx and a wtmp! */ { int f = open(wtmpf, O_WRONLY|O_APPEND); struct utmp wtmp; if (f >= 0) { strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); #ifdef HAVE_STRUCT_UTMP_UT_HOST strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); #endif wtmp.ut_time = time(NULL); write(f, &wtmp, sizeof(wtmp)); close(f); } } #endif free (utxp); } endutxent(); } /* end of rmut */