1 /* $NetBSD: utempter.c,v 1.2 2017/06/11 14:34:49 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2011, 2017 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 #include <sys/cdefs.h> 39 __RCSID("$NetBSD: utempter.c,v 1.2 2017/06/11 14:34:49 christos Exp $"); 40 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <string.h> 44 #include <errno.h> 45 #include <time.h> 46 #include <stdlib.h> 47 #include <unistd.h> 48 #include <util.h> 49 #include <paths.h> 50 51 #ifdef SUPPORT_UTMP 52 #include <utmp.h> 53 #endif 54 #ifdef SUPPORT_UTMPX 55 #include <utmpx.h> 56 #endif 57 58 #ifdef SUPPORT_UTMPX 59 static void 60 doutmpx(const char *username, const char *hostname, const char *tty, 61 const struct timeval *now, int type, pid_t pid) 62 { 63 struct utmpx ut; 64 const char *t; 65 66 (void)memset(&ut, 0, sizeof(ut)); 67 ut.ut_tv = *now; 68 (void)strncpy(ut.ut_name, username, sizeof(ut.ut_name)); 69 if (hostname) 70 (void)strncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); 71 (void)strncpy(ut.ut_line, tty, sizeof(ut.ut_line)); 72 ut.ut_type = type; 73 ut.ut_pid = pid; 74 t = tty + strlen(tty); 75 if ((size_t)(t - tty) >= sizeof(ut.ut_id)) 76 tty = t - sizeof(ut.ut_id); 77 (void)strncpy(ut.ut_id, tty, sizeof(ut.ut_id)); 78 (void)pututxline(&ut); 79 endutxent(); 80 } 81 static void 82 login_utmpx(const char *username, const char *hostname, const char *tty, 83 const struct timeval *now) 84 { 85 doutmpx(username, hostname, tty, now, USER_PROCESS, getpid()); 86 } 87 88 static void 89 logout_utmpx(const char *username, const char *tty, const struct timeval *now) 90 { 91 doutmpx(username, "", tty, now, DEAD_PROCESS, 0); 92 } 93 #endif 94 95 #ifdef SUPPORT_UTMP 96 static void 97 login_utmp(const char *username, const char *hostname, const char *tty, 98 const struct timeval *now) 99 { 100 struct utmp ut; 101 (void)memset(&ut, 0, sizeof(ut)); 102 ut.ut_time = now->tv_sec; 103 (void)strncpy(ut.ut_name, username, sizeof(ut.ut_name)); 104 if (hostname) 105 (void)strncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); 106 (void)strncpy(ut.ut_line, tty, sizeof(ut.ut_line)); 107 login(&ut); 108 } 109 110 static void 111 logout_utmp(const char *username __unused, 112 const char *tty, const struct timeval *now __unused) 113 { 114 logout(tty); 115 } 116 #endif 117 118 static int 119 utmp_create(int fd, const char *host) 120 { 121 struct timeval tv; 122 char username[LOGIN_NAME_MAX]; 123 char tty[128], *ttyp; 124 125 if (getlogin_r(username, sizeof(username)) == -1) 126 return -1; 127 128 if ((errno = ttyname_r(fd, tty, sizeof(tty))) != 0) 129 return -1; 130 ttyp = tty + sizeof(_PATH_DEV) - 1; 131 132 (void)gettimeofday(&tv, NULL); 133 #ifdef SUPPORT_UTMPX 134 login_utmpx(username, host, ttyp, &tv); 135 #endif 136 #ifdef SUPPORT_UTMP 137 login_utmp(username, host, ttyp, &tv); 138 #endif 139 return 0; 140 } 141 142 static int 143 utmp_destroy(int fd) 144 { 145 struct timeval tv; 146 char username[LOGIN_NAME_MAX]; 147 char tty[128], *ttyp; 148 149 if (getlogin_r(username, sizeof(username)) == -1) 150 return -1; 151 152 if ((errno = ttyname_r(fd, tty, sizeof(tty))) != 0) 153 return -1; 154 155 ttyp = tty + sizeof(_PATH_DEV) - 1; 156 (void)gettimeofday(&tv, NULL); 157 #ifdef SUPPORT_UTMPX 158 logout_utmpx(username, ttyp, &tv); 159 #endif 160 #ifdef SUPPORT_UTMP 161 logout_utmp(username, ttyp, &tv); 162 #endif 163 return 0; 164 } 165 166 #include "utempter.h" 167 168 static int last_fd = -1; 169 170 int 171 utempter_add_record(int fd, const char *host) 172 { 173 if (utmp_create(fd, host) == -1) 174 return -1; 175 last_fd = fd; 176 return 0; 177 } 178 179 int 180 utempter_remove_added_record(void) 181 { 182 183 if (last_fd < 0) 184 return -1; 185 utmp_destroy(last_fd); 186 last_fd = -1; 187 return 0; 188 } 189 190 int 191 utempter_remove_record(int fd) 192 { 193 194 utmp_destroy(fd); 195 if (last_fd == fd) 196 last_fd = -1; 197 return 0; 198 } 199 200 void 201 addToUtmp(const char *pty __unused, const char *host, int fd) 202 { 203 204 utempter_add_record(fd, host); 205 } 206 207 void 208 removeFromUtmp(void) 209 { 210 211 utempter_remove_added_record(); 212 } 213 214 void 215 removeLineFromUtmp(const char *pty __unused, int fd) 216 { 217 218 utempter_remove_record(fd); 219 } 220