ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libptytty/src/logging.C
Revision: 1.71
Committed: Mon May 24 14:22:50 2021 UTC (5 years, 3 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
Changes since 1.70: +139 -169 lines
Log Message:
Stop using utmp if utmpx is available

This commit changes ptytty to use only utmpx on systems where both
utmpx and utmp are available, as utmp is generally deprecated and
pointless to use on these, glibc being the exception. The commit also
refactors code to reduce the amount of ifdeffery.

File Contents

# User Rev Content
1 root 1.6 /*----------------------------------------------------------------------*
2 root 1.1 * File: logging.C
3     *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1992 John Bovey <jdb@ukc.ac.uk>
7     * - original version
8     * Copyright (c) 1993 lipka
9     * Copyright (c) 1993 Brian Stempien <stempien@cs.wmich.edu>
10     * Copyright (c) 1995 Raul Garcia Garcia <rgg@tid.es>
11     * Copyright (c) 1995 Piet W. Plomp <piet@idefix.icce.rug.nl>
12     * Copyright (c) 1997 Raul Garcia Garcia <rgg@tid.es>
13     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
14     * - extensive modifications
15     * Copyright (c) 1999 D J Hawkey Jr <hawkeyd@visi.com>
16     * - lastlog support
17 sf-exg 1.30 * Copyright (c) 2004-2006 Marc Lehmann <schmorp@schmorp.de>
18 sf-exg 1.71 * Copyright (c) 2006-2021 Emanuele Giaquinta <e.giaquinta@glauco.it>
19 root 1.1 *
20     * This program is free software; you can redistribute it and/or modify
21     * it under the terms of the GNU General Public License as published by
22 sf-exg 1.68 * the Free Software Foundation; either version 2 of the License, or
23 root 1.1 * (at your option) any later version.
24     *
25     * This program is distributed in the hope that it will be useful,
26     * but WITHOUT ANY WARRANTY; without even the implied warranty of
27     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28     * GNU General Public License for more details.
29     *
30     * You should have received a copy of the GNU General Public License
31     * along with this program; if not, write to the Free Software
32     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33     *----------------------------------------------------------------------*/
34    
35 sf-exg 1.26 #include "config.h"
36 root 1.4
37 root 1.10 #include "ptytty.h"
38    
39 sf-exg 1.71 #include <pwd.h>
40     #include <stdio.h>
41     #include <string.h>
42 sf-exg 1.69 #include <sys/types.h>
43 sf-exg 1.71 #include <time.h>
44     #include <unistd.h>
45    
46     static void
47     fill_id (char *id, const char *line, size_t id_size)
48     {
49     size_t len = strlen (line);
50    
51     if (len > id_size)
52     line += len - id_size;
53     strncpy (id, line, id_size);
54     }
55    
56     /*
57     * BSD style utmp entry
58     * ut_line, ut_name, ut_host, ut_time
59     * SYSV style utmp (and utmpx) entry
60     * ut_user, ut_id, ut_line, ut_pid, ut_type, ut_exit, ut_time
61     */
62    
63     #if defined(USE_UTMPX)
64    
65     #include <utmpx.h>
66 sf-exg 1.69
67 sf-exg 1.71 #if !defined(WTMPX_FILE)
68     # if defined(_PATH_WTMPX)
69     # define WTMPX_FILE _PATH_WTMPX
70     # elif defined(PT_WTMPX_FILE)
71     # define WTMPX_FILE PT_WTMPX_FILE
72     # endif
73     #endif
74 root 1.10
75 sf-exg 1.71 #if !defined(LASTLOGX_FILE)
76     # if defined(_PATH_LASTLOGX)
77     # define LASTLOGX_FILE _PATH_LASTLOGX
78     # elif defined(PT_LASTLOGX_FILE)
79     # define LASTLOGX_FILE PT_LASTLOGX_FILE
80     # endif
81 sf-exg 1.56 #endif
82 sf-exg 1.71
83     #ifdef LASTLOG_SUPPORT
84     static void
85     update_lastlog (const char *pty, const char *host)
86     {
87     # if defined(HAVE_STRUCT_LASTLOGX) && defined(HAVE_UPDLASTLOGX)
88     struct lastlogx llx;
89    
90     memset (&llx, 0, sizeof (llx));
91     llx.ll_tv.tv_sec = time (NULL);
92     llx.ll_tv.tv_usec = 0;
93     strncpy (llx.ll_line, pty, sizeof (llx.ll_line));
94     strncpy (llx.ll_host, host, sizeof (llx.ll_host));
95     updlastlogx (LASTLOGX_FILE, getuid (), &llx);
96     # endif
97     }
98 sf-exg 1.56 #endif
99 sf-exg 1.71
100     static void
101     fill_utmpx (struct utmpx *utx, bool login, int pid, const char *line, const char *user, const char *host)
102     {
103     memset (utx, 0, sizeof (struct utmpx));
104    
105     // posix says that ut_line is not meaningful for DEAD_PROCESS
106     // records, but most implementations of last use ut_line to
107     // associate records in wtmp file
108     strncpy (utx->ut_line, line, sizeof (utx->ut_line));
109     fill_id (utx->ut_id, line, sizeof (utx->ut_id));
110     utx->ut_pid = pid;
111     utx->ut_type = login ? USER_PROCESS : DEAD_PROCESS;
112     utx->ut_tv.tv_sec = time (NULL);
113     utx->ut_tv.tv_usec = 0;
114    
115     // posix says that ut_user is not meaningful for DEAD_PROCESS
116     // records, but solaris utmp_update helper requires that the ut_user
117     // field of a DEAD_PROCESS entry matches the one of an existing
118     // USER_PROCESS entry for the same line, if any
119     strncpy (utx->ut_user, user, sizeof (utx->ut_user));
120    
121     #ifdef HAVE_UTMPX_HOST
122     if (login)
123     strncpy (utx->ut_host, host, sizeof (utx->ut_host));
124     #endif
125     }
126    
127     void
128     ptytty_unix::log_session (bool login, const char *hostname)
129     {
130     struct passwd *pwent = getpwuid (getuid ());
131     const char *user = (pwent && pwent->pw_name) ? pwent->pw_name : "?";
132    
133     const char *pty = name;
134    
135     if (!strncmp (pty, "/dev/", 5))
136     pty += 5; /* skip /dev/ prefix */
137    
138     struct utmpx *tmputx;
139     struct utmpx utx;
140     fill_utmpx (&utx, login, cmd_pid, pty, user, hostname);
141    
142     setutxent ();
143     if (login || ((tmputx = getutxid (&utx)) && tmputx->ut_pid == cmd_pid))
144     pututxline (&utx);
145     endutxent ();
146    
147     if (login_shell)
148     {
149     #if defined(WTMP_SUPPORT) && defined(HAVE_UPDWTMPX)
150     updwtmpx (WTMPX_FILE, &utx);
151     #endif
152    
153     #ifdef LASTLOG_SUPPORT
154     if (login)
155     {
156     if (pwent)
157     update_lastlog (pty, hostname);
158     else
159     PTYTTY_WARN ("no entry in password file, not updating lastlog.\n");
160     }
161     #endif
162     }
163     }
164    
165     #elif defined(USE_UTMP)
166    
167     #include <utmp.h>
168 sf-exg 1.56 #ifdef HAVE_LASTLOG_H
169     # include <lastlog.h>
170     #endif
171    
172 sf-exg 1.58 #if !defined(UTMP_FILE)
173     # if defined(_PATH_UTMP)
174     # define UTMP_FILE _PATH_UTMP
175     # elif defined(PT_UTMP_FILE)
176     # define UTMP_FILE PT_UTMP_FILE
177     # endif
178     #endif
179 sf-exg 1.71
180 sf-exg 1.58 #if !defined(WTMP_FILE)
181     # if defined(_PATH_WTMP)
182     # define WTMP_FILE _PATH_WTMP
183     # elif defined(PT_WTMP_FILE)
184     # define WTMP_FILE PT_WTMP_FILE
185     # endif
186     #endif
187 sf-exg 1.71
188 sf-exg 1.58 #if !defined(LASTLOG_FILE)
189     # if defined(_PATH_LASTLOG)
190     # define LASTLOG_FILE _PATH_LASTLOG
191     # elif defined(PT_LASTLOG_FILE)
192     # define LASTLOG_FILE PT_LASTLOG_FILE
193     # endif
194     #endif
195 root 1.7
196     #include <sys/stat.h>
197 ayin 1.23 #include <fcntl.h>
198 ayin 1.24 #include <errno.h>
199 root 1.7
200 sf-exg 1.53 static void
201 sf-exg 1.70 write_record (const char *path, off_t pos, const void *record, size_t size)
202 ayin 1.12 {
203 sf-exg 1.70 int fd = open (path, O_WRONLY);
204     if (fd >= 0)
205     {
206     pwrite (fd, record, size, pos * size);
207     close (fd);
208     }
209 ayin 1.12 }
210    
211     /* ------------------------------------------------------------------------- */
212     /*
213     * Update a BSD style wtmp entry
214     */
215 sf-exg 1.71 #if defined(WTMP_SUPPORT) && !defined(HAVE_UPDWTMP)
216 ayin 1.12 static void
217 sf-exg 1.71 updwtmp (const char *fname, const struct utmp *ut)
218 ayin 1.12 {
219 sf-exg 1.29 int fd, gotlock, retry;
220 ayin 1.12 struct flock lck; /* fcntl locking scheme */
221     struct stat sbuf;
222    
223     if ((fd = open (fname, O_WRONLY | O_APPEND, 0)) < 0)
224     return;
225    
226     lck.l_whence = SEEK_END; /* start lock at current eof */
227     lck.l_len = 0; /* end at ``largest possible eof'' */
228     lck.l_start = 0;
229     lck.l_type = F_WRLCK; /* we want a write lock */
230    
231     /* attempt lock with F_SETLK; F_SETLKW would cause a deadlock! */
232 sf-exg 1.29 for (retry = 10, gotlock = 0; retry--;)
233 ayin 1.12 if (fcntl (fd, F_SETLK, &lck) != -1)
234     {
235 sf-exg 1.29 gotlock = 1;
236 ayin 1.12 break;
237     }
238     else if (errno != EAGAIN && errno != EACCES)
239 sf-exg 1.29 break;
240 sf-exg 1.57
241     if (gotlock)
242 sf-exg 1.29 {
243 sf-exg 1.57 if (fstat (fd, &sbuf) == 0)
244     if (write (fd, ut, sizeof (struct utmp)) != sizeof (struct utmp))
245     ftruncate (fd, sbuf.st_size); /* remove bad writes */
246    
247     lck.l_type = F_UNLCK; /* unlocking the file */
248     fcntl (fd, F_SETLK, &lck);
249 sf-exg 1.29 }
250 ayin 1.12
251     close (fd);
252     }
253     #endif
254    
255     /* ------------------------------------------------------------------------- */
256     #ifdef LASTLOG_SUPPORT
257     static void
258 sf-exg 1.31 update_lastlog (const char *pty, const char *host)
259 ayin 1.12 {
260     # ifdef HAVE_STRUCT_LASTLOG
261 sf-exg 1.70 struct lastlog ll;
262 ayin 1.12
263     memset (&ll, 0, sizeof (ll));
264     ll.ll_time = time (NULL);
265     strncpy (ll.ll_line, pty, sizeof (ll.ll_line));
266     strncpy (ll.ll_host, host, sizeof (ll.ll_host));
267 sf-exg 1.70 write_record (LASTLOG_FILE, getuid (), &ll, sizeof (ll));
268 ayin 1.17 # endif /* HAVE_STRUCT_LASTLOG */
269 ayin 1.12 }
270 ayin 1.17 #endif /* LASTLOG_SUPPORT */
271 ayin 1.12
272 sf-exg 1.32 static void
273 sf-exg 1.45 fill_utmp (struct utmp *ut, bool login, int pid, const char *line, const char *user, const char *host)
274 sf-exg 1.32 {
275     memset (ut, 0, sizeof (struct utmp));
276    
277 sf-exg 1.40 strncpy (ut->ut_line, line, sizeof (ut->ut_line));
278 sf-exg 1.71 #ifdef HAVE_UTMP_PID
279 sf-exg 1.45 fill_id (ut->ut_id, line, sizeof (ut->ut_id));
280 sf-exg 1.32 ut->ut_pid = pid;
281 sf-exg 1.35 ut->ut_type = login ? USER_PROCESS : DEAD_PROCESS;
282 sf-exg 1.71 #endif
283 sf-exg 1.32 ut->ut_time = time (NULL);
284    
285     if (login)
286     {
287 sf-exg 1.71 #ifdef HAVE_UTMP_PID
288 sf-exg 1.32 strncpy (ut->ut_user, user, sizeof (ut->ut_user));
289 sf-exg 1.71 #else
290 sf-exg 1.32 strncpy (ut->ut_name, user, sizeof (ut->ut_name));
291 sf-exg 1.71 #endif
292     #ifdef HAVE_UTMP_HOST
293 sf-exg 1.32 strncpy (ut->ut_host, host, sizeof (ut->ut_host));
294     #endif
295     }
296     }
297 sf-exg 1.54
298     void
299     ptytty_unix::log_session (bool login, const char *hostname)
300     {
301 root 1.1 struct passwd *pwent = getpwuid (getuid ());
302 sf-exg 1.39 const char *user = (pwent && pwent->pw_name) ? pwent->pw_name : "?";
303 root 1.1
304 sf-exg 1.54 const char *pty = name;
305    
306 root 1.1 if (!strncmp (pty, "/dev/", 5))
307     pty += 5; /* skip /dev/ prefix */
308    
309 sf-exg 1.54 struct utmp *tmput;
310 sf-exg 1.55 struct utmp ut;
311     fill_utmp (&ut, login, cmd_pid, pty, user, hostname);
312 root 1.1
313 sf-exg 1.71 #ifdef HAVE_UTMP_PID
314 sf-exg 1.37 setutent ();
315 sf-exg 1.55 if (login || ((tmput = getutid (&ut)) && tmput->ut_pid == cmd_pid))
316     pututline (&ut);
317 sf-exg 1.42 endutent ();
318 sf-exg 1.71 #else
319 sf-exg 1.70 if (utmp_pos > 0)
320     write_record (UTMP_FILE, utmp_pos, &ut, sizeof (ut));
321 root 1.1 #endif
322    
323 root 1.2 if (login_shell)
324 root 1.1 {
325 sf-exg 1.71 #ifdef WTMP_SUPPORT
326 sf-exg 1.55 updwtmp (WTMP_FILE, &ut);
327 root 1.1 #endif
328 sf-exg 1.54
329 sf-exg 1.31 #ifdef LASTLOG_SUPPORT
330 sf-exg 1.54 if (login)
331 sf-exg 1.60 {
332     if (pwent)
333     update_lastlog (pty, hostname);
334     else
335 sf-exg 1.66 PTYTTY_WARN ("no entry in password file, not updating lastlog.\n");
336 sf-exg 1.60 }
337 root 1.1 #endif
338 sf-exg 1.71 }
339 root 1.1 }
340    
341 root 1.5 #endif
342