]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libc/gen/getutxent.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libc / gen / getutxent.c
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$");
29
30 #include "namespace.h"
31 #include <sys/endian.h>
32 #include <sys/param.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <utmpx.h>
38 #include "utxdb.h"
39 #include "un-namespace.h"
40
41 static FILE *uf = NULL;
42 static int udb;
43
44 int
45 setutxdb(int db, const char *file)
46 {
47         struct stat sb;
48
49         switch (db) {
50         case UTXDB_ACTIVE:
51                 if (file == NULL)
52                         file = _PATH_UTX_ACTIVE;
53                 break;
54         case UTXDB_LASTLOGIN:
55                 if (file == NULL)
56                         file = _PATH_UTX_LASTLOGIN;
57                 break;
58         case UTXDB_LOG:
59                 if (file == NULL)
60                         file = _PATH_UTX_LOG;
61                 break;
62         default:
63                 errno = EINVAL;
64                 return (-1);
65         }
66
67         if (uf != NULL)
68                 fclose(uf);
69         uf = fopen(file, "r");
70         if (uf == NULL)
71                 return (-1);
72
73         if (db != UTXDB_LOG) {
74                 /* Safety check: never use broken files. */
75                 if (_fstat(fileno(uf), &sb) != -1 &&
76                     sb.st_size % sizeof(struct futx) != 0) {
77                         fclose(uf);
78                         uf = NULL;
79                         errno = EFTYPE;
80                         return (-1);
81                 }
82                 /* Prevent reading of partial records. */
83                 (void)setvbuf(uf, NULL, _IOFBF,
84                     rounddown(BUFSIZ, sizeof(struct futx)));
85         }
86
87         udb = db;
88         return (0);
89 }
90
91 void
92 setutxent(void)
93 {
94
95         setutxdb(UTXDB_ACTIVE, NULL);
96 }
97
98 void
99 endutxent(void)
100 {
101
102         if (uf != NULL) {
103                 fclose(uf);
104                 uf = NULL;
105         }
106 }
107
108 static int
109 getfutxent(struct futx *fu)
110 {
111
112         if (uf == NULL)
113                 setutxent();
114         if (uf == NULL)
115                 return (-1);
116
117         if (udb == UTXDB_LOG) {
118                 uint16_t len;
119
120                 if (fread(&len, sizeof(len), 1, uf) != 1)
121                         return (-1);
122                 len = be16toh(len);
123                 if (len > sizeof *fu) {
124                         /* Forward compatibility. */
125                         if (fread(fu, sizeof(*fu), 1, uf) != 1)
126                                 return (-1);
127                         fseek(uf, len - sizeof(*fu), SEEK_CUR);
128                 } else {
129                         /* Partial record. */
130                         memset(fu, 0, sizeof(*fu));
131                         if (fread(fu, len, 1, uf) != 1)
132                                 return (-1);
133                 }
134         } else {
135                 if (fread(fu, sizeof(*fu), 1, uf) != 1)
136                         return (-1);
137         }
138         return (0);
139 }
140
141 struct utmpx *
142 getutxent(void)
143 {
144         struct futx fu;
145
146         if (getfutxent(&fu) != 0)
147                 return (NULL);
148         return (futx_to_utx(&fu));
149 }
150
151 struct utmpx *
152 getutxid(const struct utmpx *id)
153 {
154         struct futx fu;
155
156         for (;;) {
157                 if (getfutxent(&fu) != 0)
158                         return (NULL);
159
160                 switch (fu.fu_type) {
161                 case USER_PROCESS:
162                 case INIT_PROCESS:
163                 case LOGIN_PROCESS:
164                 case DEAD_PROCESS:
165                         switch (id->ut_type) {
166                         case USER_PROCESS:
167                         case INIT_PROCESS:
168                         case LOGIN_PROCESS:
169                         case DEAD_PROCESS:
170                                 if (memcmp(fu.fu_id, id->ut_id,
171                                     MIN(sizeof(fu.fu_id), sizeof(id->ut_id))) ==
172                                     0)
173                                         goto found;
174                         }
175                         break;
176                 default:
177                         if (fu.fu_type == id->ut_type)
178                                 goto found;
179                         break;
180                 }
181         }
182
183 found:
184         return (futx_to_utx(&fu));
185 }
186
187 struct utmpx *
188 getutxline(const struct utmpx *line)
189 {
190         struct futx fu;
191
192         for (;;) {
193                 if (getfutxent(&fu) != 0)
194                         return (NULL);
195
196                 switch (fu.fu_type) {
197                 case USER_PROCESS:
198                 case LOGIN_PROCESS:
199                         if (strncmp(fu.fu_line, line->ut_line,
200                             MIN(sizeof(fu.fu_line), sizeof(line->ut_line))) ==
201                             0)
202                                 goto found;
203                         break;
204                 }
205         }
206
207 found:
208         return (futx_to_utx(&fu));
209 }
210
211 struct utmpx *
212 getutxuser(const char *user)
213 {
214         struct futx fu;
215
216         for (;;) {
217                 if (getfutxent(&fu) != 0)
218                         return (NULL);
219
220                 switch (fu.fu_type) {
221                 case USER_PROCESS:
222                         if (strncmp(fu.fu_user, user, sizeof(fu.fu_user)) == 0)
223                                 goto found;
224                         break;
225                 }
226         }
227
228 found:
229         return (futx_to_utx(&fu));
230 }