1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39: #include <sys/cdefs.h>
40: #ifndef lint
41: __RCSID("$NetBSD: utmpentry.c,v 1.5 2004/10/22 15:50:47 christos Exp $");
42: #endif
43:
44: #include <sys/stat.h>
45:
46: #include <time.h>
47: #include <string.h>
48: #include <err.h>
49: #include <stdlib.h>
50:
51: #ifdef SUPPORT_UTMP
52: #include <utmp.h>
53: #endif
54: #ifdef SUPPORT_UTMPX
55: #include <utmpx.h>
56: #endif
57:
58: #include "utmpentry.h"
59:
60:
61: #ifdef SUPPORT_UTMP
62: static void getentry(struct utmpentry *, struct utmp *);
63: static time_t utmptime = 0;
64: #endif
65: #ifdef SUPPORT_UTMPX
66: static void getentryx(struct utmpentry *, struct utmpx *);
67: static time_t utmpxtime = 0;
68: #endif
69: #if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
70: static int setup(const char *);
71: static void adjust_size(struct utmpentry *e);
72: #endif
73:
74: int maxname = 8, maxline = 8, maxhost = 16;
75: static int numutmp = 0;
76: static struct utmpentry *ehead;
77:
78: #if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
79: static void
80: adjust_size(struct utmpentry *e)
81: {
82: int max;
83:
84: if ((max = strlen(e->name)) > maxname)
85: maxname = max;
86: if ((max = strlen(e->line)) > maxline)
87: maxline = max;
88: if ((max = strlen(e->host)) > maxhost)
89: maxhost = max;
90: }
91:
92: static int
93: setup(const char *fname)
94: {
95: int what = 3;
96: struct stat st;
97: const char *sfname;
98:
99: if (fname == NULL) {
100: #ifdef SUPPORT_UTMPX
101: setutxent();
102: #endif
103: #ifdef SUPPORT_UTMP
104: setutent();
105: #endif
106: } else {
107: size_t len = strlen(fname);
108: if (len == 0)
109: errx(1, "Filename cannot be 0 length.");
110: what = fname[len - 1] == 'x' ? 1 : 2;
111: if (what == 1) {
112: #ifdef SUPPORT_UTMPX
113: if (utmpxname(fname) == 0)
114: warnx("Cannot set utmpx file to `%s'",
115: fname);
116: #else
117: warnx("utmpx support not compiled in");
118: #endif
119: } else {
120: #ifdef SUPPORT_UTMP
121: if (utmpname(fname) == 0)
122: warnx("Cannot set utmp file to `%s'",
123: fname);
124: #else
125: warnx("utmp support not compiled in");
126: #endif
127: }
128: }
129: #ifdef SUPPORT_UTMPX
130: if (what & 1) {
131: sfname = fname ? fname : _PATH_UTMPX;
132: if (stat(sfname, &st) == -1) {
133: warn("Cannot stat `%s'", sfname);
134: what &= ~1;
135: } else {
136: if (st.st_mtime > utmpxtime)
137: utmpxtime = st.st_mtime;
138: else
139: what &= ~1;
140: }
141: }
142: #endif
143: #ifdef SUPPORT_UTMP
144: if (what & 2) {
145: sfname = fname ? fname : _PATH_UTMP;
146: if (stat(sfname, &st) == -1) {
147: warn("Cannot stat `%s'", sfname);
148: what &= ~2;
149: } else {
150: if (st.st_mtime > utmptime)
151: utmptime = st.st_mtime;
152: else
153: what &= ~2;
154: }
155: }
156: #endif
157: return what;
158: }
159: #endif
160:
161: void
162: freeutentries(struct utmpentry *ep)
163: {
164: #ifdef SUPPORT_UTMP
165: utmptime = 0;
166: #endif
167: #ifdef SUPPORT_UTMPX
168: utmpxtime = 0;
169: #endif
170: if (ep == ehead) {
171: ehead = NULL;
172: numutmp = 0;
173: }
174: while (ep) {
175: struct utmpentry *sep = ep;
176: ep = ep->next;
177: free(sep);
178: }
179: }
180:
181: int
182: getutentries(const char *fname, struct utmpentry **epp)
183: {
184: #ifdef SUPPORT_UTMPX
185: struct utmpx *utx;
186: #endif
187: #ifdef SUPPORT_UTMP
188: struct utmp *ut;
189: #endif
190: #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
191: struct utmpentry *ep;
192: int what = setup(fname);
193: struct utmpentry **nextp = &ehead;
194: switch (what) {
195: case 0:
196:
197: *epp = ehead;
198: return numutmp;
199: default:
200:
201: ehead = NULL;
202: numutmp = 0;
203: }
204: #endif
205:
206: #ifdef SUPPORT_UTMPX
207: while ((what & 1) && (utx = getutxent()) != NULL) {
208: if (fname == NULL && utx->ut_type != USER_PROCESS)
209: continue;
210: if ((ep = calloc(1, sizeof(struct utmpentry))) == NULL) {
211: warn(NULL);
212: return 0;
213: }
214: getentryx(ep, utx);
215: *nextp = ep;
216: nextp = &(ep->next);
217: }
218: #endif
219:
220: #ifdef SUPPORT_UTMP
221: while ((what & 2) && (ut = getutent()) != NULL) {
222: if (fname == NULL && (*ut->ut_name == '\0' ||
223: *ut->ut_line == '\0'))
224: continue;
225:
226: for (ep = ehead; ep != NULL; ep = ep->next) {
227: if (strncmp(ep->line, ut->ut_line,
228: sizeof(ut->ut_line)) == 0)
229: break;
230: }
231: if (ep != NULL)
232: continue;
233: if ((ep = calloc(1, sizeof(struct utmpentry))) == NULL) {
234: warn(NULL);
235: return 0;
236: }
237: getentry(ep, ut);
238: *nextp = ep;
239: nextp = &(ep->next);
240: }
241: #endif
242: numutmp = 0;
243: #if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
244: if (ehead != NULL) {
245: struct utmpentry *from = ehead, *save;
246:
247: ehead = NULL;
248: while (from != NULL) {
249: for (nextp = &ehead;
250: (*nextp) && strcmp(from->line, (*nextp)->line) > 0;
251: nextp = &(*nextp)->next)
252: continue;
253: save = from;
254: from = from->next;
255: save->next = *nextp;
256: *nextp = save;
257: numutmp++;
258: }
259: }
260: *epp = ehead;
261: return numutmp;
262: #else
263: *epp = NULL;
264: return 0;
265: #endif
266: }
267:
268: #ifdef SUPPORT_UTMP
269: static void
270: getentry(struct utmpentry *e, struct utmp *up)
271: {
272: (void)strncpy(e->name, up->ut_name, sizeof(up->ut_name));
273: e->name[sizeof(e->name) - 1] = '\0';
274: (void)strncpy(e->line, up->ut_line, sizeof(up->ut_line));
275: e->line[sizeof(e->line) - 1] = '\0';
276: (void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
277: e->name[sizeof(e->host) - 1] = '\0';
278: e->tv.tv_sec = up->ut_time;
279: e->tv.tv_usec = 0;
280: adjust_size(e);
281: }
282: #endif
283:
284: #ifdef SUPPORT_UTMPX
285: static void
286: getentryx(struct utmpentry *e, struct utmpx *up)
287: {
288: (void)strncpy(e->name, up->ut_name, sizeof(up->ut_name));
289: e->name[sizeof(e->name) - 1] = '\0';
290: (void)strncpy(e->line, up->ut_line, sizeof(up->ut_line));
291: e->line[sizeof(e->line) - 1] = '\0';
292: (void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
293: e->name[sizeof(e->host) - 1] = '\0';
294: e->tv = up->ut_tv;
295: adjust_size(e);
296: }
297: #endif