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