1 /* vi: set sw=4 ts=4: */
2 /* utent.c <ndf@linux.mit.edu> */
3 /* Let it be known that this is very possibly the worst standard ever. HP-UX
4 does one thing, someone else does another, linux another... If anyone
5 actually has the standard, please send it to me.
7 Note that because of the way this stupid stupid standard works, you
8 have to call endutent() to close the file even if you've not called
9 setutent -- getutid and family use the same file descriptor.
11 Modified by Erik Andersen for uClibc...
23 #include <not-cancel.h>
24 #include <bits/uClibc_mutex.h>
26 __UCLIBC_MUTEX_STATIC(utmplock
, PTHREAD_MUTEX_INITIALIZER
);
28 /* Some global crap */
29 static int static_fd
= -1;
30 static struct utmp static_utmp
;
31 static const char default_file_name
[] = _PATH_UTMP
;
32 static const char *static_ut_name
= default_file_name
;
34 /* This function must be called with the LOCK held */
35 static void __setutent_unlocked(void)
38 static_fd
= open_not_cancel_2(static_ut_name
, O_RDWR
| O_CLOEXEC
);
40 static_fd
= open_not_cancel_2(static_ut_name
, O_RDONLY
| O_CLOEXEC
);
42 return; /* static_fd remains < 0 */
45 #ifndef __ASSUME_O_CLOEXEC
46 /* Make sure the file will be closed on exec() */
47 fcntl_not_cancel(static_fd
, F_SETFD
, FD_CLOEXEC
);
51 lseek(static_fd
, 0, SEEK_SET
);
53 #if defined __UCLIBC_HAS_THREADS__
56 __UCLIBC_MUTEX_LOCK(utmplock
);
57 __setutent_unlocked();
58 __UCLIBC_MUTEX_UNLOCK(utmplock
);
61 strong_alias(__setutent_unlocked
,setutent
)
63 libc_hidden_def(setutent
)
65 /* This function must be called with the LOCK held */
66 static struct utmp
*__getutent_unlocked(void)
69 __setutent_unlocked();
74 if (read_not_cancel(static_fd
, &static_utmp
,
75 sizeof(static_utmp
)) == sizeof(static_utmp
)) {
81 #if defined __UCLIBC_HAS_THREADS__
82 struct utmp
*getutent(void)
86 __UCLIBC_MUTEX_LOCK(utmplock
);
87 ret
= __getutent_unlocked();
88 __UCLIBC_MUTEX_UNLOCK(utmplock
);
92 strong_alias(__getutent_unlocked
,getutent
)
94 libc_hidden_def(getutent
)
96 static void __endutent(void)
98 __UCLIBC_MUTEX_LOCK(utmplock
);
100 close_not_cancel_no_status(static_fd
);
102 __UCLIBC_MUTEX_UNLOCK(utmplock
);
104 strong_alias(__endutent
,endutent
)
105 libc_hidden_def(endutent
)
107 /* This function must be called with the LOCK held */
108 static struct utmp
*__getutid_unlocked(const struct utmp
*utmp_entry
)
113 /* We use the fact that constants we are interested in are: */
114 /* RUN_LVL=1, ... OLD_TIME=4; INIT_PROCESS=5, ... USER_PROCESS=8 */
115 type
= utmp_entry
->ut_type
- 1;
118 while ((lutmp
= __getutent_unlocked()) != NULL
) {
119 if (type
== 0 && lutmp
->ut_type
== utmp_entry
->ut_type
) {
120 /* one of RUN_LVL, BOOT_TIME, NEW_TIME, OLD_TIME */
124 && strncmp(lutmp
->ut_id
, utmp_entry
->ut_id
,
125 sizeof(lutmp
->ut_id
)) == 0) {
126 /* INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, DEAD_PROCESS */
133 #if defined __UCLIBC_HAS_THREADS__
134 struct utmp
*getutid(const struct utmp
*utmp_entry
)
138 __UCLIBC_MUTEX_LOCK(utmplock
);
139 ret
= __getutid_unlocked(utmp_entry
);
140 __UCLIBC_MUTEX_UNLOCK(utmplock
);
144 strong_alias(__getutid_unlocked
,getutid
)
146 libc_hidden_def(getutid
)
148 struct utmp
*getutline(const struct utmp
*utmp_entry
)
152 __UCLIBC_MUTEX_LOCK(utmplock
);
153 while ((lutmp
= __getutent_unlocked()) != NULL
) {
154 if (lutmp
->ut_type
== USER_PROCESS
|| lutmp
->ut_type
== LOGIN_PROCESS
) {
155 if (strncmp(lutmp
->ut_line
, utmp_entry
->ut_line
,
156 sizeof(lutmp
->ut_line
)) == 0) {
161 __UCLIBC_MUTEX_UNLOCK(utmplock
);
164 libc_hidden_def(getutline
)
166 struct utmp
*pututline(const struct utmp
*utmp_entry
)
168 __UCLIBC_MUTEX_LOCK(utmplock
);
169 /* Ignore the return value. That way, if they've already positioned
170 the file pointer where they want it, everything will work out. */
171 lseek(static_fd
, (off_t
) - sizeof(struct utmp
), SEEK_CUR
);
173 if (__getutid_unlocked(utmp_entry
) != NULL
)
174 lseek(static_fd
, (off_t
) - sizeof(struct utmp
), SEEK_CUR
);
176 lseek(static_fd
, (off_t
) 0, SEEK_END
);
177 if (write(static_fd
, utmp_entry
, sizeof(struct utmp
))
178 != sizeof(struct utmp
))
181 __UCLIBC_MUTEX_UNLOCK(utmplock
);
182 return (struct utmp
*)utmp_entry
;
184 libc_hidden_def(pututline
)
186 int utmpname(const char *new_ut_name
)
188 __UCLIBC_MUTEX_LOCK(utmplock
);
189 if (new_ut_name
!= NULL
) {
190 if (static_ut_name
!= default_file_name
)
191 free((char *)static_ut_name
);
192 static_ut_name
= strdup(new_ut_name
);
193 if (static_ut_name
== NULL
) {
194 /* We should probably whine about out-of-memory
195 * errors here... Instead just reset to the default */
196 static_ut_name
= default_file_name
;
200 if (static_fd
>= 0) {
201 close_not_cancel_no_status(static_fd
);
204 __UCLIBC_MUTEX_UNLOCK(utmplock
);
205 return 0; /* or maybe return -(static_ut_name != new_ut_name)? */
207 libc_hidden_def(utmpname
)