1 /* Copyright (C) 2008-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <sys/types.h>
19 #include <utmp.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 
23 #include "utmp32.h"
24 #include "utmp-convert.h"
25 
26 /* Allocate a static buffer to be returned to the caller.  As well as
27    with the existing version of these functions the caller has to be
28    aware that the contents of this buffer will change with subsequent
29    calls.  */
30 #define ALLOCATE_UTMP32_OUT(OUT)			\
31   static struct utmp32 *OUT = NULL;			\
32 							\
33   if (OUT == NULL)					\
34     {							\
35       OUT = malloc (sizeof (struct utmp32));		\
36       if (OUT == NULL)					\
37 	return NULL;					\
38     }
39 
40 /* Perform a lookup for a utmp entry matching FIELD using function
41    FUNC.  FIELD is converted to a 64 bit utmp and the result is
42    converted back to 32 bit utmp.  */
43 #define ACCESS_UTMP_ENTRY(FUNC, FIELD)			\
44   struct utmp in64;					\
45   struct utmp *out64;					\
46   ALLOCATE_UTMP32_OUT (out32);				\
47 							\
48   utmp_convert32to64 (FIELD, &in64);			\
49   out64 = FUNC (&in64);					\
50 							\
51   if (out64 == NULL)					\
52     return NULL;					\
53 							\
54   utmp_convert64to32 (out64, out32);			\
55 							\
56   return out32;
57 
58 /* Search forward from the current point in the utmp file until the
59    next entry with a ut_type matching ID->ut_type.  */
60 struct utmp32 *
getutid32(const struct utmp32 * id)61 getutid32 (const struct utmp32 *id)
62 {
63   ACCESS_UTMP_ENTRY (__getutid, id)
64 }
65 symbol_version (getutid32, getutid, GLIBC_2.0);
66 
67 /* Search forward from the current point in the utmp file until the
68    next entry with a ut_line matching LINE->ut_line.  */
69 struct utmp32 *
getutline32(const struct utmp32 * line)70 getutline32 (const struct utmp32 *line)
71 {
72   ACCESS_UTMP_ENTRY (__getutline, line)
73 }
74 symbol_version (getutline32, getutline, GLIBC_2.0);
75 
76 /* Write out entry pointed to by UTMP_PTR into the utmp file.  */
77 struct utmp32 *
pututline32(const struct utmp32 * utmp_ptr)78 pututline32 (const struct utmp32 *utmp_ptr)
79 {
80   ACCESS_UTMP_ENTRY (__pututline, utmp_ptr)
81 }
82 symbol_version (pututline32, pututline, GLIBC_2.0);
83 
84 /* Read next entry from a utmp-like file.  */
85 struct utmp32 *
getutent32(void)86 getutent32 (void)
87 {
88   struct utmp *out64;
89   ALLOCATE_UTMP32_OUT (out32);
90 
91   out64 = __getutent ();
92   if (!out64)
93     return NULL;
94 
95   utmp_convert64to32 (out64, out32);
96   return out32;
97 }
98 symbol_version (getutent32, getutent, GLIBC_2.0);
99 
100 /* Reentrant versions of the file for handling utmp files.  */
101 
102 int
getutent32_r(struct utmp32 * buffer,struct utmp32 ** result)103 getutent32_r (struct utmp32 *buffer, struct utmp32 **result)
104 {
105   struct utmp out64;
106   struct utmp *out64p;
107   int ret;
108 
109   ret = __getutent_r (&out64, &out64p);
110   if (ret == -1)
111     {
112       *result = NULL;
113       return -1;
114     }
115 
116   utmp_convert64to32 (out64p, buffer);
117   *result = buffer;
118 
119   return 0;
120 }
121 symbol_version (getutent32_r, getutent_r, GLIBC_2.0);
122 
123 int
getutid32_r(const struct utmp32 * id,struct utmp32 * buffer,struct utmp32 ** result)124 getutid32_r (const struct utmp32 *id, struct utmp32 *buffer,
125 	       struct utmp32 **result)
126 {
127   struct utmp in64;
128   struct utmp out64;
129   struct utmp *out64p;
130   int ret;
131 
132   utmp_convert32to64 (id, &in64);
133 
134   ret = __getutid_r (&in64, &out64, &out64p);
135   if (ret == -1)
136     {
137       *result = NULL;
138       return -1;
139     }
140 
141   utmp_convert64to32 (out64p, buffer);
142   *result = buffer;
143 
144   return 0;
145 }
146 symbol_version (getutid32_r, getutid_r, GLIBC_2.0);
147 
148 int
getutline32_r(const struct utmp32 * line,struct utmp32 * buffer,struct utmp32 ** result)149 getutline32_r (const struct utmp32 *line,
150 		 struct utmp32 *buffer, struct utmp32 **result)
151 {
152   struct utmp in64;
153   struct utmp out64;
154   struct utmp *out64p;
155   int ret;
156 
157   utmp_convert32to64 (line, &in64);
158 
159   ret = __getutline_r (&in64, &out64, &out64p);
160   if (ret == -1)
161     {
162       *result = NULL;
163       return -1;
164     }
165 
166   utmp_convert64to32 (out64p, buffer);
167   *result = buffer;
168 
169   return 0;
170 
171 }
172 symbol_version (getutline32_r, getutline_r, GLIBC_2.0);
173 
174 /* Append entry UTMP to the wtmp-like file WTMP_FILE.  */
175 void
updwtmp32(const char * wtmp_file,const struct utmp32 * utmp)176 updwtmp32 (const char *wtmp_file, const struct utmp32 *utmp)
177 {
178   struct utmp in32;
179 
180   utmp_convert32to64 (utmp, &in32);
181   __updwtmp (wtmp_file, &in32);
182 }
183 symbol_version (updwtmp32, updwtmp, GLIBC_2.0);
184