static void cleanup_utmp(void) { #ifndef OMIT_UTMP FILE *wtmp; time_t uttime; if (!pty_stamped_utmp) return; utmp_entry.ut_type = DEAD_PROCESS; memset(utmp_entry.ut_user, 0, lenof(utmp_entry.ut_user)); time(&uttime); utmp_entry.ut_time = uttime; if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); fclose(wtmp); } memset(utmp_entry.ut_line, 0, lenof(utmp_entry.ut_line)); utmp_entry.ut_time = 0; #if defined HAVE_PUTUTLINE utmpname(UTMP_FILE); setutent(); pututline(&utmp_entry); endutent(); #endif pty_stamped_utmp = 0; /* ensure we never double-cleanup */ #endif }
static int count_users(void) { int total = 0; #if HAVE_UTMPX_H #define setutent setutxent #define pututline pututxline #define getutent getutxent #define endutent endutxent struct utmpx *utmp_p; #else struct utmp *utmp_p; #endif setutent(); while ((utmp_p = getutent()) != NULL) { #ifndef UTMP_HAS_NO_TYPE if (utmp_p->ut_type != USER_PROCESS) continue; #endif #ifndef UTMP_HAS_NO_PID /* This block of code fixes zombie user PIDs in the utmp/utmpx file that would otherwise be counted as a current user */ if (kill(utmp_p->ut_pid, 0) == -1 && errno == ESRCH) { utmp_p->ut_type = DEAD_PROCESS; pututline(utmp_p); continue; } #endif ++total; } endutent(); return total; }
static int clear_utmp(struct initpid *ip, uint16_t count, pid_t pid) { uint16_t i; for (i = 0; i < count; i++) { if (ip->pid == pid) { uint8_t *p = initpid[i].id; /* Clear the utmp entry */ ut.ut_pid = 1; ut.ut_type = INIT_PROCESS; *ut.ut_line = 0; ut.ut_id[0] = p[1]; ut.ut_id[1] = p[2]; *ut.ut_user = 0; pututline(&ut); /* Mark as done */ initpid[i].pid = 0; /* Respawn the task if appropriate */ if ((p[3] & (1 << runlevel)) && p[4] == INIT_RESPAWN) initpid[i].pid = spawn_process(p, 0); return 0; } ip++; } return -1; }
/* * Clear any dead processes */ static void clear_zombies(int flags) { int i; pid_t pid = waitpid(-1, NULL, flags); /* Interrupted ? */ if (pid < 0) return; /* See if we care what died. If we do then also check that * do not need to respawn it */ for (i = 0; i < initcount; i++) { if (initpid[i] == pid) { uint8_t *p = initptr[i]; /* Clear the utmp entry */ ut.ut_pid = 1; ut.ut_type = INIT_PROCESS; *ut.ut_line = 0; ut.ut_id[0] = p[1]; ut.ut_id[1] = p[2]; *ut.ut_user = 0; pututline(&ut); /* Mark as done */ initpid[i] = 0; /* Respawn the task if appropriate */ if ((p[3] & (1 << runlevel)) && p[4] == INIT_RESPAWN) initpid[i] = spawn_process(p, 0); break; } } }
static void makeutmp(int runlevel) { D_("Making utmp file for runlevel %d\n", runlevel); struct utmp utmp; time_t t; /* * this is created by bootmisc, if this isn't there we can't set * runlevel. */ if (access(UTMP_FILE, F_OK) < 0) { F_("/var/run/utmp does not exist, this should be created by " "bootmisc.i\n"); return; } /* TODO, is this a good idea or a bad idea? utmpname("/var/run/utmp"); */ setutent(); memset(&utmp, 0, sizeof(utmp)); utmp.ut_type = RUN_LVL; utmp.ut_pid = ('#' << 8) + runlevel + '0'; time(&t); utmp.ut_time = (int)t; if (!pututline(&utmp)) { F_("pututline failed\n"); endutent(); return; } endutent(); return; }
static void _add_utmp(TE_Pty* pty, int spid) { memset(&pty->ut_entry, 0, sizeof(pty->ut_entry) ); #if 0 pty->ut_entry.ut_type = USER_PROCESS; pty->ut_entry.ut_pid = spid; // strcpy(pty->ut_entry.ut_line, pty->ptyname+5); // printf("ut name \"%s\" (%d)\n", pty->ut_entry.ut_user, getuid()); #ifdef __APPLE__ // strcpy(pty->ut_entry.ut_id, pty->ptyname+8); strcpy(pty->ut_entry.ut_user, getpwuid(getuid())->pw_name); gettimeofday(&pty->ut_entry.ut_tv, NULL); setutxent(); pututxline(&pty->ut_entry); endutxent(); #else strcpy(pty->ut_entry.ut_host, getenv("DISPLAY")); time_t tt; time(&tt); pty->ut_entry.ut_time = tt; pty->ut_entry.ut_addr = 0; setutent(); pututline(&pty->ut_entry); endutent(); #endif #endif }
void utmp_login(char *tty, const char *username, const char *hostname) { struct utmp utmp; int fd; prepare_utmp (&utmp, tty, username, hostname); #ifdef HAVE_SETUTENT utmpname(_PATH_UTMP); setutent(); pututline(&utmp); endutent(); #else #ifdef HAVE_TTYSLOT { int ttyno; ttyno = ttyslot(); if (ttyno > 0 && (fd = open(_PATH_UTMP, O_WRONLY, 0)) >= 0) { lseek(fd, (long)(ttyno * sizeof(struct utmp)), SEEK_SET); write(fd, &utmp, sizeof(struct utmp)); close(fd); } } #endif /* HAVE_TTYSLOT */ #endif /* HAVE_SETUTENT */ if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { write(fd, &utmp, sizeof(struct utmp)); close(fd); } }
static int simulate_logout (const char *line) { int n; for (n = 0; n < num_entries; n++) { if (strcmp (line, entry[n].ut_line) == 0) { entry[n].ut_type = DEAD_PROCESS; strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user)); #if _HAVE_UT_TV - 0 || defined UTMPX entry[n].ut_tv.tv_sec = (entry_time += 1000); #else entry[n].ut_time = (entry_time += 1000); #endif setutent (); if (pututline (&entry[n]) == NULL) { perror("cannot write UTMP entry"); ++errors; return 1; } endutent (); return 0; } } printf ("no entry found for `%s'", line); ++errors; return 1; }
static pid_t spawn_process(uint8_t * p, uint8_t wait) { static const char *args[MAX_ARGS + 3]; uint8_t *dp = p + 5; uint8_t *ep = p + *p - 1; /* -1 as there is a final \0 */ pid_t pid; int an = 3; args[0] = "/bin/sh"; args[1] = "-c"; args[2] = dp; /* Set pointers to each string */ while (dp < ep) { if (*dp++ == 0 && an < MAX_ARGS) args[an++] = dp; } args[an] = NULL; /* Check for internal processes */ if (strcmp(args[2], "getty") == 0) pid = getty(args[3], p + 1); else { /* External */ pid = fork(); if (pid == -1) { perror("fork"); return 0; } if (pid == 0) { /* Child */ ut.ut_type = INIT_PROCESS; ut.ut_pid = getpid(); ut.ut_id[0] = p[1]; ut.ut_id[1] = p[2]; pututline(&ut); /* Don't leak utmp into the child */ endutent(); /* Run the child */ execv(args[2], (char**) (args + 2)); /* If it didn't look binary run it via the shell */ if (errno == ENOEXEC) execv("/bin/sh", (char**) args); /* Oh bugger */ perror(args[2]); exit(1); } } /* We need to force utmp closed otherwise we may end up fd sharing with our child and having our lseek() calls messed up. Or maybe it's time to support pread/pwrite ? */ endutent(); /* Let it complete if that is the instruction */ if (wait) { while (waitpid(pid, NULL, 0) != pid); return 0; } else return pid; }
static int utmp_write_library(struct logininfo *li, struct utmp *ut) { setutent(); pututline(ut); # ifdef HAVE_ENDUTENT endutent(); # endif return (1); }
static void spawn_login(struct passwd *pwd, const char *tty, const char *id) { char *p, buf[50]; /* utmp */ ut.ut_type = USER_PROCESS; ut.ut_pid = getpid(); strncpy(ut.ut_line, tty, UT_LINESIZE); strncpy(ut.ut_id, id, 2); time(&ut.ut_time); strncpy(ut.ut_user, pwd->pw_name, UT_NAMESIZE); pututline(&ut); /* Don't leak utmp into the child */ endutent(); /* We don't care if initgroups fails - it only grants extra rights */ //initgroups(pwd->pw_name, pwd->pw_gid); /* But we do care if these fail! */ if (setgid(pwd->pw_gid) == -1 || setuid(pwd->pw_uid) == -1) _exit(255); signal(SIGINT, SIG_DFL); /* setup user environment variables */ envset("LOGNAME", pwd->pw_name); envset("HOME", pwd->pw_dir); envset("SHELL", pwd->pw_shell); /* home directory */ if (chdir(pwd->pw_dir)) putstr("login: unable to change to home directory, using /\n"); /* show the motd file */ if (!showfile("/etc/motd")) crlf(); /* and spawn the shell */ strcpy(buf, "-"); if ((p = strrchr(pwd->pw_shell, '/')) != NULL) strcat(buf, ++p); else strcat(buf, pwd->pw_shell); argp[0] = buf; argp[1] = NULL; execve(pwd->pw_shell, (void *) argp, (void *) env); putstr("login: can't execute shell\n"); exit(1); }
int logout (const char *line) { struct UT tmp; struct UT *ut; int result = 0; /* if (utmpname (_PATH_UTMP) == -1) return 0; - why? * this makes it impossible for caller to use other file! * Does any standard or historical precedent says this must be done? */ /* Open UTMP file. */ setutent (); /* Fill in search information. */ #if _HAVE_UT_TYPE - 0 tmp.ut_type = USER_PROCESS; #endif strncpy (tmp.ut_line, line, sizeof tmp.ut_line); /* Read the record. */ if ((ut = getutline(&tmp)) != NULL) { /* Clear information about who & from where. */ memset (ut->ut_name, 0, sizeof ut->ut_name); #if _HAVE_UT_HOST - 0 memset (ut->ut_host, 0, sizeof ut->ut_host); #endif #if _HAVE_UT_TV - 0 # if !defined __WORDSIZE_TIME64_COMPAT32 gettimeofday (&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; } # endif #else time (&ut->ut_time); #endif #if _HAVE_UT_TYPE - 0 ut->ut_type = DEAD_PROCESS; #endif if (pututline (ut) != NULL) result = 1; } /* Close UTMP file. */ endutent (); return result; }
int main() { //将utmp记录写入文件 struct utmp ut; ut.ut_type = USER_PROCESS; ut.ut_pid = getpid(); strcpy(ut.ut_user,"kids"); strcpy(ut.ut_line,"pts/1"); strcpy(ut.ut_host,"www.gun.org"); pututline(&ut); }
void deallocpty(void) { #ifndef NO_ROOT setutent(); myu.ut_type = DEAD_PROCESS; getutid(&myu); pututline(&myu); endutent(); #endif /*NO_ROOT*/ }
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); }
void runlevel_set(int pre, int now) { struct utmp utent; utent.ut_type = RUN_LVL; utent.ut_pid = (encode(pre) << 8) | (encode(now) & 0xFF); strlcpy(utent.ut_user, "runlevel", sizeof(utent.ut_user)); setutent(); pututline(&utent); endutent(); }
static void setup_utmp(char *ttyname, char *location) { #ifndef OMIT_UTMP #ifdef HAVE_LASTLOG struct lastlog lastlog_entry; FILE *lastlog; #endif struct passwd *pw; FILE *wtmp; time_t uttime; pw = getpwuid(getuid()); memset(&utmp_entry, 0, sizeof(utmp_entry)); utmp_entry.ut_type = USER_PROCESS; utmp_entry.ut_pid = getpid(); strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line)); strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id)); strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user)); strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host)); /* Apparently there are some architectures where (struct utmp).ut_time * is not essentially time_t (e.g. Linux amd64). Hence the temporary. */ time(&uttime); utmp_entry.ut_time = uttime; /* may truncate */ #if defined HAVE_PUTUTLINE utmpname(UTMP_FILE); setutent(); pututline(&utmp_entry); endutent(); #endif if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); fclose(wtmp); } #ifdef HAVE_LASTLOG memset(&lastlog_entry, 0, sizeof(lastlog_entry)); strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line)); strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host)); time(&lastlog_entry.ll_time); if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) { fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET); fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog); fclose(lastlog); } #endif pty_stamped_utmp = 1; #endif }
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); }
/* * Setup standard FHS 2.3 structure in /var, and * write runlevel to UTMP, needed by, e.g., printerdrake. */ static void setup(void *UNUSED(arg)) { #ifdef RUNLEVEL struct utmp entry; #endif _d("Setting up FHS structure in /var ..."); makedir("/var/cache", 0755); makedir("/var/games", 0755); makedir("/var/lib", 0755); makedir("/var/lib/misc", 0755); makedir("/var/lib/alarm", 0755); makedir("/var/lock", 0755); makedir("/var/log", 0755); makedir("/var/mail", 0755); makedir("/var/opt", 0755); makedir("/var/run", 0755); makedir("/var/spool", 0755); makedir("/var/spool/cron", 0755); makedir("/var/tmp", 0755); makedir("/var/empty", 0755); _d("Setting up necessary UTMP files ..."); touch("/var/run/utmp"); chown("/var/run/utmp", 0, getgroup("utmp")); #ifdef RUNLEVEL memset(&entry, 0, sizeof(struct utmp)); entry.ut_type = RUN_LVL; entry.ut_pid = '0' + RUNLEVEL; setutent(); pututline(&entry); endutent(); #endif #ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE touch("/etc/network/run/ifstate"); #else erase("/etc/network/run/ifstate"); #endif _d("Setting up misc files ..."); makedir("/var/run/lldpd", 0755); /* Needed by lldpd */ makedir("/var/run/pluto", 0755); /* Needed by Openswan */ makedir("/var/run/quagga", 0755); /* Needed by Quagga */ makedir("/var/log/quagga", 0755); /* Needed by Quagga */ makedir("/var/run/sshd", 01755); /* OpenSSH */ makefifo("/dev/xconsole", 0640); /* sysklogd */ chown("/dev/xconsole", 0, getgroup("tty")); }
/* 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 */ }
static void setup_utmp(char *ttyname, char *location) { #ifndef OMIT_UTMP #ifdef HAVE_LASTLOG struct lastlog lastlog_entry; FILE *lastlog; #endif struct passwd *pw; FILE *wtmp; pw = getpwuid(getuid()); memset(&utmp_entry, 0, sizeof(utmp_entry)); utmp_entry.ut_type = USER_PROCESS; utmp_entry.ut_pid = getpid(); strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line)); strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id)); strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user)); strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host)); time(&utmp_entry.ut_time); #if defined HAVE_PUTUTLINE utmpname(UTMP_FILE); setutent(); pututline(&utmp_entry); endutent(); #endif if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); fclose(wtmp); } #ifdef HAVE_LASTLOG memset(&lastlog_entry, 0, sizeof(lastlog_entry)); strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line)); strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host)); time(&lastlog_entry.ll_time); if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) { fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET); fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog); fclose(lastlog); } #endif pty_stamped_utmp = 1; #endif }
/* Write the given entry into utmp and wtmp. */ void login (const struct utmp *entry) { struct utmp copy = *entry; utmpname(_PATH_UTMP); setutent(); #if _HAVE_UT_TYPE - 0 copy.ut_type = USER_PROCESS; #endif #if _HAVE_UT_PID - 0 copy.ut_pid = getpid(); #endif strncpy (copy.ut_line, entry->ut_line, UT_LINESIZE); pututline(entry); endutent(); }
/* * 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 }
/* * 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; }
int logout (const char *line) { struct utmp tmp, utbuf; struct utmp *ut; int result = 0; /* Tell that we want to use the UTMP file. */ if (utmpname (_PATH_UTMP) == -1) return 0; /* Open UTMP file. */ setutent (); /* Fill in search information. */ #if _HAVE_UT_TYPE - 0 tmp.ut_type = USER_PROCESS; #endif strncpy (tmp.ut_line, line, sizeof tmp.ut_line); /* Read the record. */ if (getutline_r (&tmp, &utbuf, &ut) >= 0) { /* Clear information about who & from where. */ bzero (ut->ut_name, sizeof ut->ut_name); #if _HAVE_UT_HOST - 0 bzero (ut->ut_host, sizeof ut->ut_host); #endif #if _HAVE_UT_TV - 0 gettimeofday (&ut->ut_tv, NULL); #else time (&ut->ut_time); #endif #if _HAVE_UT_TYPE - 0 ut->ut_type = DEAD_PROCESS; #endif if (pututline (ut) != NULL) result = 1; } /* Close UTMP file. */ endutent (); return result; }
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); }
static int do_init (void) { int n; setutent (); for (n = 0; n < num_entries; n++) { if (pututline (&entry[n]) == NULL) { error (0, errno, "cannot write UTMP entry"); return 1; } } endutent (); return 0; }
/**************************************************************************** * 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); }