xref: /netbsd-src/external/bsd/tmux/usr.bin/tmux/utempter.c (revision 218284c94bb947a2d1e1e5577ba0524c2af8e8bd)
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
doutmpx(const char * username,const char * hostname,const char * tty,const struct timeval * now,int type,pid_t pid)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
login_utmpx(const char * username,const char * hostname,const char * tty,const struct timeval * now)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
logout_utmpx(const char * username,const char * tty,const struct timeval * now)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
login_utmp(const char * username,const char * hostname,const char * tty,const struct timeval * now)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
logout_utmp(const char * username __unused,const char * tty,const struct timeval * now __unused)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
utmp_create(int fd,const char * host)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
utmp_destroy(int fd)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
utempter_add_record(int fd,const char * host)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
utempter_remove_added_record(void)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
utempter_remove_record(int fd)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
addToUtmp(const char * pty __unused,const char * host,int fd)201 addToUtmp(const char *pty __unused, const char *host, int fd)
202 {
203 
204 	utempter_add_record(fd, host);
205 }
206 
207 void
removeFromUtmp(void)208 removeFromUtmp(void)
209 {
210 
211 	utempter_remove_added_record();
212 }
213 
214 void
removeLineFromUtmp(const char * pty __unused,int fd)215 removeLineFromUtmp(const char *pty __unused, int fd)
216 {
217 
218 	utempter_remove_record(fd);
219 }
220