1202188Sed/*-
2202188Sed * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
3202188Sed * All rights reserved.
4202188Sed *
5202188Sed * Redistribution and use in source and binary forms, with or without
6202188Sed * modification, are permitted provided that the following conditions
7202188Sed * are met:
8202188Sed * 1. Redistributions of source code must retain the above copyright
9202188Sed *    notice, this list of conditions and the following disclaimer.
10202188Sed * 2. Redistributions in binary form must reproduce the above copyright
11202188Sed *    notice, this list of conditions and the following disclaimer in the
12202188Sed *    documentation and/or other materials provided with the distribution.
13202188Sed *
14202188Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15202188Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16202188Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17202188Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18202188Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19202188Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20202188Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21202188Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22202188Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23202188Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24202188Sed * SUCH DAMAGE.
25202188Sed */
26202188Sed
27202188Sed#include <sys/cdefs.h>
28202188Sed__FBSDID("$FreeBSD$");
29202188Sed
30202188Sed#include "namespace.h"
31202188Sed#include <sys/endian.h>
32202188Sed#include <sys/param.h>
33202876Sed#include <sys/time.h>
34202530Sed#include <stdlib.h>
35202188Sed#include <string.h>
36202188Sed#include <utmpx.h>
37202188Sed#include "utxdb.h"
38202188Sed#include "un-namespace.h"
39202188Sed
40202188Sed#define	UTOF_STRING(ut, fu, field) do { \
41202188Sed	strncpy((fu)->fu_ ## field, (ut)->ut_ ## field,		\
42202188Sed	    MIN(sizeof (fu)->fu_ ## field, sizeof (ut)->ut_ ## field));	\
43202188Sed} while (0)
44202188Sed#define	UTOF_ID(ut, fu) do { \
45202188Sed	memcpy((fu)->fu_id, (ut)->ut_id,				\
46202188Sed	    MIN(sizeof (fu)->fu_id, sizeof (ut)->ut_id));		\
47202188Sed} while (0)
48202188Sed#define	UTOF_PID(ut, fu) do { \
49202188Sed	(fu)->fu_pid = htobe32((ut)->ut_pid);				\
50202188Sed} while (0)
51202188Sed#define	UTOF_TYPE(ut, fu) do { \
52202188Sed	(fu)->fu_type = (ut)->ut_type;					\
53202188Sed} while (0)
54202876Sed#define	UTOF_TV(fu) do { \
55202876Sed	struct timeval tv;						\
56202876Sed	gettimeofday(&tv, NULL);					\
57202876Sed	(fu)->fu_tv = htobe64((uint64_t)tv.tv_sec * 1000000 +		\
58202876Sed	    (uint64_t)tv.tv_usec);					\
59202188Sed} while (0)
60202188Sed
61202188Sedvoid
62202188Sedutx_to_futx(const struct utmpx *ut, struct futx *fu)
63202188Sed{
64202188Sed
65202188Sed	memset(fu, 0, sizeof *fu);
66202188Sed
67202188Sed	switch (ut->ut_type) {
68202188Sed	case BOOT_TIME:
69202188Sed	case OLD_TIME:
70202188Sed	case NEW_TIME:
71202188Sed	/* Extension: shutdown time. */
72202188Sed	case SHUTDOWN_TIME:
73202188Sed		break;
74202188Sed	case USER_PROCESS:
75202188Sed		UTOF_ID(ut, fu);
76202188Sed		UTOF_STRING(ut, fu, user);
77202188Sed		UTOF_STRING(ut, fu, line);
78202188Sed		/* Extension: host name. */
79202188Sed		UTOF_STRING(ut, fu, host);
80202188Sed		UTOF_PID(ut, fu);
81202188Sed		break;
82202188Sed	case INIT_PROCESS:
83202188Sed		UTOF_ID(ut, fu);
84202188Sed		UTOF_PID(ut, fu);
85202188Sed		break;
86202188Sed	case LOGIN_PROCESS:
87202188Sed		UTOF_ID(ut, fu);
88202188Sed		UTOF_STRING(ut, fu, user);
89202530Sed		UTOF_STRING(ut, fu, line);
90202188Sed		UTOF_PID(ut, fu);
91202188Sed		break;
92202188Sed	case DEAD_PROCESS:
93202188Sed		UTOF_ID(ut, fu);
94202188Sed		UTOF_PID(ut, fu);
95202188Sed		break;
96202188Sed	default:
97202188Sed		fu->fu_type = EMPTY;
98202188Sed		return;
99202188Sed	}
100202188Sed
101202188Sed	UTOF_TYPE(ut, fu);
102202876Sed	UTOF_TV(fu);
103202188Sed}
104202188Sed
105202188Sed#define	FTOU_STRING(fu, ut, field) do { \
106202188Sed	strncpy((ut)->ut_ ## field, (fu)->fu_ ## field,		\
107202188Sed	    MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \
108202188Sed} while (0)
109202188Sed#define	FTOU_ID(fu, ut) do { \
110202188Sed	memcpy((ut)->ut_id, (fu)->fu_id,				\
111202188Sed	    MIN(sizeof (ut)->ut_id, sizeof (fu)->fu_id));		\
112202188Sed} while (0)
113202188Sed#define	FTOU_PID(fu, ut) do { \
114202188Sed	(ut)->ut_pid = be32toh((fu)->fu_pid);				\
115202188Sed} while (0)
116202188Sed#define	FTOU_TYPE(fu, ut) do { \
117202188Sed	(ut)->ut_type = (fu)->fu_type;					\
118202188Sed} while (0)
119202188Sed#define	FTOU_TV(fu, ut) do { \
120202188Sed	uint64_t t;							\
121202188Sed	t = be64toh((fu)->fu_tv);					\
122202188Sed	(ut)->ut_tv.tv_sec = t / 1000000;				\
123202188Sed	(ut)->ut_tv.tv_usec = t % 1000000;				\
124202188Sed} while (0)
125202188Sed
126202530Sedstruct utmpx *
127202530Sedfutx_to_utx(const struct futx *fu)
128202188Sed{
129202530Sed	static struct utmpx *ut;
130202188Sed
131202530Sed	if (ut == NULL) {
132202530Sed		ut = calloc(1, sizeof *ut);
133202530Sed		if (ut == NULL)
134202530Sed			return (NULL);
135218846Sed	} else
136202530Sed		memset(ut, 0, sizeof *ut);
137202188Sed
138202188Sed	switch (fu->fu_type) {
139202188Sed	case BOOT_TIME:
140202188Sed	case OLD_TIME:
141202188Sed	case NEW_TIME:
142202188Sed	/* Extension: shutdown time. */
143202188Sed	case SHUTDOWN_TIME:
144202188Sed		break;
145202188Sed	case USER_PROCESS:
146202188Sed		FTOU_ID(fu, ut);
147202188Sed		FTOU_STRING(fu, ut, user);
148202188Sed		FTOU_STRING(fu, ut, line);
149202188Sed		/* Extension: host name. */
150202188Sed		FTOU_STRING(fu, ut, host);
151202188Sed		FTOU_PID(fu, ut);
152202188Sed		break;
153202188Sed	case INIT_PROCESS:
154202188Sed		FTOU_ID(fu, ut);
155202188Sed		FTOU_PID(fu, ut);
156202188Sed		break;
157202188Sed	case LOGIN_PROCESS:
158202188Sed		FTOU_ID(fu, ut);
159202188Sed		FTOU_STRING(fu, ut, user);
160202530Sed		FTOU_STRING(fu, ut, line);
161202188Sed		FTOU_PID(fu, ut);
162202188Sed		break;
163202188Sed	case DEAD_PROCESS:
164202188Sed		FTOU_ID(fu, ut);
165202188Sed		FTOU_PID(fu, ut);
166202188Sed		break;
167202188Sed	default:
168202188Sed		ut->ut_type = EMPTY;
169202530Sed		return (ut);
170202188Sed	}
171202188Sed
172202188Sed	FTOU_TYPE(fu, ut);
173202188Sed	FTOU_TV(fu, ut);
174202530Sed	return (ut);
175202188Sed}
176