]>
git.saurik.com Git - apple/libc.git/blob - gen/NetBSD/utmpx.c
1 /* $NetBSD: utmpx.c,v 1.25 2008/04/28 20:22:59 martin Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
34 __RCSID("$NetBSD: utmpx.c,v 1.25 2008/04/28 20:22:59 martin Exp $");
35 #endif /* LIBC_SCCS and not lint */
37 #include "namespace.h"
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
58 static int readonly
= 0;
59 static struct utmpx ut
;
60 static char utfile
[MAXPATHLEN
] = _PATH_UTMPX
;
62 static struct utmpx
*utmp_update(const struct utmpx
*);
64 static const char vers
[] = "utmpx-1.00";
70 (void)memset(&ut
, 0, sizeof(ut
));
73 (void)fseeko(fp
, (off_t
)sizeof(ut
), SEEK_SET
);
81 (void)memset(&ut
, 0, sizeof(ut
));
97 if ((fp
= fopen(utfile
, "r+")) == NULL
)
98 if ((fp
= fopen(utfile
, "w+")) == NULL
) {
99 if ((fp
= fopen(utfile
, "r")) == NULL
)
106 /* get file size in order to check if new file */
107 if (fstat(fileno(fp
), &st
) == -1)
110 if (st
.st_size
== 0) {
111 /* new file, add signature record */
112 (void)memset(&ut
, 0, sizeof(ut
));
113 ut
.ut_type
= SIGNATURE
;
114 (void)memcpy(ut
.ut_user
, vers
, sizeof(vers
));
115 if (fwrite(&ut
, sizeof(ut
), 1, fp
) != 1)
118 /* old file, read signature record */
119 if (fread(&ut
, sizeof(ut
), 1, fp
) != 1)
121 if (memcmp(ut
.ut_user
, vers
, sizeof(vers
)) != 0 ||
122 ut
.ut_type
!= SIGNATURE
)
127 if (fread(&ut
, sizeof(ut
), 1, fp
) != 1)
134 (void)memset(&ut
, 0, sizeof(ut
));
140 getutxid(const struct utmpx
*utx
)
143 _DIAGASSERT(utx
!= NULL
);
145 if (utx
->ut_type
== EMPTY
)
149 if (ut
.ut_type
== EMPTY
)
151 switch (utx
->ut_type
) {
158 if (ut
.ut_type
== utx
->ut_type
)
165 switch (ut
.ut_type
) {
170 if (memcmp(ut
.ut_id
, utx
->ut_id
,
171 sizeof(ut
.ut_id
)) == 0)
181 } while (getutxent() != NULL
);
187 getutxline(const struct utmpx
*utx
)
190 _DIAGASSERT(utx
!= NULL
);
193 switch (ut
.ut_type
) {
198 if (strncmp(ut
.ut_line
, utx
->ut_line
,
199 sizeof(ut
.ut_line
)) == 0)
205 } while (getutxent() != NULL
);
211 pututxline(const struct utmpx
*utx
)
213 struct utmpx temp
, *u
= NULL
;
216 _DIAGASSERT(utx
!= NULL
);
221 if (strcmp(_PATH_UTMPX
, utfile
) == 0)
222 if ((fp
!= NULL
&& readonly
) || (fp
== NULL
&& geteuid() != 0))
223 return utmp_update(utx
);
226 (void)memcpy(&temp
, utx
, sizeof(temp
));
230 if (fp
== NULL
|| readonly
)
234 if (getutxid(&temp
) == NULL
) {
236 if (getutxid(&temp
) == NULL
) {
237 if (lockf(fileno(fp
), F_LOCK
, (off_t
)0) == -1)
240 if (fseeko(fp
, (off_t
)0, SEEK_END
) == -1)
246 /* we are not appending */
247 if (fseeko(fp
, -(off_t
)sizeof(ut
), SEEK_CUR
) == -1)
251 if (fwrite(&temp
, sizeof (temp
), 1, fp
) != 1)
254 if (fflush(fp
) == -1)
257 u
= memcpy(&ut
, &temp
, sizeof(ut
));
260 if (lockf(fileno(fp
), F_ULOCK
, (off_t
)0) == -1)
267 static struct utmpx
*
268 utmp_update(const struct utmpx
*utx
)
270 char buf
[sizeof(*utx
) * 4 + 1];
274 _DIAGASSERT(utx
!= NULL
);
276 (void)strvisx(buf
, (const char *)(const void *)utx
, sizeof(*utx
),
278 switch (pid
= fork()) {
280 (void)execl(_PATH_UTMP_UPDATE
,
281 strrchr(_PATH_UTMP_UPDATE
, '/') + 1, buf
, NULL
);
287 if (waitpid(pid
, &status
, 0) == -1)
289 if (WIFEXITED(status
) && WEXITSTATUS(status
) == 0)
290 return memcpy(&ut
, utx
, sizeof(ut
));
297 * The following are extensions and not part of the X/Open spec.
300 updwtmpx(const char *file
, const struct utmpx
*utx
)
305 _DIAGASSERT(file
!= NULL
);
306 _DIAGASSERT(utx
!= NULL
);
308 fd
= open(file
, O_WRONLY
|O_APPEND
|O_SHLOCK
);
311 if ((fd
= open(file
, O_CREAT
|O_WRONLY
|O_EXLOCK
, 0644)) == -1)
313 (void)memset(&ut
, 0, sizeof(ut
));
314 ut
.ut_type
= SIGNATURE
;
315 (void)memcpy(ut
.ut_user
, vers
, sizeof(vers
));
316 if (write(fd
, &ut
, sizeof(ut
)) == -1)
319 if (write(fd
, utx
, sizeof(*utx
)) == -1)
334 utmpxname(const char *fname
)
338 _DIAGASSERT(fname
!= NULL
);
342 if (len
>= sizeof(utfile
))
346 if (fname
[len
- 1] != 'x')
349 (void)strlcpy(utfile
, fname
, sizeof(utfile
));
356 getutmp(const struct utmpx
*ux
, struct utmp
*u
)
359 _DIAGASSERT(ux
!= NULL
);
360 _DIAGASSERT(u
!= NULL
);
362 (void)memcpy(u
->ut_name
, ux
->ut_name
, sizeof(u
->ut_name
));
363 (void)memcpy(u
->ut_line
, ux
->ut_line
, sizeof(u
->ut_line
));
364 (void)memcpy(u
->ut_host
, ux
->ut_host
, sizeof(u
->ut_host
));
365 u
->ut_time
= ux
->ut_tv
.tv_sec
;
369 getutmpx(const struct utmp
*u
, struct utmpx
*ux
)
372 _DIAGASSERT(ux
!= NULL
);
373 _DIAGASSERT(u
!= NULL
);
375 (void)memcpy(ux
->ut_name
, u
->ut_name
, sizeof(u
->ut_name
));
376 (void)memcpy(ux
->ut_line
, u
->ut_line
, sizeof(u
->ut_line
));
377 (void)memcpy(ux
->ut_host
, u
->ut_host
, sizeof(u
->ut_host
));
378 ux
->ut_tv
.tv_sec
= u
->ut_time
;
379 ux
->ut_tv
.tv_usec
= 0;
380 (void)memset(&ux
->ut_ss
, 0, sizeof(ux
->ut_ss
));
382 ux
->ut_type
= USER_PROCESS
;
384 ux
->ut_exit
.e_termination
= 0;
385 ux
->ut_exit
.e_exit
= 0;
389 getlastlogx(const char *fname
, uid_t uid
, struct lastlogx
*ll
)
394 _DIAGASSERT(fname
!= NULL
);
395 _DIAGASSERT(ll
!= NULL
);
397 db
= dbopen(fname
, O_RDONLY
|O_SHLOCK
, 0, DB_HASH
, NULL
);
403 key
.size
= sizeof(uid
);
405 if ((db
->get
)(db
, &key
, &data
, 0) != 0)
408 if (data
.size
!= sizeof(*ll
)) {
414 if ((ll
= malloc(sizeof(*ll
))) == NULL
)
417 (void)memcpy(ll
, data
.data
, sizeof(*ll
));
427 updlastlogx(const char *fname
, uid_t uid
, struct lastlogx
*ll
)
433 _DIAGASSERT(fname
!= NULL
);
434 _DIAGASSERT(ll
!= NULL
);
436 db
= dbopen(fname
, O_RDWR
|O_CREAT
|O_EXLOCK
, 0644, DB_HASH
, NULL
);
442 key
.size
= sizeof(uid
);
444 data
.size
= sizeof(*ll
);
445 if ((db
->put
)(db
, &key
, &data
, 0) != 0)