/* * Log failed login attempts in _PATH_BTMP if that exists. */ static void log_btmp(struct passwd const* pw) { struct utmp ut; struct timeval tv; const char* tty_name, *tty_num; memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_user, pw && pw->pw_name ? pw->pw_name : "(unknown)", sizeof(ut.ut_user)); get_terminal_name(STDERR_FILENO, NULL, &tty_name, &tty_num); if (tty_num) { xstrncpy(ut.ut_id, tty_num, sizeof(ut.ut_id)); } if (tty_name) { xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line)); } #if defined(_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 */ } #endif ut.ut_type = LOGIN_PROCESS; /* XXX doesn't matter */ ut.ut_pid = getpid(); updwtmp(_PATH_BTMP, &ut); }
static void logbtmp(const char *line, const char *username, const char *hostname) { struct utmp ut; memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_user, username ? username : "******", sizeof(ut.ut_user)); strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); xstrncpy(ut.ut_line, line, sizeof(ut.ut_line)); #if defined(_HAVE_UT_TV) /* in <utmpbits.h> included by <utmp.h> */ gettimeofday(&ut.ut_tv, NULL); #else { time_t t; time(&t); ut.ut_time = t; /* ut_time is not always a time_t */ } #endif ut.ut_type = LOGIN_PROCESS; /* XXX doesn't matter */ ut.ut_pid = pid; if (hostname) { xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); if (hostaddress[0]) memcpy(&ut.ut_addr, hostaddress, sizeof(ut.ut_addr)); } #if HAVE_UPDWTMP /* bad luck for ancient systems */ updwtmp(_PATH_BTMP, &ut); #endif }
void logwtmp (const char *line, const char *name, const char *host) { struct utmp ut; /* Set information in new entry. */ memset (&ut, 0, sizeof (ut)); #if _HAVE_UT_PID - 0 ut.ut_pid = getpid (); #endif #if _HAVE_UT_TYPE - 0 ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS; #endif strncpy (ut.ut_line, line, sizeof ut.ut_line); strncpy (ut.ut_name, name, sizeof ut.ut_name); #if _HAVE_UT_HOST - 0 strncpy (ut.ut_host, host, sizeof ut.ut_host); #endif #if _HAVE_UT_TV - 0 struct timeval tv; __gettimeofday (&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; #else ut.ut_time = time (NULL); #endif updwtmp (_PATH_WTMP, &ut); }
void setutmp (const char *name, const char *line, const char *host) { utent.ut_type = USER_PROCESS; strncpy (utent.ut_user, name, sizeof utent.ut_user); utent.ut_time = time (NULL); /* other fields already filled in by checkutmp above */ setutent (); pututline (&utent); endutent (); updwtmp (_WTMP_FILE, &utent); }
/* This is enabled in uClibc/libutil/logwtmp.c */ void logwtmp (const char *line, const char *name, const char *host) { struct utmp lutmp; memset(&lutmp, 0, sizeof(lutmp)); lutmp.ut_type = (name && *name) ? USER_PROCESS : DEAD_PROCESS; lutmp.ut_pid = getpid(); strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); gettimeofday(&(lutmp.ut_tv), NULL); updwtmp(_PATH_WTMP, &lutmp); }
static void setutmp(const char *name, const char *line) { utent.ut_type = USER_PROCESS; strncpy(utent.ut_user, name, sizeof utent.ut_user); time(&utent.ut_time); /* other fields already filled in by checkutmp above */ setutent(); pututline(&utent); endutent(); if (access(_PATH_WTMP, R_OK|W_OK) == -1) { close(creat(_PATH_WTMP, 0664)); } updwtmp(_PATH_WTMP, &utent); }
/* Write the given entry into utmp and wtmp. * Note: the match in utmp is done against ut_id field, * which is NOT set by this function - caller must set it. */ void login(const struct utmp *entry) { struct utmp copy; char tty_name[sizeof(copy.ut_line) + 6]; int fd; // Manpage: // login() takes the argument ut struct, fills the field ut->ut_type // (if there is such a field) with the value USER_PROCESS, // and fills the field ut->ut_pid (if there is such a field) // with the process ID of the calling process. copy = *entry; #if _HAVE_UT_TYPE - 0 copy.ut_type = USER_PROCESS; #endif #if _HAVE_UT_PID - 0 copy.ut_pid = getpid(); #endif // Then it tries to fill the field ut->ut_line. It takes the first of stdin, // stdout, stderr that is a tty, and stores the corresponding pathname minus // a possible leading /dev/ into this field, and then writes the struct // to the utmp file. On the other hand, if no tty name was found, // this field is filled with "???" and the struct is not written // to the utmp file. fd = 0; while (fd != 3 && ttyname_r(fd, tty_name, sizeof(tty_name)) != 0) fd++; if (fd != 3) { if (strncmp(tty_name, "/dev/", 5) == 0) strncpy(copy.ut_line, tty_name + 5, sizeof(copy.ut_line)-1); else strncpy(copy.ut_line, tty_name, sizeof(copy.ut_line)-1); copy.ut_line[sizeof(copy.ut_line)-1] = '\0'; /* utmpname(_PATH_UTMP); - why? * this makes it impossible for caller to use other file! * Does any standard or historical precedent says this must be done? */ setutent(); /* Replaces record with matching ut_id, or appends new one: */ pututline(©); endutent(); } else { strncpy(copy.ut_line, "???", sizeof(copy.ut_line)); } // After this, the struct is written to the wtmp file. updwtmp(_PATH_WTMP, ©); }
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 */ }
/* * setutmp - Update an entry in utmp and log an entry in wtmp * * Return 1 on failure and 0 on success. */ int setutmp (struct utmp *ut) { int err = 0; assert (NULL != ut); setutent (); if (pututline (ut) == NULL) { err = 1; } endutent (); updwtmp (_WTMP_FILE, ut); return err; }
/* * write_utent - put a USER_PROCESS entry in the utmp file * * write_utent changes the type of the current utmp entry to * USER_PROCESS. the wtmp file will be updated as well. */ static void write_utent(struct utmp *utptr, const char *username) { utptr->ut_type = USER_PROCESS; strncpy(utptr->ut_user, username, sizeof(utptr->ut_user)); utptr->ut_tv.tv_sec = time(NULL); /* other fields already filled in by read_or_build_utent above */ setutent(); pututline(utptr); endutent(); #if ENABLE_FEATURE_WTMP if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) { close(creat(bb_path_wtmp_file, 0664)); } updwtmp(bb_path_wtmp_file, utptr); #endif }
static void write_wtmp(void) { struct utmp utmp; struct utsname uts; /* "man utmp" says wtmp file should *not* be created automagically */ /*if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) { close(creat(bb_path_wtmp_file, 0664)); }*/ memset(&utmp, 0, sizeof(utmp)); utmp.ut_tv.tv_sec = time(NULL); strcpy(utmp.ut_user, "shutdown"); /* it is wide enough */ utmp.ut_type = RUN_LVL; utmp.ut_id[0] = '~'; utmp.ut_id[1] = '~'; /* = strcpy(utmp.ut_id, "~~"); */ utmp.ut_line[0] = '~'; utmp.ut_line[1] = '~'; /* = strcpy(utmp.ut_line, "~~"); */ uname(&uts); safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host)); updwtmp(bb_path_wtmp_file, &utmp); }
void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname) { struct utmp utent; char *id; unsigned width; memset(&utent, 0, sizeof(utent)); utent.ut_pid = pid; utent.ut_type = new_type; tty_name = skip_dev_pfx(tty_name); safe_strncpy(utent.ut_line, tty_name, sizeof(utent.ut_line)); if (username) safe_strncpy(utent.ut_user, username, sizeof(utent.ut_user)); if (hostname) safe_strncpy(utent.ut_host, hostname, sizeof(utent.ut_host)); utent.ut_tv.tv_sec = time(NULL); /* Invent our own ut_id. ut_id is only 4 chars wide. * Try to fit something remotely meaningful... */ id = utent.ut_id; width = sizeof(utent.ut_id); if (tty_name[0] == 'p') { /* if "ptyXXX", map to "pXXX" */ /* if "pts/XX", map to "p/XX" */ *id++ = 'p'; width--; } /* else: usually it's "ttyXXXX", map to "XXXX" */ if (strlen(tty_name) > 3) tty_name += 3; strncpy(id, tty_name, width); touch(_PATH_UTMP); //utmpname(_PATH_UTMP); setutent(); /* Append new one (hopefully, unless we collide on ut_id) */ pututline(&utent); endutent(); #if ENABLE_FEATURE_WTMP /* "man utmp" says wtmp file should *not* be created automagically */ /*touch(bb_path_wtmp_file);*/ updwtmp(bb_path_wtmp_file, &utent); #endif }
static void utmp_log (int login) { char id[UT_LINESIZE + 1]; struct utmp ut; struct timeval tv; int pid; pid = getpid (); snprintf (id, UT_LINESIZE, "%d", pid); assert (pwd != NULL); utmpname (_PATH_UTMP); setutent (); memset (&ut, 0, sizeof(ut)); strncpy (ut.ut_id, id, sizeof (ut.ut_id)); ut.ut_id[sizeof (ut.ut_id) - 1] = 0; ut.ut_line[0] = 0; if (login) { strncpy (ut.ut_user, pwd->pw_name, sizeof(ut.ut_user)); ut.ut_user[sizeof (ut.ut_user) - 1] = 0; strncpy (ut.ut_host, rhost, sizeof(ut.ut_host)); ut.ut_host[sizeof (ut.ut_host) - 1] = 0; } gettimeofday (&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; ut.ut_type = login ? LOGIN_PROCESS : DEAD_PROCESS; ut.ut_pid = pid; pututline (&ut); endutent (); updwtmp (_PATH_WTMP, &ut); }
/* * Logs failed login attempts in _PATH_BTMP, if it exists. * Must be called only with username the name of an actual user. * The most common login failure is to give password instead of username. */ static void log_btmp(struct login_context *cxt) { struct utmp ut; #if defined(_HAVE_UT_TV) /* in <utmpbits.h> included by <utmp.h> */ struct timeval tv; #endif memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_user, cxt->username ? cxt->username : "******", sizeof(ut.ut_user)); if (cxt->tty_number) strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id)); if (cxt->tty_name) xstrncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); #if defined(_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 */ } #endif ut.ut_type = LOGIN_PROCESS; /* XXX doesn't matter */ 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)); } updwtmp(_PATH_BTMP, &ut); }
/**************************************************************************** * write a utmp entry to the utmp file ***************************************************************************/ int write_utmp(struct utmp * u) { int pos; // regain root privileges seteuid(0); utmpname(UTMP); setutent(); pututline(u); endutent(); updwtmp(WTMP_FILE, u); pos = (int)NULL; madeutent = 1; // drop root privileges again seteuid(getuid()); return(pos); }
/* * there is a nice function "endutent" defined in <utmp.h>; * like "setutent" it takes no arguments, so I think it gets all information * from library-calls. * That's why "setutent" has to be called by the child-process with * file-descriptors 0/1 set to the pty. But that child execs to the * application-program and therefore can't clean it's own utmp-entry!(?) * The master on the other hand doesn't have the correct process-id * and io-channels... I'll do it by hand: * (what's the position of the utmp-entry, the child wrote? :-) */ void cleanutent() { int pid; struct utmp *u; // regain root privileges seteuid(0); utmpname(UTMP); setutent(); pid = getpid(); /* The following 11 lines of code were copied from the * poeigl-1.20 login/init package. Special thanks to * poe for the code examples. */ while((u = getutent())) { if(u->ut_pid == pid) { time(&u->ut_time); #ifdef SVR4 memset(&u->ut_user, 0, sizeof(u->ut_user)); #else memset(&u->ut_user, 0, sizeof(u->ut_user)); memset(&u->ut_host, 0, sizeof(u->ut_host)); #endif u->ut_type = DEAD_PROCESS; u->ut_pid = 0; #if !defined(SVR4) && !defined(AIXV3) u->ut_addr = 0; #endif pututline(u); /* Was reversed with in the original */ endutent(); updwtmp(WTMP_FILE, u); } } // drop root privileges again seteuid(getuid()); }
static void utmp_log (int login) { struct utmp ut; struct timeval tv; int pid = getpid (); const char *id = line + strlen (line) - sizeof(ut.ut_id); utmpname (_PATH_UTMP); setutent (); memset (&ut, 0, sizeof(ut)); strncpy (ut.ut_id, id, sizeof (ut.ut_id)); ut.ut_id[sizeof (ut.ut_id) - 1] = 0; strncpy (ut.ut_line, line, sizeof (ut.ut_line)); ut.ut_line[sizeof (ut.ut_line) - 1] = 0; if (login) { strncpy (ut.ut_user, user, sizeof(ut.ut_user)); ut.ut_user[sizeof (ut.ut_user) - 1] = 0; strncpy (ut.ut_host, rhost, sizeof(ut.ut_host)); ut.ut_host[sizeof (ut.ut_host) - 1] = 0; } gettimeofday (&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; ut.ut_type = login ? USER_PROCESS : DEAD_PROCESS; ut.ut_pid = pid; pututline (&ut); endutent (); updwtmp (_PATH_WTMP, &ut); }
void logwtmp(const char *line, const char *name, const char *host) { struct utmp ut; memset(&ut, 0, sizeof(struct utmp)); ut.ut_pid = getpid (); ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS; memccpy (ut.ut_line, line, 0, sizeof ut.ut_line); memccpy (ut.ut_name, name, 0, sizeof ut.ut_name); memccpy (ut.ut_host, host, 0, sizeof ut.ut_host); if (sizeof(ut.ut_tv) == sizeof(struct timeval)) gettimeofday((struct timeval *)&ut.ut_tv, NULL); else { struct timeval tv; gettimeofday(&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec; } updwtmp (_PATH_WTMP, &ut); }
void logwtmp (const char *line, const char *name, const char *host) { struct utmp lutmp; memset (&(lutmp), 0, sizeof (struct utmp)); lutmp.ut_type = (name && *name)? USER_PROCESS : DEAD_PROCESS; lutmp.ut_pid = getpid(); strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); #if __WORDSIZE_COMPAT32 == 0 gettimeofday(&(lutmp.ut_tv), NULL); #else { struct timeval tv; gettimeofday (&tv, NULL); lutmp.ut_tv.tv_sec = tv.tv_sec; lutmp.ut_tv.tv_usec = tv.tv_usec; } #endif updwtmp(_PATH_WTMP, &(lutmp)); }
/* 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 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); }
/* 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 }
/* 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 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; }
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 }
/* * 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 }
void login (const struct utmp *ut) { #ifdef PATH_MAX char _tty[PATH_MAX + UT_LINESIZE]; #else char _tty[512 + UT_LINESIZE]; #endif char *tty = _tty; int found_tty; const char *ttyp; struct utmp copy = *ut; /* Fill in those fields we supply. */ #if _HAVE_UT_TYPE - 0 copy.ut_type = USER_PROCESS; #endif #if _HAVE_UT_PID - 0 copy.ut_pid = getpid (); #endif /* Seek tty. */ found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty)); if (found_tty < 0) found_tty = tty_name (STDOUT_FILENO, &tty, sizeof (_tty)); if (found_tty < 0) found_tty = tty_name (STDERR_FILENO, &tty, sizeof (_tty)); if (found_tty >= 0) { /* We only want to insert the name of the tty without path. But take care of name like /dev/pts/3. */ if (strncmp (tty, "/dev/", 5) == 0) ttyp = tty + 5; /* Skip the "/dev/". */ else ttyp = basename (tty); /* Position to record for this tty. */ strncpy (copy.ut_line, ttyp, UT_LINESIZE); /* Tell that we want to use the UTMP file. */ if (utmpname (_PATH_UTMP) == 0) { /* Open UTMP file. */ setutent (); /* Write the entry. */ pututline (©); /* Close UTMP file. */ endutent (); } if (tty != _tty) free (tty); /* Free buffer malloced by tty_name. */ } else /* We provide a default value so that the output does not contain an random bytes in this field. */ strncpy (copy.ut_line, "???", UT_LINESIZE); /* Update the WTMP file. Here we have to add a new entry. */ updwtmp (_PATH_WTMP, ©); }
void setutmp(const char *name, const char *line) { struct utmp utmp; int fd; int found = 0; if ((fd = open(_UTMP_FILE, O_RDWR)) < 0) return; #if !defined(SUN) && !defined(BSD) && !defined(SUN4) /* XXX */ while (!found && read(fd, (char *)&utmp, sizeof utmp) == sizeof utmp) { if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line)) found++; } #endif if (! found) { /* * This is a brand-new entry. Clear it out and fill it in * later. */ memzero(&utmp, sizeof utmp); strncpy(utmp.ut_line, line, (int) sizeof utmp.ut_line); } /* * Fill in the parts of the UTMP entry. BSD has just the name, * while System V has the name, PID and a type. */ strncpy(utmp.ut_user, name, sizeof utent.ut_user); #ifdef USER_PROCESS utmp.ut_type = USER_PROCESS; utmp.ut_pid = getpid (); #endif /* * Put in the current time (common to everyone) */ (void) time (&utmp.ut_time); #ifdef UT_HOST /* * Update the host name field for systems with networking support */ (void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host); #endif /* * Locate the correct position in the UTMP file for this * entry. */ #ifdef HAVE_TTYSLOT (void) lseek (fd, (off_t) (sizeof utmp) * ttyslot (), SEEK_SET); #else if (found) /* Back up a splot */ lseek (fd, (off_t) - sizeof utmp, SEEK_CUR); else /* Otherwise, go to the end of the file */ lseek (fd, (off_t) 0, SEEK_END); #endif /* * Scribble out the new entry and close the file. We're done * with UTMP, next we do WTMP (which is real easy, put it on * the end of the file. */ (void) write (fd, (char *) &utmp, sizeof utmp); (void) close (fd); updwtmp(_WTMP_FILE, &utmp); utent = utmp; }
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 }