The Pedigree Project  0.1
glue-utmpx.c
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "newlib.h"
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/errno.h>
25 #include <utmpx.h>
26 
27 static FILE *utmp = 0;
28 
29 #define CHECK_UTMP_FILE(badval) \
30  do \
31  { \
32  if (!utmp) \
33  { \
34  utmp = fopen(UTMP_FILE, "r+"); \
35  if (!utmp) \
36  return badval; \
37  } \
38  } while (0)
39 
43 void endutxent(void)
44 {
45  if (utmp)
46  {
47  fclose(utmp);
48  utmp = 0;
49  }
50 }
51 
55 struct utmpx *getutxent(void)
56 {
57  static struct utmpx ut;
58 
59  CHECK_UTMP_FILE(0);
60 
61  size_t n = fread(&ut, sizeof(struct utmpx), 1, utmp);
62  if (!n)
63  return 0; // EOF
64 
65  return &ut;
66 }
67 
71 struct utmpx *getutxid(const struct utmpx *ut)
72 {
73  if ((!ut) || (ut->ut_type == EMPTY))
74  {
75  errno = EINVAL;
76  return 0;
77  }
78 
79  CHECK_UTMP_FILE(0);
80 
81  // Search forwards.
82  struct utmpx *p = 0;
83  do
84  {
85  p = getutxent();
86  if (p)
87  {
88  if ((ut->ut_type >= RUN_LVL && ut->ut_type <= NEW_TIME) &&
89  (p->ut_type == ut->ut_type))
90  {
91  break;
92  }
93  else if (!strcmp(p->ut_id, ut->ut_id))
94  {
95  break;
96  }
97  }
98  } while (p);
99 
100  return p;
101 }
102 
106 struct utmpx *getutxline(const struct utmpx *ut)
107 {
108  if (!ut)
109  {
110  errno = EINVAL;
111  return 0;
112  }
113 
114  CHECK_UTMP_FILE(0);
115 
116  struct utmpx *p = 0;
117  do
118  {
119  p = getutxent();
120  if (p)
121  {
122  if ((p->ut_type == LOGIN_PROCESS) || (p->ut_type == USER_PROCESS))
123  {
124  if (!strcmp(ut->ut_line, p->ut_line))
125  break;
126  }
127  }
128  } while (p);
129 
130  return p;
131 }
132 
136 struct utmpx *pututxline(const struct utmpx *ut)
137 {
138  if (!ut)
139  {
140  errno = EINVAL;
141  return 0;
142  }
143 
144  CHECK_UTMP_FILE(0);
145 
146  // Fidn a match for the given entry.
147  struct utmpx *p = getutxid(ut);
148  if (p)
149  {
150  // Found a match, replace it.
151  fseek(utmp, -sizeof(struct utmpx), SEEK_CUR);
152  fwrite(ut, sizeof(struct utmpx), 1, utmp);
153  }
154  else
155  {
156  fseek(utmp, 0, SEEK_END);
157  fwrite(ut, sizeof(struct utmpx), 1, utmp);
158  }
159 
160  return getutxid(ut);
161 }
162 
166 void setutxent()
167 {
168  if (utmp)
169  {
170  fseek(utmp, 0, SEEK_SET);
171  }
172 }