utmp: indent
[uclibc-ng.git] / libc / misc / utmp / utent.c
blob4d71f5e29486ff18c84fe1384a84df6bf2c29d2b
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...
14 #include <features.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <paths.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <utmp.h>
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)
37 if (static_fd < 0) {
38 static_fd = open_not_cancel_2(static_ut_name, O_RDWR | O_CLOEXEC);
39 if (static_fd < 0) {
40 static_fd = open_not_cancel_2(static_ut_name, O_RDONLY | O_CLOEXEC);
41 if (static_fd < 0) {
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);
48 #endif
49 return;
51 lseek(static_fd, 0, SEEK_SET);
53 #if defined __UCLIBC_HAS_THREADS__
54 void setutent(void)
56 __UCLIBC_MUTEX_LOCK(utmplock);
57 __setutent_unlocked();
58 __UCLIBC_MUTEX_UNLOCK(utmplock);
60 #else
61 strong_alias(__setutent_unlocked,setutent)
62 #endif
63 libc_hidden_def(setutent)
65 /* This function must be called with the LOCK held */
66 static struct utmp *__getutent_unlocked(void)
68 if (static_fd < 0) {
69 __setutent_unlocked();
70 if (static_fd < 0)
71 return NULL;
74 if (read_not_cancel(static_fd, &static_utmp,
75 sizeof(static_utmp)) == sizeof(static_utmp)) {
76 return &static_utmp;
79 return NULL;
81 #if defined __UCLIBC_HAS_THREADS__
82 struct utmp *getutent(void)
84 struct utmp *ret;
86 __UCLIBC_MUTEX_LOCK(utmplock);
87 ret = __getutent_unlocked();
88 __UCLIBC_MUTEX_UNLOCK(utmplock);
89 return ret;
91 #else
92 strong_alias(__getutent_unlocked,getutent)
93 #endif
94 libc_hidden_def(getutent)
96 static void __endutent(void)
98 __UCLIBC_MUTEX_LOCK(utmplock);
99 if (static_fd >= 0)
100 close_not_cancel_no_status(static_fd);
101 static_fd = -1;
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)
110 struct utmp *lutmp;
111 unsigned type;
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;
116 type /= 4;
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 */
121 return lutmp;
123 if (type == 1
124 && strncmp(lutmp->ut_id, utmp_entry->ut_id,
125 sizeof(lutmp->ut_id)) == 0) {
126 /* INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, DEAD_PROCESS */
127 return lutmp;
131 return NULL;
133 #if defined __UCLIBC_HAS_THREADS__
134 struct utmp *getutid(const struct utmp *utmp_entry)
136 struct utmp *ret;
138 __UCLIBC_MUTEX_LOCK(utmplock);
139 ret = __getutid_unlocked(utmp_entry);
140 __UCLIBC_MUTEX_UNLOCK(utmplock);
141 return ret;
143 #else
144 strong_alias(__getutid_unlocked,getutid)
145 #endif
146 libc_hidden_def(getutid)
148 struct utmp *getutline(const struct utmp *utmp_entry)
150 struct utmp *lutmp;
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) {
157 break;
161 __UCLIBC_MUTEX_UNLOCK(utmplock);
162 return lutmp;
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);
175 else
176 lseek(static_fd, (off_t) 0, SEEK_END);
177 if (write(static_fd, utmp_entry, sizeof(struct utmp))
178 != sizeof(struct utmp))
179 utmp_entry = NULL;
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);
202 static_fd = -1;
204 __UCLIBC_MUTEX_UNLOCK(utmplock);
205 return 0; /* or maybe return -(static_ut_name != new_ut_name)? */
207 libc_hidden_def(utmpname)