📄 loginrec.c
字号:
/* * 'line' string utility functions * * These functions process the 'line' string into one of three forms: * * 1. The full filename (including '/dev') * 2. The stripped name (excluding '/dev') * 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00 * /dev/pts/1 -> ts/1 ) * * Form 3 is used on some systems to identify a .tmp.? entry when * attempting to remove it. Typically both addition and removal is * performed by one application - say, sshd - so as long as the choice * uniquely identifies a terminal it's ok. *//* line_fullname(): add the leading '/dev/' if it doesn't exist make * sure dst has enough space, if not just copy src (ugh) */char *line_fullname(char *dst, const char *src, int dstsize){ memset(dst, '\0', dstsize); if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5))) { strlcpy(dst, src, dstsize); } else { strlcpy(dst, "/dev/", dstsize); strlcat(dst, src, dstsize); } return dst;}/* line_stripname(): strip the leading '/dev' if it exists, return dst */char *line_stripname(char *dst, const char *src, int dstsize){ memset(dst, '\0', dstsize); if (strncmp(src, "/dev/", 5) == 0) strlcpy(dst, src + 5, dstsize); else strlcpy(dst, src, dstsize); return dst;}/* line_abbrevname(): Return the abbreviated (usually four-character) * form of the line (Just use the last <dstsize> characters of the * full name.) * * NOTE: use strncpy because we do NOT necessarily want zero * termination */char *line_abbrevname(char *dst, const char *src, int dstsize){ size_t len; memset(dst, '\0', dstsize); /* Always skip prefix if present */ if (strncmp(src, "/dev/", 5) == 0) src += 5;#ifdef WITH_ABBREV_NO_TTY if (strncmp(src, "tty", 3) == 0) src += 3;#endif len = strlen(src); if (len > 0) { if (((int)len - dstsize) > 0) src += ((int)len - dstsize); /* note: _don't_ change this to strlcpy */ strncpy(dst, src, (size_t)dstsize); } return dst;}/** ** utmp utility functions ** ** These functions manipulate struct utmp, taking system differences ** into account. **/#if defined(USE_UTMP) || defined (USE_WTMP) || defined (USE_LOGIN)/* build the utmp structure */voidset_utmp_time(struct logininfo *li, struct utmp *ut){# ifdef HAVE_TV_IN_UTMP ut->ut_tv.tv_sec = li->tv_sec; ut->ut_tv.tv_usec = li->tv_usec;# else# ifdef HAVE_TIME_IN_UTMP ut->ut_time = li->tv_sec;# endif# endif}voidconstruct_utmp(struct logininfo *li, struct utmp *ut){ memset(ut, '\0', sizeof(*ut)); /* First fill out fields used for both logins and logouts */# ifdef HAVE_ID_IN_UTMP line_abbrevname(ut->ut_id, li->line, sizeof(ut->ut_id));# endif# ifdef HAVE_TYPE_IN_UTMP /* This is done here to keep utmp constants out of struct logininfo */ switch (li->type) { case LTYPE_LOGIN: ut->ut_type = USER_PROCESS;#ifdef _CRAY cray_set_tmpdir(ut);#endif break; case LTYPE_LOGOUT: ut->ut_type = DEAD_PROCESS;#ifdef _CRAY cray_retain_utmp(ut, li->pid);#endif break; }# endif set_utmp_time(li, ut); line_stripname(ut->ut_line, li->line, sizeof(ut->ut_line));# ifdef HAVE_PID_IN_UTMP ut->ut_pid = li->pid;# endif /* If we're logging out, leave all other fields blank */ if (li->type == LTYPE_LOGOUT) return; /* * These fields are only used when logging in, and are blank * for logouts. */ /* Use strncpy because we don't necessarily want null termination */ strncpy(ut->ut_name, li->username, MIN_SIZEOF(ut->ut_name, li->username));# ifdef HAVE_HOST_IN_UTMP strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname));# endif# ifdef HAVE_ADDR_IN_UTMP /* this is just a 32-bit IP address */ if (li->hostaddr.sa.sa_family == AF_INET) ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;# endif}#endif /* USE_UTMP || USE_WTMP || USE_LOGIN *//** ** utmpx utility functions ** ** These functions manipulate struct utmpx, accounting for system ** variations. **/#if defined(USE_UTMPX) || defined (USE_WTMPX)/* build the utmpx structure */voidset_utmpx_time(struct logininfo *li, struct utmpx *utx){# ifdef HAVE_TV_IN_UTMPX utx->ut_tv.tv_sec = li->tv_sec; utx->ut_tv.tv_usec = li->tv_usec;# else /* HAVE_TV_IN_UTMPX */# ifdef HAVE_TIME_IN_UTMPX utx->ut_time = li->tv_sec;# endif /* HAVE_TIME_IN_UTMPX */# endif /* HAVE_TV_IN_UTMPX */}voidconstruct_utmpx(struct logininfo *li, struct utmpx *utx){ memset(utx, '\0', sizeof(*utx));# ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id));# endif /* this is done here to keep utmp constants out of loginrec.h */ switch (li->type) { case LTYPE_LOGIN: utx->ut_type = USER_PROCESS; break; case LTYPE_LOGOUT: utx->ut_type = DEAD_PROCESS; break; } line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line)); set_utmpx_time(li, utx); utx->ut_pid = li->pid; /* strncpy(): Don't necessarily want null termination */ strncpy(utx->ut_name, li->username, MIN_SIZEOF(utx->ut_name, li->username)); if (li->type == LTYPE_LOGOUT) return; /* * These fields are only used when logging in, and are blank * for logouts. */# ifdef HAVE_HOST_IN_UTMPX strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname));# endif# ifdef HAVE_ADDR_IN_UTMPX /* this is just a 32-bit IP address */ if (li->hostaddr.sa.sa_family == AF_INET) utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;# endif# ifdef HAVE_SYSLEN_IN_UTMPX /* ut_syslen is the length of the utx_host string */ utx->ut_syslen = MIN(strlen(li->hostname), sizeof(utx->ut_host));# endif}#endif /* USE_UTMPX || USE_WTMPX *//** ** Low-level utmp functions **//* FIXME: (ATL) utmp_write_direct needs testing */#ifdef USE_UTMP/* if we can, use pututline() etc. */# if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \ defined(HAVE_PUTUTLINE)# define UTMP_USE_LIBRARY# endif/* write a utmp entry with the system's help (pututline() and pals) */# ifdef UTMP_USE_LIBRARYstatic intutmp_write_library(struct logininfo *li, struct utmp *ut){ setutent(); pututline(ut);# ifdef HAVE_ENDUTENT endutent();# endif return 1;}# else /* UTMP_USE_LIBRARY *//* write a utmp entry direct to the file *//* This is a slightly modification of code in OpenBSD's login.c */static intutmp_write_direct(struct logininfo *li, struct utmp *ut){ struct utmp old_ut; register int fd; int tty; /* FIXME: (ATL) ttyslot() needs local implementation */#if defined(HAVE_GETTTYENT) register struct ttyent *ty; tty=0; setttyent(); while ((struct ttyent *)0 != (ty = getttyent())) { tty++; if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line))) break; } endttyent(); if((struct ttyent *)0 == ty) { log("utmp_write_entry: tty not found"); return(1); }#else /* FIXME */ tty = ttyslot(); /* seems only to work for /dev/ttyp? style names */#endif /* HAVE_GETTTYENT */ if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) { (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); /* * Prevent luser from zero'ing out ut_host. * If the new ut_line is empty but the old one is not * and ut_line and ut_name match, preserve the old ut_line. */ if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) && (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') && (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) && (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) { (void)memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); } (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) log("utmp_write_direct: error writing %s: %s", UTMP_FILE, strerror(errno)); (void)close(fd); return 1; } else { return 0; }}# endif /* UTMP_USE_LIBRARY */static intutmp_perform_login(struct logininfo *li){ struct utmp ut; construct_utmp(li, &ut);# ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { log("utmp_perform_login: utmp_write_library() failed"); return 0; }# else if (!utmp_write_direct(li, &ut)) { log("utmp_perform_login: utmp_write_direct() failed"); return 0; }# endif return 1;}static intutmp_perform_logout(struct logininfo *li){ struct utmp ut; construct_utmp(li, &ut);# ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { log("utmp_perform_logout: utmp_write_library() failed"); return 0; }# else if (!utmp_write_direct(li, &ut)) { log("utmp_perform_logout: utmp_write_direct() failed"); return 0; }# endif return 1;}intutmp_write_entry(struct logininfo *li){ switch(li->type) { case LTYPE_LOGIN: return utmp_perform_login(li); case LTYPE_LOGOUT: return utmp_perform_logout(li); default: log("utmp_write_entry: invalid type field"); return 0; }}#endif /* USE_UTMP *//** ** Low-level utmpx functions **//* not much point if we don't want utmpx entries */#ifdef USE_UTMPX/* if we have the wherewithall, use pututxline etc. */# if !defined(DISABLE_PUTUTXLINE) && defined(HAVE_SETUTXENT) && \ defined(HAVE_PUTUTXLINE)# define UTMPX_USE_LIBRARY# endif/* write a utmpx entry with the system's help (pututxline() and pals) */# ifdef UTMPX_USE_LIBRARYstatic intutmpx_write_library(struct logininfo *li, struct utmpx *utx){ setutxent(); pututxline(utx);# ifdef HAVE_ENDUTXENT endutxent();# endif return 1;}# else /* UTMPX_USE_LIBRARY *//* write a utmp entry direct to the file */static intutmpx_write_direct(struct logininfo *li, struct utmpx *utx){ log("utmpx_write_direct: not implemented!"); return 0;}# endif /* UTMPX_USE_LIBRARY */static intutmpx_perform_login(struct logininfo *li){ struct utmpx utx; construct_utmpx(li, &utx);# ifdef UTMPX_USE_LIBRARY if (!utmpx_write_library(li, &utx)) { log("utmpx_perform_login: utmp_write_library() failed"); return 0; }# else if (!utmpx_write_direct(li, &ut)) { log("utmpx_perform_login: utmp_write_direct() failed"); return 0; }# endif return 1;}static intutmpx_perform_logout(struct logininfo *li){ struct utmpx utx; construct_utmpx(li, &utx);# ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id));# endif# ifdef HAVE_TYPE_IN_UTMPX utx.ut_type = DEAD_PROCESS;# endif# ifdef UTMPX_USE_LIBRARY utmpx_write_library(li, &utx);# else utmpx_write_direct(li, &utx);# endif return 1;}intutmpx_write_entry(struct logininfo *li){ switch(li->type) { case LTYPE_LOGIN: return utmpx_perform_login(li); case LTYPE_LOGOUT: return utmpx_perform_logout(li); default: log("utmpx_write_entry: invalid type field"); return 0; }}#endif /* USE_UTMPX *//** ** Low-level wtmp functions **/#ifdef USE_WTMP/* write a wtmp entry direct to the end of the file *//* This is a slight modification of code in OpenBSD's logwtmp.c */static intwtmp_write(struct logininfo *li, struct utmp *ut){ struct stat buf; int fd, ret = 1; if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { log("wtmp_write: problem writing %s: %s", WTMP_FILE, strerror(errno)); return 0; } if (fstat(fd, &buf) == 0) if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) { ftruncate(fd, buf.st_size); log("wtmp_write: problem writing %s: %s", WTMP_FILE, strerror(errno)); ret = 0; } (void)close(fd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -