struct utmp * pututline(struct utmp * utmp_entry) { struct utmp * ut; /* Ignore the return value. That way, if they've already positioned the file pointer where they want it, everything will work out. */ (void) lseek(ut_fd, (off_t) -sizeof(utmp_entry), SEEK_CUR); if ((ut=getutid(utmp_entry))!=NULL) { lseek(ut_fd, (off_t) -sizeof(utmp_entry), SEEK_CUR); if (write(ut_fd, (char *) utmp_entry, sizeof(utmp_entry)) != sizeof(utmp_entry)) return NULL; } else { lseek(ut_fd, (off_t) 0, SEEK_END); if (write(ut_fd, (char *) utmp_entry, sizeof(utmp_entry)) != sizeof(utmp_entry)) return NULL; } return utmp_entry; }
char platform_get_runlevel() { char runlevel; struct utmp ut, save, *next = NULL; struct timeval tv; int flag = 0, counter = 0; MUTEX_LOCK(utmp_lock); memset(&ut, 0, sizeof(struct utmp)); memset(&save, 0, sizeof(struct utmp)); memset(&tv, 0, sizeof(struct timeval)); ut.ut_type = RUN_LVL; setutent(); next = getutid(&ut); while (next != NULL) { if (next->ut_tv.tv_sec > tv.tv_sec) { memcpy(&save, next, sizeof(*next)); flag = 1; } else if (next->ut_tv.tv_sec == tv.tv_sec) { if (next->ut_tv.tv_usec > tv.tv_usec) { memcpy(&save, next, sizeof(*next)); flag = 1; } } counter++; next = getutid(&ut); } if (flag) { //printf("prev_runlevel=%c, runlevel=%c\n", save.ut_pid / 256, save.ut_pid % 256); runlevel = save.ut_pid % 256; } else { //printf("unknown\n"); runlevel = 'u'; } MUTEX_UNLOCK(utmp_lock); return runlevel; }
int main() { //从utmp文件中查找特定的记录 struct utmp ut,*u; ut.ut_type=RUN_LVL; while((u = getutid(&ut))) printf("%d %s %s %s\n",u->ut_type,u->ut_user,u->ut_line,u->ut_host); }
void deallocpty(void) { #ifndef NO_ROOT setutent(); myu.ut_type = DEAD_PROCESS; getutid(&myu); pututline(&myu); endutent(); #endif /*NO_ROOT*/ }
int get_boottime(struct timeval *tv) { struct utmp *ut, key; memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; if ((ut = getutid(&key)) != NULL) { tv->tv_sec = ut->ut_time; tv->tv_usec = 0; endutent(); } return ut != NULL; }
struct utmp * get_next_line(char *id, char *line) { struct utmp request; if (!id && !line) return getutent(); memset(&request, 0, sizeof(request)); if (line) { strncpy(&request.ut_line[0], line, UT_LINESIZE); return getutline(&request); } request.ut_type = INIT_PROCESS; strncpy(&request.ut_id[0], id, 4); return getutid(&request); }
bool get_boottime(struct timespec *ts) { struct utmp *ut, key; debug_decl(get_boottime, SUDOERS_DEBUG_UTIL) memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; setutent(); if ((ut = getutid(&key)) != NULL) { sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "BOOT_TIME: %lld", (long long)ut->ut_time); ts->tv_sec = ut->ut_time; ts->tv_nsec = 0; } endutent(); debug_return_bool(ut != NULL); }
void get_boot_time_1 (const char *filename, int newest) { struct utmp ut, *utp; int desc; if (filename) { /* On some versions of IRIX, opening a nonexistent file name is likely to crash in the utmp routines. */ desc = emacs_open (filename, O_RDONLY, 0); if (desc < 0) return; emacs_close (desc); utmpname (filename); } setutent (); while (1) { /* Find the next reboot record. */ ut.ut_type = BOOT_TIME; utp = getutid (&ut); if (! utp) break; /* Compare reboot times and use the newest one. */ if (utp->ut_time > boot_time) { boot_time = utp->ut_time; if (! newest) break; } /* Advance on element in the file so that getutid won't repeat the same one. */ utp = getutent (); if (! utp) break; } endutent (); }
struct utmp *pututline (const struct utmp *utmp_entry) { __UCLIBC_MUTEX_LOCK(utmplock); /* Ignore the return value. That way, if they've already positioned the file pointer where they want it, everything will work out. */ lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); if (getutid(utmp_entry) != NULL) { lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) return NULL; } else { lseek(static_fd, (off_t) 0, SEEK_END); if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) return NULL; } __UCLIBC_MUTEX_UNLOCK(utmplock); return (struct utmp *)utmp_entry; }
void mkutmp(char *name, int pty2, int uid, int gid) { char *line; char buf[255]; line = mtos(); strcpy(myu.ut_user, name); #ifdef linux strncpy(myu.ut_id,line+8,2); #else strncpy(myu.ut_id, line+12,2); #endif strcpy(buf, "/dev/tty"); strcat(buf, myu.ut_id); #ifdef linux strcpy(myu.ut_line, line+5); #else strcpy(myu.ut_line, line+9); #endif myu.ut_pid = getpid(); myu.ut_type = USER_PROCESS; myu.ut_time = time(NULL); #ifdef HAVE_UT_ADDR strcpy(myu.ut_host, "Queue process"); myu.ut_addr = 0L; #endif setutent(); getutid(&myu); pututline(&myu); fchown(pty2, uid, gid); fchmod(pty2, S_IRUSR|S_IWUSR); if(!strcmp(buf,"/dev/tty")) { syslog(LOG_ERR,"queue: pty.c: mkutmp: bug: buf equals /dev/tty."); } else { chown(buf, uid, gid); chmod(buf, S_IRUSR|S_IWUSR); } }
static int check_id (const char *id) { struct utmp *up; struct utmp ut; int n; setutent (); ut.ut_type = USER_PROCESS; strcpy (ut.ut_id, id); up = getutid (&ut); if (up == NULL) { printf ("cannot get entry for ID `%s' (%d)", id, errno); ++errors; return 1; } endutent (); for (n = 0; n < num_entries; n++) { if (strcmp (id, entry[n].ut_id) == 0) { if (memcmp (up, &entry[n], sizeof (struct utmp))) { printf ("UTMP entry does not match"); ++errors; return 1; } return 0; } } printf ("bogus entry for ID `%s'", id); ++errors; return 1; }
struct utmp *pututline(struct utmp *ut) { struct utmp *rec; setutent(); rec = getutid(ut); if (NULL == rec) { if (utmp_f_end >= MAX_ENT_COUNT) { errno = ENOMEM; return NULL; } utmp_f_pos = ++utmp_f_end; } rec = &utmp_f[--utmp_f_pos]; ++utmp_f_pos; return memcpy(rec, ut, sizeof(struct utmp)); }
static int check_type (int type) { struct utmp *up; struct utmp ut; int n; setutent (); ut.ut_type = type; up = getutid (&ut); if (up == NULL) { printf ("cannot get entry for type `%d' (%d)", type, errno); ++errors; return 1; } endutent (); for (n = 0; n < num_entries; n++) { if (type == entry[n].ut_type) { if (memcmp (up, &entry[n], sizeof (struct utmp))) { printf ("UTMP entry does not match"); ++errors; return 1; } return 0; } } printf ("bogus entry for type `%d'", type); ++errors; return 1; }
void get_boot_time_1 (const char *filename, bool newest) { struct utmp ut, *utp; if (filename) { /* On some versions of IRIX, opening a nonexistent file name is likely to crash in the utmp routines. */ if (faccessat (AT_FDCWD, filename, R_OK, AT_EACCESS) != 0) return; utmpname (filename); } setutent (); while (1) { /* Find the next reboot record. */ ut.ut_type = BOOT_TIME; utp = getutid (&ut); if (! utp) break; /* Compare reboot times and use the newest one. */ if (utp->ut_time > boot_time) { boot_time = utp->ut_time; if (! newest) break; } /* Advance on element in the file so that getutid won't repeat the same one. */ utp = getutent (); if (! utp) break; } endutent (); }
struct utmp * pututline(const struct utmp * utmp_entry) { struct utmp * ut; int xerrno=errno; #if 0 /* Ignore the return value. That way, if they've already positioned the file pointer where they want it, everything will work out. */ if (ut_fd!=-1) (void) lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); #endif if ((ut=getutid(utmp_entry))!=NULL) lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); else if( ut_fd==-1 ) return NULL; else lseek(ut_fd, (off_t) 0, SEEK_END); /* * At this point I could make sure the offset we're at is an exact multiple * of the sizeof struct utmp. Should I? Up or down? --RdB */ if (write(ut_fd, (char *) utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) return NULL; /* I think this final lseek gets the result Nat was after ... RdB */ lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); /* Ignoring untrapped errors */ errno=xerrno; return utmp_entry; }
int main (int argc, char **argv) { #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE) int utmp; #endif #ifndef USE_UTMPX int wtmp; #endif time_t current_time; #ifdef USE_UTMP struct utmp utmp_entry; #endif #ifdef USE_UTMPX struct utmpx utmpx_entry; #endif char * line = NULL; program_name = argv[0]; while (*++argv && **argv == '-') { switch (*++*argv) { case 'w': wtmp_file = getstring (&argv, &wflag); if (!strcmp (wtmp_file, "none")) wtmp_none = 1; #if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX) else wtmpx_file = wtmp_file; #endif break; case 'u': utmp_file = getstring (&argv, &uflag); if (!strcmp (utmp_file, "none")) utmp_none = 1; #if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME) else utmpx_file = utmp_file; #endif break; #ifdef USE_LASTLOG case 'L': llog_file = getstring (&argv, &Lflag); if (!strcmp (llog_file, "none")) llog_none = 1; break; #endif case 't': ttys_file = getstring (&argv, &tflag); break; case 'l': line = getstring (&argv, &lflag); break; case 'h': host_name = getstring (&argv, &hflag); break; case 's': #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE) slot_number = atoi (getstring (&argv, &sflag)); #endif break; case 'x': xservers_file = getstring (&argv, &xflag); break; case 'a': aflag++; break; case 'd': dflag++; break; case 'V': printf("%s\n", PACKAGE_STRING); exit (0); default: fprintf (stderr, "%s: unrecognized option '%s'\n", program_name, argv[0]); usage (1); } } user_name = *argv++; if (user_name == NULL) { fprintf (stderr, "%s: missing required user-name argument\n", program_name); usage (1); } if (*argv != NULL) { fprintf (stderr, "%s: unrecognized argument '%s'\n", program_name, argv[0]); usage (1); } /* * complain if neither aflag nor dflag are set, * or if both are set. */ if (!(aflag ^ dflag)) { fprintf (stderr, "%s: must specify exactly one of -a or -d\n", program_name); usage (1); } if (xflag && !lflag) { fprintf (stderr, "%s: must specify -l when -x is used\n", program_name); usage (1); } /* set up default file names */ if (!wflag) { wtmp_file = WTMP_FILE; #if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX) wtmpx_file = WTMPX_FILE; #endif } if (!uflag) { utmp_file = UTMP_FILE; #if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME) utmpx_file = UTMPX_FILE; #endif } #ifdef USE_LASTLOG if (!Lflag) llog_file = LLOG_FILE; #endif #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE) if (!tflag) ttys_file = TTYS_FILE; if (!sflag && !utmp_none) { if (xflag) sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot"); else sysnerr (slot_number = ttyslot (), "ttyslot"); } #endif if (!lflag) { sysnerr ((line = ttyname (0)) != NULL, "ttyname"); if (strncmp(line, "/dev/", 5) == 0) line += 5; } time (¤t_time); #ifdef USE_UTMP set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag); #endif #ifdef USE_UTMPX /* need to set utmpxname() before calling set_utmpx() for UtmpxIdOpen to work */ # ifdef HAVE_UTMPXNAME if (utmpx_file != NULL) { utmpxname (utmpx_file); } # endif set_utmpx (&utmpx_entry, line, user_name, host_name, current_time, aflag); #endif if (!utmp_none) { #ifdef USE_UTMPX # ifdef HAVE_UTMPXNAME if (utmpx_file != NULL) # endif { setutxent (); (void) getutxid (&utmpx_entry); pututxline (&utmpx_entry); endutxent (); } #endif #ifdef USE_UTMP # ifdef HAVE_PUTUTLINE utmpname (utmp_file); setutent (); (void) getutid (&utmp_entry); pututline (&utmp_entry); endutent (); # else utmp = open (utmp_file, O_RDWR); if (utmp != -1) { syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek"); sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry)) == sizeof (utmp_entry), "write utmp entry"); close (utmp); } # endif #endif /* USE_UTMP */ } if (!wtmp_none) { #ifdef USE_UTMPX # ifdef HAVE_UPDWTMPX if (wtmpx_file != NULL) { updwtmpx(wtmpx_file, &utmpx_entry); } # endif #else wtmp = open (wtmp_file, O_WRONLY|O_APPEND); if (wtmp != -1) { sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry)) == sizeof (utmp_entry), "write wtmp entry"); close (wtmp); } #endif } #ifdef USE_LASTLOG if (aflag && !llog_none) { int llog; struct passwd *pwd = getpwnam(user_name); sysnerr( pwd != NULL, "get user id"); llog = open (llog_file, O_RDWR); if (llog != -1) { struct lastlog ll; sysnerr (lseek(llog, (long) (pwd->pw_uid*sizeof(ll)), 0) != -1, "seeking lastlog entry"); memset(&ll, 0, sizeof(ll)); ll.ll_time = current_time; if (line) (void) strncpy (ll.ll_line, line, sizeof (ll.ll_line)); if (host_name) (void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host)); sysnerr (write (llog, (char *) &ll, sizeof (ll)) == sizeof (ll), "write lastlog entry"); close (llog); } } #endif return 0; }
/*************************************************************************** * * Account * * update utmp/wtmp files. ***************************************************************************/ void Account( struct display *d, char *user, char *line, pid_t pid, #if NeedWidePrototypes int type, #else short type, #endif /* NeedWidePrototypes */ waitType exitcode ) { #if !defined(CSRG_BASED) /* we cannot do this on BSD ... */ struct utmp utmp; /* local struct for new entry */ struct utmp *u; /* pointer to entry in utmp file */ int fd; char buf[32]; char* user_str = user ? user : "******"; char* line_str = line ? line : "NULL"; #ifdef __PASSWD_ETC struct rtmp rtmp; struct rtmp *r; int tty_slot; int rtmp_fd; #endif if (d->utmpId == NULL) return; switch (type) { case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break; case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break; case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break; case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break; default: strcpy(buf, "UNKNOWN"); break; } Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n", d->utmpId, user_str, line_str, pid, buf); #ifdef PAM PamAccounting("dtlogin", d->name, d->utmpId, user, line, pid, type, exitcode); #else # ifdef SUNAUTH solaris_accounting("dtlogin", d->name, d->utmpId, user, line, pid, type, exitcode); # endif #endif #ifdef sun return; #else bzero(&utmp, sizeof(struct utmp)); strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id)); utmp.ut_type = LOGIN_PROCESS; setutent(); if ( (u = getutid(&utmp)) == NULL ) u = &utmp; /* * make sure process ID's match if this is DEAD_PROCESS... * don't update an already DEAD_PROCESS... */ if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) || (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) { endutent(); return; } /* * fill in required fields of utmp structure... * * Note: for USER_PRCESS the "e_exit" field is overloaded to contain * the method for counting this user. This is used later to * determine if restricted user licenses have been exceeded. * Currently, an unlimited number of foreign displays can log in. */ if (user) strncpy(u->ut_user, user, sizeof(u->ut_user)); if (line) { #ifdef _AIX /* For AIX the Init process writes the exact mapped device name for console to the utmp file (like hft/0), if a getty on /dev/console record exists in the Inittab file.Hitherto, we need to have a similar logic to make sure for having the correct entry in the utmp file in order for the correct operation of the GettyRunning function. It should be noted that by having the correct value in the d->gettyLine field, the utmp file eventuallly updated by the Account function in dm.c will have the right value. And thus the GettyRunning function returns the appropriate value. So, it is important that the following logic be included here for AIX platform only. Raghu Krovvidi 07.06.93 */ if (!strcmp(line,"console")) { char *ttynm; int fd=0; fd = open("/dev/console",O_RDONLY); ttynm = ttyname(fd); ttynm += 5; strcpy(u->ut_line,ttynm); close(fd); } else strncpy(u->ut_line, line, sizeof(u->ut_line)); #else strncpy(u->ut_line, line, sizeof(u->ut_line)); #endif } if (pid ) u->ut_pid = pid; if (type) { u->ut_type = type; if (type == DEAD_PROCESS) { u->ut_exit.e_termination = waitSig(exitcode); u->ut_exit.e_exit = waitCode(exitcode); #ifndef SVR4 (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host)); #endif } if (type == LOGIN_PROCESS && d->displayType.location != Local ) { #ifndef SVR4 strncpy(u->ut_host, d->name, sizeof(u->ut_host)); #endif #ifdef __hpux u->ut_addr = 0; #endif } if (type == USER_PROCESS) u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 ); } (void) time(&u->ut_time); /* * write to utmp... * * (Do not close utmp yet. If "u" points to the static structure, it is * cleared upon close. This does not bode well for the following write * to wtmp!) */ pututline(u); /* * write the same entry to wtmp... */ if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) { write(fd, u, sizeof(utmp)); close(fd); } /* * close utmp... */ endutent(); #ifdef __PASSWD_ETC /* Now fill in the "rgy utmp" struct */ if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line)); bzero(rtmp.rt_host, sizeof(rtmp.rt_host)); rtmp.rt_time = u->ut_time; r = &rtmp; /* Write entry to rtmp */ tty_slot = ttyslot(); if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) { lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0); write(rtmp_fd, (char *) r, sizeof(struct rtmp)); close(rtmp_fd); } #endif #if defined(AIXV3) && !defined(_POWER) /* Log the lastlogin data .. RK 09.13.93 */ /** in AIX 4.1 this is taken care of during authentication **/ if(type == USER_PROCESS) { int loginType; char tempTtyName[128]; char *hostname; GetLoginInfo(d, &loginType, tempTtyName, &hostname); time(&last_login.stime); if(line) { Debug("tty_last_login is (line=%s)\n",line); last_login.stty = (char *)malloc(strlen(line) + 1); strcpy(last_login.stty,line); } else { last_login.stty = (char *)malloc(strlen(tempTtyName) + 1); strcpy(last_login.stty,tempTtyName); } last_login.shost = (char *) malloc (MAXHOSTNAMELEN); if (hostname == NULL) { gethostname (last_login.shost , MAXHOSTNAMELEN); } else { strncpy(last_login.shost, hostname, MAXHOSTNAMELEN); last_login.shost[MAXHOSTNAMELEN -1] = '\0'; } Debug("logging lastlogin entry (user=%s)\n",user); dt_lastlogin(user,&last_login); free(last_login.stty); free(last_login.shost); } #endif #endif /* !sun */ #endif /* !CSRG_BASED */ }
/* 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 }
/* 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 */ }
/* * Update wtmp and utmp logs. */ static void log_utmp(struct login_context *cxt) { struct utmp ut; struct utmp *utp; struct timeval tv; utmpname(_PATH_UTMP); setutent(); /* 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 = getutent())) 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) { setutent(); ut.ut_type = LOGIN_PROCESS; strncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); utp = getutline(&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) { setutent(); ut.ut_type = DEAD_PROCESS; strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id)); utp = getutid(&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) strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id)); if (cxt->username) strncpy(ut.ut_user, cxt->username, sizeof(ut.ut_user)); if (cxt->tty_name) xstrncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); #ifdef _HAVE_UT_TV /* in <utmpbits.h> included by <utmp.h> */ gettimeofday(&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; #else { time_t t; time(&t); ut.ut_time = t; /* ut_time is not always a time_t */ /* glibc2 #defines it as ut_tv.tv_sec */ } #endif ut.ut_type = USER_PROCESS; ut.ut_pid = cxt->pid; if (cxt->hostname) { xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host)); if (*cxt->hostaddress) memcpy(&ut.ut_addr_v6, cxt->hostaddress, sizeof(ut.ut_addr_v6)); } pututline(&ut); endutent(); updwtmp(_PATH_WTMP, &ut); }
/* * 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; }
/* * 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 }
/* 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 }
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 }