1 /* $NetBSD: utmpentry.c,v 1.16 2008/10/28 14:01:46 christos Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
42 #include "utmpentry.h"
44 /* Operations on timespecs. */
45 #define timespec2ns(x) (((uint64_t)(x)->tv_sec) * 1000000000L + (x)->tv_nsec)
48 #define COMPILE_ASSERT(x) _Static_assert(x, "assertion failed")
51 static void getentryx(struct utmpentry
*, struct utmpx
*);
52 static struct timespec utmpxtime
= {0, 0};
53 static int setup(const char *);
54 static void adjust_size(struct utmpentry
*e
);
56 int maxname
= 8, maxline
= 8, maxhost
= 16;
57 int etype
= 1 << USER_PROCESS
;
58 static int numutmp
= 0;
59 static struct utmpentry
*ehead
;
62 adjust_size(struct utmpentry
*e
)
66 if ((max
= strlen(e
->name
)) > maxname
)
68 if ((max
= strlen(e
->line
)) > maxline
)
70 if ((max
= strlen(e
->host
)) > maxhost
)
75 setup(const char *fname
)
84 size_t len
= strlen(fname
);
86 errx(1, "Filename cannot be 0 length.");
87 what
= fname
[len
- 1] == 'x' ? 1 : 2;
89 if (utmpxname(fname
) == 0)
90 warnx("Cannot set utmpx file to `%s'",
95 sfname
= fname
? fname
: _PATH_UTMPX
;
96 if (stat(sfname
, &st
) == -1) {
97 warn("Cannot stat `%s'", sfname
);
100 if (timespeccmp(&st
.st_mtimespec
, &utmpxtime
, >))
101 utmpxtime
= st
.st_mtimespec
;
112 struct utmpentry
*ep
;
114 timespecclear(&utmpxtime
);
117 struct utmpentry
*sep
= ep
;
126 getutentries(const char *fname
, struct utmpentry
**epp
)
129 struct utmpentry
*ep
;
130 int what
= setup(fname
);
131 struct utmpentry
**nextp
= &ehead
;
138 /* Need to re-scan */
143 while ((what
& 1) && (utx
= getutxent()) != NULL
) {
144 if (fname
== NULL
&& ((1 << utx
->ut_type
) & etype
) == 0) {
147 if ((ep
= calloc(1, sizeof(struct utmpentry
))) == NULL
) {
158 struct utmpentry
*from
= ehead
, *save
;
161 while (from
!= NULL
) {
163 (*nextp
) && strcmp(from
->line
, (*nextp
)->line
) > 0;
164 nextp
= &(*nextp
)->next
)
178 getentryx(struct utmpentry
*e
, struct utmpx
*up
)
180 COMPILE_ASSERT(sizeof(e
->name
) > sizeof(up
->ut_name
));
181 COMPILE_ASSERT(sizeof(e
->line
) > sizeof(up
->ut_line
));
182 COMPILE_ASSERT(sizeof(e
->host
) > sizeof(up
->ut_host
));
185 * e has just been calloc'd. We don't need to clear it or
186 * append null-terminators, because its length is strictly
187 * greater than the source string. Use strncpy to _read_
188 * up->ut_* because they may not be terminated. For this
189 * reason we use the size of the _source_ as the length
192 snprintf(e
->name
, sizeof(e
->name
), "%.*s",
193 (int)sizeof(up
->ut_name
), up
->ut_name
);
194 snprintf(e
->line
, sizeof(e
->line
), "%.*s",
195 (int)sizeof(up
->ut_line
), up
->ut_line
);
196 snprintf(e
->host
, sizeof(e
->host
), "%.*s",
197 (int)sizeof(up
->ut_host
), up
->ut_host
);
201 e
->term
= up
->ut_exit
.e_termination
;
202 e
->exit
= up
->ut_exit
.e_exit
;
203 e
->sess
= up
->ut_session
;
204 e
->type
= up
->ut_type
;