summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--loginrec.c642
2 files changed, 321 insertions, 327 deletions
diff --git a/ChangeLog b/ChangeLog
index 995e1bd27..8890e6235 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
120040912
2 - (djm) [loginrec.c] Start KNF and tidy up of this long-neglected file.
3 No change in resultant binary
4
120040911 520040911
2 - (djm) [ssh-agent.c] unifdef some cygwin code; ok dtucker@ 6 - (djm) [ssh-agent.c] unifdef some cygwin code; ok dtucker@
3 - (dtucker) [auth-pam.c auth-pam.h session.c] Bug #890: Send output from 7 - (dtucker) [auth-pam.c auth-pam.h session.c] Bug #890: Send output from
@@ -1734,4 +1738,4 @@
1734 - (djm) Trim deprecated options from INSTALL. Mention UsePAM 1738 - (djm) Trim deprecated options from INSTALL. Mention UsePAM
1735 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu 1739 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
1736 1740
1737$Id: ChangeLog,v 1.3547 2004/09/11 13:32:09 dtucker Exp $ 1741$Id: ChangeLog,v 1.3548 2004/09/12 05:23:14 djm Exp $
diff --git a/loginrec.c b/loginrec.c
index 3ec378b9a..8d48fb99f 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -30,125 +30,99 @@
30 **/ 30 **/
31 31
32/* 32/*
33 The new login code explained 33 * The new login code explained
34 ============================ 34 * ============================
35 35 *
36 This code attempts to provide a common interface to login recording 36 * This code attempts to provide a common interface to login recording
37 (utmp and friends) and last login time retrieval. 37 * (utmp and friends) and last login time retrieval.
38 38 *
39 Its primary means of achieving this is to use 'struct logininfo', a 39 * Its primary means of achieving this is to use 'struct logininfo', a
40 union of all the useful fields in the various different types of 40 * union of all the useful fields in the various different types of
41 system login record structures one finds on UNIX variants. 41 * system login record structures one finds on UNIX variants.
42 42 *
43 We depend on autoconf to define which recording methods are to be 43 * We depend on autoconf to define which recording methods are to be
44 used, and which fields are contained in the relevant data structures 44 * used, and which fields are contained in the relevant data structures
45 on the local system. Many C preprocessor symbols affect which code 45 * on the local system. Many C preprocessor symbols affect which code
46 gets compiled here. 46 * gets compiled here.
47 47 *
48 The code is designed to make it easy to modify a particular 48 * The code is designed to make it easy to modify a particular
49 recording method, without affecting other methods nor requiring so 49 * recording method, without affecting other methods nor requiring so
50 many nested conditional compilation blocks as were commonplace in 50 * many nested conditional compilation blocks as were commonplace in
51 the old code. 51 * the old code.
52 52 *
53 For login recording, we try to use the local system's libraries as 53 * For login recording, we try to use the local system's libraries as
54 these are clearly most likely to work correctly. For utmp systems 54 * these are clearly most likely to work correctly. For utmp systems
55 this usually means login() and logout() or setutent() etc., probably 55 * this usually means login() and logout() or setutent() etc., probably
56 in libutil, along with logwtmp() etc. On these systems, we fall back 56 * in libutil, along with logwtmp() etc. On these systems, we fall back
57 to writing the files directly if we have to, though this method 57 * to writing the files directly if we have to, though this method
58 requires very thorough testing so we do not corrupt local auditing 58 * requires very thorough testing so we do not corrupt local auditing
59 information. These files and their access methods are very system 59 * information. These files and their access methods are very system
60 specific indeed. 60 * specific indeed.
61 61 *
62 For utmpx systems, the corresponding library functions are 62 * For utmpx systems, the corresponding library functions are
63 setutxent() etc. To the author's knowledge, all utmpx systems have 63 * setutxent() etc. To the author's knowledge, all utmpx systems have
64 these library functions and so no direct write is attempted. If such 64 * these library functions and so no direct write is attempted. If such
65 a system exists and needs support, direct analogues of the [uw]tmp 65 * a system exists and needs support, direct analogues of the [uw]tmp
66 code should suffice. 66 * code should suffice.
67 67 *
68 Retrieving the time of last login ('lastlog') is in some ways even 68 * Retrieving the time of last login ('lastlog') is in some ways even
69 more problemmatic than login recording. Some systems provide a 69 * more problemmatic than login recording. Some systems provide a
70 simple table of all users which we seek based on uid and retrieve a 70 * simple table of all users which we seek based on uid and retrieve a
71 relatively standard structure. Others record the same information in 71 * relatively standard structure. Others record the same information in
72 a directory with a separate file, and others don't record the 72 * a directory with a separate file, and others don't record the
73 information separately at all. For systems in the latter category, 73 * information separately at all. For systems in the latter category,
74 we look backwards in the wtmp or wtmpx file for the last login entry 74 * we look backwards in the wtmp or wtmpx file for the last login entry
75 for our user. Naturally this is slower and on busy systems could 75 * for our user. Naturally this is slower and on busy systems could
76 incur a significant performance penalty. 76 * incur a significant performance penalty.
77 77 *
78 Calling the new code 78 * Calling the new code
79 -------------------- 79 * --------------------
80 80 *
81 In OpenSSH all login recording and retrieval is performed in 81 * In OpenSSH all login recording and retrieval is performed in
82 login.c. Here you'll find working examples. Also, in the logintest.c 82 * login.c. Here you'll find working examples. Also, in the logintest.c
83 program there are more examples. 83 * program there are more examples.
84 84 *
85 Internal handler calling method 85 * Internal handler calling method
86 ------------------------------- 86 * -------------------------------
87 87 *
88 When a call is made to login_login() or login_logout(), both 88 * When a call is made to login_login() or login_logout(), both
89 routines set a struct logininfo flag defining which action (log in, 89 * routines set a struct logininfo flag defining which action (log in,
90 or log out) is to be taken. They both then call login_write(), which 90 * or log out) is to be taken. They both then call login_write(), which
91 calls whichever of the many structure-specific handlers autoconf 91 * calls whichever of the many structure-specific handlers autoconf
92 selects for the local system. 92 * selects for the local system.
93 93 *
94 The handlers themselves handle system data structure specifics. Both 94 * The handlers themselves handle system data structure specifics. Both
95 struct utmp and struct utmpx have utility functions (see 95 * struct utmp and struct utmpx have utility functions (see
96 construct_utmp*()) to try to make it simpler to add extra systems 96 * construct_utmp*()) to try to make it simpler to add extra systems
97 that introduce new features to either structure. 97 * that introduce new features to either structure.
98 98 *
99 While it may seem terribly wasteful to replicate so much similar 99 * While it may seem terribly wasteful to replicate so much similar
100 code for each method, experience has shown that maintaining code to 100 * code for each method, experience has shown that maintaining code to
101 write both struct utmp and utmpx in one function, whilst maintaining 101 * write both struct utmp and utmpx in one function, whilst maintaining
102 support for all systems whether they have library support or not, is 102 * support for all systems whether they have library support or not, is
103 a difficult and time-consuming task. 103 * a difficult and time-consuming task.
104 104 *
105 Lastlog support proceeds similarly. Functions login_get_lastlog() 105 * Lastlog support proceeds similarly. Functions login_get_lastlog()
106 (and its OpenSSH-tuned friend login_get_lastlog_time()) call 106 * (and its OpenSSH-tuned friend login_get_lastlog_time()) call
107 getlast_entry(), which tries one of three methods to find the last 107 * getlast_entry(), which tries one of three methods to find the last
108 login time. It uses local system lastlog support if it can, 108 * login time. It uses local system lastlog support if it can,
109 otherwise it tries wtmp or wtmpx before giving up and returning 0, 109 * otherwise it tries wtmp or wtmpx before giving up and returning 0,
110 meaning "tilt". 110 * meaning "tilt".
111 111 *
112 Maintenance 112 * Maintenance
113 ----------- 113 * -----------
114 114 *
115 In many cases it's possible to tweak autoconf to select the correct 115 * In many cases it's possible to tweak autoconf to select the correct
116 methods for a particular platform, either by improving the detection 116 * methods for a particular platform, either by improving the detection
117 code (best), or by presetting DISABLE_<method> or CONF_<method>_FILE 117 * code (best), or by presetting DISABLE_<method> or CONF_<method>_FILE
118 symbols for the platform. 118 * symbols for the platform.
119 119 *
120 Use logintest to check which symbols are defined before modifying 120 * Use logintest to check which symbols are defined before modifying
121 configure.ac and loginrec.c. (You have to build logintest yourself 121 * configure.ac and loginrec.c. (You have to build logintest yourself
122 with 'make logintest' as it's not built by default.) 122 * with 'make logintest' as it's not built by default.)
123 123 *
124 Otherwise, patches to the specific method(s) are very helpful! 124 * Otherwise, patches to the specific method(s) are very helpful!
125 125 */
126*/
127
128/**
129 ** TODO:
130 ** homegrown ttyslot()
131 ** test, test, test
132 **
133 ** Platform status:
134 ** ----------------
135 **
136 ** Known good:
137 ** Linux (Redhat 6.2, Debian)
138 ** Solaris
139 ** HP-UX 10.20 (gcc only)
140 ** IRIX
141 ** NeXT - M68k/HPPA/Sparc (4.2/3.3)
142 **
143 ** Testing required: Please send reports!
144 ** NetBSD
145 ** HP-UX 11
146 ** AIX
147 **
148 ** Platforms with known problems:
149 ** Some variants of Slackware Linux
150 **
151 **/
152 126
153#include "includes.h" 127#include "includes.h"
154 128
@@ -158,16 +132,16 @@
158#include "log.h" 132#include "log.h"
159#include "atomicio.h" 133#include "atomicio.h"
160 134
161RCSID("$Id: loginrec.c,v 1.59 2004/08/23 11:53:28 djm Exp $");
162
163#ifdef HAVE_UTIL_H 135#ifdef HAVE_UTIL_H
164# include <util.h> 136# include <util.h>
165#endif 137#endif
166 138
167#ifdef HAVE_LIBUTIL_H 139#ifdef HAVE_LIBUTIL_H
168# include <libutil.h> 140# include <libutil.h>
169#endif 141#endif
170 142
143RCSID("$Id: loginrec.c,v 1.60 2004/09/12 05:18:55 djm Exp $");
144
171/** 145/**
172 ** prototypes for helper functions in this file 146 ** prototypes for helper functions in this file
173 **/ 147 **/
@@ -195,13 +169,14 @@ int wtmp_get_entry(struct logininfo *li);
195int wtmpx_get_entry(struct logininfo *li); 169int wtmpx_get_entry(struct logininfo *li);
196 170
197/* pick the shortest string */ 171/* pick the shortest string */
198#define MIN_SIZEOF(s1,s2) ( sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2) ) 172#define MIN_SIZEOF(s1,s2) (sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2))
199 173
200/** 174/**
201 ** platform-independent login functions 175 ** platform-independent login functions
202 **/ 176 **/
203 177
204/* login_login(struct logininfo *) -Record a login 178/*
179 * login_login(struct logininfo *) - Record a login
205 * 180 *
206 * Call with a pointer to a struct logininfo initialised with 181 * Call with a pointer to a struct logininfo initialised with
207 * login_init_entry() or login_alloc_entry() 182 * login_init_entry() or login_alloc_entry()
@@ -211,14 +186,15 @@ int wtmpx_get_entry(struct logininfo *li);
211 * 0 on failure (will use OpenSSH's logging facilities for diagnostics) 186 * 0 on failure (will use OpenSSH's logging facilities for diagnostics)
212 */ 187 */
213int 188int
214login_login (struct logininfo *li) 189login_login(struct logininfo *li)
215{ 190{
216 li->type = LTYPE_LOGIN; 191 li->type = LTYPE_LOGIN;
217 return login_write(li); 192 return (login_write(li));
218} 193}
219 194
220 195
221/* login_logout(struct logininfo *) - Record a logout 196/*
197 * login_logout(struct logininfo *) - Record a logout
222 * 198 *
223 * Call as with login_login() 199 * Call as with login_login()
224 * 200 *
@@ -230,10 +206,11 @@ int
230login_logout(struct logininfo *li) 206login_logout(struct logininfo *li)
231{ 207{
232 li->type = LTYPE_LOGOUT; 208 li->type = LTYPE_LOGOUT;
233 return login_write(li); 209 return (login_write(li));
234} 210}
235 211
236/* login_get_lastlog_time(int) - Retrieve the last login time 212/*
213 * login_get_lastlog_time(int) - Retrieve the last login time
237 * 214 *
238 * Retrieve the last login time for the given uid. Will try to use the 215 * Retrieve the last login time for the given uid. Will try to use the
239 * system lastlog facilities if they are available, but will fall back 216 * system lastlog facilities if they are available, but will fall back
@@ -256,12 +233,13 @@ login_get_lastlog_time(const int uid)
256 struct logininfo li; 233 struct logininfo li;
257 234
258 if (login_get_lastlog(&li, uid)) 235 if (login_get_lastlog(&li, uid))
259 return li.tv_sec; 236 return (li.tv_sec);
260 else 237 else
261 return 0; 238 return (0);
262} 239}
263 240
264/* login_get_lastlog(struct logininfo *, int) - Retrieve a lastlog entry 241/*
242 * login_get_lastlog(struct logininfo *, int) - Retrieve a lastlog entry
265 * 243 *
266 * Retrieve a logininfo structure populated (only partially) with 244 * Retrieve a logininfo structure populated (only partially) with
267 * information from the system lastlog data, or from wtmp/wtmpx if no 245 * information from the system lastlog data, or from wtmp/wtmpx if no
@@ -272,7 +250,6 @@ login_get_lastlog_time(const int uid)
272 * Returns: 250 * Returns:
273 * >0: A pointer to your struct logininfo if successful 251 * >0: A pointer to your struct logininfo if successful
274 * 0 on failure (will use OpenSSH's logging facilities for diagnostics) 252 * 0 on failure (will use OpenSSH's logging facilities for diagnostics)
275 *
276 */ 253 */
277struct logininfo * 254struct logininfo *
278login_get_lastlog(struct logininfo *li, const int uid) 255login_get_lastlog(struct logininfo *li, const int uid)
@@ -292,17 +269,18 @@ login_get_lastlog(struct logininfo *li, const int uid)
292 fatal("login_get_lastlog: Cannot find account for uid %i", uid); 269 fatal("login_get_lastlog: Cannot find account for uid %i", uid);
293 270
294 /* No MIN_SIZEOF here - we absolutely *must not* truncate the 271 /* No MIN_SIZEOF here - we absolutely *must not* truncate the
295 * username */ 272 * username (XXX - so check for trunc!) */
296 strlcpy(li->username, pw->pw_name, sizeof(li->username)); 273 strlcpy(li->username, pw->pw_name, sizeof(li->username));
297 274
298 if (getlast_entry(li)) 275 if (getlast_entry(li))
299 return li; 276 return (li);
300 else 277 else
301 return NULL; 278 return (NULL);
302} 279}
303 280
304 281
305/* login_alloc_entry(int, char*, char*, char*) - Allocate and initialise 282/*
283 * login_alloc_entry(int, char*, char*, char*) - Allocate and initialise
306 * a logininfo structure 284 * a logininfo structure
307 * 285 *
308 * This function creates a new struct logininfo, a data structure 286 * This function creates a new struct logininfo, a data structure
@@ -313,13 +291,13 @@ login_get_lastlog(struct logininfo *li, const int uid)
313 */ 291 */
314struct 292struct
315logininfo *login_alloc_entry(int pid, const char *username, 293logininfo *login_alloc_entry(int pid, const char *username,
316 const char *hostname, const char *line) 294 const char *hostname, const char *line)
317{ 295{
318 struct logininfo *newli; 296 struct logininfo *newli;
319 297
320 newli = (struct logininfo *) xmalloc (sizeof(*newli)); 298 newli = xmalloc(sizeof(*newli));
321 (void)login_init_entry(newli, pid, username, hostname, line); 299 login_init_entry(newli, pid, username, hostname, line);
322 return newli; 300 return (newli);
323} 301}
324 302
325 303
@@ -341,7 +319,7 @@ login_free_entry(struct logininfo *li)
341 */ 319 */
342int 320int
343login_init_entry(struct logininfo *li, int pid, const char *username, 321login_init_entry(struct logininfo *li, int pid, const char *username,
344 const char *hostname, const char *line) 322 const char *hostname, const char *line)
345{ 323{
346 struct passwd *pw; 324 struct passwd *pw;
347 325
@@ -356,18 +334,21 @@ login_init_entry(struct logininfo *li, int pid, const char *username,
356 if (username) { 334 if (username) {
357 strlcpy(li->username, username, sizeof(li->username)); 335 strlcpy(li->username, username, sizeof(li->username));
358 pw = getpwnam(li->username); 336 pw = getpwnam(li->username);
359 if (pw == NULL) 337 if (pw == NULL) {
360 fatal("login_init_entry: Cannot find user \"%s\"", li->username); 338 fatal("login_init_entry: Cannot find user \"%s\"",
339 li->username);
340 }
361 li->uid = pw->pw_uid; 341 li->uid = pw->pw_uid;
362 } 342 }
363 343
364 if (hostname) 344 if (hostname)
365 strlcpy(li->hostname, hostname, sizeof(li->hostname)); 345 strlcpy(li->hostname, hostname, sizeof(li->hostname));
366 346
367 return 1; 347 return (1);
368} 348}
369 349
370/* login_set_current_time(struct logininfo *) - set the current time 350/*
351 * login_set_current_time(struct logininfo *) - set the current time
371 * 352 *
372 * Set the current time in a logininfo structure. This function is 353 * Set the current time in a logininfo structure. This function is
373 * meant to eliminate the need to deal with system dependencies for 354 * meant to eliminate the need to deal with system dependencies for
@@ -387,7 +368,7 @@ login_set_current_time(struct logininfo *li)
387/* copy a sockaddr_* into our logininfo */ 368/* copy a sockaddr_* into our logininfo */
388void 369void
389login_set_addr(struct logininfo *li, const struct sockaddr *sa, 370login_set_addr(struct logininfo *li, const struct sockaddr *sa,
390 const unsigned int sa_size) 371 const unsigned int sa_size)
391{ 372{
392 unsigned int bufsize = sa_size; 373 unsigned int bufsize = sa_size;
393 374
@@ -395,7 +376,7 @@ login_set_addr(struct logininfo *li, const struct sockaddr *sa,
395 if (sizeof(li->hostaddr) < sa_size) 376 if (sizeof(li->hostaddr) < sa_size)
396 bufsize = sizeof(li->hostaddr); 377 bufsize = sizeof(li->hostaddr);
397 378
398 memcpy((void *)&(li->hostaddr.sa), (const void *)sa, bufsize); 379 memcpy(&li->hostaddr.sa, sa, bufsize);
399} 380}
400 381
401 382
@@ -404,12 +385,12 @@ login_set_addr(struct logininfo *li, const struct sockaddr *sa,
404 ** results 385 ** results
405 **/ 386 **/
406int 387int
407login_write (struct logininfo *li) 388login_write(struct logininfo *li)
408{ 389{
409#ifndef HAVE_CYGWIN 390#ifndef HAVE_CYGWIN
410 if ((int)geteuid() != 0) { 391 if (geteuid() != 0) {
411 logit("Attempt to write login records by non-root user (aborting)"); 392 logit("Attempt to write login records by non-root user (aborting)");
412 return 1; 393 return (1);
413 } 394 }
414#endif 395#endif
415 396
@@ -419,9 +400,8 @@ login_write (struct logininfo *li)
419 syslogin_write_entry(li); 400 syslogin_write_entry(li);
420#endif 401#endif
421#ifdef USE_LASTLOG 402#ifdef USE_LASTLOG
422 if (li->type == LTYPE_LOGIN) { 403 if (li->type == LTYPE_LOGIN)
423 lastlog_write_entry(li); 404 lastlog_write_entry(li);
424 }
425#endif 405#endif
426#ifdef USE_UTMP 406#ifdef USE_UTMP
427 utmp_write_entry(li); 407 utmp_write_entry(li);
@@ -440,7 +420,7 @@ login_write (struct logininfo *li)
440 !sys_auth_record_login(li->username,li->hostname,li->line)) 420 !sys_auth_record_login(li->username,li->hostname,li->line))
441 logit("Writing login record failed for %s", li->username); 421 logit("Writing login record failed for %s", li->username);
442#endif 422#endif
443 return 0; 423 return (0);
444} 424}
445 425
446#ifdef LOGIN_NEEDS_UTMPX 426#ifdef LOGIN_NEEDS_UTMPX
@@ -461,7 +441,7 @@ login_utmp_only(struct logininfo *li)
461# ifdef USE_WTMPX 441# ifdef USE_WTMPX
462 wtmpx_write_entry(li); 442 wtmpx_write_entry(li);
463# endif 443# endif
464 return 0; 444 return (0);
465} 445}
466#endif 446#endif
467 447
@@ -478,25 +458,21 @@ getlast_entry(struct logininfo *li)
478 return(lastlog_get_entry(li)); 458 return(lastlog_get_entry(li));
479#else /* !USE_LASTLOG */ 459#else /* !USE_LASTLOG */
480 460
481#ifdef DISABLE_LASTLOG 461#if defined(DISABLE_LASTLOG)
482 /* On some systems we shouldn't even try to obtain last login 462 /* On some systems we shouldn't even try to obtain last login
483 * time, e.g. AIX */ 463 * time, e.g. AIX */
484 return 0; 464 return (0);
485# else /* DISABLE_LASTLOG */ 465# elif defined(USE_WTMP) && \
486 /* Try to retrieve the last login time from wtmp */ 466 (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP))
487# if defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP))
488 /* retrieve last login time from utmp */ 467 /* retrieve last login time from utmp */
489 return (wtmp_get_entry(li)); 468 return (wtmp_get_entry(li));
490# else /* defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) */ 469# elif defined(USE_WTMPX) && \
470 (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX))
491 /* If wtmp isn't available, try wtmpx */ 471 /* If wtmp isn't available, try wtmpx */
492# if defined(USE_WTMPX) && (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX))
493 /* retrieve last login time from utmpx */
494 return (wtmpx_get_entry(li)); 472 return (wtmpx_get_entry(li));
495# else 473# else
496 /* Give up: No means of retrieving last login time */ 474 /* Give up: No means of retrieving last login time */
497 return 0; 475 return (0);
498# endif /* USE_WTMPX && (HAVE_TIME_IN_UTMPX || HAVE_TV_IN_UTMPX) */
499# endif /* USE_WTMP && (HAVE_TIME_IN_UTMP || HAVE_TV_IN_UTMP) */
500# endif /* DISABLE_LASTLOG */ 476# endif /* DISABLE_LASTLOG */
501#endif /* USE_LASTLOG */ 477#endif /* USE_LASTLOG */
502} 478}
@@ -520,19 +496,21 @@ getlast_entry(struct logininfo *li)
520 */ 496 */
521 497
522 498
523/* line_fullname(): add the leading '/dev/' if it doesn't exist make 499/*
524 * sure dst has enough space, if not just copy src (ugh) */ 500 * line_fullname(): add the leading '/dev/' if it doesn't exist make
501 * sure dst has enough space, if not just copy src (ugh)
502 */
525char * 503char *
526line_fullname(char *dst, const char *src, int dstsize) 504line_fullname(char *dst, const char *src, int dstsize)
527{ 505{
528 memset(dst, '\0', dstsize); 506 memset(dst, '\0', dstsize);
529 if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5))) { 507 if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5)))
530 strlcpy(dst, src, dstsize); 508 strlcpy(dst, src, dstsize);
531 } else { 509 else {
532 strlcpy(dst, "/dev/", dstsize); 510 strlcpy(dst, "/dev/", dstsize);
533 strlcat(dst, src, dstsize); 511 strlcat(dst, src, dstsize);
534 } 512 }
535 return dst; 513 return (dst);
536} 514}
537 515
538/* line_stripname(): strip the leading '/dev' if it exists, return dst */ 516/* line_stripname(): strip the leading '/dev' if it exists, return dst */
@@ -544,15 +522,17 @@ line_stripname(char *dst, const char *src, int dstsize)
544 strlcpy(dst, src + 5, dstsize); 522 strlcpy(dst, src + 5, dstsize);
545 else 523 else
546 strlcpy(dst, src, dstsize); 524 strlcpy(dst, src, dstsize);
547 return dst; 525 return (dst);
548} 526}
549 527
550/* line_abbrevname(): Return the abbreviated (usually four-character) 528/*
529 * line_abbrevname(): Return the abbreviated (usually four-character)
551 * form of the line (Just use the last <dstsize> characters of the 530 * form of the line (Just use the last <dstsize> characters of the
552 * full name.) 531 * full name.)
553 * 532 *
554 * NOTE: use strncpy because we do NOT necessarily want zero 533 * NOTE: use strncpy because we do NOT necessarily want zero
555 * termination */ 534 * termination
535 */
556char * 536char *
557line_abbrevname(char *dst, const char *src, int dstsize) 537line_abbrevname(char *dst, const char *src, int dstsize)
558{ 538{
@@ -579,7 +559,7 @@ line_abbrevname(char *dst, const char *src, int dstsize)
579 strncpy(dst, src, (size_t)dstsize); 559 strncpy(dst, src, (size_t)dstsize);
580 } 560 }
581 561
582 return dst; 562 return (dst);
583} 563}
584 564
585/** 565/**
@@ -595,13 +575,11 @@ line_abbrevname(char *dst, const char *src, int dstsize)
595void 575void
596set_utmp_time(struct logininfo *li, struct utmp *ut) 576set_utmp_time(struct logininfo *li, struct utmp *ut)
597{ 577{
598# ifdef HAVE_TV_IN_UTMP 578# if defined(HAVE_TV_IN_UTMP)
599 ut->ut_tv.tv_sec = li->tv_sec; 579 ut->ut_tv.tv_sec = li->tv_sec;
600 ut->ut_tv.tv_usec = li->tv_usec; 580 ut->ut_tv.tv_usec = li->tv_usec;
601# else 581# elif defined(HAVE_TIME_IN_UTMP)
602# ifdef HAVE_TIME_IN_UTMP
603 ut->ut_time = li->tv_sec; 582 ut->ut_time = li->tv_sec;
604# endif
605# endif 583# endif
606} 584}
607 585
@@ -611,7 +589,8 @@ construct_utmp(struct logininfo *li,
611{ 589{
612# ifdef HAVE_ADDR_V6_IN_UTMP 590# ifdef HAVE_ADDR_V6_IN_UTMP
613 struct sockaddr_in6 *sa6; 591 struct sockaddr_in6 *sa6;
614# endif 592# endif
593
615 memset(ut, '\0', sizeof(*ut)); 594 memset(ut, '\0', sizeof(*ut));
616 595
617 /* First fill out fields used for both logins and logouts */ 596 /* First fill out fields used for both logins and logouts */
@@ -647,7 +626,7 @@ construct_utmp(struct logininfo *li,
647 626
648 /* If we're logging out, leave all other fields blank */ 627 /* If we're logging out, leave all other fields blank */
649 if (li->type == LTYPE_LOGOUT) 628 if (li->type == LTYPE_LOGOUT)
650 return; 629 return;
651 630
652 /* 631 /*
653 * These fields are only used when logging in, and are blank 632 * These fields are only used when logging in, and are blank
@@ -655,9 +634,11 @@ construct_utmp(struct logininfo *li,
655 */ 634 */
656 635
657 /* Use strncpy because we don't necessarily want null termination */ 636 /* Use strncpy because we don't necessarily want null termination */
658 strncpy(ut->ut_name, li->username, MIN_SIZEOF(ut->ut_name, li->username)); 637 strncpy(ut->ut_name, li->username,
638 MIN_SIZEOF(ut->ut_name, li->username));
659# ifdef HAVE_HOST_IN_UTMP 639# ifdef HAVE_HOST_IN_UTMP
660 strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname)); 640 strncpy(ut->ut_host, li->hostname,
641 MIN_SIZEOF(ut->ut_host, li->hostname));
661# endif 642# endif
662# ifdef HAVE_ADDR_IN_UTMP 643# ifdef HAVE_ADDR_IN_UTMP
663 /* this is just a 32-bit IP address */ 644 /* this is just a 32-bit IP address */
@@ -692,14 +673,12 @@ construct_utmp(struct logininfo *li,
692void 673void
693set_utmpx_time(struct logininfo *li, struct utmpx *utx) 674set_utmpx_time(struct logininfo *li, struct utmpx *utx)
694{ 675{
695# ifdef HAVE_TV_IN_UTMPX 676# if defined(HAVE_TV_IN_UTMPX)
696 utx->ut_tv.tv_sec = li->tv_sec; 677 utx->ut_tv.tv_sec = li->tv_sec;
697 utx->ut_tv.tv_usec = li->tv_usec; 678 utx->ut_tv.tv_usec = li->tv_usec;
698# else /* HAVE_TV_IN_UTMPX */ 679# elif defined(HAVE_TIME_IN_UTMPX)
699# ifdef HAVE_TIME_IN_UTMPX
700 utx->ut_time = li->tv_sec; 680 utx->ut_time = li->tv_sec;
701# endif /* HAVE_TIME_IN_UTMPX */ 681# endif
702# endif /* HAVE_TV_IN_UTMPX */
703} 682}
704 683
705void 684void
@@ -709,6 +688,7 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx)
709 struct sockaddr_in6 *sa6; 688 struct sockaddr_in6 *sa6;
710# endif 689# endif
711 memset(utx, '\0', sizeof(*utx)); 690 memset(utx, '\0', sizeof(*utx));
691
712# ifdef HAVE_ID_IN_UTMPX 692# ifdef HAVE_ID_IN_UTMPX
713 line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id)); 693 line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id));
714# endif 694# endif
@@ -725,8 +705,10 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx)
725 line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line)); 705 line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line));
726 set_utmpx_time(li, utx); 706 set_utmpx_time(li, utx);
727 utx->ut_pid = li->pid; 707 utx->ut_pid = li->pid;
708
728 /* strncpy(): Don't necessarily want null termination */ 709 /* strncpy(): Don't necessarily want null termination */
729 strncpy(utx->ut_name, li->username, MIN_SIZEOF(utx->ut_name, li->username)); 710 strncpy(utx->ut_name, li->username,
711 MIN_SIZEOF(utx->ut_name, li->username));
730 712
731 if (li->type == LTYPE_LOGOUT) 713 if (li->type == LTYPE_LOGOUT)
732 return; 714 return;
@@ -737,7 +719,8 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx)
737 */ 719 */
738 720
739# ifdef HAVE_HOST_IN_UTMPX 721# ifdef HAVE_HOST_IN_UTMPX
740 strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); 722 strncpy(utx->ut_host, li->hostname,
723 MIN_SIZEOF(utx->ut_host, li->hostname));
741# endif 724# endif
742# ifdef HAVE_ADDR_IN_UTMPX 725# ifdef HAVE_ADDR_IN_UTMPX
743 /* this is just a 32-bit IP address */ 726 /* this is just a 32-bit IP address */
@@ -785,16 +768,17 @@ utmp_write_library(struct logininfo *li, struct utmp *ut)
785{ 768{
786 setutent(); 769 setutent();
787 pututline(ut); 770 pututline(ut);
788
789# ifdef HAVE_ENDUTENT 771# ifdef HAVE_ENDUTENT
790 endutent(); 772 endutent();
791# endif 773# endif
792 return 1; 774 return (1);
793} 775}
794# else /* UTMP_USE_LIBRARY */ 776# else /* UTMP_USE_LIBRARY */
795 777
796/* write a utmp entry direct to the file */ 778/*
797/* This is a slightly modification of code in OpenBSD's login.c */ 779 * Write a utmp entry direct to the file
780 * This is a slightly modification of code in OpenBSD's login.c
781 */
798static int 782static int
799utmp_write_direct(struct logininfo *li, struct utmp *ut) 783utmp_write_direct(struct logininfo *li, struct utmp *ut)
800{ 784{
@@ -805,19 +789,18 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut)
805 /* FIXME: (ATL) ttyslot() needs local implementation */ 789 /* FIXME: (ATL) ttyslot() needs local implementation */
806 790
807#if defined(HAVE_GETTTYENT) 791#if defined(HAVE_GETTTYENT)
808 register struct ttyent *ty; 792 struct ttyent *ty;
809 793
810 tty=0; 794 tty=0;
811
812 setttyent(); 795 setttyent();
813 while ((struct ttyent *)0 != (ty = getttyent())) { 796 while (NULL != (ty = getttyent())) {
814 tty++; 797 tty++;
815 if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line))) 798 if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line)))
816 break; 799 break;
817 } 800 }
818 endttyent(); 801 endttyent();
819 802
820 if((struct ttyent *)0 == ty) { 803 if (NULL == ty) {
821 logit("%s: tty not found", __func__); 804 logit("%s: tty not found", __func__);
822 return (0); 805 return (0);
823 } 806 }
@@ -846,11 +829,10 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut)
846 * and ut_line and ut_name match, preserve the old ut_line. 829 * and ut_line and ut_name match, preserve the old ut_line.
847 */ 830 */
848 if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) && 831 if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) &&
849 (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') && 832 (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') &&
850 (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) && 833 (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) &&
851 (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) { 834 (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0))
852 (void)memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); 835 memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host));
853 }
854 836
855 if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { 837 if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {
856 logit("%s: lseek: %s", __func__, strerror(errno)); 838 logit("%s: lseek: %s", __func__, strerror(errno));
@@ -861,14 +843,15 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut)
861 __func__, tty, UTMP_FILE); 843 __func__, tty, UTMP_FILE);
862 return (0); 844 return (0);
863 } 845 }
864 if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) 846 if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
865 logit("%s: error writing %s: %s", __func__, 847 logit("%s: error writing %s: %s", __func__,
866 UTMP_FILE, strerror(errno)); 848 UTMP_FILE, strerror(errno));
849 }
867 850
868 (void)close(fd); 851 close(fd);
869 return 1; 852 return (1);
870 } else { 853 } else {
871 return 0; 854 return (0);
872 } 855 }
873} 856}
874# endif /* UTMP_USE_LIBRARY */ 857# endif /* UTMP_USE_LIBRARY */
@@ -882,15 +865,15 @@ utmp_perform_login(struct logininfo *li)
882# ifdef UTMP_USE_LIBRARY 865# ifdef UTMP_USE_LIBRARY
883 if (!utmp_write_library(li, &ut)) { 866 if (!utmp_write_library(li, &ut)) {
884 logit("utmp_perform_login: utmp_write_library() failed"); 867 logit("utmp_perform_login: utmp_write_library() failed");
885 return 0; 868 return (0);
886 } 869 }
887# else 870# else
888 if (!utmp_write_direct(li, &ut)) { 871 if (!utmp_write_direct(li, &ut)) {
889 logit("utmp_perform_login: utmp_write_direct() failed"); 872 logit("utmp_perform_login: utmp_write_direct() failed");
890 return 0; 873 return (0);
891 } 874 }
892# endif 875# endif
893 return 1; 876 return (1);
894} 877}
895 878
896 879
@@ -903,15 +886,15 @@ utmp_perform_logout(struct logininfo *li)
903# ifdef UTMP_USE_LIBRARY 886# ifdef UTMP_USE_LIBRARY
904 if (!utmp_write_library(li, &ut)) { 887 if (!utmp_write_library(li, &ut)) {
905 logit("utmp_perform_logout: utmp_write_library() failed"); 888 logit("utmp_perform_logout: utmp_write_library() failed");
906 return 0; 889 return (0);
907 } 890 }
908# else 891# else
909 if (!utmp_write_direct(li, &ut)) { 892 if (!utmp_write_direct(li, &ut)) {
910 logit("utmp_perform_logout: utmp_write_direct() failed"); 893 logit("utmp_perform_logout: utmp_write_direct() failed");
911 return 0; 894 return (0);
912 } 895 }
913# endif 896# endif
914 return 1; 897 return (1);
915} 898}
916 899
917 900
@@ -920,14 +903,14 @@ utmp_write_entry(struct logininfo *li)
920{ 903{
921 switch(li->type) { 904 switch(li->type) {
922 case LTYPE_LOGIN: 905 case LTYPE_LOGIN:
923 return utmp_perform_login(li); 906 return (utmp_perform_login(li));
924 907
925 case LTYPE_LOGOUT: 908 case LTYPE_LOGOUT:
926 return utmp_perform_logout(li); 909 return (utmp_perform_logout(li));
927 910
928 default: 911 default:
929 logit("utmp_write_entry: invalid type field"); 912 logit("utmp_write_entry: invalid type field");
930 return 0; 913 return (0);
931 } 914 }
932} 915}
933#endif /* USE_UTMP */ 916#endif /* USE_UTMP */
@@ -958,7 +941,7 @@ utmpx_write_library(struct logininfo *li, struct utmpx *utx)
958# ifdef HAVE_ENDUTXENT 941# ifdef HAVE_ENDUTXENT
959 endutxent(); 942 endutxent();
960# endif 943# endif
961 return 1; 944 return (1);
962} 945}
963 946
964# else /* UTMPX_USE_LIBRARY */ 947# else /* UTMPX_USE_LIBRARY */
@@ -968,7 +951,7 @@ static int
968utmpx_write_direct(struct logininfo *li, struct utmpx *utx) 951utmpx_write_direct(struct logininfo *li, struct utmpx *utx)
969{ 952{
970 logit("utmpx_write_direct: not implemented!"); 953 logit("utmpx_write_direct: not implemented!");
971 return 0; 954 return (0);
972} 955}
973# endif /* UTMPX_USE_LIBRARY */ 956# endif /* UTMPX_USE_LIBRARY */
974 957
@@ -981,15 +964,15 @@ utmpx_perform_login(struct logininfo *li)
981# ifdef UTMPX_USE_LIBRARY 964# ifdef UTMPX_USE_LIBRARY
982 if (!utmpx_write_library(li, &utx)) { 965 if (!utmpx_write_library(li, &utx)) {
983 logit("utmpx_perform_login: utmp_write_library() failed"); 966 logit("utmpx_perform_login: utmp_write_library() failed");
984 return 0; 967 return (0);
985 } 968 }
986# else 969# else
987 if (!utmpx_write_direct(li, &ut)) { 970 if (!utmpx_write_direct(li, &ut)) {
988 logit("utmpx_perform_login: utmp_write_direct() failed"); 971 logit("utmpx_perform_login: utmp_write_direct() failed");
989 return 0; 972 return (0);
990 } 973 }
991# endif 974# endif
992 return 1; 975 return (1);
993} 976}
994 977
995 978
@@ -1011,7 +994,7 @@ utmpx_perform_logout(struct logininfo *li)
1011# else 994# else
1012 utmpx_write_direct(li, &utx); 995 utmpx_write_direct(li, &utx);
1013# endif 996# endif
1014 return 1; 997 return (1);
1015} 998}
1016 999
1017int 1000int
@@ -1019,12 +1002,12 @@ utmpx_write_entry(struct logininfo *li)
1019{ 1002{
1020 switch(li->type) { 1003 switch(li->type) {
1021 case LTYPE_LOGIN: 1004 case LTYPE_LOGIN:
1022 return utmpx_perform_login(li); 1005 return (utmpx_perform_login(li));
1023 case LTYPE_LOGOUT: 1006 case LTYPE_LOGOUT:
1024 return utmpx_perform_logout(li); 1007 return (utmpx_perform_logout(li));
1025 default: 1008 default:
1026 logit("utmpx_write_entry: invalid type field"); 1009 logit("utmpx_write_entry: invalid type field");
1027 return 0; 1010 return (0);
1028 } 1011 }
1029} 1012}
1030#endif /* USE_UTMPX */ 1013#endif /* USE_UTMPX */
@@ -1036,8 +1019,10 @@ utmpx_write_entry(struct logininfo *li)
1036 1019
1037#ifdef USE_WTMP 1020#ifdef USE_WTMP
1038 1021
1039/* write a wtmp entry direct to the end of the file */ 1022/*
1040/* This is a slight modification of code in OpenBSD's logwtmp.c */ 1023 * Write a wtmp entry direct to the end of the file
1024 * This is a slight modification of code in OpenBSD's logwtmp.c
1025 */
1041static int 1026static int
1042wtmp_write(struct logininfo *li, struct utmp *ut) 1027wtmp_write(struct logininfo *li, struct utmp *ut)
1043{ 1028{
@@ -1047,7 +1032,7 @@ wtmp_write(struct logininfo *li, struct utmp *ut)
1047 if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { 1032 if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) {
1048 logit("wtmp_write: problem writing %s: %s", 1033 logit("wtmp_write: problem writing %s: %s",
1049 WTMP_FILE, strerror(errno)); 1034 WTMP_FILE, strerror(errno));
1050 return 0; 1035 return (0);
1051 } 1036 }
1052 if (fstat(fd, &buf) == 0) 1037 if (fstat(fd, &buf) == 0)
1053 if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) { 1038 if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
@@ -1056,8 +1041,8 @@ wtmp_write(struct logininfo *li, struct utmp *ut)
1056 WTMP_FILE, strerror(errno)); 1041 WTMP_FILE, strerror(errno));
1057 ret = 0; 1042 ret = 0;
1058 } 1043 }
1059 (void)close(fd); 1044 close(fd);
1060 return ret; 1045 return (ret);
1061} 1046}
1062 1047
1063static int 1048static int
@@ -1066,7 +1051,7 @@ wtmp_perform_login(struct logininfo *li)
1066 struct utmp ut; 1051 struct utmp ut;
1067 1052
1068 construct_utmp(li, &ut); 1053 construct_utmp(li, &ut);
1069 return wtmp_write(li, &ut); 1054 return (wtmp_write(li, &ut));
1070} 1055}
1071 1056
1072 1057
@@ -1076,7 +1061,7 @@ wtmp_perform_logout(struct logininfo *li)
1076 struct utmp ut; 1061 struct utmp ut;
1077 1062
1078 construct_utmp(li, &ut); 1063 construct_utmp(li, &ut);
1079 return wtmp_write(li, &ut); 1064 return (wtmp_write(li, &ut));
1080} 1065}
1081 1066
1082 1067
@@ -1085,17 +1070,18 @@ wtmp_write_entry(struct logininfo *li)
1085{ 1070{
1086 switch(li->type) { 1071 switch(li->type) {
1087 case LTYPE_LOGIN: 1072 case LTYPE_LOGIN:
1088 return wtmp_perform_login(li); 1073 return (wtmp_perform_login(li));
1089 case LTYPE_LOGOUT: 1074 case LTYPE_LOGOUT:
1090 return wtmp_perform_logout(li); 1075 return (wtmp_perform_logout(li));
1091 default: 1076 default:
1092 logit("wtmp_write_entry: invalid type field"); 1077 logit("wtmp_write_entry: invalid type field");
1093 return 0; 1078 return (0);
1094 } 1079 }
1095} 1080}
1096 1081
1097 1082
1098/* Notes on fetching login data from wtmp/wtmpx 1083/*
1084 * Notes on fetching login data from wtmp/wtmpx
1099 * 1085 *
1100 * Logouts are usually recorded with (amongst other things) a blank 1086 * Logouts are usually recorded with (amongst other things) a blank
1101 * username on a given tty line. However, some systems (HP-UX is one) 1087 * username on a given tty line. However, some systems (HP-UX is one)
@@ -1116,15 +1102,15 @@ static int
1116wtmp_islogin(struct logininfo *li, struct utmp *ut) 1102wtmp_islogin(struct logininfo *li, struct utmp *ut)
1117{ 1103{
1118 if (strncmp(li->username, ut->ut_name, 1104 if (strncmp(li->username, ut->ut_name,
1119 MIN_SIZEOF(li->username, ut->ut_name)) == 0) { 1105 MIN_SIZEOF(li->username, ut->ut_name)) == 0) {
1120# ifdef HAVE_TYPE_IN_UTMP 1106# ifdef HAVE_TYPE_IN_UTMP
1121 if (ut->ut_type & USER_PROCESS) 1107 if (ut->ut_type & USER_PROCESS)
1122 return 1; 1108 return (1);
1123# else 1109# else
1124 return 1; 1110 return (1);
1125# endif 1111# endif
1126 } 1112 }
1127 return 0; 1113 return (0);
1128} 1114}
1129 1115
1130int 1116int
@@ -1132,7 +1118,7 @@ wtmp_get_entry(struct logininfo *li)
1132{ 1118{
1133 struct stat st; 1119 struct stat st;
1134 struct utmp ut; 1120 struct utmp ut;
1135 int fd, found=0; 1121 int fd, found = 0;
1136 1122
1137 /* Clear the time entries in our logininfo */ 1123 /* Clear the time entries in our logininfo */
1138 li->tv_sec = li->tv_usec = 0; 1124 li->tv_sec = li->tv_usec = 0;
@@ -1140,20 +1126,20 @@ wtmp_get_entry(struct logininfo *li)
1140 if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { 1126 if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) {
1141 logit("wtmp_get_entry: problem opening %s: %s", 1127 logit("wtmp_get_entry: problem opening %s: %s",
1142 WTMP_FILE, strerror(errno)); 1128 WTMP_FILE, strerror(errno));
1143 return 0; 1129 return (0);
1144 } 1130 }
1145 if (fstat(fd, &st) != 0) { 1131 if (fstat(fd, &st) != 0) {
1146 logit("wtmp_get_entry: couldn't stat %s: %s", 1132 logit("wtmp_get_entry: couldn't stat %s: %s",
1147 WTMP_FILE, strerror(errno)); 1133 WTMP_FILE, strerror(errno));
1148 close(fd); 1134 close(fd);
1149 return 0; 1135 return (0);
1150 } 1136 }
1151 1137
1152 /* Seek to the start of the last struct utmp */ 1138 /* Seek to the start of the last struct utmp */
1153 if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) { 1139 if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) {
1154 /* Looks like we've got a fresh wtmp file */ 1140 /* Looks like we've got a fresh wtmp file */
1155 close(fd); 1141 close(fd);
1156 return 0; 1142 return (0);
1157 } 1143 }
1158 1144
1159 while (!found) { 1145 while (!found) {
@@ -1161,12 +1147,14 @@ wtmp_get_entry(struct logininfo *li)
1161 logit("wtmp_get_entry: read of %s failed: %s", 1147 logit("wtmp_get_entry: read of %s failed: %s",
1162 WTMP_FILE, strerror(errno)); 1148 WTMP_FILE, strerror(errno));
1163 close (fd); 1149 close (fd);
1164 return 0; 1150 return (0);
1165 } 1151 }
1166 if ( wtmp_islogin(li, &ut) ) { 1152 if ( wtmp_islogin(li, &ut) ) {
1167 found = 1; 1153 found = 1;
1168 /* We've already checked for a time in struct 1154 /*
1169 * utmp, in login_getlast(). */ 1155 * We've already checked for a time in struct
1156 * utmp, in login_getlast()
1157 */
1170# ifdef HAVE_TIME_IN_UTMP 1158# ifdef HAVE_TIME_IN_UTMP
1171 li->tv_sec = ut.ut_time; 1159 li->tv_sec = ut.ut_time;
1172# else 1160# else
@@ -1175,24 +1163,24 @@ wtmp_get_entry(struct logininfo *li)
1175# endif 1163# endif
1176# endif 1164# endif
1177 line_fullname(li->line, ut.ut_line, 1165 line_fullname(li->line, ut.ut_line,
1178 MIN_SIZEOF(li->line, ut.ut_line)); 1166 MIN_SIZEOF(li->line, ut.ut_line));
1179# ifdef HAVE_HOST_IN_UTMP 1167# ifdef HAVE_HOST_IN_UTMP
1180 strlcpy(li->hostname, ut.ut_host, 1168 strlcpy(li->hostname, ut.ut_host,
1181 MIN_SIZEOF(li->hostname, ut.ut_host)); 1169 MIN_SIZEOF(li->hostname, ut.ut_host));
1182# endif 1170# endif
1183 continue; 1171 continue;
1184 } 1172 }
1185 /* Seek back 2 x struct utmp */ 1173 /* Seek back 2 x struct utmp */
1186 if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) { 1174 if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) {
1187 /* We've found the start of the file, so quit */ 1175 /* We've found the start of the file, so quit */
1188 close (fd); 1176 close(fd);
1189 return 0; 1177 return (0);
1190 } 1178 }
1191 } 1179 }
1192 1180
1193 /* We found an entry. Tidy up and return */ 1181 /* We found an entry. Tidy up and return */
1194 close(fd); 1182 close(fd);
1195 return 1; 1183 return (1);
1196} 1184}
1197# endif /* USE_WTMP */ 1185# endif /* USE_WTMP */
1198 1186
@@ -1202,8 +1190,10 @@ wtmp_get_entry(struct logininfo *li)
1202 **/ 1190 **/
1203 1191
1204#ifdef USE_WTMPX 1192#ifdef USE_WTMPX
1205/* write a wtmpx entry direct to the end of the file */ 1193/*
1206/* This is a slight modification of code in OpenBSD's logwtmp.c */ 1194 * Write a wtmpx entry direct to the end of the file
1195 * This is a slight modification of code in OpenBSD's logwtmp.c
1196 */
1207static int 1197static int
1208wtmpx_write(struct logininfo *li, struct utmpx *utx) 1198wtmpx_write(struct logininfo *li, struct utmpx *utx)
1209{ 1199{
@@ -1214,7 +1204,7 @@ wtmpx_write(struct logininfo *li, struct utmpx *utx)
1214 if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { 1204 if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) {
1215 logit("wtmpx_write: problem opening %s: %s", 1205 logit("wtmpx_write: problem opening %s: %s",
1216 WTMPX_FILE, strerror(errno)); 1206 WTMPX_FILE, strerror(errno));
1217 return 0; 1207 return (0);
1218 } 1208 }
1219 1209
1220 if (fstat(fd, &buf) == 0) 1210 if (fstat(fd, &buf) == 0)
@@ -1224,12 +1214,12 @@ wtmpx_write(struct logininfo *li, struct utmpx *utx)
1224 WTMPX_FILE, strerror(errno)); 1214 WTMPX_FILE, strerror(errno));
1225 ret = 0; 1215 ret = 0;
1226 } 1216 }
1227 (void)close(fd); 1217 close(fd);
1228 1218
1229 return ret; 1219 return (ret);
1230#else 1220#else
1231 updwtmpx(WTMPX_FILE, utx); 1221 updwtmpx(WTMPX_FILE, utx);
1232 return 1; 1222 return (1);
1233#endif 1223#endif
1234} 1224}
1235 1225
@@ -1240,7 +1230,7 @@ wtmpx_perform_login(struct logininfo *li)
1240 struct utmpx utx; 1230 struct utmpx utx;
1241 1231
1242 construct_utmpx(li, &utx); 1232 construct_utmpx(li, &utx);
1243 return wtmpx_write(li, &utx); 1233 return (wtmpx_write(li, &utx));
1244} 1234}
1245 1235
1246 1236
@@ -1250,7 +1240,7 @@ wtmpx_perform_logout(struct logininfo *li)
1250 struct utmpx utx; 1240 struct utmpx utx;
1251 1241
1252 construct_utmpx(li, &utx); 1242 construct_utmpx(li, &utx);
1253 return wtmpx_write(li, &utx); 1243 return (wtmpx_write(li, &utx));
1254} 1244}
1255 1245
1256 1246
@@ -1259,12 +1249,12 @@ wtmpx_write_entry(struct logininfo *li)
1259{ 1249{
1260 switch(li->type) { 1250 switch(li->type) {
1261 case LTYPE_LOGIN: 1251 case LTYPE_LOGIN:
1262 return wtmpx_perform_login(li); 1252 return (wtmpx_perform_login(li));
1263 case LTYPE_LOGOUT: 1253 case LTYPE_LOGOUT:
1264 return wtmpx_perform_logout(li); 1254 return (wtmpx_perform_logout(li));
1265 default: 1255 default:
1266 logit("wtmpx_write_entry: invalid type field"); 1256 logit("wtmpx_write_entry: invalid type field");
1267 return 0; 1257 return (0);
1268 } 1258 }
1269} 1259}
1270 1260
@@ -1275,16 +1265,16 @@ wtmpx_write_entry(struct logininfo *li)
1275static int 1265static int
1276wtmpx_islogin(struct logininfo *li, struct utmpx *utx) 1266wtmpx_islogin(struct logininfo *li, struct utmpx *utx)
1277{ 1267{
1278 if ( strncmp(li->username, utx->ut_name, 1268 if (strncmp(li->username, utx->ut_name,
1279 MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) { 1269 MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) {
1280# ifdef HAVE_TYPE_IN_UTMPX 1270# ifdef HAVE_TYPE_IN_UTMPX
1281 if (utx->ut_type == USER_PROCESS) 1271 if (utx->ut_type == USER_PROCESS)
1282 return 1; 1272 return (1);
1283# else 1273# else
1284 return 1; 1274 return (1);
1285# endif 1275# endif
1286 } 1276 }
1287 return 0; 1277 return (0);
1288} 1278}
1289 1279
1290 1280
@@ -1301,20 +1291,20 @@ wtmpx_get_entry(struct logininfo *li)
1301 if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { 1291 if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) {
1302 logit("wtmpx_get_entry: problem opening %s: %s", 1292 logit("wtmpx_get_entry: problem opening %s: %s",
1303 WTMPX_FILE, strerror(errno)); 1293 WTMPX_FILE, strerror(errno));
1304 return 0; 1294 return (0);
1305 } 1295 }
1306 if (fstat(fd, &st) != 0) { 1296 if (fstat(fd, &st) != 0) {
1307 logit("wtmpx_get_entry: couldn't stat %s: %s", 1297 logit("wtmpx_get_entry: couldn't stat %s: %s",
1308 WTMPX_FILE, strerror(errno)); 1298 WTMPX_FILE, strerror(errno));
1309 close(fd); 1299 close(fd);
1310 return 0; 1300 return (0);
1311 } 1301 }
1312 1302
1313 /* Seek to the start of the last struct utmpx */ 1303 /* Seek to the start of the last struct utmpx */
1314 if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) { 1304 if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) {
1315 /* probably a newly rotated wtmpx file */ 1305 /* probably a newly rotated wtmpx file */
1316 close(fd); 1306 close(fd);
1317 return 0; 1307 return (0);
1318 } 1308 }
1319 1309
1320 while (!found) { 1310 while (!found) {
@@ -1322,34 +1312,34 @@ wtmpx_get_entry(struct logininfo *li)
1322 logit("wtmpx_get_entry: read of %s failed: %s", 1312 logit("wtmpx_get_entry: read of %s failed: %s",
1323 WTMPX_FILE, strerror(errno)); 1313 WTMPX_FILE, strerror(errno));
1324 close (fd); 1314 close (fd);
1325 return 0; 1315 return (0);
1326 } 1316 }
1327 /* Logouts are recorded as a blank username on a particular line. 1317 /*
1328 * So, we just need to find the username in struct utmpx */ 1318 * Logouts are recorded as a blank username on a particular
1329 if ( wtmpx_islogin(li, &utx) ) { 1319 * line. So, we just need to find the username in struct utmpx
1320 */
1321 if (wtmpx_islogin(li, &utx)) {
1330 found = 1; 1322 found = 1;
1331# ifdef HAVE_TV_IN_UTMPX 1323# if defined(HAVE_TV_IN_UTMPX)
1332 li->tv_sec = utx.ut_tv.tv_sec; 1324 li->tv_sec = utx.ut_tv.tv_sec;
1333# else 1325# elif defined(HAVE_TIME_IN_UTMPX)
1334# ifdef HAVE_TIME_IN_UTMPX
1335 li->tv_sec = utx.ut_time; 1326 li->tv_sec = utx.ut_time;
1336# endif
1337# endif 1327# endif
1338 line_fullname(li->line, utx.ut_line, sizeof(li->line)); 1328 line_fullname(li->line, utx.ut_line, sizeof(li->line));
1339# ifdef HAVE_HOST_IN_UTMPX 1329# if defined(HAVE_HOST_IN_UTMPX)
1340 strlcpy(li->hostname, utx.ut_host, 1330 strlcpy(li->hostname, utx.ut_host,
1341 MIN_SIZEOF(li->hostname, utx.ut_host)); 1331 MIN_SIZEOF(li->hostname, utx.ut_host));
1342# endif 1332# endif
1343 continue; 1333 continue;
1344 } 1334 }
1345 if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) { 1335 if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) {
1346 close (fd); 1336 close(fd);
1347 return 0; 1337 return (0);
1348 } 1338 }
1349 } 1339 }
1350 1340
1351 close(fd); 1341 close(fd);
1352 return 1; 1342 return (1);
1353} 1343}
1354#endif /* USE_WTMPX */ 1344#endif /* USE_WTMPX */
1355 1345
@@ -1363,15 +1353,15 @@ syslogin_perform_login(struct logininfo *li)
1363{ 1353{
1364 struct utmp *ut; 1354 struct utmp *ut;
1365 1355
1366 if (! (ut = (struct utmp *)malloc(sizeof(*ut)))) { 1356 if ((ut = (struct utmp *)malloc(sizeof(*ut))) == NULL) {
1367 logit("syslogin_perform_login: couldn't malloc()"); 1357 logit("syslogin_perform_login: couldn't malloc()");
1368 return 0; 1358 return (0);
1369 } 1359 }
1370 construct_utmp(li, ut); 1360 construct_utmp(li, ut);
1371 login(ut); 1361 login(ut);
1372 free(ut); 1362 free(ut);
1373 1363
1374 return 1; 1364 return (1);
1375} 1365}
1376 1366
1377static int 1367static int
@@ -1382,19 +1372,18 @@ syslogin_perform_logout(struct logininfo *li)
1382 1372
1383 (void)line_stripname(line, li->line, sizeof(line)); 1373 (void)line_stripname(line, li->line, sizeof(line));
1384 1374
1385 if (!logout(line)) { 1375 if (!logout(line))
1386 logit("syslogin_perform_logout: logout() returned an error"); 1376 logit("syslogin_perform_logout: logout() returned an error");
1387# ifdef HAVE_LOGWTMP 1377# ifdef HAVE_LOGWTMP
1388 } else { 1378 else
1389 logwtmp(line, "", ""); 1379 logwtmp(line, "", "");
1390# endif 1380# endif
1391 }
1392 /* FIXME: (ATL - if the need arises) What to do if we have 1381 /* FIXME: (ATL - if the need arises) What to do if we have
1393 * login, but no logout? what if logout but no logwtmp? All 1382 * login, but no logout? what if logout but no logwtmp? All
1394 * routines are in libutil so they should all be there, 1383 * routines are in libutil so they should all be there,
1395 * but... */ 1384 * but... */
1396# endif 1385# endif
1397 return 1; 1386 return (1);
1398} 1387}
1399 1388
1400int 1389int
@@ -1402,12 +1391,12 @@ syslogin_write_entry(struct logininfo *li)
1402{ 1391{
1403 switch (li->type) { 1392 switch (li->type) {
1404 case LTYPE_LOGIN: 1393 case LTYPE_LOGIN:
1405 return syslogin_perform_login(li); 1394 return (syslogin_perform_login(li));
1406 case LTYPE_LOGOUT: 1395 case LTYPE_LOGOUT:
1407 return syslogin_perform_logout(li); 1396 return (syslogin_perform_logout(li));
1408 default: 1397 default:
1409 logit("syslogin_write_entry: Invalid type field"); 1398 logit("syslogin_write_entry: Invalid type field");
1410 return 0; 1399 return (0);
1411 } 1400 }
1412} 1401}
1413#endif /* USE_LOGIN */ 1402#endif /* USE_LOGIN */
@@ -1429,7 +1418,7 @@ lastlog_construct(struct logininfo *li, struct lastlog *last)
1429 /* clear the structure */ 1418 /* clear the structure */
1430 memset(last, '\0', sizeof(*last)); 1419 memset(last, '\0', sizeof(*last));
1431 1420
1432 (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); 1421 line_stripname(last->ll_line, li->line, sizeof(last->ll_line));
1433 strlcpy(last->ll_host, li->hostname, 1422 strlcpy(last->ll_host, li->hostname,
1434 MIN_SIZEOF(last->ll_host, li->hostname)); 1423 MIN_SIZEOF(last->ll_host, li->hostname));
1435 last->ll_time = li->tv_sec; 1424 last->ll_time = li->tv_sec;
@@ -1441,16 +1430,16 @@ lastlog_filetype(char *filename)
1441 struct stat st; 1430 struct stat st;
1442 1431
1443 if (stat(LASTLOG_FILE, &st) != 0) { 1432 if (stat(LASTLOG_FILE, &st) != 0) {
1444 logit("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE, 1433 logit("lastlog_perform_login: Couldn't stat %s: %s",
1445 strerror(errno)); 1434 LASTLOG_FILE, strerror(errno));
1446 return 0; 1435 return (0);
1447 } 1436 }
1448 if (S_ISDIR(st.st_mode)) 1437 if (S_ISDIR(st.st_mode))
1449 return LL_DIR; 1438 return (LL_DIR);
1450 else if (S_ISREG(st.st_mode)) 1439 else if (S_ISREG(st.st_mode))
1451 return LL_FILE; 1440 return (LL_FILE);
1452 else 1441 else
1453 return LL_OTHER; 1442 return (LL_OTHER);
1454} 1443}
1455 1444
1456 1445
@@ -1464,38 +1453,39 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode)
1464 1453
1465 type = lastlog_filetype(LASTLOG_FILE); 1454 type = lastlog_filetype(LASTLOG_FILE);
1466 switch (type) { 1455 switch (type) {
1467 case LL_FILE: 1456 case LL_FILE:
1468 strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); 1457 strlcpy(lastlog_file, LASTLOG_FILE,
1469 break; 1458 sizeof(lastlog_file));
1470 case LL_DIR: 1459 break;
1471 snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", 1460 case LL_DIR:
1472 LASTLOG_FILE, li->username); 1461 snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s",
1473 break; 1462 LASTLOG_FILE, li->username);
1474 default: 1463 break;
1475 logit("lastlog_openseek: %.100s is not a file or directory!", 1464 default:
1476 LASTLOG_FILE); 1465 logit("lastlog_openseek: %.100s is not a file or directory!",
1477 return 0; 1466 LASTLOG_FILE);
1467 return (0);
1478 } 1468 }
1479 1469
1480 *fd = open(lastlog_file, filemode, 0600); 1470 *fd = open(lastlog_file, filemode, 0600);
1481 if ( *fd < 0) { 1471 if (*fd < 0) {
1482 debug("lastlog_openseek: Couldn't open %s: %s", 1472 debug("lastlog_openseek: Couldn't open %s: %s",
1483 lastlog_file, strerror(errno)); 1473 lastlog_file, strerror(errno));
1484 return 0; 1474 return (0);
1485 } 1475 }
1486 1476
1487 if (type == LL_FILE) { 1477 if (type == LL_FILE) {
1488 /* find this uid's offset in the lastlog file */ 1478 /* find this uid's offset in the lastlog file */
1489 offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); 1479 offset = (off_t) ((long)li->uid * sizeof(struct lastlog));
1490 1480
1491 if ( lseek(*fd, offset, SEEK_SET) != offset ) { 1481 if (lseek(*fd, offset, SEEK_SET) != offset) {
1492 logit("lastlog_openseek: %s->lseek(): %s", 1482 logit("lastlog_openseek: %s->lseek(): %s",
1493 lastlog_file, strerror(errno)); 1483 lastlog_file, strerror(errno));
1494 return 0; 1484 return (0);
1495 } 1485 }
1496 } 1486 }
1497 1487
1498 return 1; 1488 return (1);
1499} 1489}
1500 1490
1501static int 1491static int
@@ -1508,18 +1498,18 @@ lastlog_perform_login(struct logininfo *li)
1508 lastlog_construct(li, &last); 1498 lastlog_construct(li, &last);
1509 1499
1510 if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) 1500 if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT))
1511 return(0); 1501 return (0);
1512 1502
1513 /* write the entry */ 1503 /* write the entry */
1514 if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { 1504 if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) {
1515 close(fd); 1505 close(fd);
1516 logit("lastlog_write_filemode: Error writing to %s: %s", 1506 logit("lastlog_write_filemode: Error writing to %s: %s",
1517 LASTLOG_FILE, strerror(errno)); 1507 LASTLOG_FILE, strerror(errno));
1518 return 0; 1508 return (0);
1519 } 1509 }
1520 1510
1521 close(fd); 1511 close(fd);
1522 return 1; 1512 return (1);
1523} 1513}
1524 1514
1525int 1515int
@@ -1527,10 +1517,10 @@ lastlog_write_entry(struct logininfo *li)
1527{ 1517{
1528 switch(li->type) { 1518 switch(li->type) {
1529 case LTYPE_LOGIN: 1519 case LTYPE_LOGIN:
1530 return lastlog_perform_login(li); 1520 return (lastlog_perform_login(li));
1531 default: 1521 default:
1532 logit("lastlog_write_entry: Invalid type field"); 1522 logit("lastlog_write_entry: Invalid type field");
1533 return 0; 1523 return (0);
1534 } 1524 }
1535} 1525}
1536 1526
@@ -1539,7 +1529,7 @@ lastlog_populate_entry(struct logininfo *li, struct lastlog *last)
1539{ 1529{
1540 line_fullname(li->line, last->ll_line, sizeof(li->line)); 1530 line_fullname(li->line, last->ll_line, sizeof(li->line));
1541 strlcpy(li->hostname, last->ll_host, 1531 strlcpy(li->hostname, last->ll_host,
1542 MIN_SIZEOF(li->hostname, last->ll_host)); 1532 MIN_SIZEOF(li->hostname, last->ll_host));
1543 li->tv_sec = last->ll_time; 1533 li->tv_sec = last->ll_time;
1544} 1534}
1545 1535