summaryrefslogtreecommitdiff
path: root/loginrec.c
diff options
context:
space:
mode:
authorKevin Steves <stevesk@pobox.com>2001-02-05 12:42:17 +0000
committerKevin Steves <stevesk@pobox.com>2001-02-05 12:42:17 +0000
commitef4eea9badfb65f05ac24f786b710cc3f27f0e43 (patch)
treef54abef181ccd6ad5285a5c16b4c159d8b74e932 /loginrec.c
parentd2ddda4efab29fd8663757634773fa10e557e0f3 (diff)
- stevesk@cvs.openbsd.org 2001/02/04 08:32:27
[many files; did this manually to our top-level source dir] unexpand and remove end-of-line whitespace; ok markus@
Diffstat (limited to 'loginrec.c')
-rw-r--r--loginrec.c104
1 files changed, 52 insertions, 52 deletions
diff --git a/loginrec.c b/loginrec.c
index dc723f742..d74833224 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -30,7 +30,7 @@
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/** 33/**
34 ** loginrec.c: platform-independent login recording and lastlog retrieval 34 ** loginrec.c: platform-independent login recording and lastlog retrieval
35 **/ 35 **/
36 36
@@ -63,7 +63,7 @@
63 requires very thorough testing so we do not corrupt local auditing 63 requires very thorough testing so we do not corrupt local auditing
64 information. These files and their access methods are very system 64 information. These files and their access methods are very system
65 specific indeed. 65 specific indeed.
66 66
67 For utmpx systems, the corresponding library functions are 67 For utmpx systems, the corresponding library functions are
68 setutxent() etc. To the author's knowledge, all utmpx systems have 68 setutxent() etc. To the author's knowledge, all utmpx systems have
69 these library functions and so no direct write is attempted. If such 69 these library functions and so no direct write is attempted. If such
@@ -82,14 +82,14 @@
82 82
83 Calling the new code 83 Calling the new code
84 -------------------- 84 --------------------
85 85
86 In OpenSSH all login recording and retrieval is performed in 86 In OpenSSH all login recording and retrieval is performed in
87 login.c. Here you'll find working examples. Also, in the logintest.c 87 login.c. Here you'll find working examples. Also, in the logintest.c
88 program there are more examples. 88 program there are more examples.
89 89
90 Internal handler calling method 90 Internal handler calling method
91 ------------------------------- 91 -------------------------------
92 92
93 When a call is made to login_login() or login_logout(), both 93 When a call is made to login_login() or login_logout(), both
94 routines set a struct logininfo flag defining which action (log in, 94 routines set a struct logininfo flag defining which action (log in,
95 or log out) is to be taken. They both then call login_write(), which 95 or log out) is to be taken. They both then call login_write(), which
@@ -127,7 +127,7 @@
127 with 'make logintest' as it's not built by default.) 127 with 'make logintest' as it's not built by default.)
128 128
129 Otherwise, patches to the specific method(s) are very helpful! 129 Otherwise, patches to the specific method(s) are very helpful!
130 130
131*/ 131*/
132 132
133/** 133/**
@@ -163,7 +163,7 @@
163#include "log.h" 163#include "log.h"
164#include "atomicio.h" 164#include "atomicio.h"
165 165
166RCSID("$Id: loginrec.c,v 1.30 2001/01/22 05:34:42 mouring Exp $"); 166RCSID("$Id: loginrec.c,v 1.31 2001/02/05 12:42:17 stevesk Exp $");
167 167
168#ifdef HAVE_UTIL_H 168#ifdef HAVE_UTIL_H
169# include <util.h> 169# include <util.h>
@@ -207,7 +207,7 @@ int wtmpx_get_entry(struct logininfo *li);
207 **/ 207 **/
208 208
209/* login_login(struct logininfo *) -Record a login 209/* login_login(struct logininfo *) -Record a login
210 * 210 *
211 * Call with a pointer to a struct logininfo initialised with 211 * Call with a pointer to a struct logininfo initialised with
212 * login_init_entry() or login_alloc_entry() 212 * login_init_entry() or login_alloc_entry()
213 * 213 *
@@ -287,17 +287,17 @@ login_get_lastlog(struct logininfo *li, const int uid)
287 memset(li, '\0', sizeof(*li)); 287 memset(li, '\0', sizeof(*li));
288 li->uid = uid; 288 li->uid = uid;
289 289
290 /* 290 /*
291 * If we don't have a 'real' lastlog, we need the username to 291 * If we don't have a 'real' lastlog, we need the username to
292 * reliably search wtmp(x) for the last login (see 292 * reliably search wtmp(x) for the last login (see
293 * wtmp_get_entry().) 293 * wtmp_get_entry().)
294 */ 294 */
295 pw = getpwuid(uid); 295 pw = getpwuid(uid);
296 if (pw == NULL) 296 if (pw == NULL)
297 fatal("login_get_lastlog: Cannot find account for uid %i", uid); 297 fatal("login_get_lastlog: Cannot find account for uid %i", uid);
298 298
299 /* No MIN_SIZEOF here - we absolutely *must not* truncate the 299 /* No MIN_SIZEOF here - we absolutely *must not* truncate the
300 * username */ 300 * username */
301 strlcpy(li->username, pw->pw_name, sizeof(li->username)); 301 strlcpy(li->username, pw->pw_name, sizeof(li->username));
302 302
303 if (getlast_entry(li)) 303 if (getlast_entry(li))
@@ -308,8 +308,8 @@ login_get_lastlog(struct logininfo *li, const int uid)
308 308
309 309
310/* login_alloc_entry(int, char*, char*, char*) - Allocate and initialise 310/* login_alloc_entry(int, char*, char*, char*) - Allocate and initialise
311 * a logininfo structure 311 * a logininfo structure
312 * 312 *
313 * This function creates a new struct logininfo, a data structure 313 * This function creates a new struct logininfo, a data structure
314 * meant to carry the information required to portably record login info. 314 * meant to carry the information required to portably record login info.
315 * 315 *
@@ -338,20 +338,20 @@ login_free_entry(struct logininfo *li)
338 338
339/* login_init_entry(struct logininfo *, int, char*, char*, char*) 339/* login_init_entry(struct logininfo *, int, char*, char*, char*)
340 * - initialise a struct logininfo 340 * - initialise a struct logininfo
341 * 341 *
342 * Populates a new struct logininfo, a data structure meant to carry 342 * Populates a new struct logininfo, a data structure meant to carry
343 * the information required to portably record login info. 343 * the information required to portably record login info.
344 * 344 *
345 * Returns: 1 345 * Returns: 1
346 */ 346 */
347int 347int
348login_init_entry(struct logininfo *li, int pid, const char *username, 348login_init_entry(struct logininfo *li, int pid, const char *username,
349 const char *hostname, const char *line) 349 const char *hostname, const char *line)
350{ 350{
351 struct passwd *pw; 351 struct passwd *pw;
352 352
353 memset(li, 0, sizeof(*li)); 353 memset(li, 0, sizeof(*li));
354 354
355 li->pid = pid; 355 li->pid = pid;
356 356
357 /* set the line information */ 357 /* set the line information */
@@ -384,7 +384,7 @@ login_set_current_time(struct logininfo *li)
384 struct timeval tv; 384 struct timeval tv;
385 385
386 gettimeofday(&tv, NULL); 386 gettimeofday(&tv, NULL);
387 387
388 li->tv_sec = tv.tv_sec; 388 li->tv_sec = tv.tv_sec;
389 li->tv_usec = tv.tv_usec; 389 li->tv_usec = tv.tv_usec;
390} 390}
@@ -457,7 +457,7 @@ getlast_entry(struct logininfo *li)
457#else /* !USE_LASTLOG */ 457#else /* !USE_LASTLOG */
458 458
459#ifdef DISABLE_LASTLOG 459#ifdef DISABLE_LASTLOG
460 /* On some systems we shouldn't even try to obtain last login 460 /* On some systems we shouldn't even try to obtain last login
461 * time, e.g. AIX */ 461 * time, e.g. AIX */
462 return 0; 462 return 0;
463# else /* DISABLE_LASTLOG */ 463# else /* DISABLE_LASTLOG */
@@ -475,7 +475,7 @@ getlast_entry(struct logininfo *li)
475 return 0; 475 return 0;
476# endif /* USE_WTMPX && (HAVE_TIME_IN_UTMPX || HAVE_TV_IN_UTMPX) */ 476# endif /* USE_WTMPX && (HAVE_TIME_IN_UTMPX || HAVE_TV_IN_UTMPX) */
477# endif /* USE_WTMP && (HAVE_TIME_IN_UTMP || HAVE_TV_IN_UTMP) */ 477# endif /* USE_WTMP && (HAVE_TIME_IN_UTMP || HAVE_TV_IN_UTMP) */
478# endif /* DISABLE_LASTLOG */ 478# endif /* DISABLE_LASTLOG */
479#endif /* USE_LASTLOG */ 479#endif /* USE_LASTLOG */
480} 480}
481 481
@@ -532,12 +532,12 @@ line_stripname(char *dst, const char *src, int dstsize)
532 * NOTE: use strncpy because we do NOT necessarily want zero 532 * NOTE: use strncpy because we do NOT necessarily want zero
533 * termination */ 533 * termination */
534char * 534char *
535line_abbrevname(char *dst, const char *src, int dstsize) 535line_abbrevname(char *dst, const char *src, int dstsize)
536{ 536{
537 size_t len; 537 size_t len;
538 538
539 memset(dst, '\0', dstsize); 539 memset(dst, '\0', dstsize);
540 540
541 /* Always skip prefix if present */ 541 /* Always skip prefix if present */
542#ifdef sgi 542#ifdef sgi
543 if (strncmp(src, "/dev/tty", 8) == 0) 543 if (strncmp(src, "/dev/tty", 8) == 0)
@@ -546,7 +546,7 @@ line_abbrevname(char *dst, const char *src, int dstsize)
546 if (strncmp(src, "/dev/", 5) == 0) 546 if (strncmp(src, "/dev/", 5) == 0)
547 src += 5; 547 src += 5;
548#endif 548#endif
549 549
550 len = strlen(src); 550 len = strlen(src);
551 551
552 if (len > 0) { 552 if (len > 0) {
@@ -554,9 +554,9 @@ line_abbrevname(char *dst, const char *src, int dstsize)
554 src += ((int)len - dstsize); 554 src += ((int)len - dstsize);
555 555
556 /* note: _don't_ change this to strlcpy */ 556 /* note: _don't_ change this to strlcpy */
557 strncpy(dst, src, (size_t)dstsize); 557 strncpy(dst, src, (size_t)dstsize);
558 } 558 }
559 559
560 return dst; 560 return dst;
561} 561}
562 562
@@ -620,7 +620,7 @@ construct_utmp(struct logininfo *li,
620 620
621 /* 621 /*
622 * These fields are only used when logging in, and are blank 622 * These fields are only used when logging in, and are blank
623 * for logouts. 623 * for logouts.
624 */ 624 */
625 625
626 /* Use strncpy because we don't necessarily want null termination */ 626 /* Use strncpy because we don't necessarily want null termination */
@@ -632,7 +632,7 @@ construct_utmp(struct logininfo *li,
632 /* this is just a 32-bit IP address */ 632 /* this is just a 32-bit IP address */
633 if (li->hostaddr.sa.sa_family == AF_INET) 633 if (li->hostaddr.sa.sa_family == AF_INET)
634 ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; 634 ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;
635# endif 635# endif
636} 636}
637#endif /* USE_UTMP || USE_WTMP || USE_LOGIN */ 637#endif /* USE_UTMP || USE_WTMP || USE_LOGIN */
638 638
@@ -684,7 +684,7 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx)
684 684
685 /* 685 /*
686 * These fields are only used when logging in, and are blank 686 * These fields are only used when logging in, and are blank
687 * for logouts. 687 * for logouts.
688 */ 688 */
689 689
690 /* strncpy(): Don't necessarily want null termination */ 690 /* strncpy(): Don't necessarily want null termination */
@@ -774,18 +774,18 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut)
774 * If the new ut_line is empty but the old one is not 774 * If the new ut_line is empty but the old one is not
775 * and ut_line and ut_name match, preserve the old ut_line. 775 * and ut_line and ut_name match, preserve the old ut_line.
776 */ 776 */
777 if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) && 777 if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) &&
778 (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') && 778 (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') &&
779 (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) && 779 (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) &&
780 (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) { 780 (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) {
781 (void)memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); 781 (void)memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host));
782 } 782 }
783 783
784 (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); 784 (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
785 if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) 785 if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut))
786 log("utmp_write_direct: error writing %s: %s", 786 log("utmp_write_direct: error writing %s: %s",
787 UTMP_FILE, strerror(errno)); 787 UTMP_FILE, strerror(errno));
788 788
789 (void)close(fd); 789 (void)close(fd);
790 return 1; 790 return 1;
791 } else { 791 } else {
@@ -887,7 +887,7 @@ utmpx_write_library(struct logininfo *li, struct utmpx *utx)
887/* write a utmp entry direct to the file */ 887/* write a utmp entry direct to the file */
888static int 888static int
889utmpx_write_direct(struct logininfo *li, struct utmpx *utx) 889utmpx_write_direct(struct logininfo *li, struct utmpx *utx)
890{ 890{
891 log("utmpx_write_direct: not implemented!"); 891 log("utmpx_write_direct: not implemented!");
892 return 0; 892 return 0;
893} 893}
@@ -957,7 +957,7 @@ utmpx_write_entry(struct logininfo *li)
957 ** Low-level wtmp functions 957 ** Low-level wtmp functions
958 **/ 958 **/
959 959
960#ifdef USE_WTMP 960#ifdef USE_WTMP
961 961
962/* write a wtmp entry direct to the end of the file */ 962/* write a wtmp entry direct to the end of the file */
963/* This is a slight modification of code in OpenBSD's logwtmp.c */ 963/* This is a slight modification of code in OpenBSD's logwtmp.c */
@@ -972,7 +972,7 @@ wtmp_write(struct logininfo *li, struct utmp *ut)
972 WTMP_FILE, strerror(errno)); 972 WTMP_FILE, strerror(errno));
973 return 0; 973 return 0;
974 } 974 }
975 if (fstat(fd, &buf) == 0) 975 if (fstat(fd, &buf) == 0)
976 if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) { 976 if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
977 ftruncate(fd, buf.st_size); 977 ftruncate(fd, buf.st_size);
978 log("wtmp_write: problem writing %s: %s", 978 log("wtmp_write: problem writing %s: %s",
@@ -1019,7 +1019,7 @@ wtmp_write_entry(struct logininfo *li)
1019 1019
1020 1020
1021/* Notes on fetching login data from wtmp/wtmpx 1021/* Notes on fetching login data from wtmp/wtmpx
1022 * 1022 *
1023 * Logouts are usually recorded with (amongst other things) a blank 1023 * Logouts are usually recorded with (amongst other things) a blank
1024 * username on a given tty line. However, some systems (HP-UX is one) 1024 * username on a given tty line. However, some systems (HP-UX is one)
1025 * leave all fields set, but change the ut_type field to DEAD_PROCESS. 1025 * leave all fields set, but change the ut_type field to DEAD_PROCESS.
@@ -1038,7 +1038,7 @@ wtmp_write_entry(struct logininfo *li)
1038static int 1038static int
1039wtmp_islogin(struct logininfo *li, struct utmp *ut) 1039wtmp_islogin(struct logininfo *li, struct utmp *ut)
1040{ 1040{
1041 if (strncmp(li->username, ut->ut_name, 1041 if (strncmp(li->username, ut->ut_name,
1042 MIN_SIZEOF(li->username, ut->ut_name)) == 0) { 1042 MIN_SIZEOF(li->username, ut->ut_name)) == 0) {
1043# ifdef HAVE_TYPE_IN_UTMP 1043# ifdef HAVE_TYPE_IN_UTMP
1044 if (ut->ut_type & USER_PROCESS) 1044 if (ut->ut_type & USER_PROCESS)
@@ -1065,7 +1065,7 @@ wtmp_get_entry(struct logininfo *li)
1065 WTMP_FILE, strerror(errno)); 1065 WTMP_FILE, strerror(errno));
1066 return 0; 1066 return 0;
1067 } 1067 }
1068 if (fstat(fd, &st) != 0) { 1068 if (fstat(fd, &st) != 0) {
1069 log("wtmp_get_entry: couldn't stat %s: %s", 1069 log("wtmp_get_entry: couldn't stat %s: %s",
1070 WTMP_FILE, strerror(errno)); 1070 WTMP_FILE, strerror(errno));
1071 close(fd); 1071 close(fd);
@@ -1139,7 +1139,7 @@ wtmpx_write(struct logininfo *li, struct utmpx *utx)
1139 return 0; 1139 return 0;
1140 } 1140 }
1141 1141
1142 if (fstat(fd, &buf) == 0) 1142 if (fstat(fd, &buf) == 0)
1143 if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) { 1143 if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) {
1144 ftruncate(fd, buf.st_size); 1144 ftruncate(fd, buf.st_size);
1145 log("wtmpx_write: problem writing %s: %s", 1145 log("wtmpx_write: problem writing %s: %s",
@@ -1221,13 +1221,13 @@ wtmpx_get_entry(struct logininfo *li)
1221 WTMPX_FILE, strerror(errno)); 1221 WTMPX_FILE, strerror(errno));
1222 return 0; 1222 return 0;
1223 } 1223 }
1224 if (fstat(fd, &st) != 0) { 1224 if (fstat(fd, &st) != 0) {
1225 log("wtmpx_get_entry: couldn't stat %s: %s", 1225 log("wtmpx_get_entry: couldn't stat %s: %s",
1226 WTMP_FILE, strerror(errno)); 1226 WTMP_FILE, strerror(errno));
1227 close(fd); 1227 close(fd);
1228 return 0; 1228 return 0;
1229 } 1229 }
1230 1230
1231 /* Seek to the start of the last struct utmpx */ 1231 /* Seek to the start of the last struct utmpx */
1232 if (lseek(fd, (off_t)(0-sizeof(struct utmpx)), SEEK_END) == -1 ) { 1232 if (lseek(fd, (off_t)(0-sizeof(struct utmpx)), SEEK_END) == -1 ) {
1233 /* probably a newly rotated wtmpx file */ 1233 /* probably a newly rotated wtmpx file */
@@ -1295,7 +1295,7 @@ syslogin_perform_logout(struct logininfo *li)
1295{ 1295{
1296# ifdef HAVE_LOGOUT 1296# ifdef HAVE_LOGOUT
1297 char line[8]; 1297 char line[8];
1298 1298
1299 (void)line_stripname(line, li->line, sizeof(line)); 1299 (void)line_stripname(line, li->line, sizeof(line));
1300 1300
1301 if (!logout(line)) { 1301 if (!logout(line)) {
@@ -1344,7 +1344,7 @@ lastlog_construct(struct logininfo *li, struct lastlog *last)
1344{ 1344{
1345 /* clear the structure */ 1345 /* clear the structure */
1346 memset(last, '\0', sizeof(*last)); 1346 memset(last, '\0', sizeof(*last));
1347 1347
1348 (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); 1348 (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line));
1349 strlcpy(last->ll_host, li->hostname, 1349 strlcpy(last->ll_host, li->hostname,
1350 MIN_SIZEOF(last->ll_host, li->hostname)); 1350 MIN_SIZEOF(last->ll_host, li->hostname));
@@ -1357,7 +1357,7 @@ lastlog_filetype(char *filename)
1357 struct stat st; 1357 struct stat st;
1358 1358
1359 if (stat(LASTLOG_FILE, &st) != 0) { 1359 if (stat(LASTLOG_FILE, &st) != 0) {
1360 log("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE, 1360 log("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE,
1361 strerror(errno)); 1361 strerror(errno));
1362 return 0; 1362 return 0;
1363 } 1363 }
@@ -1399,18 +1399,18 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode)
1399 lastlog_file, strerror(errno)); 1399 lastlog_file, strerror(errno));
1400 return 0; 1400 return 0;
1401 } 1401 }
1402 1402
1403 if (type == LL_FILE) { 1403 if (type == LL_FILE) {
1404 /* find this uid's offset in the lastlog file */ 1404 /* find this uid's offset in the lastlog file */
1405 offset = (off_t) ( (long)li->uid * sizeof(struct lastlog)); 1405 offset = (off_t) ( (long)li->uid * sizeof(struct lastlog));
1406 1406
1407 if ( lseek(*fd, offset, SEEK_SET) != offset ) { 1407 if ( lseek(*fd, offset, SEEK_SET) != offset ) {
1408 log("lastlog_openseek: %s->lseek(): %s", 1408 log("lastlog_openseek: %s->lseek(): %s",
1409 lastlog_file, strerror(errno)); 1409 lastlog_file, strerror(errno));
1410 return 0; 1410 return 0;
1411 } 1411 }
1412 } 1412 }
1413 1413
1414 return 1; 1414 return 1;
1415} 1415}
1416 1416
@@ -1425,7 +1425,7 @@ lastlog_perform_login(struct logininfo *li)
1425 1425
1426 if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) 1426 if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT))
1427 return(0); 1427 return(0);
1428 1428
1429 /* write the entry */ 1429 /* write the entry */
1430 if (atomicio(write, fd, &last, sizeof(last)) != sizeof(last)) { 1430 if (atomicio(write, fd, &last, sizeof(last)) != sizeof(last)) {
1431 close(fd); 1431 close(fd);
@@ -1454,7 +1454,7 @@ static void
1454lastlog_populate_entry(struct logininfo *li, struct lastlog *last) 1454lastlog_populate_entry(struct logininfo *li, struct lastlog *last)
1455{ 1455{
1456 line_fullname(li->line, last->ll_line, sizeof(li->line)); 1456 line_fullname(li->line, last->ll_line, sizeof(li->line));
1457 strlcpy(li->hostname, last->ll_host, 1457 strlcpy(li->hostname, last->ll_host,
1458 MIN_SIZEOF(li->hostname, last->ll_host)); 1458 MIN_SIZEOF(li->hostname, last->ll_host));
1459 li->tv_sec = last->ll_time; 1459 li->tv_sec = last->ll_time;
1460} 1460}
@@ -1475,7 +1475,7 @@ lastlog_get_entry(struct logininfo *li)
1475 return 1; 1475 return 1;
1476 } 1476 }
1477 } else { 1477 } else {
1478 return 0; 1478 return 0;
1479 } 1479 }
1480} 1480}
1481#endif /* USE_LASTLOG */ 1481#endif /* USE_LASTLOG */