utxdb.c revision 202530
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: head/lib/libc/gen/utxdb.c 202530 2010-01-17 21:40:05Z ed $");
29
30#include "namespace.h"
31#include <sys/endian.h>
32#include <sys/param.h>
33#include <stdlib.h>
34#include <string.h>
35#include <utmpx.h>
36#include "utxdb.h"
37#include "un-namespace.h"
38
39#define	UTOF_STRING(ut, fu, field) do { \
40	strncpy((fu)->fu_ ## field, (ut)->ut_ ## field,		\
41	    MIN(sizeof (fu)->fu_ ## field, sizeof (ut)->ut_ ## field));	\
42} while (0)
43#define	UTOF_ID(ut, fu) do { \
44	memcpy((fu)->fu_id, (ut)->ut_id,				\
45	    MIN(sizeof (fu)->fu_id, sizeof (ut)->ut_id));		\
46} while (0)
47#define	UTOF_PID(ut, fu) do { \
48	(fu)->fu_pid = htobe32((ut)->ut_pid);				\
49} while (0)
50#define	UTOF_TYPE(ut, fu) do { \
51	(fu)->fu_type = (ut)->ut_type;					\
52} while (0)
53#define	UTOF_TV(ut, fu) do { \
54	(fu)->fu_tv = htobe64((uint64_t)(ut)->ut_tv.tv_sec * 1000000 +	\
55	    (uint64_t)(ut)->ut_tv.tv_usec);				\
56} while (0)
57
58void
59utx_to_futx(const struct utmpx *ut, struct futx *fu)
60{
61
62	memset(fu, 0, sizeof *fu);
63
64	switch (ut->ut_type) {
65	case BOOT_TIME:
66	case OLD_TIME:
67	case NEW_TIME:
68	/* Extension: shutdown time. */
69	case SHUTDOWN_TIME:
70		break;
71	case USER_PROCESS:
72		UTOF_ID(ut, fu);
73		UTOF_STRING(ut, fu, user);
74		UTOF_STRING(ut, fu, line);
75		/* Extension: host name. */
76		UTOF_STRING(ut, fu, host);
77		UTOF_PID(ut, fu);
78		break;
79	case INIT_PROCESS:
80		UTOF_ID(ut, fu);
81		UTOF_PID(ut, fu);
82		break;
83	case LOGIN_PROCESS:
84		UTOF_ID(ut, fu);
85		UTOF_STRING(ut, fu, user);
86		/* XXX: bug in the specification? Needed for getutxline(). */
87		UTOF_STRING(ut, fu, line);
88		UTOF_PID(ut, fu);
89		break;
90	case DEAD_PROCESS:
91		UTOF_ID(ut, fu);
92		UTOF_PID(ut, fu);
93		break;
94	default:
95		fu->fu_type = EMPTY;
96		return;
97	}
98
99	UTOF_TYPE(ut, fu);
100	UTOF_TV(ut, fu);
101}
102
103#define	FTOU_STRING(fu, ut, field) do { \
104	strncpy((ut)->ut_ ## field, (fu)->fu_ ## field,		\
105	    MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \
106} while (0)
107#define	FTOU_ID(fu, ut) do { \
108	memcpy((ut)->ut_id, (fu)->fu_id,				\
109	    MIN(sizeof (ut)->ut_id, sizeof (fu)->fu_id));		\
110} while (0)
111#define	FTOU_PID(fu, ut) do { \
112	(ut)->ut_pid = be32toh((fu)->fu_pid);				\
113} while (0)
114#define	FTOU_TYPE(fu, ut) do { \
115	(ut)->ut_type = (fu)->fu_type;					\
116} while (0)
117#define	FTOU_TV(fu, ut) do { \
118	uint64_t t;							\
119	t = be64toh((fu)->fu_tv);					\
120	(ut)->ut_tv.tv_sec = t / 1000000;				\
121	(ut)->ut_tv.tv_usec = t % 1000000;				\
122} while (0)
123
124struct utmpx *
125futx_to_utx(const struct futx *fu)
126{
127	static struct utmpx *ut;
128
129	if (ut == NULL) {
130		ut = calloc(1, sizeof *ut);
131		if (ut == NULL)
132			return (NULL);
133	} else {
134		memset(ut, 0, sizeof *ut);
135	}
136
137	switch (fu->fu_type) {
138	case BOOT_TIME:
139	case OLD_TIME:
140	case NEW_TIME:
141	/* Extension: shutdown time. */
142	case SHUTDOWN_TIME:
143		break;
144	case USER_PROCESS:
145		FTOU_ID(fu, ut);
146		FTOU_STRING(fu, ut, user);
147		FTOU_STRING(fu, ut, line);
148		/* Extension: host name. */
149		FTOU_STRING(fu, ut, host);
150		FTOU_PID(fu, ut);
151		break;
152	case INIT_PROCESS:
153		FTOU_ID(fu, ut);
154		FTOU_PID(fu, ut);
155		break;
156	case LOGIN_PROCESS:
157		FTOU_ID(fu, ut);
158		FTOU_STRING(fu, ut, user);
159		/* XXX: bug in the specification? Needed for getutxline(). */
160		FTOU_STRING(fu, ut, line);
161		FTOU_PID(fu, ut);
162		break;
163	case DEAD_PROCESS:
164		FTOU_ID(fu, ut);
165		FTOU_PID(fu, ut);
166		break;
167	default:
168		ut->ut_type = EMPTY;
169		return (ut);
170	}
171
172	FTOU_TYPE(fu, ut);
173	FTOU_TV(fu, ut);
174	return (ut);
175}
176