utxdb.c revision 331722
1/*-
2 * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/lib/libc/gen/utxdb.c 331722 2018-03-29 02:50:57Z eadler $");
29
30#include "namespace.h"
31#include <sys/endian.h>
32#include <sys/param.h>
33#include <sys/time.h>
34#include <stdlib.h>
35#include <string.h>
36#include <utmpx.h>
37#include "utxdb.h"
38#include "un-namespace.h"
39
40#define	UTOF_STRING(ut, fu, field) do { \
41	strncpy((fu)->fu_ ## field, (ut)->ut_ ## field,		\
42	    MIN(sizeof (fu)->fu_ ## field, sizeof (ut)->ut_ ## field));	\
43} while (0)
44#define	UTOF_ID(ut, fu) do { \
45	memcpy((fu)->fu_id, (ut)->ut_id,				\
46	    MIN(sizeof (fu)->fu_id, sizeof (ut)->ut_id));		\
47} while (0)
48#define	UTOF_PID(ut, fu) do { \
49	(fu)->fu_pid = htobe32((ut)->ut_pid);				\
50} while (0)
51#define	UTOF_TYPE(ut, fu) do { \
52	(fu)->fu_type = (ut)->ut_type;					\
53} while (0)
54#define	UTOF_TV(fu) do { \
55	struct timeval tv;						\
56	gettimeofday(&tv, NULL);					\
57	(fu)->fu_tv = htobe64((uint64_t)tv.tv_sec * 1000000 +		\
58	    (uint64_t)tv.tv_usec);					\
59} while (0)
60
61void
62utx_to_futx(const struct utmpx *ut, struct futx *fu)
63{
64
65	memset(fu, 0, sizeof *fu);
66
67	switch (ut->ut_type) {
68	case BOOT_TIME:
69	case OLD_TIME:
70	case NEW_TIME:
71	/* Extension: shutdown time. */
72	case SHUTDOWN_TIME:
73		break;
74	case USER_PROCESS:
75		UTOF_ID(ut, fu);
76		UTOF_STRING(ut, fu, user);
77		UTOF_STRING(ut, fu, line);
78		/* Extension: host name. */
79		UTOF_STRING(ut, fu, host);
80		UTOF_PID(ut, fu);
81		break;
82	case INIT_PROCESS:
83		UTOF_ID(ut, fu);
84		UTOF_PID(ut, fu);
85		break;
86	case LOGIN_PROCESS:
87		UTOF_ID(ut, fu);
88		UTOF_STRING(ut, fu, user);
89		UTOF_STRING(ut, fu, line);
90		UTOF_PID(ut, fu);
91		break;
92	case DEAD_PROCESS:
93		UTOF_ID(ut, fu);
94		UTOF_PID(ut, fu);
95		break;
96	default:
97		fu->fu_type = EMPTY;
98		return;
99	}
100
101	UTOF_TYPE(ut, fu);
102	UTOF_TV(fu);
103}
104
105#define	FTOU_STRING(fu, ut, field) do { \
106	strncpy((ut)->ut_ ## field, (fu)->fu_ ## field,		\
107	    MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \
108} while (0)
109#define	FTOU_ID(fu, ut) do { \
110	memcpy((ut)->ut_id, (fu)->fu_id,				\
111	    MIN(sizeof (ut)->ut_id, sizeof (fu)->fu_id));		\
112} while (0)
113#define	FTOU_PID(fu, ut) do { \
114	(ut)->ut_pid = be32toh((fu)->fu_pid);				\
115} while (0)
116#define	FTOU_TYPE(fu, ut) do { \
117	(ut)->ut_type = (fu)->fu_type;					\
118} while (0)
119#define	FTOU_TV(fu, ut) do { \
120	uint64_t t;							\
121	t = be64toh((fu)->fu_tv);					\
122	(ut)->ut_tv.tv_sec = t / 1000000;				\
123	(ut)->ut_tv.tv_usec = t % 1000000;				\
124} while (0)
125
126struct utmpx *
127futx_to_utx(const struct futx *fu)
128{
129#ifdef __NO_TLS
130	static struct utmpx *ut;
131#else
132	static _Thread_local struct utmpx *ut;
133#endif
134
135	if (ut == NULL) {
136		ut = calloc(1, sizeof *ut);
137		if (ut == NULL)
138			return (NULL);
139	} else
140		memset(ut, 0, sizeof *ut);
141
142	switch (fu->fu_type) {
143	case BOOT_TIME:
144	case OLD_TIME:
145	case NEW_TIME:
146	/* Extension: shutdown time. */
147	case SHUTDOWN_TIME:
148		break;
149	case USER_PROCESS:
150		FTOU_ID(fu, ut);
151		FTOU_STRING(fu, ut, user);
152		FTOU_STRING(fu, ut, line);
153		/* Extension: host name. */
154		FTOU_STRING(fu, ut, host);
155		FTOU_PID(fu, ut);
156		break;
157	case INIT_PROCESS:
158		FTOU_ID(fu, ut);
159		FTOU_PID(fu, ut);
160		break;
161	case LOGIN_PROCESS:
162		FTOU_ID(fu, ut);
163		FTOU_STRING(fu, ut, user);
164		FTOU_STRING(fu, ut, line);
165		FTOU_PID(fu, ut);
166		break;
167	case DEAD_PROCESS:
168		FTOU_ID(fu, ut);
169		FTOU_PID(fu, ut);
170		break;
171	default:
172		ut->ut_type = EMPTY;
173		return (ut);
174	}
175
176	FTOU_TYPE(fu, ut);
177	FTOU_TV(fu, ut);
178	return (ut);
179}
180