📄 utmp.c
字号:
/* * This file contains machine specific code for making sure getlogin() works. * See the function setlogin below. * * Make sure login database is updated getut(3c), but this is not * available in POSIX, or SYSV XPG3; it's only a SYSV XPG2 feature. * There thus is no machine independent way to make getlogin work. * * The least-common denominator of utmp entries * * char ut_line[] device name without path component (e.g. "ttyp4") * 8 chars on BSD, 12 on hp-ux * char ut_host[16] host name if remote * time_t ut_time time entry was made (long on BSD) * char ut_name[8] login name of the user * * Unfortunately, BSD and System V use different names for the field containing * the user login name. The type and size is the same though. It's called * ut_user on system V, and ut_name on BSD. Also, the order of the fields is * different. * * For BSD, empty slots are indicated by ut_name is a null string. * Remote users are indicated by a non-null ut_host field. * * For System V, empty slots are indicated by ut_type field as * DEAD_PROCESS, EMPTY; The ut_user is not set to null. */#define _POSIX_SOURCE#include <unistd.h> /* open read write lseek getuid */#include <stdio.h>#include <fcntl.h> /* O_RDWR */#include <string.h> /* strchr memset */#include <time.h> /* time */#include <pwd.h> /* struct passwd, getpwuid */#include <sys/types.h> /* uid_t */#include <utmp.h> /* struct utmp: very machine specific */#include "utmp.h"#include "log.h"#ifdef USER_PROCESS /* system V */#define ut_login ut_user#else#define ut_login ut_name#endif/* * Must minimize the time the file is open to prevent write conflict with * other processes trying to update utmp. This routine also updates * /etc/wtmp, the file containing login history. * * Returns: 0 for success * <0 failure (-1 for utmp, -2 for wtmp) */int writeut(utp, offset) struct utmp *utp; long offset; { off_t lres; int res = -1; int fd = open(UTMP_FILE, O_WRONLY), count; if (fd < 0) return -1;#ifdef USER_PROCESS if (utp->ut_login[0] != '\0') { utp->ut_type = USER_PROCESS; utp->ut_pid = getpid(); }#endif lres = lseek(fd, (off_t) offset, SEEK_SET); if (lres == (off_t) offset) { count = write(fd, utp, sizeof *utp); if (count == sizeof *utp) res = 0; } close(fd); fd = open(WTMP_FILE, O_WRONLY | O_APPEND); if (fd < 0) return -2; count = write(fd, utp, sizeof *utp); if (count != sizeof *utp) { res = -2; } else { res = 0; } close(fd); return res;}/* * Find the offset into the utmp file where the specified line is. If the * line is not present, will position to where to perform the write to add it. * * NOTE: No check is made to see if the line is in use. */long findutoffset(line) char *line;{ int fd = open(UTMP_FILE, O_RDONLY), count; long offset = -1; struct utmp ut; if (fd < 0) return -1; while ((count = read(fd, &ut, sizeof ut)) == sizeof ut) { if (strncmp(line, ut.ut_line, sizeof ut.ut_line) == 0) { break; } offset += sizeof ut; } if (offset != -1) offset++; close(fd); return offset;}/* * The inverse of the POSIX getlogin call. Setup the login for the given * user name. * * Input: * tty = the device file assigned as the controlling terminal * name = the login name (only first 8 characters signifacant) * rhost = the hostname of the remote host (only 1st 16 chars used) * * If name is a null pointer, delete the entry associated with that tty. * * The calling process should ensure that it owns the tty before it calls * this routine, or it could overwrite a legitimate processes tty. */int setlogin(tty, username, rhost) char *tty, *username, *rhost;{ char *line; struct utmp ut; long offset; if (tty == (char *) 0) return -1; line = strrchr(tty, '/'); if (line == (char *) 0) line = tty; else line++; offset = findutoffset(line); if (offset < 0) { return -1; } memset(&ut, '\0', sizeof ut); strncpy(ut.ut_line, line, sizeof ut.ut_line); time((time_t *) &ut.ut_time); if (username != (char *) 0) { strncpy(ut.ut_login, username, sizeof ut.ut_login); } if (rhost != (char *) 0) { strncpy(ut.ut_host, rhost, sizeof ut.ut_host); } return writeut(&ut, offset);}/* * Because of severe braindamage, the POSIX getlogin() call has a * high-probability of failing to work on many machines. The things to * consider are: * * This process must have a controlling terminal to determine the tty line * to lookup in utmp. * * There must be a (unique) entry for that line in utmp. * * There is no guarantee that the contents of utmp is correct. (It's world * writable on most SUN BSD machines for example! Thus, the login name * returned there may not be correct at all. * * cuserid() is obsolete. The problem is that it could return the login * name corresponding to the effective user id instead of the real user id. * * There may be multiple user names corresponding to each user id. * * The bottom line is that there is *no way* to accurately determine which * of the (possibly many) login names were used to get this particular real * user id. * * I've decided not to trust utmp at all, and just to get the first valid * user id using the POSIX.1 conformant calls to <pwd.h>, getpwuid. * * Note that the only "portable" fields of a struct passwd are: * * char *pw_name * char *pw_passwd * uid_t pw_uid * gid_t pw_gid * * The only way this routine should fail (returning (char *) 0) is if * /etc/passwd is not readable. Note that yellow-pages lookups could occur * as a result of using this function. * * AnnexB.4.2.4:2682-2694 * The getlogin() function returns a pointer to the user's login name. The * same user ID may be shared by several login names. If it is desired to get * the user database entry that is used during login, the result of getlogin() * should be used to provide the argument to the getpwnam() function. (This * might be used to determine the user's login shell, particularly where a * single user has multiple login shells with distinct login names, but the * same user ID.) * The information provided by the cuserid() function, which was originally * defined in IEEE Std 1003.1-1990 and subsequently removed, can be obtained * by the following: getpwuid(geteuid()), while the information provided by * historical implementations of cuserid() can be obtained by: * getpwuid(getuid()). */char *getLoginName() { register uid_t uid = getuid(); register struct passwd *pwent; pwent = getpwuid(uid); if (pwent == (struct passwd *) 0) { return (char *) 0; } else { return pwent->pw_name; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -